@vellumai/assistant 0.10.8 → 0.10.9-dev.202607152225.ec6fdbf

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 (1453) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +52 -88
  3. package/README.md +14 -35
  4. package/docs/activation-funnel-telemetry.md +20 -18
  5. package/docs/architecture/scheduling.md +0 -86
  6. package/docs/runbook-trusted-contacts.md +19 -19
  7. package/docs/trusted-contact-access.md +70 -69
  8. package/docs/workspace-tools.md +4 -2
  9. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +62 -360
  10. package/eslint-rules/cli-no-daemon-internals.js +91 -275
  11. package/eslint.config.mjs +4 -4
  12. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  13. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  14. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  15. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
  16. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  17. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  18. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +575 -0
  19. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
  20. package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +687 -0
  21. package/node_modules/@vellumai/gateway-client/src/index.ts +82 -0
  22. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  23. package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
  24. package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
  25. package/openapi.yaml +353 -742
  26. package/package.json +2 -2
  27. package/scripts/build-test-fixtures.ts +3 -2
  28. package/scripts/test.ts +2 -7
  29. package/src/__tests__/activation-early-marking.test.ts +1 -8
  30. package/src/__tests__/actor-token-service.test.ts +0 -7
  31. package/src/__tests__/add-message-preassigned-id.test.ts +1 -1
  32. package/src/__tests__/add-message-skip-indexing.test.ts +164 -0
  33. package/src/__tests__/agent-image-optimize.test.ts +104 -1
  34. package/src/__tests__/agent-loop-callsite-precedence.test.ts +5 -15
  35. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +0 -6
  36. package/src/__tests__/agent-loop-override-profile.test.ts +48 -50
  37. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +4 -17
  38. package/src/__tests__/agent-loop-set-system-prompt.test.ts +3 -14
  39. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -4
  40. package/src/__tests__/agent-wake-override-profile.test.ts +40 -71
  41. package/src/__tests__/always-loaded-tools-guard.test.ts +4 -7
  42. package/src/__tests__/annotate-activity-metadata.test.ts +4 -31
  43. package/src/__tests__/annotate-risk-options.test.ts +4 -31
  44. package/src/__tests__/anthropic-provider.test.ts +11 -0
  45. package/src/__tests__/app-asset-bytes.test.ts +72 -0
  46. package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
  47. package/src/__tests__/app-bundler.test.ts +4 -20
  48. package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -8
  49. package/src/__tests__/app-executors.test.ts +2 -49
  50. package/src/__tests__/app-routes-csp.test.ts +126 -157
  51. package/src/__tests__/approval-cascade.test.ts +0 -82
  52. package/src/__tests__/approval-interception-trust-gates.test.ts +0 -7
  53. package/src/__tests__/approval-primitive.test.ts +1 -9
  54. package/src/__tests__/approval-routes-http.test.ts +5 -63
  55. package/src/__tests__/assistant-event-hub-machine-name.test.ts +1 -19
  56. package/src/__tests__/assistant-events-sse-hardening.test.ts +4 -21
  57. package/src/__tests__/attachment-stored-path-annotation.test.ts +1 -19
  58. package/src/__tests__/attachment-upload-trusted-source.test.ts +0 -13
  59. package/src/__tests__/attachments-store-heic-normalize.test.ts +0 -13
  60. package/src/__tests__/attachments-store.test.ts +5 -19
  61. package/src/__tests__/audit-log-rotation.test.ts +1 -9
  62. package/src/__tests__/auth-fallback-events-store.test.ts +43 -59
  63. package/src/__tests__/available-skills.test.ts +7 -15
  64. package/src/__tests__/avatar-e2e.test.ts +0 -19
  65. package/src/__tests__/avatar-generator.test.ts +0 -9
  66. package/src/__tests__/background-shell-bash.test.ts +0 -20
  67. package/src/__tests__/background-shell-host-bash.test.ts +0 -34
  68. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -43
  69. package/src/__tests__/browser-fill-credential.test.ts +0 -7
  70. package/src/__tests__/browser-manager.test.ts +1 -8
  71. package/src/__tests__/browser-skill-endstate.test.ts +1 -5
  72. package/src/__tests__/btw-routes.test.ts +7 -30
  73. package/src/__tests__/build-persisted-content.test.ts +96 -29
  74. package/src/__tests__/bundle-scanner.test.ts +27 -1
  75. package/src/__tests__/call-controller.test.ts +96 -149
  76. package/src/__tests__/call-conversation-messages.test.ts +2 -9
  77. package/src/__tests__/call-domain.test.ts +21 -56
  78. package/src/__tests__/call-pointer-message-composer.test.ts +0 -8
  79. package/src/__tests__/call-pointer-messages.test.ts +1 -8
  80. package/src/__tests__/call-recovery.test.ts +4 -11
  81. package/src/__tests__/call-routes-http.test.ts +12 -47
  82. package/src/__tests__/call-site-routing-provider.test.ts +5 -16
  83. package/src/__tests__/call-start-guardian-guard.test.ts +0 -10
  84. package/src/__tests__/call-state.test.ts +1 -8
  85. package/src/__tests__/call-store.test.ts +4 -11
  86. package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -32
  87. package/src/__tests__/catalog-cache.test.ts +0 -8
  88. package/src/__tests__/catalog-files.test.ts +0 -8
  89. package/src/__tests__/catalog-install-normalize.test.ts +0 -7
  90. package/src/__tests__/ces-rpc-credential-backend.test.ts +0 -7
  91. package/src/__tests__/channel-approval-routes.test.ts +23 -34
  92. package/src/__tests__/channel-approvals.test.ts +0 -7
  93. package/src/__tests__/channel-delivery-store.test.ts +6 -17
  94. package/src/__tests__/channel-guardian.test.ts +0 -7
  95. package/src/__tests__/channel-inbound-disk-pressure.test.ts +15 -20
  96. package/src/__tests__/channel-readiness-routes.test.ts +41 -67
  97. package/src/__tests__/channel-readiness-service.test.ts +13 -45
  98. package/src/__tests__/channel-readiness-slack-remote.test.ts +5 -22
  99. package/src/__tests__/channel-reply-delivery.test.ts +18 -5
  100. package/src/__tests__/channel-retry-sweep.test.ts +0 -7
  101. package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
  102. package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
  103. package/src/__tests__/checker.test.ts +0 -24
  104. package/src/__tests__/clawhub-files.test.ts +0 -8
  105. package/src/__tests__/clawhub.test.ts +0 -7
  106. package/src/__tests__/clear-all-lexical.test.ts +0 -6
  107. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -0
  108. package/src/__tests__/client-os-metadata-persistence.test.ts +0 -5
  109. package/src/__tests__/compaction-events.test.ts +26 -99
  110. package/src/__tests__/compaction-ledger-store.test.ts +1 -7
  111. package/src/__tests__/compaction-summary-head-persisted-count.test.ts +0 -27
  112. package/src/__tests__/compaction-trail-store.test.ts +1 -19
  113. package/src/__tests__/compaction.benchmark.test.ts +2 -6
  114. package/src/__tests__/compactor-call-site-logging.test.ts +0 -21
  115. package/src/__tests__/compactor-fixed-boundary.test.ts +0 -21
  116. package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -10
  117. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -21
  118. package/src/__tests__/compactor-media-strip.test.ts +0 -21
  119. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -21
  120. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -21
  121. package/src/__tests__/compactor-web-search-strip.test.ts +0 -21
  122. package/src/__tests__/config-get-vision-flag.test.ts +24 -53
  123. package/src/__tests__/config-loader-backfill.test.ts +9 -25
  124. package/src/__tests__/config-loader-platform-defaults.test.ts +0 -21
  125. package/src/__tests__/config-schema-cmd.test.ts +10 -11
  126. package/src/__tests__/config-schema.test.ts +221 -275
  127. package/src/__tests__/config-set-route.test.ts +32 -62
  128. package/src/__tests__/config-watcher-cleanup-throttle.test.ts +44 -83
  129. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -16
  130. package/src/__tests__/config-watcher.test.ts +2 -17
  131. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +57 -63
  132. package/src/__tests__/contact-store-interaction-info.test.ts +1 -8
  133. package/src/__tests__/contact-store-user-file.test.ts +1 -8
  134. package/src/__tests__/contacts-tools.test.ts +21 -26
  135. package/src/__tests__/contacts-write.test.ts +1 -8
  136. package/src/__tests__/context-search-memory-v2-source.test.ts +0 -6
  137. package/src/__tests__/context-window-manager-compact-retry.test.ts +0 -27
  138. package/src/__tests__/context-window-manager-overflow-rung.test.ts +0 -21
  139. package/src/__tests__/conversation-abort-tool-results.test.ts +9 -90
  140. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +5 -41
  141. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +16 -54
  142. package/src/__tests__/conversation-agent-loop-overflow.test.ts +14 -79
  143. package/src/__tests__/conversation-agent-loop.test.ts +213 -136
  144. package/src/__tests__/conversation-app-control-instantiation.test.ts +10 -16
  145. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -43
  146. package/src/__tests__/conversation-attachments.test.ts +0 -17
  147. package/src/__tests__/conversation-attention-store.test.ts +1 -9
  148. package/src/__tests__/conversation-attention-telegram.test.ts +0 -8
  149. package/src/__tests__/conversation-clear-safety.test.ts +20 -20
  150. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -82
  151. package/src/__tests__/conversation-crud-enabled-plugins.test.ts +1 -7
  152. package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -7
  153. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -7
  154. package/src/__tests__/conversation-disk-view-integration.test.ts +1 -26
  155. package/src/__tests__/conversation-disk-view.test.ts +1 -26
  156. package/src/__tests__/conversation-enabledplugins-route.test.ts +3 -21
  157. package/src/__tests__/conversation-error.test.ts +21 -7
  158. package/src/__tests__/conversation-fork-crud.test.ts +35 -44
  159. package/src/__tests__/conversation-fork-retrospective.test.ts +9 -24
  160. package/src/__tests__/conversation-fork-route.test.ts +0 -32
  161. package/src/__tests__/conversation-history-web-search.test.ts +20 -17
  162. package/src/__tests__/conversation-inference-profile-list.test.ts +0 -17
  163. package/src/__tests__/conversation-inference-profile-route.test.ts +2 -24
  164. package/src/__tests__/conversation-init.benchmark.test.ts +3 -56
  165. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -33
  166. package/src/__tests__/conversation-lifecycle.test.ts +63 -103
  167. package/src/__tests__/conversation-list-source.test.ts +0 -18
  168. package/src/__tests__/conversation-load-history-repair.test.ts +39 -91
  169. package/src/__tests__/conversation-load-history-stripped.test.ts +12 -57
  170. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +10 -20
  171. package/src/__tests__/conversation-message-id-uuidv7.test.ts +1 -18
  172. package/src/__tests__/conversation-pairing.test.ts +0 -7
  173. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -9
  174. package/src/__tests__/conversation-process-callsite.test.ts +15 -97
  175. package/src/__tests__/conversation-provider-retry-repair.test.ts +3 -84
  176. package/src/__tests__/conversation-queue.test.ts +12 -108
  177. package/src/__tests__/conversation-routes-disk-view.test.ts +8 -60
  178. package/src/__tests__/conversation-routes-enabled-plugins.test.ts +5 -63
  179. package/src/__tests__/conversation-routes-guardian-reply.test.ts +13 -22
  180. package/src/__tests__/conversation-routes-hidden-queue.test.ts +5 -64
  181. package/src/__tests__/conversation-routes-slash-commands.test.ts +19 -87
  182. package/src/__tests__/conversation-runtime-assembly.test.ts +34 -37
  183. package/src/__tests__/conversation-seed-composer.test.ts +3 -3
  184. package/src/__tests__/conversation-skill-tools.test.ts +19 -32
  185. package/src/__tests__/conversation-slash-queue.test.ts +3 -90
  186. package/src/__tests__/conversation-slash-unknown.test.ts +0 -87
  187. package/src/__tests__/conversation-speed-override.test.ts +19 -94
  188. package/src/__tests__/conversation-starter-routes.test.ts +0 -7
  189. package/src/__tests__/conversation-store.test.ts +72 -66
  190. package/src/__tests__/conversation-summarize-route.test.ts +0 -11
  191. package/src/__tests__/conversation-summarize-up-to.test.ts +4 -89
  192. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +131 -0
  193. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +36 -36
  194. package/src/__tests__/conversation-surfaces-data-persist.test.ts +4 -2
  195. package/src/__tests__/conversation-title-service.test.ts +0 -7
  196. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
  197. package/src/__tests__/conversation-tool-setup-attribution.test.ts +37 -60
  198. package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +17 -17
  199. package/src/__tests__/conversation-unread-route.test.ts +0 -7
  200. package/src/__tests__/conversation-usage.test.ts +21 -71
  201. package/src/__tests__/conversation-wait-for-idle.test.ts +0 -82
  202. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -45
  203. package/src/__tests__/conversation-workspace-injection.test.ts +0 -88
  204. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -88
  205. package/src/__tests__/conversations-defer-cli.test.ts +3 -0
  206. package/src/__tests__/conversations-import-system-filter.test.ts +0 -17
  207. package/src/__tests__/credential-broker-browser-fill.test.ts +0 -9
  208. package/src/__tests__/credential-broker-server-use.test.ts +0 -9
  209. package/src/__tests__/credential-health-service.test.ts +14 -31
  210. package/src/__tests__/credential-metadata-store.test.ts +0 -8
  211. package/src/__tests__/credential-prompt-route.test.ts +9 -15
  212. package/src/__tests__/credential-resolve.test.ts +0 -8
  213. package/src/__tests__/credential-routes.test.ts +250 -0
  214. package/src/__tests__/credential-security-invariants.test.ts +4 -8
  215. package/src/__tests__/credential-token-resolver.test.ts +0 -9
  216. package/src/__tests__/cross-provider-web-search.test.ts +12 -18
  217. package/src/__tests__/daemon-assistant-events.test.ts +1 -9
  218. package/src/__tests__/daemon-credential-client.test.ts +0 -7
  219. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +1 -8
  220. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +1 -7
  221. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +0 -8
  222. package/src/__tests__/db-readiness-http-gate.test.ts +0 -18
  223. package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +1 -7
  224. package/src/__tests__/db-test-helpers.ts +10 -3
  225. package/src/__tests__/delete-managed-skill-tool.test.ts +0 -7
  226. package/src/__tests__/delete-propagation.test.ts +0 -7
  227. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -7
  228. package/src/__tests__/device-id.test.ts +1 -9
  229. package/src/__tests__/disk-pressure-guard.test.ts +0 -4
  230. package/src/__tests__/disk-pressure-routes.test.ts +0 -4
  231. package/src/__tests__/disk-pressure-tools.test.ts +4 -42
  232. package/src/__tests__/dm-backfill.test.ts +0 -7
  233. package/src/__tests__/dm-persistence.test.ts +0 -5
  234. package/src/__tests__/docker-signing-key-bootstrap.test.ts +1 -8
  235. package/src/__tests__/drain-requeue-on-contention.test.ts +1 -8
  236. package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -43
  237. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -27
  238. package/src/__tests__/edit-propagation.test.ts +1 -8
  239. package/src/__tests__/email-invite-adapter.test.ts +8 -33
  240. package/src/__tests__/embedding-managed-proxy-selection.test.ts +0 -8
  241. package/src/__tests__/emit-event-signal.test.ts +1 -1
  242. package/src/__tests__/emit-signal-routing-intent.test.ts +0 -7
  243. package/src/__tests__/empty-state-greeting-cache.test.ts +9 -9
  244. package/src/__tests__/encrypted-store.test.ts +0 -9
  245. package/src/__tests__/ensure-conversation-exists.test.ts +1 -18
  246. package/src/__tests__/events-client-registration.test.ts +1 -19
  247. package/src/__tests__/events-dev-bypass-actor.test.ts +0 -7
  248. package/src/__tests__/events-tail-route.test.ts +1 -8
  249. package/src/__tests__/file-list-tool.test.ts +22 -15
  250. package/src/__tests__/followup-tools.test.ts +1 -16
  251. package/src/__tests__/gateway-only-enforcement.test.ts +3 -44
  252. package/src/__tests__/get-skill-detail-audit.test.ts +0 -7
  253. package/src/__tests__/google-calendar-watcher.test.ts +175 -0
  254. package/src/__tests__/guardian-action-sweep.test.ts +0 -7
  255. package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -7
  256. package/src/__tests__/guardian-card-withdrawal.test.ts +60 -64
  257. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -135
  258. package/src/__tests__/guardian-dispatch.test.ts +58 -157
  259. package/src/__tests__/guardian-expiry-notifier.test.ts +56 -48
  260. package/src/__tests__/guardian-gateway-sim.ts +626 -0
  261. package/src/__tests__/guardian-outbound-http.test.ts +0 -7
  262. package/src/__tests__/guardian-routing-invariants.test.ts +229 -220
  263. package/src/__tests__/guardian-routing-state.test.ts +2 -9
  264. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -17
  265. package/src/__tests__/guardian-wait-controller.test.ts +44 -43
  266. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +26 -91
  267. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +18 -103
  268. package/src/__tests__/headless-browser-interactions.test.ts +0 -7
  269. package/src/__tests__/headless-browser-mode.test.ts +0 -9
  270. package/src/__tests__/headless-browser-navigate.test.ts +0 -7
  271. package/src/__tests__/headless-browser-read-tools.test.ts +0 -7
  272. package/src/__tests__/headless-browser-snapshot.test.ts +0 -7
  273. package/src/__tests__/heartbeat-disk-pressure.test.ts +9 -38
  274. package/src/__tests__/heartbeat-service.test.ts +83 -106
  275. package/src/__tests__/helpers/channel-test-adapter.ts +10 -0
  276. package/src/__tests__/helpers/gateway-guardian-requests-store-bridge.ts +155 -0
  277. package/src/__tests__/helpers/set-config.ts +40 -0
  278. package/src/__tests__/host-bash-proxy.test.ts +18 -34
  279. package/src/__tests__/host-browser-proxy.test.ts +15 -20
  280. package/src/__tests__/host-shell-tool.test.ts +2 -34
  281. package/src/__tests__/http-conversation-lineage.test.ts +3 -19
  282. package/src/__tests__/http-user-message-parity.test.ts +3 -95
  283. package/src/__tests__/identity-routes.test.ts +1 -9
  284. package/src/__tests__/image-recovery-hook.test.ts +36 -0
  285. package/src/__tests__/inbound-admitted-introduction-nudge.test.ts +6 -12
  286. package/src/__tests__/inbound-invite-redemption.test.ts +0 -7
  287. package/src/__tests__/inbound-slack-persistence.test.ts +0 -5
  288. package/src/__tests__/inbound-trust-verdict.test.ts +2 -8
  289. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
  290. package/src/__tests__/inference-profile-reaper.test.ts +1 -7
  291. package/src/__tests__/inference-profile-session-handler.test.ts +4 -30
  292. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -20
  293. package/src/__tests__/ingress-url-consistency.test.ts +1 -23
  294. package/src/__tests__/injector-background-turn.test.ts +10 -24
  295. package/src/__tests__/injector-chain.test.ts +4 -13
  296. package/src/__tests__/injector-pkb-v2-silenced.test.ts +19 -17
  297. package/src/__tests__/inline-command-runner.test.ts +0 -34
  298. package/src/__tests__/inline-skill-load-permissions.test.ts +1 -30
  299. package/src/__tests__/install-skill-routing.test.ts +7 -6
  300. package/src/__tests__/integration-status.test.ts +25 -17
  301. package/src/__tests__/intent-routing.test.ts +1 -50
  302. package/src/__tests__/internal-telemetry-routes.test.ts +41 -22
  303. package/src/__tests__/interrupted-turn-reconciler.test.ts +1 -8
  304. package/src/__tests__/introduction-card-resolver.test.ts +108 -117
  305. package/src/__tests__/invite-redeemed-ipc.test.ts +0 -7
  306. package/src/__tests__/invite-routes-http.test.ts +12 -23
  307. package/src/__tests__/jobs-store-has-pending-job.test.ts +59 -0
  308. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +1 -14
  309. package/src/__tests__/jobs-store-skill-card-upsert.test.ts +191 -0
  310. package/src/__tests__/jobs-store-upsert-debounced.test.ts +1 -14
  311. package/src/__tests__/lexical-index-dual-write.test.ts +0 -6
  312. package/src/__tests__/list-all-apps.test.ts +200 -0
  313. package/src/__tests__/list-messages-attachments.test.ts +11 -20
  314. package/src/__tests__/list-messages-background-tool-completion.test.ts +6 -18
  315. package/src/__tests__/list-messages-client-message-id.test.ts +4 -16
  316. package/src/__tests__/list-messages-hidden-metadata.test.ts +6 -18
  317. package/src/__tests__/list-messages-page-latest.test.ts +3 -19
  318. package/src/__tests__/list-messages-queued.test.ts +1 -18
  319. package/src/__tests__/list-messages-tool-merge.test.ts +7 -18
  320. package/src/__tests__/llm-context-resolution.test.ts +32 -56
  321. package/src/__tests__/llm-context-route-provider.test.ts +1 -8
  322. package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +1 -19
  323. package/src/__tests__/llm-request-log-call-site.test.ts +1 -19
  324. package/src/__tests__/llm-request-log-clickhouse-routing.test.ts +114 -0
  325. package/src/__tests__/llm-request-log-clickhouse-writer-guards.test.ts +108 -0
  326. package/src/__tests__/llm-request-log-disabled-writes.test.ts +11 -30
  327. package/src/__tests__/llm-request-log-sink-clickhouse.test.ts +205 -0
  328. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +1 -22
  329. package/src/__tests__/llm-request-log-source-factory.test.ts +23 -69
  330. package/src/__tests__/llm-request-log-turn-query.test.ts +1 -19
  331. package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
  332. package/src/__tests__/llm-resolver.test.ts +342 -602
  333. package/src/__tests__/llm-schema.test.ts +79 -37
  334. package/src/__tests__/llm-usage-store.test.ts +1 -7
  335. package/src/__tests__/log-export-routes.test.ts +0 -7
  336. package/src/__tests__/log-export-workspace.test.ts +0 -7
  337. package/src/__tests__/managed-profile-guard.test.ts +125 -137
  338. package/src/__tests__/managed-skill-lifecycle.test.ts +6 -50
  339. package/src/__tests__/managed-speech-defaults.test.ts +138 -0
  340. package/src/__tests__/managed-store.test.ts +1 -16
  341. package/src/__tests__/mcp-auth-routes.test.ts +15 -26
  342. package/src/__tests__/mcp-config-secret-boundary.test.ts +49 -91
  343. package/src/__tests__/mcp-health-check.test.ts +14 -20
  344. package/src/__tests__/media-generate-image.test.ts +25 -32
  345. package/src/__tests__/media-stream-output.test.ts +0 -9
  346. package/src/__tests__/media-stream-server-integration.test.ts +19 -27
  347. package/src/__tests__/media-stream-stt-session.test.ts +16 -29
  348. package/src/__tests__/memory-jobs-worker-backoff.test.ts +6 -19
  349. package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -12
  350. package/src/__tests__/memory-jobs-worker-lanes.test.ts +10 -29
  351. package/src/__tests__/memory-recall-log-store.test.ts +1 -19
  352. package/src/__tests__/memory-retrieval-hook.test.ts +0 -3
  353. package/src/__tests__/memory-upsert-concurrency.test.ts +12 -35
  354. package/src/__tests__/memory-v2-static-injector.test.ts +5 -17
  355. package/src/__tests__/messages-after-tiebreaker.test.ts +1 -7
  356. package/src/__tests__/messaging-send-tool.test.ts +67 -7
  357. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -18
  358. package/src/__tests__/migration-export-http.test.ts +10 -23
  359. package/src/__tests__/migration-export-streaming.test.ts +0 -18
  360. package/src/__tests__/migration-export-to-gcs.test.ts +0 -19
  361. package/src/__tests__/migration-import-commit-http.test.ts +11 -23
  362. package/src/__tests__/migration-import-from-gcs.test.ts +0 -19
  363. package/src/__tests__/migration-import-from-url.test.ts +0 -19
  364. package/src/__tests__/migration-import-preflight-http.test.ts +10 -22
  365. package/src/__tests__/migration-jobs-status.test.ts +8 -23
  366. package/src/__tests__/migration-validate-http.test.ts +2 -19
  367. package/src/__tests__/mtime-cache.test.ts +116 -2
  368. package/src/__tests__/native-web-search.test.ts +0 -21
  369. package/src/__tests__/non-member-access-request.test.ts +102 -93
  370. package/src/__tests__/notification-broadcaster.test.ts +32 -21
  371. package/src/__tests__/notification-candidate-guardian-context.test.ts +36 -34
  372. package/src/__tests__/notification-decision-fallback.test.ts +0 -7
  373. package/src/__tests__/notification-decision-identity.test.ts +0 -7
  374. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -7
  375. package/src/__tests__/notification-deep-link.test.ts +0 -7
  376. package/src/__tests__/notification-guardian-path.test.ts +48 -93
  377. package/src/__tests__/notification-platform-adapter.test.ts +0 -7
  378. package/src/__tests__/notification-routing-intent.test.ts +1 -9
  379. package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -9
  380. package/src/__tests__/notification-telegram-adapter.test.ts +0 -7
  381. package/src/__tests__/oauth-cli.test.ts +0 -19
  382. package/src/__tests__/oauth-commands-routes.test.ts +28 -43
  383. package/src/__tests__/oauth-connect-orchestrator.test.ts +17 -26
  384. package/src/__tests__/oauth-connect-routes.test.ts +19 -18
  385. package/src/__tests__/oauth-provider-profiles.test.ts +3 -9
  386. package/src/__tests__/oauth-provider-visibility.test.ts +0 -7
  387. package/src/__tests__/oauth-store.test.ts +0 -7
  388. package/src/__tests__/oauth2-gateway-transport.test.ts +41 -43
  389. package/src/__tests__/openai-responses-prompt-cache.test.ts +355 -0
  390. package/src/__tests__/openai-responses-provider.test.ts +98 -9
  391. package/src/__tests__/openrouter-responses-transport.test.ts +170 -0
  392. package/src/__tests__/outbound-slack-persistence.test.ts +13 -46
  393. package/src/__tests__/outlook-email-watcher.test.ts +0 -9
  394. package/src/__tests__/outlook-messaging-provider.test.ts +71 -0
  395. package/src/__tests__/path-policy.test.ts +0 -7
  396. package/src/__tests__/persist-media-references.test.ts +1 -6
  397. package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -3
  398. package/src/__tests__/persist-unsendable-image.test.ts +39 -7
  399. package/src/__tests__/persistence-secret-redaction.test.ts +7 -28
  400. package/src/__tests__/platform-bash-auto-approve.test.ts +0 -46
  401. package/src/__tests__/platform-callback-registration.test.ts +10 -9
  402. package/src/__tests__/platform-proxy-context.test.ts +0 -8
  403. package/src/__tests__/playbook-execution.test.ts +0 -14
  404. package/src/__tests__/playbook-tools.test.ts +0 -14
  405. package/src/__tests__/plugin-api-model-profiles.test.ts +12 -35
  406. package/src/__tests__/plugin-app-serve-routes.test.ts +315 -0
  407. package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -3
  408. package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -2
  409. package/src/__tests__/plugin-types.test.ts +0 -7
  410. package/src/__tests__/prechat-onboarding-contract.test.ts +0 -27
  411. package/src/__tests__/pricing.test.ts +45 -0
  412. package/src/__tests__/process-message-background-slack.test.ts +7 -21
  413. package/src/__tests__/process-message-display-content.test.ts +37 -6
  414. package/src/__tests__/processing-flag-persist-failure.test.ts +0 -44
  415. package/src/__tests__/provider-commit-message-generator.test.ts +57 -63
  416. package/src/__tests__/provider-error-scenarios.test.ts +5 -6
  417. package/src/__tests__/provider-platform-proxy-integration.test.ts +21 -57
  418. package/src/__tests__/provider-registry-ollama.test.ts +8 -18
  419. package/src/__tests__/provider-send-message-override-profile.test.ts +28 -39
  420. package/src/__tests__/provider-streaming.benchmark.test.ts +1 -6
  421. package/src/__tests__/provider-usage-tracking.test.ts +13 -35
  422. package/src/__tests__/proxy-approval-callback.test.ts +0 -16
  423. package/src/__tests__/prune-old-conversations-job.test.ts +29 -21
  424. package/src/__tests__/prune-old-tool-invocations-job.test.ts +1 -9
  425. package/src/__tests__/public-ingress-urls.test.ts +1 -24
  426. package/src/__tests__/published-app-updater.test.ts +22 -16
  427. package/src/__tests__/qdrant-collection-migration.test.ts +0 -7
  428. package/src/__tests__/qdrant-manager.test.ts +0 -8
  429. package/src/__tests__/ratelimit.test.ts +1 -8
  430. package/src/__tests__/reaction-persistence.test.ts +18 -24
  431. package/src/__tests__/rebuild-index-graph-nodes.test.ts +0 -14
  432. package/src/__tests__/recording-handler.test.ts +0 -27
  433. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +4 -16
  434. package/src/__tests__/require-fresh-approval.test.ts +0 -45
  435. package/src/__tests__/retry-openrouter-only-normalization.test.ts +24 -36
  436. package/src/__tests__/retry-prompt-cache-key.test.ts +123 -0
  437. package/src/__tests__/retry-thinking-adaptive-only.test.ts +45 -61
  438. package/src/__tests__/retry-thinking-tool-choice.test.ts +60 -80
  439. package/src/__tests__/retry-verbosity-normalization.test.ts +27 -37
  440. package/src/__tests__/reveal-success-registry.test.ts +123 -0
  441. package/src/__tests__/run-conversation-turn-persistence.test.ts +113 -0
  442. package/src/__tests__/{scheduler-worker-standdown.test.ts → run-due-schedules.test.ts} +5 -77
  443. package/src/__tests__/runtime-attachment-metadata.test.ts +5 -18
  444. package/src/__tests__/runtime-events-sse-bilingual.test.ts +1 -19
  445. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -20
  446. package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -19
  447. package/src/__tests__/runtime-events-sse.test.ts +1 -20
  448. package/src/__tests__/scaffold-managed-skill-tool.test.ts +306 -5
  449. package/src/__tests__/schedule-retry.test.ts +22 -23
  450. package/src/__tests__/schedule-routes-workflow-validation.test.ts +18 -42
  451. package/src/__tests__/schedule-routes.test.ts +2 -150
  452. package/src/__tests__/schedule-store.test.ts +0 -8
  453. package/src/__tests__/schedule-tools.test.ts +1 -16
  454. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -26
  455. package/src/__tests__/scheduler-recurrence.test.ts +43 -76
  456. package/src/__tests__/scheduler-reuse-conversation.test.ts +19 -35
  457. package/src/__tests__/scheduler-wake.test.ts +8 -24
  458. package/src/__tests__/scoped-approval-grants.test.ts +1 -9
  459. package/src/__tests__/scoped-grant-security-matrix.test.ts +1 -9
  460. package/src/__tests__/search-skills-unified.test.ts +0 -6
  461. package/src/__tests__/secret-allowlist.test.ts +1 -8
  462. package/src/__tests__/secret-fixtures.ts +9 -0
  463. package/src/__tests__/secret-ingress-channel.test.ts +4 -32
  464. package/src/__tests__/secret-ingress-cli.test.ts +3 -37
  465. package/src/__tests__/secret-ingress-http.test.ts +15 -78
  466. package/src/__tests__/secret-ingress.test.ts +14 -31
  467. package/src/__tests__/secret-prompt-log-hygiene.test.ts +4 -10
  468. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -9
  469. package/src/__tests__/secret-routes-platform-proxy.test.ts +3 -40
  470. package/src/__tests__/secure-keys-managed-failover.test.ts +0 -7
  471. package/src/__tests__/secure-keys.test.ts +0 -9
  472. package/src/__tests__/send-endpoint-busy.test.ts +47 -91
  473. package/src/__tests__/sequence-store.test.ts +0 -9
  474. package/src/__tests__/server-history-render.test.ts +29 -8
  475. package/src/__tests__/set-permission-mode.test.ts +8 -16
  476. package/src/__tests__/settings-routes.test.ts +0 -7
  477. package/src/__tests__/shell-credential-ref.test.ts +0 -18
  478. package/src/__tests__/shell-observability.test.ts +0 -21
  479. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -34
  480. package/src/__tests__/skill-load-feature-flag.test.ts +0 -27
  481. package/src/__tests__/skill-load-inline-command.test.ts +0 -25
  482. package/src/__tests__/skill-load-inline-includes.test.ts +0 -25
  483. package/src/__tests__/skill-load-plugin-scope.test.ts +0 -24
  484. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -33
  485. package/src/__tests__/skill-projection.benchmark.test.ts +14 -19
  486. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -39
  487. package/src/__tests__/skills-file-content-endpoint.test.ts +0 -7
  488. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -14
  489. package/src/__tests__/slack-channel-config.test.ts +24 -79
  490. package/src/__tests__/slack-inbound-verification.test.ts +5 -13
  491. package/src/__tests__/{slack-reaction-canonical-approval.test.ts → slack-reaction-guardian-approval.test.ts} +18 -74
  492. package/src/__tests__/slack-share-routes.test.ts +0 -1
  493. package/src/__tests__/slim-skill-category.test.ts +0 -14
  494. package/src/__tests__/stale-approval-dedup.test.ts +0 -7
  495. package/src/__tests__/subagent-call-site-routing.test.ts +72 -111
  496. package/src/__tests__/subagent-detail.test.ts +1 -1
  497. package/src/__tests__/subagent-fork-prompt-role.test.ts +0 -12
  498. package/src/__tests__/subagent-notify-parent.test.ts +4 -6
  499. package/src/__tests__/subagent-spawn-and-await.test.ts +0 -18
  500. package/src/__tests__/subagent-tool-filtering.test.ts +21 -31
  501. package/src/__tests__/subagent-tool-gate-mode.test.ts +6 -32
  502. package/src/__tests__/subagent-tools.test.ts +92 -67
  503. package/src/__tests__/suggestion-routes.test.ts +28 -42
  504. package/src/__tests__/summarize-boundary.test.ts +2 -1
  505. package/src/__tests__/system-prompt-ask-mode.test.ts +0 -25
  506. package/src/__tests__/system-prompt.test.ts +0 -33
  507. package/src/__tests__/task-memory-cleanup.test.ts +18 -192
  508. package/src/__tests__/telegram-bot-username-resolution.test.ts +24 -48
  509. package/src/__tests__/telegram-config.test.ts +0 -8
  510. package/src/__tests__/telemetry-routes.test.ts +100 -0
  511. package/src/__tests__/telephony-credential-preflight.test.ts +7 -11
  512. package/src/__tests__/telephony-tts-guard.test.ts +38 -21
  513. package/src/__tests__/terminal-tools.test.ts +0 -21
  514. package/src/__tests__/thread-backfill.test.ts +0 -7
  515. package/src/__tests__/title-generate-hook.test.ts +11 -10
  516. package/src/__tests__/token-manager.test.ts +0 -9
  517. package/src/__tests__/tool-approval-handler.test.ts +0 -8
  518. package/src/__tests__/tool-execution-abort-cleanup.test.ts +5 -33
  519. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +3 -23
  520. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -48
  521. package/src/__tests__/tool-executor.test.ts +3 -49
  522. package/src/__tests__/tool-grant-request-escalation.test.ts +51 -153
  523. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -29
  524. package/src/__tests__/tool-profiler.test.ts +72 -1
  525. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -29
  526. package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
  527. package/src/__tests__/tool-start-timestamp.test.ts +4 -31
  528. package/src/__tests__/tools-get-route.test.ts +2 -1
  529. package/src/__tests__/trust-context-guards.test.ts +19 -7
  530. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +75 -79
  531. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +14 -18
  532. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -7
  533. package/src/__tests__/trusted-contact-verification.test.ts +1 -9
  534. package/src/__tests__/turn-boundary-resolution.test.ts +1 -19
  535. package/src/__tests__/turn-events-store.test.ts +1 -7
  536. package/src/__tests__/turn-outcome-read.test.ts +1 -7
  537. package/src/__tests__/twilio-config.test.ts +11 -28
  538. package/src/__tests__/twilio-provider.test.ts +2 -13
  539. package/src/__tests__/twilio-routes-twiml.test.ts +1 -8
  540. package/src/__tests__/twilio-routes.test.ts +52 -103
  541. package/src/__tests__/twilio-validation.test.ts +5 -22
  542. package/src/__tests__/ui-file-upload-surface.test.ts +6 -9
  543. package/src/__tests__/usage-attribution.test.ts +25 -56
  544. package/src/__tests__/usage-cache-backfill-migration.test.ts +8 -15
  545. package/src/__tests__/usage-routes.test.ts +1 -8
  546. package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -18
  547. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -24
  548. package/src/__tests__/vercel-config.test.ts +0 -7
  549. package/src/__tests__/verification-control-plane-policy.test.ts +0 -45
  550. package/src/__tests__/voice-approval-resolver-relay.test.ts +106 -75
  551. package/src/__tests__/voice-config-update.test.ts +114 -21
  552. package/src/__tests__/voice-ingress-preflight.test.ts +16 -15
  553. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -30
  554. package/src/__tests__/voice-session-bridge-processing-wait.test.ts +1 -17
  555. package/src/__tests__/voice-session-bridge.test.ts +14 -46
  556. package/src/__tests__/web-search-backend-failure.test.ts +0 -21
  557. package/src/__tests__/whatsapp-invite-adapter.test.ts +11 -30
  558. package/src/__tests__/workspace-git-service.test.ts +801 -2
  559. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -26
  560. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -26
  561. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +1 -26
  562. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -9
  563. package/src/a2a/__tests__/task-store.test.ts +0 -9
  564. package/src/acp/__tests__/session-manager-persistence.test.ts +1 -8
  565. package/src/acp/__tests__/session-manager-resume.test.ts +0 -7
  566. package/src/acp/__tests__/session-manager-startup.test.ts +1 -8
  567. package/src/agent/image-optimize.ts +80 -0
  568. package/src/agent/loop.ts +20 -5
  569. package/src/api/events/open-conversation.test.ts +64 -0
  570. package/src/api/events/open-conversation.ts +33 -0
  571. package/src/api/index.ts +6 -0
  572. package/src/approvals/AGENTS.md +1 -1
  573. package/src/approvals/guardian-card-withdrawal.ts +26 -19
  574. package/src/approvals/guardian-decision-primitive.ts +172 -102
  575. package/src/approvals/guardian-expiry-notifier.ts +20 -19
  576. package/src/approvals/guardian-request-resolvers.ts +305 -275
  577. package/src/apps/app-store.ts +320 -15
  578. package/src/background-wake/background-wake-routes.test.ts +2 -3
  579. package/src/background-wake/next-wake.test.ts +23 -20
  580. package/src/background-wake/wake-intent-hooks.test.ts +0 -10
  581. package/src/bundler/app-bundler.ts +34 -48
  582. package/src/bundler/app-compiler.ts +39 -4
  583. package/src/bundler/bundle-scanner.ts +13 -0
  584. package/src/bundler/manifest.ts +1 -1
  585. package/src/calls/__tests__/call-setup-router.test.ts +84 -88
  586. package/src/calls/__tests__/fish-audio-client.test.ts +6 -11
  587. package/src/calls/__tests__/voice-control-protocol.test.ts +47 -0
  588. package/src/calls/__tests__/voice-session-bridge.test.ts +151 -16
  589. package/src/calls/__tests__/voice-triage-escalate.test.ts +128 -0
  590. package/src/calls/access-request-wait.ts +35 -35
  591. package/src/calls/call-controller.ts +48 -45
  592. package/src/calls/call-setup-flow.ts +2 -2
  593. package/src/calls/call-setup-router.ts +1 -24
  594. package/src/calls/guardian-dispatch.ts +47 -30
  595. package/src/calls/guardian-wait-controller.ts +31 -18
  596. package/src/calls/media-turn-detector.ts +11 -1
  597. package/src/calls/telephony-credential-preflight.ts +19 -1
  598. package/src/calls/telephony-tts-capability.ts +18 -1
  599. package/src/calls/voice-control-protocol.ts +12 -0
  600. package/src/calls/voice-session-bridge.ts +110 -15
  601. package/src/calls/voice-triage-escalate.ts +136 -0
  602. package/src/channels/__tests__/gateway-guardian-requests.test.ts +669 -0
  603. package/src/channels/gateway-guardian-requests.ts +410 -0
  604. package/src/channels/types.ts +10 -5
  605. package/src/cli/AGENTS.md +77 -51
  606. package/src/cli/__tests__/cli-command-help-coverage.test.ts +29 -0
  607. package/src/cli/commands/__tests__/conversations-import.test.ts +23 -24
  608. package/src/cli/commands/__tests__/gateway.test.ts +55 -0
  609. package/src/cli/commands/__tests__/inference-models.test.ts +3 -0
  610. package/src/cli/commands/__tests__/inference-profiles.test.ts +3 -0
  611. package/src/cli/commands/__tests__/inference-providers.test.ts +3 -0
  612. package/src/cli/commands/__tests__/inference-send.test.ts +0 -10
  613. package/src/cli/commands/__tests__/inference-session.test.ts +4 -11
  614. package/src/cli/commands/__tests__/ui.test.ts +2 -2
  615. package/src/cli/commands/apps.help.ts +46 -0
  616. package/src/cli/commands/apps.ts +51 -0
  617. package/src/cli/commands/avatar.help.ts +229 -0
  618. package/src/cli/commands/avatar.ts +58 -250
  619. package/src/cli/commands/backup.help.ts +183 -0
  620. package/src/cli/commands/backup.ts +107 -276
  621. package/src/cli/commands/bash.help.ts +38 -0
  622. package/src/cli/commands/bash.ts +51 -75
  623. package/src/cli/commands/browser.help.ts +193 -0
  624. package/src/cli/commands/browser.ts +234 -347
  625. package/src/cli/commands/cache.help.ts +123 -0
  626. package/src/cli/commands/cache.ts +72 -166
  627. package/src/cli/commands/changelog.help.ts +59 -0
  628. package/src/cli/commands/changelog.ts +29 -61
  629. package/src/cli/commands/channel-verification-sessions.help.ts +178 -0
  630. package/src/cli/commands/channel-verification-sessions.ts +71 -226
  631. package/src/cli/commands/channels/index.help.ts +67 -0
  632. package/src/cli/commands/channels/index.ts +55 -105
  633. package/src/cli/commands/clients.help.ts +72 -0
  634. package/src/cli/commands/clients.ts +100 -153
  635. package/src/cli/commands/completions.help.ts +33 -0
  636. package/src/cli/commands/completions.ts +43 -66
  637. package/src/cli/commands/config.help.ts +126 -0
  638. package/src/cli/commands/config.ts +59 -174
  639. package/src/cli/commands/contacts.help.ts +327 -0
  640. package/src/cli/commands/contacts.ts +318 -603
  641. package/src/cli/commands/conversations-defer.ts +141 -202
  642. package/src/cli/commands/conversations-import.ts +80 -113
  643. package/src/cli/commands/conversations.help.ts +364 -0
  644. package/src/cli/commands/conversations.ts +143 -328
  645. package/src/cli/commands/credentials.help.ts +290 -0
  646. package/src/cli/commands/credentials.ts +271 -487
  647. package/src/cli/commands/db/index.help.ts +27 -0
  648. package/src/cli/commands/db/index.ts +7 -3
  649. package/src/cli/commands/db/refresh.ts +131 -0
  650. package/src/cli/commands/db/repair-step-conversation-backfill.ts +19 -9
  651. package/src/cli/commands/db/repair.ts +41 -43
  652. package/src/cli/commands/db/status.ts +79 -83
  653. package/src/cli/commands/domain.help.ts +34 -0
  654. package/src/cli/commands/domain.ts +10 -15
  655. package/src/cli/commands/email.help.ts +176 -0
  656. package/src/cli/commands/email.ts +323 -412
  657. package/src/cli/commands/gateway.help.ts +115 -0
  658. package/src/cli/commands/gateway.ts +105 -123
  659. package/src/cli/commands/image-generation.help.ts +72 -0
  660. package/src/cli/commands/image-generation.ts +13 -62
  661. package/src/cli/commands/inference-callsites.ts +34 -49
  662. package/src/cli/commands/inference-models.ts +6 -21
  663. package/src/cli/commands/inference-profiles.ts +95 -156
  664. package/src/cli/commands/inference-providers-default.ts +27 -42
  665. package/src/cli/commands/inference-providers.ts +25 -87
  666. package/src/cli/commands/inference-session.ts +189 -249
  667. package/src/cli/commands/inference.help.ts +485 -0
  668. package/src/cli/commands/inference.ts +104 -165
  669. package/src/cli/commands/keys.help.ts +46 -0
  670. package/src/cli/commands/keys.ts +37 -71
  671. package/src/cli/commands/mcp.help.ts +167 -0
  672. package/src/cli/commands/mcp.ts +123 -267
  673. package/src/cli/commands/memory/__tests__/memory-items.test.ts +4 -0
  674. package/src/cli/commands/memory/__tests__/memory-v2.test.ts +4 -0
  675. package/src/cli/commands/memory/__tests__/memory-v3.test.ts +4 -0
  676. package/src/cli/commands/memory/__tests__/worker.test.ts +12 -5
  677. package/src/cli/commands/memory/index.help.ts +814 -0
  678. package/src/cli/commands/memory/index.ts +5 -27
  679. package/src/cli/commands/memory/items.ts +257 -404
  680. package/src/cli/commands/memory/memory-retrospective.ts +31 -71
  681. package/src/cli/commands/memory/memory-v2-compare-render.ts +2 -2
  682. package/src/cli/commands/memory/memory-v2.ts +435 -646
  683. package/src/cli/commands/memory/memory-v3.ts +158 -283
  684. package/src/cli/commands/memory/nodes.ts +154 -249
  685. package/src/cli/commands/memory/worker.ts +83 -128
  686. package/src/cli/commands/monitoring.help.ts +57 -0
  687. package/src/cli/commands/monitoring.ts +17 -41
  688. package/src/cli/commands/notifications.help.ts +293 -0
  689. package/src/cli/commands/notifications.ts +420 -657
  690. package/src/cli/commands/oauth/apps.ts +182 -315
  691. package/src/cli/commands/oauth/connect.ts +4 -35
  692. package/src/cli/commands/oauth/disconnect.ts +44 -71
  693. package/src/cli/commands/oauth/index.help.ts +855 -0
  694. package/src/cli/commands/oauth/index.ts +5 -31
  695. package/src/cli/commands/oauth/mode.ts +5 -28
  696. package/src/cli/commands/oauth/ping.ts +44 -66
  697. package/src/cli/commands/oauth/providers.ts +413 -772
  698. package/src/cli/commands/oauth/request.ts +6 -35
  699. package/src/cli/commands/oauth/shared.ts +1 -1
  700. package/src/cli/commands/oauth/status.test.ts +6 -6
  701. package/src/cli/commands/oauth/status.ts +45 -62
  702. package/src/cli/commands/oauth/token.ts +32 -71
  703. package/src/cli/commands/pending.help.ts +26 -0
  704. package/src/cli/commands/pending.ts +77 -78
  705. package/src/cli/commands/platform/__tests__/connect.test.ts +3 -1
  706. package/src/cli/commands/platform/__tests__/disconnect.test.ts +4 -4
  707. package/src/cli/commands/platform/__tests__/status.test.ts +0 -90
  708. package/src/cli/commands/platform/connect.ts +10 -21
  709. package/src/cli/commands/platform/disconnect.ts +11 -26
  710. package/src/cli/commands/platform/index.help.ts +187 -0
  711. package/src/cli/commands/platform/index.ts +22 -169
  712. package/src/cli/commands/plugins.help.ts +247 -0
  713. package/src/cli/commands/plugins.ts +356 -437
  714. package/src/cli/commands/ps.help.ts +26 -0
  715. package/src/cli/commands/ps.ts +5 -17
  716. package/src/cli/commands/routes.help.ts +72 -0
  717. package/src/cli/commands/routes.ts +78 -125
  718. package/src/cli/commands/schedules-worker.ts +70 -138
  719. package/src/cli/commands/schedules.help.ts +514 -0
  720. package/src/cli/commands/schedules.ts +494 -871
  721. package/src/cli/commands/sequence.help.ts +183 -0
  722. package/src/cli/commands/sequence.ts +181 -343
  723. package/src/cli/commands/skills.help.ts +159 -0
  724. package/src/cli/commands/skills.ts +230 -368
  725. package/src/cli/commands/status.help.ts +32 -0
  726. package/src/cli/commands/status.ts +38 -3
  727. package/src/cli/commands/stt.help.ts +52 -0
  728. package/src/cli/commands/stt.ts +9 -47
  729. package/src/cli/commands/telemetry.help.ts +14 -0
  730. package/src/cli/commands/telemetry.ts +19 -17
  731. package/src/cli/commands/tools-run.ts +30 -45
  732. package/src/cli/commands/tools.help.ts +81 -0
  733. package/src/cli/commands/tools.ts +43 -83
  734. package/src/cli/commands/trust.help.ts +43 -0
  735. package/src/cli/commands/trust.ts +82 -109
  736. package/src/cli/commands/tts.help.ts +88 -0
  737. package/src/cli/commands/tts.ts +116 -188
  738. package/src/cli/commands/ui.help.ts +213 -0
  739. package/src/cli/commands/ui.ts +363 -380
  740. package/src/cli/commands/usage.help.ts +147 -0
  741. package/src/cli/commands/usage.ts +87 -206
  742. package/src/cli/commands/watchers.help.ts +211 -0
  743. package/src/cli/commands/watchers.ts +261 -417
  744. package/src/cli/commands/webhooks.help.ts +95 -0
  745. package/src/cli/commands/webhooks.ts +44 -115
  746. package/src/cli/index.help.ts +91 -0
  747. package/src/cli/lib/__tests__/global-json-option.test.ts +97 -0
  748. package/src/cli/lib/__tests__/install-from-github.test.ts +144 -4
  749. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +96 -132
  750. package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +65 -0
  751. package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +167 -0
  752. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +197 -0
  753. package/src/cli/lib/__tests__/plugin-details.test.ts +349 -240
  754. package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +31 -0
  755. package/src/cli/lib/__tests__/plugin-icon-file.test.ts +50 -1
  756. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +94 -0
  757. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +147 -0
  758. package/src/cli/lib/__tests__/search-plugins.test.ts +193 -309
  759. package/src/cli/lib/bundled-marketplace.json +439 -0
  760. package/src/cli/lib/cli-command-help.ts +83 -10
  761. package/src/cli/lib/global-json-option.ts +41 -0
  762. package/src/cli/lib/install-from-github.ts +69 -2
  763. package/src/cli/lib/plugin-catalog-cache.ts +22 -50
  764. package/src/cli/lib/plugin-catalog-local.ts +71 -0
  765. package/src/cli/lib/plugin-catalog-platform.ts +117 -0
  766. package/src/cli/lib/plugin-catalog-resolve.ts +72 -0
  767. package/src/cli/lib/plugin-details.ts +100 -34
  768. package/src/cli/lib/plugin-fingerprint.ts +18 -7
  769. package/src/cli/lib/plugin-icon-file.ts +38 -26
  770. package/src/cli/lib/plugin-marketplace.ts +15 -2
  771. package/src/cli/lib/publish-plugin.ts +3 -3
  772. package/src/cli/lib/search-plugins.ts +48 -111
  773. package/src/cli/program.ts +7 -0
  774. package/src/cli.ts +22 -13
  775. package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
  776. package/src/config/__tests__/default-provider.test.ts +0 -21
  777. package/src/config/__tests__/deployment-context-defaults.test.ts +0 -21
  778. package/src/config/__tests__/feature-flag-registry-bundled.test.ts +2 -2
  779. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -21
  780. package/src/config/__tests__/loader-last-known-good.test.ts +0 -21
  781. package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +0 -21
  782. package/src/config/__tests__/platform-rehydration.test.ts +125 -0
  783. package/src/config/__tests__/profile-materialization.test.ts +1 -88
  784. package/src/config/__tests__/seed-default-provider.test.ts +0 -21
  785. package/src/config/__tests__/sync-gated-profiles.test.ts +0 -21
  786. package/src/config/bundled-skills/app-builder/SKILL.md +24 -1
  787. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +30 -0
  788. package/src/config/bundled-skills/contacts/SKILL.md +1 -1
  789. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +4 -2
  790. package/src/config/bundled-skills/messaging/TOOLS.json +2 -2
  791. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +28 -20
  792. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
  793. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
  794. package/src/config/bundled-skills/schedule/SKILL.md +0 -1
  795. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  796. package/src/config/bundled-skills/settings/TOOLS.json +5 -3
  797. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +84 -10
  798. package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +0 -7
  799. package/src/config/call-site-defaults.ts +3 -3
  800. package/src/config/feature-flag-registry.json +15 -63
  801. package/src/config/llm-resolver.ts +88 -475
  802. package/src/config/managed-speech-defaults.ts +115 -0
  803. package/src/config/platform-rehydration.ts +76 -0
  804. package/src/config/profile-materialization.ts +11 -11
  805. package/src/config/schema.ts +93 -129
  806. package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
  807. package/src/config/schemas/__tests__/stt.test.ts +37 -0
  808. package/src/config/schemas/live-voice.ts +10 -4
  809. package/src/config/schemas/llm.ts +51 -15
  810. package/src/config/schemas/memory-lifecycle.ts +1 -13
  811. package/src/config/schemas/memory-retrospective.ts +8 -0
  812. package/src/config/schemas/memory.ts +0 -4
  813. package/src/config/schemas/stt.ts +33 -6
  814. package/src/config/schemas/tts.ts +53 -6
  815. package/src/config/schemas/workspace-git.ts +8 -0
  816. package/src/contacts/contact-store.ts +3 -58
  817. package/src/contacts/types.ts +1 -1
  818. package/src/conversations/__tests__/message-consolidation.test.ts +6 -5
  819. package/src/conversations/message-consolidation.ts +34 -112
  820. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +64 -7
  821. package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +3 -7
  822. package/src/daemon/__tests__/conversation-tool-setup.test.ts +8 -6
  823. package/src/daemon/__tests__/embedding-reconcile.test.ts +0 -11
  824. package/src/daemon/__tests__/inference-profile-notification.test.ts +5 -11
  825. package/src/daemon/__tests__/inflight-message-content.test.ts +219 -0
  826. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -27
  827. package/src/daemon/__tests__/route-conversation-post.test.ts +158 -0
  828. package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +0 -6
  829. package/src/daemon/__tests__/web-search-status-text.test.ts +0 -29
  830. package/src/daemon/app-source-watcher.ts +17 -23
  831. package/src/daemon/chat-credential-redaction.ts +1365 -0
  832. package/src/daemon/conversation-agent-loop-handlers.ts +742 -77
  833. package/src/daemon/conversation-agent-loop.ts +10 -17
  834. package/src/daemon/conversation-error.ts +53 -16
  835. package/src/daemon/conversation-history.ts +6 -12
  836. package/src/daemon/conversation-messaging.ts +13 -1
  837. package/src/daemon/conversation-process.ts +16 -11
  838. package/src/daemon/conversation-runtime-assembly.ts +148 -52
  839. package/src/daemon/conversation-surfaces.ts +217 -100
  840. package/src/daemon/conversation-tool-setup.ts +59 -112
  841. package/src/daemon/conversation-turn-finalize.ts +18 -0
  842. package/src/daemon/conversation.ts +35 -66
  843. package/src/daemon/event-loop-watchdog.test.ts +1 -6
  844. package/src/daemon/external-plugins-bootstrap.ts +20 -74
  845. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -7
  846. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -8
  847. package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -8
  848. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -8
  849. package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -8
  850. package/src/daemon/handlers/conversation-history.ts +6 -4
  851. package/src/daemon/handlers/conversations.ts +19 -9
  852. package/src/daemon/handlers/shared.ts +24 -1
  853. package/src/daemon/inflight-message-content.ts +228 -0
  854. package/src/daemon/lifecycle.ts +21 -31
  855. package/src/daemon/message-protocol.ts +2 -7
  856. package/src/daemon/message-provenance.ts +17 -8
  857. package/src/daemon/message-types/conversations.ts +6 -17
  858. package/src/daemon/message-types/host-ui-snapshot.ts +44 -0
  859. package/src/daemon/message-types/inbox.ts +3 -46
  860. package/src/daemon/orphan-reaper.test.ts +1 -6
  861. package/src/daemon/process-message.ts +9 -0
  862. package/src/daemon/providers-setup.ts +5 -75
  863. package/src/daemon/route-conversation-post.ts +158 -0
  864. package/src/daemon/shutdown-handlers.ts +11 -17
  865. package/src/daemon/sqlite-corruption-watchdog.test.ts +0 -6
  866. package/src/documents/document-comments-store.test.ts +1 -7
  867. package/src/export/__tests__/transcript-formatter.test.ts +8 -8
  868. package/src/export/formatter.ts +8 -17
  869. package/src/export/transcript-formatter.ts +4 -1
  870. package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +0 -9
  871. package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -57
  872. package/src/home/__tests__/home-content-refresh.test.ts +0 -7
  873. package/src/home/__tests__/suggested-prompts.test.ts +0 -11
  874. package/src/ipc/__tests__/contacts-info-ipc.test.ts +12 -10
  875. package/src/ipc/__tests__/email-ipc.test.ts +90 -0
  876. package/src/ipc/assistant-server.ts +10 -22
  877. package/src/ipc/routes/__tests__/guardian-label-ipc-routes.test.ts +74 -0
  878. package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +0 -7
  879. package/src/ipc/routes/guardian-label-ipc-routes.ts +42 -0
  880. package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -8
  881. package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +89 -49
  882. package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
  883. package/src/live-voice/__tests__/live-voice-resume-registry.test.ts +58 -0
  884. package/src/live-voice/__tests__/live-voice-resume-turn.test.ts +280 -0
  885. package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +337 -0
  886. package/src/live-voice/__tests__/live-voice-tts.test.ts +0 -4
  887. package/src/live-voice/__tests__/live-voice-vad.test.ts +432 -12
  888. package/src/live-voice/__tests__/protocol.test.ts +122 -0
  889. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -41
  890. package/src/live-voice/live-voice-credential-preflight.ts +27 -3
  891. package/src/live-voice/live-voice-resume-registry.ts +54 -0
  892. package/src/live-voice/live-voice-session.ts +602 -61
  893. package/src/live-voice/protocol.ts +143 -1
  894. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +3 -7
  895. package/src/messaging/provider-types.ts +9 -0
  896. package/src/messaging/providers/a2a/__tests__/deliver.test.ts +0 -9
  897. package/src/messaging/providers/outlook/adapter.ts +17 -2
  898. package/src/messaging/providers/outlook/client.ts +11 -2
  899. package/src/messaging/providers/outlook/types.ts +9 -0
  900. package/src/messaging/providers/slack/__tests__/download.test.ts +1 -8
  901. package/src/messaging/providers/slack/binding-metadata.test.ts +23 -21
  902. package/src/messaging/providers/slack/send.test.ts +0 -7
  903. package/src/messaging/providers/slack/withdraw.test.ts +0 -6
  904. package/src/messaging/providers/telegram-bot/send.test.ts +0 -7
  905. package/src/monitoring/__tests__/plugin-source-watch.test.ts +40 -1
  906. package/src/monitoring/plugin-source-watch.ts +56 -62
  907. package/src/monitoring/recovery/__tests__/inflight-content.test.ts +166 -0
  908. package/src/monitoring/recovery/inflight-content.ts +260 -0
  909. package/src/monitoring/recovery/run-recovery.ts +72 -0
  910. package/src/monitoring/worker.ts +68 -7
  911. package/src/notifications/AGENTS.md +1 -1
  912. package/src/notifications/README.md +4 -4
  913. package/src/notifications/__tests__/broadcaster.test.ts +4 -17
  914. package/src/notifications/__tests__/connected-channels.test.ts +11 -8
  915. package/src/notifications/__tests__/decision-engine.test.ts +0 -7
  916. package/src/notifications/__tests__/destination-resolver.test.ts +18 -12
  917. package/src/notifications/__tests__/deterministic-checks.test.ts +1 -9
  918. package/src/notifications/adapters/macos.ts +3 -5
  919. package/src/notifications/adapters/platform.ts +1 -1
  920. package/src/notifications/broadcaster.ts +13 -4
  921. package/src/notifications/conversation-candidates.ts +21 -28
  922. package/src/notifications/copy-composer.ts +0 -6
  923. package/src/notifications/decision-engine.ts +1 -1
  924. package/src/notifications/{canonical-delivery-recorder.ts → guardian-delivery-recorder.ts} +47 -33
  925. package/src/notifications/home-feed-side-effect.ts +0 -2
  926. package/src/notifications/signal.ts +0 -4
  927. package/src/oauth/byo-connection.test.ts +0 -9
  928. package/src/oauth/connection-resolver.test.ts +18 -46
  929. package/src/oauth/seed-providers.ts +6 -0
  930. package/src/onboarding/__tests__/onboarding-events-store.test.ts +122 -44
  931. package/src/onboarding/onboarding-events-store.ts +67 -115
  932. package/src/onboarding/onboarding-research-events-store.test.ts +222 -0
  933. package/src/onboarding/onboarding-research-events-store.ts +92 -0
  934. package/src/permissions/checker.test.ts +10 -24
  935. package/src/permissions/confirmation-guardian-request.test.ts +94 -0
  936. package/src/permissions/{confirmation-canonical-request.ts → confirmation-guardian-request.ts} +44 -29
  937. package/src/permissions/gateway-threshold-reader.test.ts +0 -8
  938. package/src/permissions/prompter.ts +6 -4
  939. package/src/permissions/question-prompter.test.ts +7 -14
  940. package/src/persistence/__tests__/bulk-write-gate.test.ts +1 -7
  941. package/src/persistence/__tests__/conversation-queries-search.test.ts +0 -7
  942. package/src/persistence/__tests__/main-db-readonly-probe.ts +80 -0
  943. package/src/persistence/__tests__/main-db-readonly.test.ts +35 -0
  944. package/src/persistence/__tests__/message-content-file.test.ts +161 -52
  945. package/src/persistence/__tests__/raw-query-telemetry.test.ts +74 -0
  946. package/src/persistence/conversation-crud.ts +175 -45
  947. package/src/persistence/conversation-disk-view.ts +32 -15
  948. package/src/persistence/conversation-group-migration.test.ts +1 -8
  949. package/src/persistence/conversation-title-service.ts +59 -22
  950. package/src/persistence/db-connection.ts +46 -1
  951. package/src/persistence/db-singleton.ts +7 -1
  952. package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +3 -7
  953. package/src/persistence/embeddings/messages-lexical-index.ts +11 -0
  954. package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +0 -7
  955. package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +0 -6
  956. package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +0 -7
  957. package/src/persistence/job-handlers/cleanup.ts +30 -16
  958. package/src/persistence/job-handlers/message-lexical-backfill.ts +8 -5
  959. package/src/persistence/job-handlers/message-lexical.ts +2 -2
  960. package/src/persistence/jobs-store.ts +123 -17
  961. package/src/persistence/lifecycle-events-store.test.ts +84 -0
  962. package/src/persistence/lifecycle-events-store.ts +27 -52
  963. package/src/persistence/llm-request-log-sink-clickhouse.ts +325 -0
  964. package/src/persistence/llm-request-log-store.ts +185 -106
  965. package/src/persistence/llm-request-log-writer-types.ts +80 -0
  966. package/src/persistence/llm-usage-store.ts +5 -2
  967. package/src/persistence/message-content-file.ts +182 -71
  968. package/src/persistence/message-content.ts +18 -10
  969. package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
  970. package/src/persistence/migrations/325-create-config-setting-events.ts +40 -0
  971. package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +104 -0
  972. package/src/persistence/migrations/327-create-flush-checkpoints.ts +86 -0
  973. package/src/persistence/migrations/328-drop-memory-v3-learned-edge-tables.ts +16 -0
  974. package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.test.ts +179 -0
  975. package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.ts +119 -0
  976. package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.test.ts +197 -0
  977. package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.ts +108 -0
  978. package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.test.ts +159 -0
  979. package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.ts +97 -0
  980. package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.test.ts +219 -0
  981. package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.ts +128 -0
  982. package/src/persistence/migrations/333-create-telemetry-events-table.test.ts +66 -0
  983. package/src/persistence/migrations/333-create-telemetry-events-table.ts +43 -0
  984. package/src/persistence/migrations/334-backfill-telemetry-events-outbox.test.ts +584 -0
  985. package/src/persistence/migrations/334-backfill-telemetry-events-outbox.ts +386 -0
  986. package/src/persistence/migrations/335-collapse-memory-embed-backlog.test.ts +181 -0
  987. package/src/persistence/migrations/335-collapse-memory-embed-backlog.ts +177 -0
  988. package/src/persistence/migrations/__tests__/327-create-flush-checkpoints.test.ts +124 -0
  989. package/src/persistence/raw-query.ts +27 -1
  990. package/src/persistence/schema/calls.ts +0 -23
  991. package/src/persistence/schema/conversation-starters.ts +31 -0
  992. package/src/persistence/schema/conversations.ts +3 -3
  993. package/src/persistence/schema/guardian.ts +0 -150
  994. package/src/persistence/schema/index.ts +1 -0
  995. package/src/persistence/schema/infrastructure.ts +25 -72
  996. package/src/persistence/schema/memory-core.ts +0 -25
  997. package/src/persistence/schema/memory-injection.ts +3 -1
  998. package/src/persistence/schema/tasks.ts +1 -60
  999. package/src/persistence/steps.ts +22 -0
  1000. package/src/platform/client.test.ts +110 -0
  1001. package/src/platform/client.ts +24 -4
  1002. package/src/platform/consent-cache.test.ts +5 -18
  1003. package/src/platform/consent-cache.ts +8 -6
  1004. package/src/platform/managed-speech.test.ts +218 -0
  1005. package/src/platform/managed-speech.ts +204 -0
  1006. package/src/plugin-api/conversation-turn.ts +250 -0
  1007. package/src/plugin-api/index.ts +21 -0
  1008. package/src/plugin-api/model-profiles.test.ts +29 -28
  1009. package/src/plugin-api/vision-support.test.ts +25 -38
  1010. package/src/plugin-api/vision-support.ts +26 -17
  1011. package/src/plugins/AGENTS.md +8 -0
  1012. package/src/plugins/__tests__/source-fingerprint.test.ts +41 -0
  1013. package/src/plugins/collect-source-versions.ts +77 -0
  1014. package/src/plugins/defaults/image-recovery/detect.ts +32 -10
  1015. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +20 -18
  1016. package/src/plugins/defaults/image-recovery/recover.ts +86 -59
  1017. package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +1 -8
  1018. package/src/plugins/defaults/memory/__tests__/clear-stale-processing-flags.test.ts +1 -8
  1019. package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +1 -8
  1020. package/src/plugins/defaults/memory/__tests__/conversation-row-batch-delete.test.ts +7 -18
  1021. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +22 -18
  1022. package/src/plugins/defaults/memory/__tests__/embedding-cache.test.ts +0 -6
  1023. package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -8
  1024. package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +7 -18
  1025. package/src/plugins/defaults/memory/__tests__/jobs-store-enqueue-gate.test.ts +29 -39
  1026. package/src/plugins/defaults/memory/__tests__/jobs-worker-memory-disabled.test.ts +11 -26
  1027. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +3 -22
  1028. package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +215 -1
  1029. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +0 -7
  1030. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +114 -16
  1031. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +180 -0
  1032. package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +153 -519
  1033. package/src/plugins/defaults/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +0 -7
  1034. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +6 -17
  1035. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -7
  1036. package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -19
  1037. package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +0 -18
  1038. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +8 -7
  1039. package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +49 -0
  1040. package/src/{persistence → plugins/defaults/memory}/__tests__/worker-control.test.ts +8 -10
  1041. package/src/plugins/defaults/memory/graph/capability-seed.ts +4 -6
  1042. package/src/plugins/defaults/memory/graph/extraction.ts +5 -1
  1043. package/src/plugins/defaults/memory/graph/graph-search.test.ts +2 -8
  1044. package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +0 -6
  1045. package/src/plugins/defaults/memory/graph/tool-handlers.ts +2 -2
  1046. package/src/plugins/defaults/memory/graph/tools.ts +47 -13
  1047. package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +81 -2
  1048. package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +67 -32
  1049. package/src/plugins/defaults/memory/hooks/shutdown.ts +8 -11
  1050. package/src/plugins/defaults/memory/indexer.ts +2 -1
  1051. package/src/plugins/defaults/memory/job-handlers/backfill.ts +8 -5
  1052. package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +0 -7
  1053. package/src/plugins/defaults/memory/job-handlers/embedding.ts +2 -2
  1054. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +7 -2
  1055. package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +73 -8
  1056. package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +5 -3
  1057. package/src/plugins/defaults/memory/jobs/embed-pkb-file.test.ts +0 -13
  1058. package/src/plugins/defaults/memory/jobs-worker.ts +139 -107
  1059. package/src/plugins/defaults/memory/memory-db.ts +27 -0
  1060. package/src/plugins/defaults/memory/memory-retrospective-constants.ts +4 -4
  1061. package/src/plugins/defaults/memory/memory-retrospective-job.ts +56 -180
  1062. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
  1063. package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +122 -202
  1064. package/src/plugins/defaults/memory/message-media.ts +2 -2
  1065. package/src/plugins/defaults/memory/paths.ts +3 -2
  1066. package/src/plugins/defaults/memory/pkb/pkb-index.test.ts +0 -12
  1067. package/src/plugins/defaults/memory/pkb/pkb-reconcile.test.ts +0 -9
  1068. package/src/plugins/defaults/memory/pkb/pkb-search.test.ts +0 -6
  1069. package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +15 -92
  1070. package/src/plugins/defaults/memory/routes/__tests__/memory-worker-routes.test.ts +201 -0
  1071. package/src/plugins/defaults/memory/routes/memory-item-routes.test.ts +7 -21
  1072. package/src/plugins/defaults/memory/routes/memory-v2-routes.ts +3 -8
  1073. package/src/plugins/defaults/memory/routes/memory-worker-routes.ts +162 -0
  1074. package/src/plugins/defaults/memory/startup.ts +6 -7
  1075. package/src/plugins/defaults/memory/task-memory-cleanup.ts +11 -22
  1076. package/src/plugins/defaults/memory/tools.test.ts +40 -8
  1077. package/src/plugins/defaults/memory/tools.ts +12 -2
  1078. package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +0 -19
  1079. package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +63 -40
  1080. package/src/plugins/defaults/memory/v2/__tests__/cli-command-store.test.ts +61 -130
  1081. package/src/plugins/defaults/memory/v2/__tests__/consolidation-job.test.ts +406 -10
  1082. package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -10
  1083. package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -10
  1084. package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -10
  1085. package/src/plugins/defaults/memory/v2/__tests__/injection-events.test.ts +61 -69
  1086. package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +0 -19
  1087. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +11 -10
  1088. package/src/plugins/defaults/memory/v2/__tests__/page-index.test.ts +0 -5
  1089. package/src/plugins/defaults/memory/v2/__tests__/qdrant.test.ts +6 -22
  1090. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +3 -5
  1091. package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +7 -20
  1092. package/src/plugins/defaults/memory/v2/__tests__/sim.test.ts +0 -24
  1093. package/src/plugins/defaults/memory/v2/__tests__/skill-content.test.ts +17 -11
  1094. package/src/plugins/defaults/memory/v2/__tests__/skill-store.test.ts +0 -16
  1095. package/src/plugins/defaults/memory/v2/__tests__/static-context.test.ts +0 -10
  1096. package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +0 -6
  1097. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +5 -2
  1098. package/src/plugins/defaults/memory/v2/cli-command-content.ts +43 -12
  1099. package/src/plugins/defaults/memory/v2/cli-command-store.ts +34 -50
  1100. package/src/plugins/defaults/memory/v2/consolidation-job.ts +216 -10
  1101. package/src/plugins/defaults/memory/v2/harness/router-retriever.ts +1 -8
  1102. package/src/plugins/defaults/memory/v2/injection-events.ts +16 -14
  1103. package/src/plugins/defaults/memory/v2/injection.ts +1 -2
  1104. package/src/plugins/defaults/memory/v2/memory-v2-startup.test.ts +0 -5
  1105. package/src/plugins/defaults/memory/v2/migration.ts +55 -24
  1106. package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
  1107. package/src/plugins/defaults/memory/v2/router.ts +4 -14
  1108. package/src/plugins/defaults/memory/v2/sweep-job.ts +1 -0
  1109. package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +10 -22
  1110. package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +0 -5
  1111. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -20
  1112. package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +0 -5
  1113. package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +5 -9
  1114. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -31
  1115. package/src/plugins/defaults/memory/v3/prune.test.ts +3 -11
  1116. package/src/{persistence → plugins/defaults/memory}/worker-control.ts +12 -21
  1117. package/src/plugins/defaults/memory/worker.ts +19 -2
  1118. package/src/plugins/mtime-cache.ts +166 -70
  1119. package/src/plugins/plugin-tree-walk.ts +41 -4
  1120. package/src/plugins/source-fingerprint.ts +9 -3
  1121. package/src/plugins/surface-import.ts +28 -0
  1122. package/src/plugins/types.ts +9 -23
  1123. package/src/prompts/__tests__/system-prompt.test.ts +0 -28
  1124. package/src/prompts/__tests__/task-progress-hint-section.test.ts +0 -28
  1125. package/src/providers/__tests__/connection-model-compat.test.ts +6 -19
  1126. package/src/providers/__tests__/count-tokens-forwarding.test.ts +1 -21
  1127. package/src/providers/__tests__/dispatch-connection-routing.test.ts +9 -26
  1128. package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
  1129. package/src/providers/__tests__/retry-callsite.test.ts +240 -235
  1130. package/src/providers/__tests__/satellite-connection-routing.test.ts +11 -36
  1131. package/src/providers/__tests__/vellum-mismatch-routing.test.ts +0 -5
  1132. package/src/providers/anthropic/client.ts +9 -3
  1133. package/src/providers/call-site-routing.ts +7 -3
  1134. package/src/providers/connection-resolution.ts +9 -11
  1135. package/src/providers/content-block-schema.ts +149 -0
  1136. package/src/providers/inference/__tests__/base-url-route-validation.test.ts +7 -11
  1137. package/src/providers/inference/__tests__/codex-token-refresh.test.ts +1 -15
  1138. package/src/providers/inference/auth.ts +23 -0
  1139. package/src/providers/inference/backfill.ts +25 -9
  1140. package/src/providers/model-catalog.ts +213 -5
  1141. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +54 -0
  1142. package/src/providers/openai/chat-completions-provider.ts +13 -2
  1143. package/src/providers/openai/responses-provider.ts +232 -5
  1144. package/src/providers/openrouter/client.ts +53 -0
  1145. package/src/providers/retry.ts +25 -2
  1146. package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +13 -0
  1147. package/src/providers/speech-to-text/__tests__/resolve.test.ts +211 -74
  1148. package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +408 -0
  1149. package/src/providers/speech-to-text/__tests__/vellum-managed.test.ts +121 -0
  1150. package/src/providers/speech-to-text/__tests__/vellum-speech-relay-connection.test.ts +126 -0
  1151. package/src/providers/speech-to-text/deepgram-realtime.ts +167 -37
  1152. package/src/providers/speech-to-text/incremental-batch-stream.ts +413 -0
  1153. package/src/providers/speech-to-text/openai-whisper-stream.ts +16 -363
  1154. package/src/providers/speech-to-text/provider-catalog.ts +26 -1
  1155. package/src/providers/speech-to-text/resolve.ts +74 -13
  1156. package/src/providers/speech-to-text/vellum-managed-realtime.ts +309 -0
  1157. package/src/providers/speech-to-text/vellum-managed.ts +71 -0
  1158. package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +174 -0
  1159. package/src/providers/types.ts +23 -4
  1160. package/src/providers/vellum-model-routing.test.ts +26 -0
  1161. package/src/providers/vellum-model-routing.ts +30 -0
  1162. package/src/runtime/AGENTS.md +1 -1
  1163. package/src/runtime/__tests__/actor-trust-resolver.test.ts +2 -8
  1164. package/src/runtime/__tests__/agent-wake.test.ts +100 -27
  1165. package/src/runtime/__tests__/background-job-runner.test.ts +22 -0
  1166. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -5
  1167. package/src/runtime/__tests__/member-verdict-cache.test.ts +2 -9
  1168. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +22 -5
  1169. package/src/runtime/access-request-helper.ts +84 -60
  1170. package/src/runtime/actor-trust-resolver.ts +2 -2
  1171. package/src/runtime/agent-wake.ts +75 -26
  1172. package/src/runtime/assistant-event-hub.ts +1 -0
  1173. package/src/runtime/auth/__tests__/middleware.test.ts +1 -10
  1174. package/src/runtime/auth/__tests__/route-policy.test.ts +0 -7
  1175. package/src/runtime/auth/__tests__/token-service.test.ts +1 -8
  1176. package/src/runtime/auth/same-actor.ts +2 -1
  1177. package/src/runtime/background-job-runner.ts +22 -0
  1178. package/src/runtime/channel-approval-types.ts +1 -1
  1179. package/src/runtime/channel-reply-delivery.ts +38 -19
  1180. package/src/runtime/confirmation-request-guardian-bridge.ts +45 -39
  1181. package/src/runtime/for-chat-mint-registry.ts +118 -0
  1182. package/src/runtime/guardian-action-service.ts +32 -27
  1183. package/src/runtime/guardian-decision-types.ts +2 -2
  1184. package/src/runtime/guardian-reply-router.ts +80 -98
  1185. package/src/runtime/http-server.ts +61 -41
  1186. package/src/runtime/introduction-policy.ts +2 -2
  1187. package/src/runtime/local-actor-identity.ts +19 -7
  1188. package/src/runtime/pending-interactions.ts +1 -0
  1189. package/src/runtime/reveal-nonce.ts +49 -0
  1190. package/src/runtime/reveal-success-registry.ts +306 -0
  1191. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -7
  1192. package/src/runtime/routes/__tests__/backup-routes.test.ts +195 -125
  1193. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +4 -1
  1194. package/src/runtime/routes/__tests__/client-routes.test.ts +0 -7
  1195. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +1 -19
  1196. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +1 -8
  1197. package/src/runtime/routes/__tests__/contact-routes-merge-relay.test.ts +186 -0
  1198. package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +2 -3
  1199. package/src/runtime/routes/__tests__/content-source-routes.test.ts +0 -7
  1200. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +5 -27
  1201. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +0 -7
  1202. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +12 -30
  1203. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +59 -56
  1204. package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +0 -7
  1205. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +53 -73
  1206. package/src/runtime/routes/__tests__/gateway-status-routes.test.ts +84 -0
  1207. package/src/runtime/routes/__tests__/inference-callsites-routes.test.ts +2 -10
  1208. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +58 -90
  1209. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -93
  1210. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +6 -1
  1211. package/src/runtime/routes/__tests__/monitoring-routes.test.ts +0 -8
  1212. package/src/runtime/routes/__tests__/plugins-routes.test.ts +218 -64
  1213. package/src/runtime/routes/__tests__/question-routes.test.ts +2 -4
  1214. package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -8
  1215. package/src/runtime/routes/__tests__/sanity-routes.test.ts +0 -7
  1216. package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +2 -1
  1217. package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +16 -56
  1218. package/src/runtime/routes/__tests__/stt-routes.test.ts +0 -9
  1219. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +0 -7
  1220. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -0
  1221. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +354 -1
  1222. package/src/runtime/routes/__tests__/tts-routes.test.ts +0 -11
  1223. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +163 -10
  1224. package/src/runtime/routes/__tests__/user-routes-cli.test.ts +154 -0
  1225. package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +0 -7
  1226. package/src/runtime/routes/acp-routes.ts +21 -9
  1227. package/src/runtime/routes/app-management-routes.ts +231 -60
  1228. package/src/runtime/routes/app-routes.ts +130 -83
  1229. package/src/runtime/routes/auth-routes.ts +3 -1
  1230. package/src/runtime/routes/background-wake-routes.ts +0 -1
  1231. package/src/runtime/routes/cache-routes.ts +3 -3
  1232. package/src/runtime/routes/call-routes.ts +5 -1
  1233. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  1234. package/src/runtime/routes/contact-prompt-routes.ts +11 -5
  1235. package/src/runtime/routes/contact-routes.ts +34 -42
  1236. package/src/runtime/routes/conversation-attention-routes.ts +1 -1
  1237. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  1238. package/src/runtime/routes/conversation-query-routes.ts +4 -4
  1239. package/src/runtime/routes/conversation-routes.ts +111 -72
  1240. package/src/runtime/routes/credential-routes.ts +116 -3
  1241. package/src/runtime/routes/email-routes.ts +17 -1
  1242. package/src/runtime/routes/events-routes.ts +1 -0
  1243. package/src/runtime/routes/gateway-status-routes.ts +69 -0
  1244. package/src/runtime/routes/guardian-action-routes.ts +18 -16
  1245. package/src/runtime/routes/guardian-approval-interception.ts +6 -4
  1246. package/src/runtime/routes/guardian-approval-prompt.ts +7 -5
  1247. package/src/runtime/routes/guardian-expiry-sweep.ts +130 -0
  1248. package/src/runtime/routes/inbound-message-handler.ts +9 -33
  1249. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -5
  1250. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +9 -9
  1251. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +24 -6
  1252. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -7
  1253. package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -5
  1254. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +6 -3
  1255. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -1
  1256. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +0 -9
  1257. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +4 -1
  1258. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +3 -12
  1259. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +16 -14
  1260. package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +8 -2
  1261. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +15 -7
  1262. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -9
  1263. package/src/runtime/routes/index.ts +5 -5
  1264. package/src/runtime/routes/inference-provider-connection-routes.ts +73 -24
  1265. package/src/runtime/routes/inference-send-routes.ts +1 -1
  1266. package/src/runtime/routes/internal-telemetry-routes.ts +11 -2
  1267. package/src/runtime/routes/oauth-connect-routes.ts +27 -7
  1268. package/src/runtime/routes/platform-routes.ts +4 -14
  1269. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +0 -4
  1270. package/src/runtime/routes/playground/__tests__/guard.test.ts +0 -4
  1271. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +0 -14
  1272. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +0 -21
  1273. package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +0 -4
  1274. package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +16 -18
  1275. package/src/runtime/routes/playground/__tests__/state.test.ts +0 -14
  1276. package/src/runtime/routes/playground/seed-conversation.ts +5 -4
  1277. package/src/runtime/routes/playground/seeded-conversations.ts +3 -2
  1278. package/src/runtime/routes/plugins-routes.ts +163 -25
  1279. package/src/runtime/routes/profiler-routes.ts +2 -5
  1280. package/src/runtime/routes/publish-routes.ts +15 -18
  1281. package/src/runtime/routes/question-routes.ts +8 -4
  1282. package/src/runtime/routes/schedule-routes.ts +20 -78
  1283. package/src/runtime/routes/schedule-worker-routes.ts +16 -84
  1284. package/src/runtime/routes/secret-routes.ts +14 -0
  1285. package/src/runtime/routes/settings-routes.ts +21 -25
  1286. package/src/runtime/routes/subagents-routes.ts +17 -18
  1287. package/src/runtime/routes/surface-action-routes.ts +18 -39
  1288. package/src/runtime/routes/surface-content-routes.ts +59 -1
  1289. package/src/runtime/routes/surface-conversation-resolver.ts +148 -4
  1290. package/src/runtime/routes/telemetry-routes.ts +74 -1
  1291. package/src/runtime/routes/tts-routes.ts +9 -5
  1292. package/src/runtime/routes/ui-snapshot-routes.test.ts +219 -0
  1293. package/src/runtime/routes/ui-snapshot-routes.ts +313 -0
  1294. package/src/runtime/routes/user-route-dispatcher.ts +52 -53
  1295. package/src/runtime/routes/user-route-resolution.ts +141 -0
  1296. package/src/runtime/routes/user-routes-cli.ts +56 -35
  1297. package/src/runtime/routes/user-routes.ts +9 -2
  1298. package/src/runtime/routes/vellum-actor-trust.ts +67 -0
  1299. package/src/runtime/services/__tests__/auto-analysis-guard.test.ts +1 -8
  1300. package/src/runtime/tool-grant-request-helper.ts +34 -30
  1301. package/src/runtime/trust-verdict-consumer.ts +4 -6
  1302. package/src/schedule/__tests__/worker-control.test.ts +3 -3
  1303. package/src/schedule/schedule-store.ts +0 -41
  1304. package/src/schedule/scheduler.ts +38 -257
  1305. package/src/schedule/worker-control.ts +11 -21
  1306. package/src/schedule/worker.ts +18 -5
  1307. package/src/security/__tests__/oauth2-device-code.test.ts +12 -60
  1308. package/src/security/__tests__/provider-key-env-fallback.test.ts +0 -10
  1309. package/src/security/auth-fallback-events-store.ts +34 -72
  1310. package/src/security/secret-scanner.ts +26 -1
  1311. package/src/sequence/engine.ts +15 -6
  1312. package/src/services/published-app-updater.ts +6 -11
  1313. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +24 -4
  1314. package/src/stt/daemon-batch-transcriber.ts +33 -2
  1315. package/src/stt/stt-stream-session.ts +17 -11
  1316. package/src/stt/types.ts +2 -1
  1317. package/src/subagent/manager.ts +4 -3
  1318. package/src/telemetry/AGENTS.md +44 -0
  1319. package/src/telemetry/__tests__/config-setting-events-store.test.ts +63 -0
  1320. package/src/telemetry/__tests__/config-setting-snapshot.test.ts +107 -0
  1321. package/src/telemetry/__tests__/flush-checkpoints.test.ts +56 -0
  1322. package/src/telemetry/__tests__/outbox-test-harness.ts +83 -0
  1323. package/src/telemetry/__tests__/telemetry-event-fixtures.ts +258 -0
  1324. package/src/telemetry/__tests__/watchdog-events-store.test.ts +32 -122
  1325. package/src/telemetry/config-setting-events-store.ts +40 -0
  1326. package/src/telemetry/config-setting-snapshot.ts +135 -0
  1327. package/src/telemetry/flush-checkpoints.ts +70 -0
  1328. package/src/telemetry/skill-loaded-events-store.test.ts +54 -113
  1329. package/src/telemetry/skill-loaded-events-store.ts +21 -77
  1330. package/src/telemetry/telemetry-event-sources.test.ts +211 -0
  1331. package/src/telemetry/telemetry-event-sources.ts +582 -0
  1332. package/src/telemetry/telemetry-events-outbox.test.ts +330 -0
  1333. package/src/telemetry/telemetry-events-outbox.ts +204 -0
  1334. package/src/telemetry/telemetry-main-db.ts +48 -0
  1335. package/src/telemetry/telemetry-wire-source.json +4 -0
  1336. package/src/telemetry/telemetry-wire-validation.test.ts +157 -0
  1337. package/src/telemetry/telemetry-wire-validation.ts +125 -0
  1338. package/src/telemetry/telemetry-wire.generated.ts +433 -0
  1339. package/src/telemetry/tool-executed-events-store.test.ts +0 -8
  1340. package/src/telemetry/tool-executed-events-store.ts +2 -2
  1341. package/src/telemetry/turn-trace-store.test.ts +86 -7
  1342. package/src/telemetry/turn-trace-store.ts +29 -1
  1343. package/src/telemetry/types.test.ts +38 -0
  1344. package/src/telemetry/types.ts +302 -87
  1345. package/src/telemetry/usage-telemetry-reporter.test.ts +921 -364
  1346. package/src/telemetry/usage-telemetry-reporter.ts +235 -722
  1347. package/src/telemetry/watchdog-direct-emit.test.ts +0 -5
  1348. package/src/telemetry/watchdog-direct-emit.ts +7 -1
  1349. package/src/telemetry/watchdog-events-store.ts +11 -70
  1350. package/src/tools/acp/spawn.test.ts +0 -7
  1351. package/src/tools/apps/definitions.ts +1 -7
  1352. package/src/tools/apps/executors.ts +11 -36
  1353. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +11 -24
  1354. package/src/tools/browser/__tests__/browser-status.test.ts +47 -33
  1355. package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1 -11
  1356. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +75 -58
  1357. package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +0 -10
  1358. package/src/tools/browser/network-recorder.test.ts +0 -11
  1359. package/src/tools/document/document-comment-tool.test.ts +1 -7
  1360. package/src/tools/host-terminal/host-shell.test.ts +0 -32
  1361. package/src/tools/host-terminal/host-shell.ts +6 -2
  1362. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +13 -15
  1363. package/src/tools/network/__tests__/web-search-metadata.test.ts +15 -18
  1364. package/src/tools/network/__tests__/web-search.test.ts +39 -50
  1365. package/src/tools/registry.ts +148 -196
  1366. package/src/tools/skills/find-similar-skills.test.ts +0 -7
  1367. package/src/tools/skills/sandbox-runner.ts +5 -2
  1368. package/src/tools/skills/scaffold-managed.ts +105 -12
  1369. package/src/tools/subagent/read.ts +6 -4
  1370. package/src/tools/subagent/spawn.ts +20 -29
  1371. package/src/tools/terminal/safe-env.ts +7 -2
  1372. package/src/tools/terminal/shell.test.ts +4 -8
  1373. package/src/tools/terminal/shell.ts +5 -2
  1374. package/src/tools/tool-approval-handler.ts +39 -23
  1375. package/src/tools/tool-input-summary.ts +2 -1
  1376. package/src/tools/tool-manifest.ts +20 -6
  1377. package/src/tools/tool-profiler.ts +37 -6
  1378. package/src/tools/ui-surface/definitions.ts +1 -7
  1379. package/src/tools/workflows/run-workflow.test.ts +8 -22
  1380. package/src/tts/__tests__/provider-adapters.test.ts +28 -22
  1381. package/src/tts/__tests__/provider-resolution.test.ts +26 -0
  1382. package/src/tts/__tests__/synthesis-stream.test.ts +6 -6
  1383. package/src/tts/__tests__/vellum-provider.test.ts +251 -0
  1384. package/src/tts/provider-catalog.ts +6 -0
  1385. package/src/tts/providers/__tests__/vellum-tts-socket.test.ts +266 -0
  1386. package/src/tts/providers/vellum-provider.ts +220 -0
  1387. package/src/tts/providers/vellum-tts-socket.ts +377 -0
  1388. package/src/tts/synthesize-text.ts +15 -5
  1389. package/src/tts/tts-config-resolver.ts +2 -7
  1390. package/src/tts/types.ts +1 -0
  1391. package/src/usage/attribution.ts +20 -114
  1392. package/src/util/abort-reasons.ts +1 -3
  1393. package/src/util/image-conversion.ts +23 -5
  1394. package/src/util/logger.ts +8 -3
  1395. package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
  1396. package/src/util/platform.ts +0 -60
  1397. package/src/util/pricing.ts +10 -1
  1398. package/src/util/telemetry-db-path.ts +9 -7
  1399. package/src/watcher/__tests__/telemetry.test.ts +41 -11
  1400. package/src/watcher/providers/google-calendar.ts +81 -49
  1401. package/src/watcher/telemetry.ts +22 -5
  1402. package/src/workflows/engine-integration.test.ts +0 -6
  1403. package/src/workflows/engine.test.ts +1 -9
  1404. package/src/workflows/journal-store.test.ts +1 -9
  1405. package/src/workflows/leaf-runner.test.ts +17 -50
  1406. package/src/workflows/library.test.ts +1 -9
  1407. package/src/workflows/run-manager.test.ts +1 -9
  1408. package/src/workspace/git-service.ts +932 -37
  1409. package/src/workspace/provider-commit-message-generator.ts +6 -4
  1410. package/__tests__/permissions/gateway-threshold-reader.test.ts +0 -450
  1411. package/src/__tests__/canonical-guardian-store.test.ts +0 -928
  1412. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -140
  1413. package/src/__tests__/plugin-route-contribution.test.ts +0 -245
  1414. package/src/__tests__/skill-runtime-path.test.ts +0 -63
  1415. package/src/__tests__/task-compiler.test.ts +0 -317
  1416. package/src/__tests__/task-management-tools.test.ts +0 -1128
  1417. package/src/__tests__/task-scheduler.test.ts +0 -786
  1418. package/src/config/schemas/schedules.ts +0 -35
  1419. package/src/contacts/canonical-guardian-store.ts +0 -902
  1420. package/src/daemon/message-types/work-items.ts +0 -243
  1421. package/src/runtime/routes/__tests__/memory-worker-routes.test.ts +0 -306
  1422. package/src/runtime/routes/__tests__/task-routes.test.ts +0 -644
  1423. package/src/runtime/routes/assets/vellum-design-system.css +0 -1959
  1424. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +0 -129
  1425. package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +0 -158
  1426. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -187
  1427. package/src/runtime/routes/memory-worker-routes.ts +0 -227
  1428. package/src/runtime/routes/task-routes.ts +0 -380
  1429. package/src/runtime/routes/work-items-routes.test.ts +0 -75
  1430. package/src/runtime/routes/work-items-routes.ts +0 -881
  1431. package/src/runtime/skill-route-registry.ts +0 -131
  1432. package/src/tasks/SPEC.md +0 -132
  1433. package/src/tasks/task-compiler.ts +0 -194
  1434. package/src/tasks/task-runner.ts +0 -119
  1435. package/src/tasks/task-scheduler.ts +0 -22
  1436. package/src/tasks/task-store.ts +0 -153
  1437. package/src/tasks/tool-sanitizer.ts +0 -38
  1438. package/src/tools/apps/registry.ts +0 -16
  1439. package/src/tools/system/register.ts +0 -9
  1440. package/src/tools/tasks/task-delete.ts +0 -121
  1441. package/src/tools/tasks/task-list.ts +0 -56
  1442. package/src/tools/tasks/task-run.ts +0 -122
  1443. package/src/tools/tasks/task-save.ts +0 -64
  1444. package/src/tools/tasks/work-item-enqueue.ts +0 -300
  1445. package/src/tools/tasks/work-item-list.ts +0 -65
  1446. package/src/tools/tasks/work-item-remove.ts +0 -94
  1447. package/src/tools/tasks/work-item-run.ts +0 -99
  1448. package/src/tools/tasks/work-item-update.ts +0 -166
  1449. package/src/tools/ui-surface/registry.ts +0 -14
  1450. package/src/work-items/resolve-required-tools.test.ts +0 -37
  1451. package/src/work-items/resolve-required-tools.ts +0 -26
  1452. package/src/work-items/work-item-runner.ts +0 -187
  1453. package/src/work-items/work-item-store.ts +0 -416
@@ -2,6 +2,7 @@ import { execFile, spawn, spawnSync } from "node:child_process";
2
2
  import {
3
3
  chmodSync,
4
4
  existsSync,
5
+ lstatSync,
5
6
  mkdirSync,
6
7
  readFileSync,
7
8
  unlinkSync,
@@ -60,6 +61,7 @@ function cleanGitEnv(workspaceDir: string): Record<string, string> {
60
61
  * These are written to .gitignore on init and appended to existing .gitignore files.
61
62
  */
62
63
  const WORKSPACE_GITIGNORE_RULES = [
64
+ // Runtime state directories
63
65
  "data/db/",
64
66
  "data/qdrant/",
65
67
  "data/monitoring/",
@@ -69,25 +71,130 @@ const WORKSPACE_GITIGNORE_RULES = [
69
71
  "data/apps/*/records/",
70
72
  "data/apps/*/dist/",
71
73
  "data/apps/*.preview",
72
- "plugins/*/node_modules/",
74
+ // Runtime-managed installs and caches — large and restorable
75
+ "/embedding-models/",
76
+ "/external/",
77
+ "/bin/",
78
+ "/plugins-data/",
79
+ "node_modules/",
80
+ "__pycache__/",
81
+ ".venv/",
82
+ // Logs and process state
73
83
  "logs/",
74
84
  "*.log",
85
+ "*.jsonl",
75
86
  "*.sock",
76
87
  "*.pid",
77
- "*.sqlite",
78
- "*.sqlite-journal",
79
- "*.sqlite-wal",
80
- "*.sqlite-shm",
81
- "*.db",
82
- "*.db-journal",
83
- "*.db-wal",
84
- "*.db-shm",
85
- "vellum.pid",
88
+ "daemon-startup.lock",
86
89
  "session-token",
90
+ // Databases (covers sidecar -journal/-wal/-shm files)
91
+ "*.sqlite*",
92
+ "*.db",
93
+ "*.db-*",
94
+ // OS junk
95
+ ".DS_Store",
96
+ // Archives and disk images
97
+ "*.zip",
98
+ "*.tar",
99
+ "*.gz",
100
+ "*.tgz",
101
+ "*.bz2",
102
+ "*.xz",
103
+ "*.7z",
104
+ "*.rar",
105
+ "*.dmg",
106
+ "*.iso",
107
+ // Images (svg is text-based and stays tracked)
108
+ "*.png",
109
+ "*.jpg",
110
+ "*.jpeg",
111
+ "*.gif",
112
+ "*.webp",
113
+ "*.heic",
114
+ "*.bmp",
115
+ "*.tiff",
116
+ // Audio and video
117
+ "*.mp3",
118
+ "*.wav",
119
+ "*.m4a",
120
+ "*.flac",
121
+ "*.ogg",
122
+ "*.mp4",
123
+ "*.mov",
124
+ "*.avi",
125
+ "*.mkv",
126
+ "*.webm",
127
+ // Documents and model weights
128
+ "*.pdf",
129
+ "*.gguf",
130
+ "*.onnx",
131
+ "*.safetensors",
132
+ "*.pt",
133
+ "*.pth",
134
+ // Canonical user state re-included despite the extension rules above.
135
+ // Must stay after the extension rules: last matching pattern wins.
136
+ // (Not a broad !data/apps/** — that would also re-include dist/.)
137
+ // conversations/ holds the messages.jsonl disk view that DB recovery
138
+ // rebuilds from, so it survives the *.jsonl rule.
139
+ "!data/avatar/**",
140
+ "!data/sounds/**",
141
+ "!data/apps/*/icon.png",
142
+ "!conversations/**",
143
+ ];
144
+
145
+ /**
146
+ * Paths exempt from the oversized-file guard. Mirrors the `!` re-include
147
+ * rules in WORKSPACE_GITIGNORE_RULES above: canonical state the product
148
+ * explicitly insists on tracking (e.g. conversation disk views that DB
149
+ * recovery rebuilds from) must keep committing even past
150
+ * workspaceGit.maxFileSizeBytes. Keep in sync with the negation rules.
151
+ */
152
+ const SIZE_GUARD_EXEMPT_PATTERNS: RegExp[] = [
153
+ /^conversations\//,
154
+ /^data\/avatar\//,
155
+ /^data\/sounds\//,
156
+ /^data\/apps\/[^/]+\/icon\.png$/,
87
157
  ];
88
158
 
159
+ function isSizeGuardExempt(relPath: string): boolean {
160
+ return SIZE_GUARD_EXEMPT_PATTERNS.some((re) => re.test(relPath));
161
+ }
162
+
163
+ /** Default identity for automated workspace commits. */
164
+ const DEFAULT_GIT_NAME = "Vellum Assistant";
165
+ // generic-examples:ignore-next-line — reason: real daemon commit identity, not an example
166
+ const DEFAULT_GIT_EMAIL = "assistant@vellum.ai";
167
+
89
168
  const NULL_GIT_OID = "0000000000000000000000000000000000000000";
90
169
 
170
+ /**
171
+ * Git's well-known empty tree object id, used as the diff/reset base when
172
+ * HEAD does not exist yet (unborn branch, before the initial commit).
173
+ */
174
+ const EMPTY_TREE_OID = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
175
+
176
+ const DEFAULT_MAX_FILE_SIZE_BYTES = 256000;
177
+
178
+ /**
179
+ * History compaction keeps commits younger than this; older ones are
180
+ * squashed into a scrubbed base commit so oversized blobs referenced only
181
+ * by old history can be pruned from .git.
182
+ */
183
+ const HISTORY_RETENTION_DAYS = 7;
184
+
185
+ /** Timeout for one-shot history rewrite / gc operations. */
186
+ const HISTORY_COMPACTION_TIMEOUT_MS = 10 * 60_000;
187
+
188
+ /**
189
+ * Delay between init and the first compaction attempt, so boot-time
190
+ * foreground work (first turn commit, status reads) never queues on the
191
+ * git mutex behind a detection scan or rewrite.
192
+ */
193
+ const HISTORY_COMPACTION_INITIAL_DELAY_MS = 60_000;
194
+
195
+ /** Lower bound between compaction retries while blobs wait out retention. */
196
+ const HISTORY_COMPACTION_MIN_RETRY_MS = 60 * 60_000;
197
+
91
198
  const WORKSPACE_BRANCH_GUARD_HOOK = `#!/bin/sh
92
199
  set -eu
93
200
 
@@ -121,6 +228,32 @@ done
121
228
  exit 0
122
229
  `;
123
230
 
231
+ /**
232
+ * Parse NUL-terminated `git status --porcelain -z` output into status/path
233
+ * pairs. NUL termination is required so paths with special characters
234
+ * (non-ASCII, quotes, newlines) arrive verbatim instead of C-style quoted.
235
+ * A rename/copy record is followed by a bare origin-path entry, which is
236
+ * skipped.
237
+ */
238
+ function parsePorcelainZ(
239
+ stdout: string,
240
+ ): Array<{ status: string; path: string }> {
241
+ const entries = stdout.split("\0");
242
+ const parsed: Array<{ status: string; path: string }> = [];
243
+ for (let i = 0; i < entries.length; i++) {
244
+ const entry = entries[i] ?? "";
245
+ if (entry.length < 4) {
246
+ continue;
247
+ }
248
+ const status = entry.substring(0, 2);
249
+ parsed.push({ status, path: entry.substring(3) });
250
+ if (status[0] === "R" || status[0] === "C") {
251
+ i++;
252
+ }
253
+ }
254
+ return parsed;
255
+ }
256
+
124
257
  /** Properties added by Node's child_process errors. */
125
258
  interface ExecError extends Error {
126
259
  killed?: boolean;
@@ -155,6 +288,7 @@ interface GitStatus {
155
288
  * - Mutex-protected operations: prevents concurrent git command conflicts
156
289
  * - Handles both new and existing workspaces transparently
157
290
  * - Synchronous initial commit within mutex to prevent races
291
+ * - Size guard: files over workspaceGit.maxFileSizeBytes never enter commits
158
292
  */
159
293
  export class WorkspaceGitService {
160
294
  private readonly workspaceDir: string;
@@ -165,6 +299,10 @@ export class WorkspaceGitService {
165
299
  private nextAllowedAttemptMs = 0;
166
300
  private initConsecutiveFailures = 0;
167
301
  private initNextAllowedAttemptMs = 0;
302
+ /** Oversized paths already logged, to avoid re-warning every commit cycle. */
303
+ private readonly warnedOversizedPaths = new Set<string>();
304
+ private historyCompactionTimer: ReturnType<typeof setTimeout> | null = null;
305
+ private historyCompactionDueAtMs = 0;
168
306
 
169
307
  constructor(workspaceDir: string) {
170
308
  this.workspaceDir = workspaceDir;
@@ -434,13 +572,19 @@ export class WorkspaceGitService {
434
572
  // created before these helpers existed, or by external tools.
435
573
  // These calls are OUTSIDE the rev-parse try/catch so that
436
574
  // normalization errors are not misclassified as "no commits".
437
- this.ensureGitignoreRulesLocked();
438
575
  this.ensureBranchGuardHookLocked();
439
576
  await this.ensureCommitIdentityLocked();
440
577
  await this.ensureBranchGuardConfigLocked();
441
578
  await this.ensureOnMainLocked();
579
+ // After the main switch: ensureOnMainLocked can discard
580
+ // local changes, which would wipe appended gitignore rules
581
+ // and staged deletions alike.
582
+ this.ensureGitignoreRulesLocked();
583
+ await this.untrackIgnoredFilesLocked();
584
+ await this.untrackOversizedFilesLocked();
442
585
  this.initialized = true;
443
586
  this.recordInitSuccess();
587
+ this.scheduleHistoryCompaction();
444
588
  return;
445
589
  }
446
590
  }
@@ -450,15 +594,20 @@ export class WorkspaceGitService {
450
594
  // Initialize new git repository
451
595
  await this.execGit(["init", "-b", "main"]);
452
596
 
453
- // Run normalization (gitignore + identity + branch enforcement).
597
+ // Run normalization (identity + branch enforcement + gitignore).
454
598
  // For fresh `git init -b main` the branch is already main, but
455
599
  // in the corruption-recovery path we fall through here after
456
600
  // removing .git, so branch enforcement is still useful.
457
- this.ensureGitignoreRulesLocked();
458
601
  this.ensureBranchGuardHookLocked();
459
602
  await this.ensureCommitIdentityLocked();
460
603
  await this.ensureBranchGuardConfigLocked();
461
604
  await this.ensureOnMainLocked();
605
+ // After the main switch (see above). A partial init (`.git`
606
+ // exists, no commit) can carry staged now-ignored paths from an
607
+ // interrupted `git add -A`; untracking must precede the initial
608
+ // commit.
609
+ this.ensureGitignoreRulesLocked();
610
+ await this.untrackIgnoredFilesLocked();
462
611
 
463
612
  // Create initial commit synchronously within the lock to prevent
464
613
  // races with the first commitChanges() call. Without this, the
@@ -474,7 +623,7 @@ export class WorkspaceGitService {
474
623
  (f) => !autoCreatedInitFiles.has(f),
475
624
  );
476
625
 
477
- await this.execGit(["add", "-A"]);
626
+ await this.stageAllLocked();
478
627
 
479
628
  const message = hasExistingFiles
480
629
  ? "Initial commit: migrated existing workspace"
@@ -506,8 +655,8 @@ export class WorkspaceGitService {
506
655
  await this.mutex.withLock(async () => {
507
656
  this.cleanStaleLockFile();
508
657
 
509
- // Stage all changes
510
- await this.execGit(["add", "-A"]);
658
+ // Stage all changes (minus oversized files)
659
+ await this.stageAllLocked();
511
660
 
512
661
  // Build commit message with metadata if provided
513
662
  let fullMessage = message;
@@ -652,7 +801,7 @@ export class WorkspaceGitService {
652
801
  return { committed: false, status, didRunGit: true as const };
653
802
  }
654
803
 
655
- await this.execGit(["add", "-A"]);
804
+ await this.stageAllLocked();
656
805
 
657
806
  // Verify something was actually staged. Another service instance
658
807
  // (or external process) could have committed between our status
@@ -709,18 +858,23 @@ export class WorkspaceGitService {
709
858
  private async getStatusInternal(): Promise<GitStatus> {
710
859
  // Streamed via spawn (not execFile) so an oversized status from a bloated
711
860
  // working tree cannot exceed Node's default 1 MB maxBuffer and fail.
712
- const { stdout } = await this.execGitStreaming(["status", "--porcelain"]);
861
+ // --untracked-files=all enumerates files inside untracked directories
862
+ // instead of a "dir/" placeholder, so the per-file size filter below can
863
+ // see them — otherwise a directory holding only oversized files would
864
+ // keep the workspace dirty forever. -z delivers special-character paths
865
+ // verbatim (unquoted) for the same reason.
866
+ const { stdout } = await this.execGitStreaming([
867
+ "status",
868
+ "--porcelain",
869
+ "--untracked-files=all",
870
+ "-z",
871
+ ]);
713
872
 
714
873
  const staged: string[] = [];
715
874
  const modified: string[] = [];
716
875
  const untracked: string[] = [];
717
876
 
718
- for (const line of stdout.split("\n")) {
719
- if (!line) continue;
720
-
721
- const status = line.substring(0, 2);
722
- const file = line.substring(3);
723
-
877
+ for (const { status, path: file } of parsePorcelainZ(stdout)) {
724
878
  // First character is staged status, second is working tree status
725
879
  const stagedStatus = status[0];
726
880
  const workingStatus = status[1];
@@ -728,10 +882,16 @@ export class WorkspaceGitService {
728
882
  if (stagedStatus !== " " && stagedStatus !== "?") {
729
883
  staged.push(file);
730
884
  }
885
+ // Oversized files are invisible to auto-commit: they can never be
886
+ // committed (stageAllLocked unstages them), so reporting them here
887
+ // would keep the workspace permanently dirty and make every turn /
888
+ // heartbeat cycle re-attempt a commit that stages nothing.
731
889
  if (workingStatus === "M" || workingStatus === "D") {
732
- modified.push(file);
890
+ if (!this.isOversized(file)) {
891
+ modified.push(file);
892
+ }
733
893
  }
734
- if (status === "??") {
894
+ if (status === "??" && !this.isOversized(file)) {
735
895
  untracked.push(file);
736
896
  }
737
897
  }
@@ -745,6 +905,627 @@ export class WorkspaceGitService {
745
905
  };
746
906
  }
747
907
 
908
+ private maxFileSizeBytes(): number {
909
+ return (
910
+ getConfig().workspaceGit?.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES
911
+ );
912
+ }
913
+
914
+ /**
915
+ * Working-tree size check for a repo-relative path. Uses lstat so a
916
+ * symlink is measured by the link itself, not its target. Missing or
917
+ * unreadable paths (deletions, races) are treated as not oversized.
918
+ */
919
+ private isOversized(relPath: string): boolean {
920
+ if (isSizeGuardExempt(relPath)) {
921
+ return false;
922
+ }
923
+ try {
924
+ const stats = lstatSync(join(this.workspaceDir, relPath));
925
+ return stats.isFile() && stats.size > this.maxFileSizeBytes();
926
+ } catch {
927
+ return false;
928
+ }
929
+ }
930
+
931
+ /**
932
+ * Resolve the base for staged-change comparisons: HEAD when it exists,
933
+ * the empty tree on an unborn branch. Transient git errors propagate so
934
+ * callers abort instead of diffing/resetting against the wrong base.
935
+ */
936
+ private async resolveStagedDiffBaseLocked(): Promise<string> {
937
+ try {
938
+ await this.execGit(["rev-parse", "--quiet", "--verify", "HEAD"]);
939
+ return "HEAD";
940
+ } catch (err) {
941
+ if ((err as ExecError).code === 1) {
942
+ return EMPTY_TREE_OID;
943
+ }
944
+ throw err;
945
+ }
946
+ }
947
+
948
+ /**
949
+ * Drop tracked files whose on-disk size exceeds
950
+ * workspaceGit.maxFileSizeBytes from the index (working tree untouched) —
951
+ * files committed before the size guard existed, or before a limit
952
+ * decrease. Blobs referenced by older commits remain in .git. Like
953
+ * {@link untrackIgnoredFilesLocked}, the staged deletions ride along with
954
+ * the next commit and failures are logged, never blocking init. Must be
955
+ * called with the mutex lock held.
956
+ */
957
+ private async untrackOversizedFilesLocked(): Promise<void> {
958
+ try {
959
+ const tracked = await this.execGitStreaming(["ls-files", "-z"]);
960
+ const oversized = tracked.stdout
961
+ .split("\0")
962
+ .filter((p) => p.length > 0 && this.isOversized(p));
963
+ if (oversized.length === 0) {
964
+ return;
965
+ }
966
+
967
+ await this.execGitStreaming(
968
+ [
969
+ "rm",
970
+ "--cached",
971
+ "-q",
972
+ "--ignore-unmatch",
973
+ "--pathspec-from-file=-",
974
+ "--pathspec-file-nul",
975
+ ],
976
+ { input: oversized.map((p) => `:(literal)${p}`).join("\0") },
977
+ );
978
+
979
+ for (const p of oversized) {
980
+ this.warnedOversizedPaths.add(p);
981
+ }
982
+ log.warn(
983
+ {
984
+ workspaceDir: this.workspaceDir,
985
+ files: oversized,
986
+ maxFileSizeBytes: this.maxFileSizeBytes(),
987
+ },
988
+ "Untracked oversized files from workspace index",
989
+ );
990
+ } catch (err) {
991
+ log.warn({ err }, "Failed to untrack oversized files");
992
+ }
993
+ }
994
+
995
+ /**
996
+ * Schedule a background history compaction attempt. The delay keeps the
997
+ * run off the git mutex during boot, so foreground commits and status
998
+ * reads are never queued behind a rewrite. When blobs exist but all
999
+ * history is still within retention, the attempt reschedules itself for
1000
+ * when the oldest commit ages past the cutoff. Best-effort like the
1001
+ * untrack sweeps: failures are logged and never affect commits.
1002
+ */
1003
+ private scheduleHistoryCompaction(
1004
+ delayMs = HISTORY_COMPACTION_INITIAL_DELAY_MS,
1005
+ ): void {
1006
+ const dueAtMs = Date.now() + delayMs;
1007
+ if (this.historyCompactionTimer) {
1008
+ if (dueAtMs >= this.historyCompactionDueAtMs) {
1009
+ // An earlier-or-equal run is already pending; it covers this request.
1010
+ return;
1011
+ }
1012
+ // A retention retry can be days out — a fresh request (e.g. a newly
1013
+ // unstaged external blob) must not wait behind it.
1014
+ clearTimeout(this.historyCompactionTimer);
1015
+ this.historyCompactionTimer = null;
1016
+ }
1017
+ const timer = setTimeout(() => {
1018
+ void (async () => {
1019
+ let retryAfterMs: number | undefined;
1020
+ try {
1021
+ const result = await this.compactHistoryNow();
1022
+ retryAfterMs = result.retryAfterMs;
1023
+ } catch (err) {
1024
+ log.warn(
1025
+ { err, workspaceDir: this.workspaceDir },
1026
+ "Workspace history compaction failed",
1027
+ );
1028
+ }
1029
+ this.historyCompactionTimer = null;
1030
+ if (retryAfterMs !== undefined) {
1031
+ this.scheduleHistoryCompaction(retryAfterMs);
1032
+ }
1033
+ })();
1034
+ }, delayMs);
1035
+ // Never keep the process alive just for maintenance.
1036
+ timer.unref?.();
1037
+ this.historyCompactionTimer = timer;
1038
+ this.historyCompactionDueAtMs = dueAtMs;
1039
+ }
1040
+
1041
+ /**
1042
+ * Rewrite workspace history so blobs over workspaceGit.maxFileSizeBytes
1043
+ * stop occupying .git. Commits older than HISTORY_RETENTION_DAYS are
1044
+ * squashed into a single base commit whose tree is scrubbed of oversized
1045
+ * entries; younger commits are replayed verbatim (trees, messages,
1046
+ * authors, and dates preserved); reflogs are then expired and unreachable
1047
+ * objects pruned. Runs only when the object store contains an oversized
1048
+ * blob that is actionable — unreachable, or reachable at a non-exempt
1049
+ * path (see SIZE_GUARD_EXEMPT_PATTERNS) — so the steady state is a cheap
1050
+ * detection scan and exempt canonical state never triggers rewrites.
1051
+ *
1052
+ * Oversized blobs still referenced by replayed recent commits survive
1053
+ * until those commits age past retention — the result carries
1054
+ * `retryAfterMs` so the background scheduler re-runs then, and bloat
1055
+ * disappears automatically within the retention window. The working
1056
+ * tree and index are never touched (the tip tree is reused unchanged).
1057
+ * Git notes attached to rewritten commits are orphaned; enrichment only
1058
+ * targets commits created after the rewrite, so this is cosmetic.
1059
+ */
1060
+ async compactHistoryNow(): Promise<{
1061
+ rewrote: boolean;
1062
+ squashedCommits: number;
1063
+ keptCommits: number;
1064
+ /** Set when blobs remain but history must first age past retention. */
1065
+ retryAfterMs?: number;
1066
+ }> {
1067
+ await this.ensureInitialized();
1068
+ return this.mutex.withLock(() => this.compactHistoryLocked());
1069
+ }
1070
+
1071
+ /**
1072
+ * Expire all reflogs and prune unreachable objects so dropped blobs are
1073
+ * physically deleted from .git. Hooks are disabled for the same reason as
1074
+ * in {@link buildSafeCommitArgs} — workspace hooks are model-writable and
1075
+ * untrusted, and gc's pack-refs would otherwise run the branch guard
1076
+ * against legacy refs. Must be called with the mutex lock held.
1077
+ */
1078
+ private async expireReflogsAndPruneLocked(): Promise<void> {
1079
+ await this.execGit(
1080
+ [
1081
+ "-c",
1082
+ "core.hooksPath=/dev/null",
1083
+ "reflog",
1084
+ "expire",
1085
+ "--expire=now",
1086
+ "--expire-unreachable=now",
1087
+ "--all",
1088
+ ],
1089
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1090
+ );
1091
+ await this.execGit(
1092
+ ["-c", "core.hooksPath=/dev/null", "gc", "--prune=now", "--quiet"],
1093
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1094
+ );
1095
+ }
1096
+
1097
+ /**
1098
+ * Object ids of every blob in the object store exceeding the size limit.
1099
+ * Reads object metadata only — no history walk.
1100
+ */
1101
+ private async collectOversizedBlobOidsLocked(
1102
+ limit: number,
1103
+ ): Promise<Set<string>> {
1104
+ const objects = await this.execGitStreaming(
1105
+ [
1106
+ "cat-file",
1107
+ "--batch-all-objects",
1108
+ "--unordered",
1109
+ "--batch-check=%(objectname) %(objecttype) %(objectsize)",
1110
+ ],
1111
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1112
+ );
1113
+ const oids = new Set<string>();
1114
+ for (const line of objects.stdout.split("\n")) {
1115
+ const [oid, type, size] = line.split(" ");
1116
+ if (oid && type === "blob" && Number(size) > limit) {
1117
+ oids.add(oid);
1118
+ }
1119
+ }
1120
+ return oids;
1121
+ }
1122
+
1123
+ /**
1124
+ * Classify the given oversized blobs for compaction:
1125
+ * - "rewrite": at least one is reachable from main at a non-exempt path —
1126
+ * only a history rewrite removes it.
1127
+ * - "prunable": none require a rewrite, but at least one is referenced by
1128
+ * no ref at all — reflog expiry + gc reclaims it without touching
1129
+ * history (no hash changes, no orphaned notes).
1130
+ * - "none": everything is exempt canonical state (conversation disk
1131
+ * views) or retained by non-main refs that rewriting main can never
1132
+ * free — nothing to do and nothing to retry.
1133
+ */
1134
+ private async classifyOversizedBlobsLocked(
1135
+ oversized: Set<string>,
1136
+ ): Promise<"none" | "prunable" | "rewrite"> {
1137
+ if (oversized.size === 0) {
1138
+ return "none";
1139
+ }
1140
+ // Lines are "<oid>" for commits and "<oid> <path>" for trees/blobs.
1141
+ const fromMain = await this.execGitStreaming(
1142
+ ["rev-list", "--objects", "main"],
1143
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1144
+ );
1145
+ const remaining = new Set(oversized);
1146
+ for (const line of fromMain.stdout.split("\n")) {
1147
+ if (!line) {
1148
+ continue;
1149
+ }
1150
+ const spaceIdx = line.indexOf(" ");
1151
+ const oid = spaceIdx === -1 ? line : line.substring(0, spaceIdx);
1152
+ if (!remaining.has(oid)) {
1153
+ continue;
1154
+ }
1155
+ const path = spaceIdx === -1 ? "" : line.substring(spaceIdx + 1);
1156
+ if (isSizeGuardExempt(path)) {
1157
+ remaining.delete(oid);
1158
+ } else {
1159
+ return "rewrite";
1160
+ }
1161
+ }
1162
+ if (remaining.size === 0) {
1163
+ return "none";
1164
+ }
1165
+ // Drop blobs retained by any other ref — gc keeps them regardless of
1166
+ // what happens to main. Whatever is left is truly unreferenced, hence
1167
+ // prunable.
1168
+ const fromAll = await this.execGitStreaming(
1169
+ ["rev-list", "--objects", "--all"],
1170
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1171
+ );
1172
+ for (const line of fromAll.stdout.split("\n")) {
1173
+ const spaceIdx = line.indexOf(" ");
1174
+ remaining.delete(spaceIdx === -1 ? line : line.substring(0, spaceIdx));
1175
+ }
1176
+ return remaining.size > 0 ? "prunable" : "none";
1177
+ }
1178
+
1179
+ private async compactHistoryLocked(): Promise<{
1180
+ rewrote: boolean;
1181
+ squashedCommits: number;
1182
+ keptCommits: number;
1183
+ retryAfterMs?: number;
1184
+ }> {
1185
+ const noop = { rewrote: false, squashedCommits: 0, keptCommits: 0 };
1186
+ const limit = this.maxFileSizeBytes();
1187
+
1188
+ // Any oversized blobs at all? Bounds the cost of every boot where there
1189
+ // is nothing to do.
1190
+ const oversizedOids = await this.collectOversizedBlobOidsLocked(limit);
1191
+ if (oversizedOids.size === 0) {
1192
+ return noop;
1193
+ }
1194
+
1195
+ // Only rewrite linear main history from its tip.
1196
+ const head = await this.execGit(["symbolic-ref", "--short", "HEAD"]);
1197
+ if (head.stdout.trim() !== "main") {
1198
+ return noop;
1199
+ }
1200
+
1201
+ // %x1f field / %x1e record separators — %B is the raw multi-line body.
1202
+ const logOut = await this.execGitStreaming(
1203
+ [
1204
+ "log",
1205
+ "--first-parent",
1206
+ "--reverse",
1207
+ "--format=%H%x1f%T%x1f%ct%x1f%an%x1f%ae%x1f%aD%x1f%cn%x1f%ce%x1f%cD%x1f%B%x1e",
1208
+ "main",
1209
+ ],
1210
+ { timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
1211
+ );
1212
+ const commits = logOut.stdout
1213
+ .split("\x1e")
1214
+ .map((record) => record.replace(/^\n/, ""))
1215
+ .filter((record) => record.includes("\x1f"))
1216
+ .map((record) => {
1217
+ const f = record.split("\x1f");
1218
+ return {
1219
+ sha: f[0] ?? "",
1220
+ tree: f[1] ?? "",
1221
+ committedAtSec: Number(f[2] ?? "0"),
1222
+ authorName: f[3] ?? "",
1223
+ authorEmail: f[4] ?? "",
1224
+ authorDate: f[5] ?? "",
1225
+ committerName: f[6] ?? "",
1226
+ committerEmail: f[7] ?? "",
1227
+ committerDate: f[8] ?? "",
1228
+ body: f[9] ?? "",
1229
+ };
1230
+ });
1231
+ if (commits.length === 0) {
1232
+ return noop;
1233
+ }
1234
+
1235
+ const verdict = await this.classifyOversizedBlobsLocked(oversizedOids);
1236
+ if (verdict === "none") {
1237
+ // Exempt canonical state or ref-retained only — nothing to reclaim.
1238
+ return { ...noop, keptCommits: commits.length };
1239
+ }
1240
+ if (verdict === "prunable") {
1241
+ // Only unreachable blobs (e.g. an external add that stageAllLocked
1242
+ // reset) — prune reclaims them without rewriting any history.
1243
+ await this.expireReflogsAndPruneLocked();
1244
+ log.info(
1245
+ { workspaceDir: this.workspaceDir },
1246
+ "Pruned unreachable oversized blobs from workspace git",
1247
+ );
1248
+ return { ...noop, keptCommits: commits.length };
1249
+ }
1250
+
1251
+ // Squash a PREFIX of the chain so replay order stays consistent even if
1252
+ // commit timestamps are not monotonic.
1253
+ const cutoffSec =
1254
+ Math.floor(Date.now() / 1000) - HISTORY_RETENTION_DAYS * 86400;
1255
+ let splitIdx = commits.findIndex((c) => c.committedAtSec >= cutoffSec);
1256
+ if (splitIdx === -1) {
1257
+ splitIdx = commits.length;
1258
+ }
1259
+ if (splitIdx === 0) {
1260
+ // Main holds the blobs, but only in commits still within retention.
1261
+ // A mixed case can also carry unreachable blobs — prune those now,
1262
+ // and re-check in case they were all that remained actionable.
1263
+ await this.expireReflogsAndPruneLocked();
1264
+ const afterPrune = await this.collectOversizedBlobOidsLocked(limit);
1265
+ if ((await this.classifyOversizedBlobsLocked(afterPrune)) === "none") {
1266
+ log.info(
1267
+ { workspaceDir: this.workspaceDir },
1268
+ "Pruned unreachable oversized blobs from workspace git",
1269
+ );
1270
+ return { ...noop, keptCommits: commits.length };
1271
+ }
1272
+
1273
+ // Report when the oldest commit ages past the cutoff so the caller
1274
+ // can retry then — otherwise a long-running daemon would keep the
1275
+ // bloat until restart.
1276
+ const oldestCommittedAtSec = commits[0]?.committedAtSec ?? cutoffSec;
1277
+ const oldestAgesOutMs =
1278
+ (oldestCommittedAtSec + HISTORY_RETENTION_DAYS * 86400) * 1000 -
1279
+ Date.now() +
1280
+ 60_000;
1281
+ const retryAfterMs = Math.max(
1282
+ oldestAgesOutMs,
1283
+ HISTORY_COMPACTION_MIN_RETRY_MS,
1284
+ );
1285
+ log.debug(
1286
+ { workspaceDir: this.workspaceDir, retryAfterMs },
1287
+ "Oversized blobs present but all history is within retention",
1288
+ );
1289
+ return { ...noop, keptCommits: commits.length, retryAfterMs };
1290
+ }
1291
+
1292
+ const kept = commits.slice(splitIdx);
1293
+ const boundary = commits[splitIdx - 1];
1294
+ if (!boundary) {
1295
+ return noop;
1296
+ }
1297
+ const identityEnv = (c: (typeof commits)[number]) => ({
1298
+ GIT_AUTHOR_NAME: c.authorName || DEFAULT_GIT_NAME,
1299
+ GIT_AUTHOR_EMAIL: c.authorEmail || DEFAULT_GIT_EMAIL,
1300
+ GIT_AUTHOR_DATE: c.authorDate,
1301
+ GIT_COMMITTER_NAME: c.committerName || DEFAULT_GIT_NAME,
1302
+ GIT_COMMITTER_EMAIL: c.committerEmail || DEFAULT_GIT_EMAIL,
1303
+ GIT_COMMITTER_DATE: c.committerDate,
1304
+ });
1305
+
1306
+ const baseTree = await this.scrubTreeLocked(boundary.tree, limit);
1307
+ let newHead = (
1308
+ await this.execGit(
1309
+ [
1310
+ "commit-tree",
1311
+ baseTree,
1312
+ "-m",
1313
+ `Compacted workspace history (${splitIdx} commits squashed)`,
1314
+ ],
1315
+ { env: identityEnv(boundary) },
1316
+ )
1317
+ ).stdout.trim();
1318
+ for (const c of kept) {
1319
+ newHead = (
1320
+ await this.execGit(
1321
+ [
1322
+ "commit-tree",
1323
+ c.tree,
1324
+ "-p",
1325
+ newHead,
1326
+ "-m",
1327
+ c.body.trim() || "(no message)",
1328
+ ],
1329
+ { env: identityEnv(c) },
1330
+ )
1331
+ ).stdout.trim();
1332
+ }
1333
+
1334
+ // Compare-and-swap against the tip we read, in case an external git
1335
+ // process moved main while we rewrote.
1336
+ const oldHead = commits[commits.length - 1]?.sha ?? "";
1337
+ await this.execGit([
1338
+ "-c",
1339
+ "core.hooksPath=/dev/null",
1340
+ "update-ref",
1341
+ "refs/heads/main",
1342
+ newHead,
1343
+ oldHead,
1344
+ ]);
1345
+ await this.expireReflogsAndPruneLocked();
1346
+
1347
+ // Blobs referenced by a replayed kept commit survive the prune (the
1348
+ // common case: a large file untracked only days ago). Request a retry
1349
+ // for when the oldest kept commit ages past retention, so they are
1350
+ // reclaimed without waiting for a daemon restart.
1351
+ let retryAfterMs: number | undefined;
1352
+ const afterGc = await this.collectOversizedBlobOidsLocked(limit);
1353
+ if ((await this.classifyOversizedBlobsLocked(afterGc)) !== "none") {
1354
+ const oldestKeptSec =
1355
+ kept[0]?.committedAtSec ?? Math.floor(Date.now() / 1000);
1356
+ retryAfterMs = Math.max(
1357
+ (oldestKeptSec + HISTORY_RETENTION_DAYS * 86400) * 1000 -
1358
+ Date.now() +
1359
+ 60_000,
1360
+ HISTORY_COMPACTION_MIN_RETRY_MS,
1361
+ );
1362
+ }
1363
+
1364
+ log.info(
1365
+ {
1366
+ workspaceDir: this.workspaceDir,
1367
+ squashedCommits: splitIdx,
1368
+ keptCommits: kept.length,
1369
+ maxFileSizeBytes: limit,
1370
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
1371
+ },
1372
+ "Compacted workspace git history",
1373
+ );
1374
+ return {
1375
+ rewrote: true,
1376
+ squashedCommits: splitIdx,
1377
+ keptCommits: kept.length,
1378
+ retryAfterMs,
1379
+ };
1380
+ }
1381
+
1382
+ /**
1383
+ * Return a copy of `tree` with entries whose blob size exceeds the limit
1384
+ * removed, built in a temporary index so the real index is untouched.
1385
+ * Returns the original tree when nothing in it is oversized.
1386
+ */
1387
+ private async scrubTreeLocked(tree: string, limit: number): Promise<string> {
1388
+ const listing = await this.execGitStreaming(
1389
+ ["ls-tree", "-r", "-l", "-z", tree],
1390
+ {
1391
+ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS,
1392
+ },
1393
+ );
1394
+ const oversizedPaths: string[] = [];
1395
+ for (const entry of listing.stdout.split("\0")) {
1396
+ const tab = entry.indexOf("\t");
1397
+ if (tab < 0) {
1398
+ continue;
1399
+ }
1400
+ // "<mode> <type> <oid> <size>\t<path>" — size is right-aligned.
1401
+ const meta = entry.substring(0, tab).trim().split(/\s+/);
1402
+ const path = entry.substring(tab + 1);
1403
+ if (
1404
+ meta[1] === "blob" &&
1405
+ Number(meta[3]) > limit &&
1406
+ !isSizeGuardExempt(path)
1407
+ ) {
1408
+ oversizedPaths.push(path);
1409
+ }
1410
+ }
1411
+ if (oversizedPaths.length === 0) {
1412
+ return tree;
1413
+ }
1414
+
1415
+ const tmpIndex = join(this.workspaceDir, ".git", "vellum-compact-index");
1416
+ const env = { GIT_INDEX_FILE: tmpIndex };
1417
+ try {
1418
+ await this.execGit(["read-tree", tree], { env });
1419
+ await this.execGitStreaming(
1420
+ [
1421
+ "rm",
1422
+ "--cached",
1423
+ "-q",
1424
+ "--ignore-unmatch",
1425
+ "--pathspec-from-file=-",
1426
+ "--pathspec-file-nul",
1427
+ ],
1428
+ { input: oversizedPaths.map((p) => `:(literal)${p}`).join("\0"), env },
1429
+ );
1430
+ return (await this.execGit(["write-tree"], { env })).stdout.trim();
1431
+ } finally {
1432
+ try {
1433
+ unlinkSync(tmpIndex);
1434
+ } catch {
1435
+ // Never created, or already gone.
1436
+ }
1437
+ }
1438
+ }
1439
+
1440
+ /**
1441
+ * Stage all workspace changes except files whose working-tree size exceeds
1442
+ * workspaceGit.maxFileSizeBytes. Oversized files stay on disk untouched —
1443
+ * they just never enter workspace history. Deletions always stage (they
1444
+ * shrink the repo). Must be called with the lock held.
1445
+ *
1446
+ * Oversized paths are excluded from the add pathspec up front so git never
1447
+ * hashes their blobs: an `add` of a multi-GB artifact would be slow enough
1448
+ * to trip interactiveGitTimeoutMs and would bloat .git/objects even if the
1449
+ * file were unstaged afterwards. A post-add scan then unstages any
1450
+ * oversized blob that reached the index anyway (e.g. staged by an external
1451
+ * `git add` before this ran).
1452
+ */
1453
+ private async stageAllLocked(): Promise<void> {
1454
+ // Streamed: output scales with the number of changed files.
1455
+ const changed = await this.execGitStreaming([
1456
+ "status",
1457
+ "--porcelain",
1458
+ "--untracked-files=all",
1459
+ "-z",
1460
+ ]);
1461
+ const oversized = new Set<string>();
1462
+ for (const { path } of parsePorcelainZ(changed.stdout)) {
1463
+ if (this.isOversized(path)) {
1464
+ oversized.add(path);
1465
+ }
1466
+ }
1467
+
1468
+ if (oversized.size === 0) {
1469
+ await this.execGit(["add", "-A"]);
1470
+ } else {
1471
+ // Pathspecs via stdin to stay clear of OS argv limits; literal magic
1472
+ // so filenames containing glob characters are not pattern-matched.
1473
+ const pathspecs = [
1474
+ ".",
1475
+ ...[...oversized].map((p) => `:(exclude,literal)${p}`),
1476
+ ];
1477
+ await this.execGitStreaming(
1478
+ ["add", "-A", "--pathspec-from-file=-", "--pathspec-file-nul"],
1479
+ { input: pathspecs.join("\0") },
1480
+ );
1481
+ }
1482
+
1483
+ const base = await this.resolveStagedDiffBaseLocked();
1484
+ // Everything but deletions — T covers a tracked symlink/submodule
1485
+ // replaced by a staged regular file, which ACMR alone would miss.
1486
+ const staged = await this.execGitStreaming([
1487
+ "diff",
1488
+ "--cached",
1489
+ "--name-only",
1490
+ "-z",
1491
+ "--diff-filter=ACMRT",
1492
+ base,
1493
+ ]);
1494
+ const stagedOversized = staged.stdout
1495
+ .split("\0")
1496
+ .filter((p) => p.length > 0 && this.isOversized(p));
1497
+
1498
+ if (stagedOversized.length > 0) {
1499
+ // Literal pathspecs via stdin, mirroring the add above: a filename
1500
+ // containing glob characters must not unstage other matching paths.
1501
+ await this.execGitStreaming(
1502
+ ["reset", "-q", base, "--pathspec-from-file=-", "--pathspec-file-nul"],
1503
+ { input: stagedOversized.map((p) => `:(literal)${p}`).join("\0") },
1504
+ );
1505
+ // The external add already hashed these blobs into .git/objects; a
1506
+ // compaction pass prunes them even if the boot-time one already ran.
1507
+ this.scheduleHistoryCompaction();
1508
+ }
1509
+
1510
+ const excluded = [...new Set([...oversized, ...stagedOversized])];
1511
+ const newlyWarned = excluded.filter(
1512
+ (p) => !this.warnedOversizedPaths.has(p),
1513
+ );
1514
+ if (newlyWarned.length > 0) {
1515
+ for (const p of newlyWarned) {
1516
+ this.warnedOversizedPaths.add(p);
1517
+ }
1518
+ log.warn(
1519
+ {
1520
+ workspaceDir: this.workspaceDir,
1521
+ files: newlyWarned,
1522
+ maxFileSizeBytes: this.maxFileSizeBytes(),
1523
+ },
1524
+ "Excluded oversized files from workspace commit",
1525
+ );
1526
+ }
1527
+ }
1528
+
748
1529
  /**
749
1530
  * Ensure .gitignore contains all required workspace exclusion rules.
750
1531
  * Idempotent: checks for missing rules and only appends what's needed.
@@ -766,18 +1547,38 @@ export class WorkspaceGitService {
766
1547
  }
767
1548
  }
768
1549
 
1550
+ // Exact line matching: a substring check would let an existing rule like
1551
+ // "plugins/*/node_modules/" mask the broader "node_modules/" rule.
1552
+ const existingLines = new Set(
1553
+ content.split("\n").map((line) => line.trim()),
1554
+ );
769
1555
  const missingRules = WORKSPACE_GITIGNORE_RULES.filter(
770
- (rule) => !content.includes(rule),
1556
+ (rule) => !existingLines.has(rule),
771
1557
  );
772
1558
  if (hadLegacyDataRule || missingRules.length > 0) {
773
1559
  let updated = content;
774
1560
  if (missingRules.length > 0) {
1561
+ // Negation rules must trail every Vellum rule (last matching
1562
+ // pattern wins), so pull existing ones out and re-append them
1563
+ // after the additions instead of leaving them mid-file.
1564
+ const negationRules = WORKSPACE_GITIGNORE_RULES.filter((rule) =>
1565
+ rule.startsWith("!"),
1566
+ );
1567
+ const negationSet = new Set(negationRules);
1568
+ updated = updated
1569
+ .split("\n")
1570
+ .filter((line) => !negationSet.has(line.trim()))
1571
+ .join("\n");
775
1572
  if (!updated.endsWith("\n")) {
776
1573
  updated += "\n";
777
1574
  }
1575
+ const additions = [
1576
+ ...missingRules.filter((rule) => !rule.startsWith("!")),
1577
+ ...negationRules,
1578
+ ];
778
1579
  updated +=
779
1580
  "# Vellum runtime state (auto-added)\n" +
780
- missingRules.join("\n") +
1581
+ additions.join("\n") +
781
1582
  "\n";
782
1583
  }
783
1584
  writeFileSync(gitignorePath, updated, "utf-8");
@@ -791,15 +1592,75 @@ export class WorkspaceGitService {
791
1592
  }
792
1593
  }
793
1594
 
1595
+ /**
1596
+ * Drop tracked files matched by the Vellum-managed ignore rules from the
1597
+ * index (working tree untouched). Ignore rules only affect untracked
1598
+ * paths, so committed runtime state (e.g. embedding-models/) stays in the
1599
+ * index — and churns every commit — until explicitly removed here. The
1600
+ * staged deletions ride along with the next commit. Best-effort: failures
1601
+ * are logged, never block init. Must be called with the mutex lock held.
1602
+ *
1603
+ * Deliberately matches against the Vellum-managed rules only — not the
1604
+ * workspace .gitignore (which may carry user-authored rules whose matches
1605
+ * are force-added on purpose) and not --exclude-standard (the user's
1606
+ * global/local exclude files). The rules are passed via a temp file under
1607
+ * .git so gitignore semantics, including negation order, are preserved.
1608
+ */
1609
+ private async untrackIgnoredFilesLocked(): Promise<void> {
1610
+ const rulesPath = join(this.workspaceDir, ".git", "vellum-untrack-rules");
1611
+ try {
1612
+ writeFileSync(
1613
+ rulesPath,
1614
+ WORKSPACE_GITIGNORE_RULES.join("\n") + "\n",
1615
+ "utf-8",
1616
+ );
1617
+ const { stdout } = await this.execGitStreaming([
1618
+ "ls-files",
1619
+ "-z",
1620
+ "--cached",
1621
+ "--ignored",
1622
+ `--exclude-from=${rulesPath}`,
1623
+ ]);
1624
+ const files = stdout.split("\0").filter(Boolean);
1625
+ if (files.length === 0) {
1626
+ return;
1627
+ }
1628
+ // Chunked to stay under OS argv limits on bloated workspaces.
1629
+ const chunkSize = 200;
1630
+ for (let i = 0; i < files.length; i += chunkSize) {
1631
+ await this.execGit([
1632
+ "rm",
1633
+ "--cached",
1634
+ "-r",
1635
+ "-q",
1636
+ "--ignore-unmatch",
1637
+ "--",
1638
+ ...files.slice(i, i + chunkSize),
1639
+ ]);
1640
+ }
1641
+ log.info(
1642
+ { fileCount: files.length },
1643
+ "Untracked newly ignored files from workspace index",
1644
+ );
1645
+ } catch (err) {
1646
+ log.warn({ err }, "Failed to untrack newly ignored files");
1647
+ } finally {
1648
+ try {
1649
+ unlinkSync(rulesPath);
1650
+ } catch {
1651
+ // Never created, or already gone.
1652
+ }
1653
+ }
1654
+ }
1655
+
794
1656
  /**
795
1657
  * Ensure local git identity is configured for automated commits.
796
1658
  * Idempotent: git config set is a no-op if the value is already correct.
797
1659
  * Must be called with the mutex lock held.
798
1660
  */
799
1661
  private async ensureCommitIdentityLocked(): Promise<void> {
800
- const gitName = process.env.ASSISTANT_GIT_USER_NAME || "Vellum Assistant";
801
- const gitEmail =
802
- process.env.ASSISTANT_GIT_USER_EMAIL || "assistant@vellum.ai";
1662
+ const gitName = process.env.ASSISTANT_GIT_USER_NAME || DEFAULT_GIT_NAME;
1663
+ const gitEmail = process.env.ASSISTANT_GIT_USER_EMAIL || DEFAULT_GIT_EMAIL;
803
1664
  await this.execGit(["config", "user.name", gitName]);
804
1665
  await this.execGit(["config", "user.email", gitEmail]);
805
1666
  }
@@ -891,16 +1752,23 @@ export class WorkspaceGitService {
891
1752
  */
892
1753
  private async execGit(
893
1754
  args: string[],
894
- options?: { signal?: AbortSignal },
1755
+ options?: {
1756
+ signal?: AbortSignal;
1757
+ timeoutMs?: number;
1758
+ env?: Record<string, string>;
1759
+ },
895
1760
  ): Promise<{ stdout: string; stderr: string }> {
896
1761
  const config = getConfig();
897
- const timeoutMs = config.workspaceGit?.interactiveGitTimeoutMs ?? 10_000;
1762
+ const timeoutMs =
1763
+ options?.timeoutMs ??
1764
+ config.workspaceGit?.interactiveGitTimeoutMs ??
1765
+ 10_000;
898
1766
  try {
899
1767
  const { stdout, stderr } = await execFileAsync("git", args, {
900
1768
  cwd: this.workspaceDir,
901
1769
  encoding: "utf-8",
902
1770
  timeout: timeoutMs,
903
- env: cleanGitEnv(this.workspaceDir),
1771
+ env: { ...cleanGitEnv(this.workspaceDir), ...options?.env },
904
1772
  signal: options?.signal,
905
1773
  });
906
1774
  return { stdout, stderr };
@@ -925,20 +1793,35 @@ export class WorkspaceGitService {
925
1793
  * workspace) cannot fail with `ERR_CHILD_PROCESS_STDIO_MAXBUFFER`. Used for
926
1794
  * read paths where output is unbounded; errors are enhanced identically to
927
1795
  * {@link execGit} so callers can still distinguish timeouts and permissions.
1796
+ * `options.input` is written to the child's stdin, which is closed either
1797
+ * way so commands reading stdin to EOF (`--pathspec-from-file=-`) terminate.
928
1798
  */
929
1799
  private execGitStreaming(
930
1800
  args: string[],
931
- options?: { signal?: AbortSignal },
1801
+ options?: {
1802
+ signal?: AbortSignal;
1803
+ input?: string;
1804
+ timeoutMs?: number;
1805
+ env?: Record<string, string>;
1806
+ },
932
1807
  ): Promise<{ stdout: string; stderr: string }> {
933
1808
  const config = getConfig();
934
- const timeoutMs = config.workspaceGit?.interactiveGitTimeoutMs ?? 10_000;
1809
+ const timeoutMs =
1810
+ options?.timeoutMs ??
1811
+ config.workspaceGit?.interactiveGitTimeoutMs ??
1812
+ 10_000;
935
1813
  return new Promise((resolve, reject) => {
936
1814
  const child = spawn("git", args, {
937
1815
  cwd: this.workspaceDir,
938
- env: cleanGitEnv(this.workspaceDir),
1816
+ env: { ...cleanGitEnv(this.workspaceDir), ...options?.env },
939
1817
  signal: options?.signal,
940
1818
  });
941
1819
 
1820
+ // Swallow EPIPE from a child that exits without reading stdin; the
1821
+ // failure still surfaces through the close/error handlers below.
1822
+ child.stdin?.on("error", () => {});
1823
+ child.stdin?.end(options?.input ?? "");
1824
+
942
1825
  const stdoutChunks: Buffer[] = [];
943
1826
  const stderrChunks: Buffer[] = [];
944
1827
  let timedOut = false;
@@ -1233,3 +2116,15 @@ export function _getInitConsecutiveFailures(
1233
2116
  return (service as unknown as { initConsecutiveFailures: number })
1234
2117
  .initConsecutiveFailures;
1235
2118
  }
2119
+
2120
+ /**
2121
+ * @internal Test-only: whether a history compaction run is pending
2122
+ */
2123
+ export function _hasPendingHistoryCompaction(
2124
+ service: WorkspaceGitService,
2125
+ ): boolean {
2126
+ return (
2127
+ (service as unknown as { historyCompactionTimer: unknown })
2128
+ .historyCompactionTimer !== null
2129
+ );
2130
+ }