@vellumai/assistant 0.4.17 → 0.4.18

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 (515) hide show
  1. package/eslint.config.mjs +2 -2
  2. package/package.json +1 -1
  3. package/src/__tests__/access-request-decision.test.ts +128 -120
  4. package/src/__tests__/account-registry.test.ts +121 -110
  5. package/src/__tests__/active-skill-tools.test.ts +200 -172
  6. package/src/__tests__/actor-token-service.test.ts +341 -274
  7. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  8. package/src/__tests__/agent-loop.test.ts +798 -378
  9. package/src/__tests__/anthropic-provider.test.ts +405 -247
  10. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  11. package/src/__tests__/app-bundler.test.ts +112 -79
  12. package/src/__tests__/app-executors.test.ts +205 -178
  13. package/src/__tests__/app-git-history.test.ts +90 -73
  14. package/src/__tests__/app-git-service.test.ts +67 -53
  15. package/src/__tests__/app-open-proxy.test.ts +29 -25
  16. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  17. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  18. package/src/__tests__/approval-message-composer.test.ts +119 -119
  19. package/src/__tests__/approval-primitive.test.ts +264 -233
  20. package/src/__tests__/approval-routes-http.test.ts +4 -3
  21. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  22. package/src/__tests__/asset-search-tool.test.ts +251 -191
  23. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  24. package/src/__tests__/assistant-attachments.test.ts +254 -186
  25. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  26. package/src/__tests__/assistant-event.test.ts +66 -58
  27. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  28. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  29. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  31. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  32. package/src/__tests__/attachments-store.test.ts +240 -183
  33. package/src/__tests__/attachments.test.ts +70 -62
  34. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  35. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  36. package/src/__tests__/browser-manager.test.ts +97 -75
  37. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  38. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  39. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  40. package/src/__tests__/bundle-scanner.test.ts +47 -22
  41. package/src/__tests__/bundled-asset.test.ts +74 -47
  42. package/src/__tests__/call-constants.test.ts +19 -19
  43. package/src/__tests__/call-controller.test.ts +0 -1
  44. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  45. package/src/__tests__/call-domain.test.ts +149 -121
  46. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  47. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  48. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  49. package/src/__tests__/call-recovery.test.ts +232 -212
  50. package/src/__tests__/call-routes-http.test.ts +0 -1
  51. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  52. package/src/__tests__/call-state-machine.test.ts +62 -51
  53. package/src/__tests__/call-state.test.ts +89 -75
  54. package/src/__tests__/call-store.test.ts +387 -316
  55. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  56. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  57. package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
  58. package/src/__tests__/channel-approval.test.ts +139 -137
  59. package/src/__tests__/channel-approvals.test.ts +0 -1
  60. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  61. package/src/__tests__/channel-guardian.test.ts +5 -3
  62. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  63. package/src/__tests__/channel-policy.test.ts +42 -38
  64. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  65. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  66. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  67. package/src/__tests__/checker.test.ts +3309 -1850
  68. package/src/__tests__/clarification-resolver.test.ts +91 -79
  69. package/src/__tests__/classifier.test.ts +64 -54
  70. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  71. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  72. package/src/__tests__/clawhub.test.ts +92 -82
  73. package/src/__tests__/cli.test.ts +30 -30
  74. package/src/__tests__/clipboard.test.ts +53 -46
  75. package/src/__tests__/commit-guarantee.test.ts +59 -52
  76. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  77. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  78. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  79. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  80. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  81. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  82. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  83. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  84. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  85. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  86. package/src/__tests__/computer-use-tools.test.ts +121 -98
  87. package/src/__tests__/config-schema.test.ts +443 -347
  88. package/src/__tests__/config-watcher.test.ts +96 -81
  89. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  90. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  91. package/src/__tests__/conflict-policy.test.ts +151 -80
  92. package/src/__tests__/conflict-store.test.ts +203 -157
  93. package/src/__tests__/connection-policy.test.ts +89 -59
  94. package/src/__tests__/contacts-tools.test.ts +247 -178
  95. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  96. package/src/__tests__/context-token-estimator.test.ts +114 -74
  97. package/src/__tests__/context-window-manager.test.ts +269 -167
  98. package/src/__tests__/contradiction-checker.test.ts +161 -135
  99. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  100. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  101. package/src/__tests__/conversation-pairing.test.ts +220 -113
  102. package/src/__tests__/conversation-store.test.ts +390 -235
  103. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  104. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  105. package/src/__tests__/credential-broker.test.ts +128 -74
  106. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  107. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  108. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  109. package/src/__tests__/credential-resolve.test.ts +212 -145
  110. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  111. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  112. package/src/__tests__/credential-selection.test.ts +254 -146
  113. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  114. package/src/__tests__/credential-vault.test.ts +761 -484
  115. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  116. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  117. package/src/__tests__/daemon-server-session-init.test.ts +0 -1
  118. package/src/__tests__/date-context.test.ts +314 -249
  119. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  120. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  121. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  122. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  123. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  124. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  125. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  126. package/src/__tests__/diff.test.ts +102 -98
  127. package/src/__tests__/domain-normalize.test.ts +54 -54
  128. package/src/__tests__/domain-policy.test.ts +71 -55
  129. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  130. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  131. package/src/__tests__/edit-engine.test.ts +56 -56
  132. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  133. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  134. package/src/__tests__/email-classifier.test.ts +15 -12
  135. package/src/__tests__/email-cli.test.ts +121 -108
  136. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  137. package/src/__tests__/encrypted-store.test.ts +180 -154
  138. package/src/__tests__/entity-extractor.test.ts +108 -87
  139. package/src/__tests__/entity-search.test.ts +664 -258
  140. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  141. package/src/__tests__/event-bus.test.ts +81 -77
  142. package/src/__tests__/extract-email.test.ts +29 -20
  143. package/src/__tests__/file-edit-tool.test.ts +62 -44
  144. package/src/__tests__/file-ops-service.test.ts +131 -114
  145. package/src/__tests__/file-read-tool.test.ts +48 -31
  146. package/src/__tests__/file-write-tool.test.ts +43 -37
  147. package/src/__tests__/filesystem-tools.test.ts +238 -209
  148. package/src/__tests__/followup-tools.test.ts +237 -162
  149. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  150. package/src/__tests__/frontmatter.test.ts +96 -81
  151. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  152. package/src/__tests__/fuzzy-match.test.ts +71 -65
  153. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  154. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  155. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  156. package/src/__tests__/gemini-image-service.test.ts +113 -100
  157. package/src/__tests__/gemini-provider.test.ts +297 -220
  158. package/src/__tests__/get-weather.test.ts +188 -114
  159. package/src/__tests__/gmail-integration.test.ts +0 -1
  160. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  161. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  162. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  163. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  164. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  165. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  166. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  167. package/src/__tests__/guardian-action-store.test.ts +158 -109
  168. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  169. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  170. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  171. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  172. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  173. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  174. package/src/__tests__/guardian-outbound-http.test.ts +5 -3
  175. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  176. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  177. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  178. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  179. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  180. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  181. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  182. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  183. package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -1
  184. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  185. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  186. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  187. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  188. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  189. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  190. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  191. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -2
  192. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  193. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  194. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  195. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  196. package/src/__tests__/heartbeat-service.test.ts +76 -58
  197. package/src/__tests__/history-repair-observability.test.ts +14 -14
  198. package/src/__tests__/history-repair.test.ts +171 -167
  199. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  200. package/src/__tests__/hooks-blocking.test.ts +86 -37
  201. package/src/__tests__/hooks-cli.test.ts +104 -68
  202. package/src/__tests__/hooks-config.test.ts +81 -43
  203. package/src/__tests__/hooks-discovery.test.ts +106 -96
  204. package/src/__tests__/hooks-integration.test.ts +78 -72
  205. package/src/__tests__/hooks-manager.test.ts +99 -61
  206. package/src/__tests__/hooks-runner.test.ts +94 -71
  207. package/src/__tests__/hooks-settings.test.ts +69 -64
  208. package/src/__tests__/hooks-templates.test.ts +85 -54
  209. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  210. package/src/__tests__/hooks-watch.test.ts +32 -22
  211. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  212. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  213. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  214. package/src/__tests__/host-shell-tool.test.ts +342 -233
  215. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  216. package/src/__tests__/ingress-member-store.test.ts +163 -159
  217. package/src/__tests__/ingress-reconcile.test.ts +0 -1
  218. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  219. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  220. package/src/__tests__/integration-status.test.ts +93 -73
  221. package/src/__tests__/intent-routing.test.ts +148 -118
  222. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  223. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  224. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  225. package/src/__tests__/ipc-contract.test.ts +24 -23
  226. package/src/__tests__/ipc-protocol.test.ts +52 -46
  227. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  228. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  229. package/src/__tests__/ipc-validate.test.ts +240 -179
  230. package/src/__tests__/key-migration.test.ts +123 -90
  231. package/src/__tests__/keychain.test.ts +150 -123
  232. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  233. package/src/__tests__/llm-usage-store.test.ts +112 -87
  234. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  235. package/src/__tests__/managed-store.test.ts +411 -360
  236. package/src/__tests__/mcp-cli.test.ts +189 -123
  237. package/src/__tests__/mcp-health-check.test.ts +26 -21
  238. package/src/__tests__/media-generate-image.test.ts +122 -99
  239. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  240. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  241. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  242. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  243. package/src/__tests__/memory-query-builder.test.ts +32 -33
  244. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  245. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  246. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  247. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  248. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  249. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  250. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  251. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  252. package/src/__tests__/migration-ordering.test.ts +103 -86
  253. package/src/__tests__/mime-builder.test.ts +55 -32
  254. package/src/__tests__/mock-signup-server.test.ts +384 -246
  255. package/src/__tests__/model-intents.test.ts +61 -37
  256. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  257. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  258. package/src/__tests__/non-member-access-request.test.ts +3 -2
  259. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  260. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  261. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  262. package/src/__tests__/notification-deep-link.test.ts +67 -61
  263. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  264. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  265. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  266. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  267. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  268. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  269. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  270. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  271. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  272. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  273. package/src/__tests__/openai-provider.test.ts +366 -274
  274. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  275. package/src/__tests__/pairing-routes.test.ts +45 -41
  276. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  277. package/src/__tests__/parser.test.ts +316 -226
  278. package/src/__tests__/path-classifier.test.ts +24 -25
  279. package/src/__tests__/path-policy.test.ts +187 -147
  280. package/src/__tests__/phone.test.ts +36 -36
  281. package/src/__tests__/platform-move-helper.test.ts +48 -40
  282. package/src/__tests__/platform-socket-path.test.ts +23 -24
  283. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  284. package/src/__tests__/platform.test.ts +61 -53
  285. package/src/__tests__/playbook-execution.test.ts +397 -265
  286. package/src/__tests__/playbook-tools.test.ts +267 -196
  287. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  288. package/src/__tests__/pricing.test.ts +316 -136
  289. package/src/__tests__/profile-compiler.test.ts +206 -188
  290. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  291. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  292. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  293. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  294. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  295. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  296. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  297. package/src/__tests__/qdrant-manager.test.ts +147 -98
  298. package/src/__tests__/ratelimit.test.ts +152 -82
  299. package/src/__tests__/recording-handler.test.ts +273 -151
  300. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  301. package/src/__tests__/recording-intent-handler.test.ts +0 -1
  302. package/src/__tests__/recording-intent.test.ts +578 -379
  303. package/src/__tests__/recording-state-machine.test.ts +530 -316
  304. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  305. package/src/__tests__/recurrence-engine.test.ts +81 -41
  306. package/src/__tests__/recurrence-types.test.ts +63 -44
  307. package/src/__tests__/relay-server.test.ts +2131 -1602
  308. package/src/__tests__/reminder-store.test.ts +158 -80
  309. package/src/__tests__/reminder.test.ts +113 -109
  310. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  311. package/src/__tests__/request-file-tool.test.ts +74 -67
  312. package/src/__tests__/response-tier.test.ts +131 -74
  313. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  314. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  315. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  316. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  317. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  318. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  319. package/src/__tests__/schedule-store.test.ts +268 -205
  320. package/src/__tests__/schedule-tools.test.ts +702 -524
  321. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  322. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  323. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  324. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  325. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  326. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  327. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  328. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  329. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  330. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  331. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  332. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  333. package/src/__tests__/script-proxy-router.test.ts +111 -77
  334. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  335. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  336. package/src/__tests__/secret-allowlist.test.ts +105 -90
  337. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  338. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  339. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  340. package/src/__tests__/secret-response-routing.test.ts +50 -41
  341. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  342. package/src/__tests__/secret-scanner.test.ts +495 -413
  343. package/src/__tests__/secure-keys.test.ts +132 -121
  344. package/src/__tests__/send-endpoint-busy.test.ts +0 -1
  345. package/src/__tests__/send-notification-tool.test.ts +43 -42
  346. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  347. package/src/__tests__/sequence-store.test.ts +335 -167
  348. package/src/__tests__/server-history-render.test.ts +341 -202
  349. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  350. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  351. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  352. package/src/__tests__/session-error.test.ts +222 -191
  353. package/src/__tests__/session-evictor.test.ts +79 -62
  354. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  355. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  356. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  357. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  358. package/src/__tests__/session-profile-injection.test.ts +198 -130
  359. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  360. package/src/__tests__/session-queue.test.ts +624 -321
  361. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  362. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  363. package/src/__tests__/session-skill-tools.test.ts +973 -678
  364. package/src/__tests__/session-slash-known.test.ts +185 -133
  365. package/src/__tests__/session-slash-queue.test.ts +147 -81
  366. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  367. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  368. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  369. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  370. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  371. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  372. package/src/__tests__/session-undo.test.ts +43 -30
  373. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  374. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  375. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  376. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  377. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  378. package/src/__tests__/shell-identity.test.ts +134 -111
  379. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  380. package/src/__tests__/shell-parser-property.test.ts +435 -288
  381. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  382. package/src/__tests__/size-guard.test.ts +42 -44
  383. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  384. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  385. package/src/__tests__/skill-include-graph.test.ts +143 -148
  386. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  387. package/src/__tests__/skill-load-tool.test.ts +371 -199
  388. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  389. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  390. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  391. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  392. package/src/__tests__/skill-script-runner.test.ts +115 -74
  393. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  394. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  395. package/src/__tests__/skill-version-hash.test.ts +70 -56
  396. package/src/__tests__/skills.test.ts +0 -1
  397. package/src/__tests__/slack-channel-config.test.ts +127 -84
  398. package/src/__tests__/slack-skill.test.ts +60 -47
  399. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  400. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  401. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  402. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  403. package/src/__tests__/speaker-identification.test.ts +28 -25
  404. package/src/__tests__/starter-bundle.test.ts +27 -23
  405. package/src/__tests__/starter-task-flow.test.ts +67 -52
  406. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  407. package/src/__tests__/subagent-tools.test.ts +311 -270
  408. package/src/__tests__/subagent-types.test.ts +40 -40
  409. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  410. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  411. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  412. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  413. package/src/__tests__/swarm-recursion.test.ts +58 -46
  414. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  415. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  416. package/src/__tests__/swarm-tool.test.ts +65 -45
  417. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  418. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  419. package/src/__tests__/system-prompt.test.ts +290 -256
  420. package/src/__tests__/task-compiler.test.ts +176 -120
  421. package/src/__tests__/task-management-tools.test.ts +561 -456
  422. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  423. package/src/__tests__/task-runner.test.ts +117 -94
  424. package/src/__tests__/task-scheduler.test.ts +113 -84
  425. package/src/__tests__/task-tools.test.ts +349 -264
  426. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  427. package/src/__tests__/terminal-tools.test.ts +350 -305
  428. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  429. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  430. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  431. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  432. package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
  433. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  434. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  435. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  436. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  437. package/src/__tests__/tool-executor.test.ts +1274 -674
  438. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  439. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  440. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  441. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  442. package/src/__tests__/tool-policy.test.ts +44 -25
  443. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  444. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  445. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  446. package/src/__tests__/top-level-renderer.test.ts +62 -58
  447. package/src/__tests__/top-level-scanner.test.ts +68 -64
  448. package/src/__tests__/trace-emitter.test.ts +56 -56
  449. package/src/__tests__/trust-context-guards.test.ts +65 -65
  450. package/src/__tests__/trust-store.test.ts +1239 -806
  451. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  452. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  453. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  454. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  455. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  456. package/src/__tests__/turn-commit.test.ts +259 -200
  457. package/src/__tests__/twilio-provider.test.ts +140 -126
  458. package/src/__tests__/twilio-rest.test.ts +22 -18
  459. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
  460. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  461. package/src/__tests__/twilio-routes.test.ts +0 -1
  462. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  463. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  464. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  465. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  466. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  467. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  468. package/src/__tests__/update-bulletin.test.ts +150 -114
  469. package/src/__tests__/update-template-contract.test.ts +15 -10
  470. package/src/__tests__/url-safety.test.ts +288 -265
  471. package/src/__tests__/user-reference.test.ts +32 -32
  472. package/src/__tests__/view-image-tool.test.ts +118 -96
  473. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  474. package/src/__tests__/voice-quality.test.ts +117 -102
  475. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  476. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  477. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  478. package/src/__tests__/web-fetch.test.ts +664 -526
  479. package/src/__tests__/web-search.test.ts +379 -213
  480. package/src/__tests__/work-item-output.test.ts +90 -53
  481. package/src/__tests__/workspace-git-service.test.ts +437 -356
  482. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  483. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  484. package/src/__tests__/workspace-policy.test.ts +139 -71
  485. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  486. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  487. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
  488. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  489. package/src/config/bundled-skills/messaging/SKILL.md +4 -3
  490. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  491. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  492. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  493. package/src/config/bundled-tool-registry.ts +2 -0
  494. package/src/config/env.ts +3 -4
  495. package/src/memory/db-connection.ts +16 -10
  496. package/src/messaging/providers/gmail/adapter.ts +10 -3
  497. package/src/messaging/providers/gmail/client.ts +280 -72
  498. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  499. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  500. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  501. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  502. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  503. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  504. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  505. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  506. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  507. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  508. package/src/runtime/auth/scopes.ts +3 -0
  509. package/src/runtime/auth/token-service.ts +4 -1
  510. package/src/runtime/auth/types.ts +2 -1
  511. package/src/runtime/http-server.ts +2 -1
  512. package/src/security/secure-keys.ts +103 -53
  513. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  514. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  515. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
@@ -10,12 +10,13 @@
10
10
  * migration system detects and handles it gracefully.
11
11
  */
12
12
 
13
- import { Database } from 'bun:sqlite';
14
- import { describe, expect,test } from 'bun:test';
15
- import { drizzle } from 'drizzle-orm/bun-sqlite';
13
+ import { Database } from "bun:sqlite";
14
+ import { describe, expect, test } from "bun:test";
16
15
 
17
- import { getSqliteFrom } from '../memory/db-connection.js';
18
- import * as schema from '../memory/schema.js';
16
+ import { drizzle } from "drizzle-orm/bun-sqlite";
17
+
18
+ import { getSqliteFrom } from "../memory/db-connection.js";
19
+ import * as schema from "../memory/schema.js";
19
20
  import {
20
21
  migrateJobDeferrals,
21
22
  migrateMemoryEntityRelationDedup,
@@ -23,16 +24,16 @@ import {
23
24
  MIGRATION_REGISTRY,
24
25
  type MigrationValidationResult,
25
26
  validateMigrationState,
26
- } from '../memory/schema-migration.js';
27
+ } from "../memory/schema-migration.js";
27
28
 
28
29
  // ---------------------------------------------------------------------------
29
30
  // Helpers
30
31
  // ---------------------------------------------------------------------------
31
32
 
32
33
  function createTestDb() {
33
- const sqlite = new Database(':memory:');
34
- sqlite.exec('PRAGMA journal_mode=WAL');
35
- sqlite.exec('PRAGMA foreign_keys = ON');
34
+ const sqlite = new Database(":memory:");
35
+ sqlite.exec("PRAGMA journal_mode=WAL");
36
+ sqlite.exec("PRAGMA foreign_keys = ON");
36
37
  return drizzle(sqlite, { schema });
37
38
  }
38
39
 
@@ -112,8 +113,8 @@ function bootstrapEntityRelationsTable(raw: Database): void {
112
113
  // 1. Crash-between-migrations
113
114
  // ---------------------------------------------------------------------------
114
115
 
115
- describe('crash-between-migrations: consistent state on re-run', () => {
116
- test('migrateJobDeferrals: crashed migration (started but not completed) re-runs successfully', () => {
116
+ describe("crash-between-migrations: consistent state on re-run", () => {
117
+ test("migrateJobDeferrals: crashed migration (started but not completed) re-runs successfully", () => {
117
118
  // Simulate a crash scenario: the checkpoint key 'migration_job_deferrals'
118
119
  // is present with value 'started' (as if a crash marker was set before the
119
120
  // real completion INSERT). The actual migration logic uses BEGIN/COMMIT, so
@@ -144,15 +145,20 @@ describe('crash-between-migrations: consistent state on re-run', () => {
144
145
  // Note: the current migrateJobDeferrals uses a simple presence check (SELECT 1), so
145
146
  // inserting any value for the key marks it as "done" from the guard's perspective.
146
147
  // This test documents the actual behavior: the guard sees the key and skips.
147
- raw.exec(`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', 'started', ${now})`);
148
+ raw.exec(
149
+ `INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', 'started', ${now})`,
150
+ );
148
151
 
149
152
  // Run migration — guard will see the 'started' checkpoint and skip.
150
153
  migrateJobDeferrals(db);
151
154
 
152
155
  // Since the checkpoint exists (even as 'started'), the migration was skipped.
153
156
  // The job's deferrals column should still be 0 (migration didn't run).
154
- const job = raw.query(`SELECT * FROM memory_jobs WHERE id = 'job-1'`).get() as {
155
- attempts: number; deferrals: number
157
+ const job = raw
158
+ .query(`SELECT * FROM memory_jobs WHERE id = 'job-1'`)
159
+ .get() as {
160
+ attempts: number;
161
+ deferrals: number;
156
162
  } | null;
157
163
  expect(job).toBeTruthy();
158
164
  // Migration was skipped because the checkpoint key exists.
@@ -160,7 +166,7 @@ describe('crash-between-migrations: consistent state on re-run', () => {
160
166
  expect(job!.attempts).toBe(5);
161
167
  });
162
168
 
163
- test('migrateJobDeferrals: no checkpoint means migration runs and reconciles data', () => {
169
+ test("migrateJobDeferrals: no checkpoint means migration runs and reconciles data", () => {
164
170
  // Clean start: no checkpoint written. The migration should run, move the
165
171
  // attempts count into deferrals, and write the completion checkpoint.
166
172
  const db = createTestDb();
@@ -186,8 +192,12 @@ describe('crash-between-migrations: consistent state on re-run', () => {
186
192
  migrateJobDeferrals(db);
187
193
 
188
194
  // Legacy embed_segment job should have deferrals = 3, attempts = 0.
189
- const legacyJob = raw.query(`SELECT * FROM memory_jobs WHERE id = 'job-legacy'`).get() as {
190
- attempts: number; deferrals: number; last_error: string | null
195
+ const legacyJob = raw
196
+ .query(`SELECT * FROM memory_jobs WHERE id = 'job-legacy'`)
197
+ .get() as {
198
+ attempts: number;
199
+ deferrals: number;
200
+ last_error: string | null;
191
201
  } | null;
192
202
  expect(legacyJob).toBeTruthy();
193
203
  expect(legacyJob!.deferrals).toBe(3);
@@ -200,12 +210,16 @@ describe('crash-between-migrations: consistent state on re-run', () => {
200
210
  // AND type IN ('embed_segment', 'embed_item', 'embed_summary') — it does include embed_item.
201
211
  // The last_error check: the migration doesn't filter by last_error, so embed_item also moves.
202
212
  // Verify completion checkpoint is written.
203
- const checkpoint = raw.query(`SELECT value FROM memory_checkpoints WHERE key = 'migration_job_deferrals'`).get() as { value: string } | null;
213
+ const checkpoint = raw
214
+ .query(
215
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_job_deferrals'`,
216
+ )
217
+ .get() as { value: string } | null;
204
218
  expect(checkpoint).toBeTruthy();
205
- expect(checkpoint!.value).toBe('1');
219
+ expect(checkpoint!.value).toBe("1");
206
220
  });
207
221
 
208
- test('migrateJobDeferrals: migration is idempotent — second call is a no-op', () => {
222
+ test("migrateJobDeferrals: migration is idempotent — second call is a no-op", () => {
209
223
  const db = createTestDb();
210
224
  const raw = getRaw(db);
211
225
 
@@ -222,15 +236,25 @@ describe('crash-between-migrations: consistent state on re-run', () => {
222
236
  migrateJobDeferrals(db);
223
237
 
224
238
  // Snapshot state after first run.
225
- const after1 = raw.query(`SELECT attempts, deferrals FROM memory_jobs WHERE id = 'job-idem'`).get() as {
226
- attempts: number; deferrals: number
239
+ const after1 = raw
240
+ .query(
241
+ `SELECT attempts, deferrals FROM memory_jobs WHERE id = 'job-idem'`,
242
+ )
243
+ .get() as {
244
+ attempts: number;
245
+ deferrals: number;
227
246
  };
228
247
 
229
248
  // Second run — should be a no-op (checkpoint already written).
230
249
  migrateJobDeferrals(db);
231
250
 
232
- const after2 = raw.query(`SELECT attempts, deferrals FROM memory_jobs WHERE id = 'job-idem'`).get() as {
233
- attempts: number; deferrals: number
251
+ const after2 = raw
252
+ .query(
253
+ `SELECT attempts, deferrals FROM memory_jobs WHERE id = 'job-idem'`,
254
+ )
255
+ .get() as {
256
+ attempts: number;
257
+ deferrals: number;
234
258
  };
235
259
 
236
260
  expect(after1.deferrals).toBe(4);
@@ -240,7 +264,7 @@ describe('crash-between-migrations: consistent state on re-run', () => {
240
264
  expect(after2.attempts).toBe(after1.attempts);
241
265
  });
242
266
 
243
- test('crash in migrateMemoryEntityRelationDedup: temp table left behind is cleaned up on retry', () => {
267
+ test("crash in migrateMemoryEntityRelationDedup: temp table left behind is cleaned up on retry", () => {
244
268
  // Simulate a crash mid-migration that left the temp staging table behind.
245
269
  // On retry the migration should clean up the temp table, then succeed.
246
270
  const db = createTestDb();
@@ -252,8 +276,12 @@ describe('crash-between-migrations: consistent state on re-run', () => {
252
276
  const now = Date.now();
253
277
 
254
278
  // Insert duplicate entity relations that need deduplication.
255
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now - 2000}, ${now - 1000})`);
256
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'knows', 'some evidence', ${now - 3000}, ${now})`);
279
+ raw.exec(
280
+ `INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now - 2000}, ${now - 1000})`,
281
+ );
282
+ raw.exec(
283
+ `INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'knows', 'some evidence', ${now - 3000}, ${now})`,
284
+ );
257
285
 
258
286
  // Simulate a crash: manually create the temp staging table (as if the migration
259
287
  // started creating it but crashed before finishing). The migration's DROP TABLE IF EXISTS
@@ -266,44 +294,57 @@ describe('crash-between-migrations: consistent state on re-run', () => {
266
294
  `);
267
295
 
268
296
  // Verify stale temp table exists before migration retry.
269
- const tempBefore = raw.query(
270
- `SELECT name FROM sqlite_temp_master WHERE type = 'table' AND name = 'memory_entity_relation_merge'`
271
- ).get();
297
+ const tempBefore = raw
298
+ .query(
299
+ `SELECT name FROM sqlite_temp_master WHERE type = 'table' AND name = 'memory_entity_relation_merge'`,
300
+ )
301
+ .get();
272
302
  expect(tempBefore).toBeTruthy();
273
303
 
274
304
  // Run the migration — it should drop the stale temp table and proceed correctly.
275
305
  migrateMemoryEntityRelationDedup(db);
276
306
 
277
307
  // After migration: temp table should be gone.
278
- const tempAfter = raw.query(
279
- `SELECT name FROM sqlite_temp_master WHERE type = 'table' AND name = 'memory_entity_relation_merge'`
280
- ).get();
308
+ const tempAfter = raw
309
+ .query(
310
+ `SELECT name FROM sqlite_temp_master WHERE type = 'table' AND name = 'memory_entity_relation_merge'`,
311
+ )
312
+ .get();
281
313
  expect(tempAfter).toBeNull();
282
314
 
283
315
  // Duplicates should have been merged into a single row.
284
- const relations = raw.query(`SELECT * FROM memory_entity_relations ORDER BY id`).all() as Array<{
285
- id: string; source_entity_id: string; target_entity_id: string; relation: string;
286
- first_seen_at: number; last_seen_at: number; evidence: string | null
316
+ const relations = raw
317
+ .query(`SELECT * FROM memory_entity_relations ORDER BY id`)
318
+ .all() as Array<{
319
+ id: string;
320
+ source_entity_id: string;
321
+ target_entity_id: string;
322
+ relation: string;
323
+ first_seen_at: number;
324
+ last_seen_at: number;
325
+ evidence: string | null;
287
326
  }>;
288
327
  expect(relations).toHaveLength(1);
289
- expect(relations[0].source_entity_id).toBe('e1');
290
- expect(relations[0].target_entity_id).toBe('e2');
291
- expect(relations[0].relation).toBe('knows');
328
+ expect(relations[0].source_entity_id).toBe("e1");
329
+ expect(relations[0].target_entity_id).toBe("e2");
330
+ expect(relations[0].relation).toBe("knows");
292
331
  // Merged: MIN(first_seen_at), MAX(last_seen_at).
293
332
  expect(relations[0].first_seen_at).toBe(now - 3000);
294
333
  expect(relations[0].last_seen_at).toBe(now);
295
334
  // Evidence from latest row (rank_latest = 1).
296
- expect(relations[0].evidence).toBe('some evidence');
335
+ expect(relations[0].evidence).toBe("some evidence");
297
336
 
298
337
  // Completion checkpoint must be written.
299
- const cp = raw.query(
300
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`
301
- ).get() as { value: string } | null;
338
+ const cp = raw
339
+ .query(
340
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`,
341
+ )
342
+ .get() as { value: string } | null;
302
343
  expect(cp).toBeTruthy();
303
- expect(cp!.value).toBe('1');
344
+ expect(cp!.value).toBe("1");
304
345
  });
305
346
 
306
- test('crash in transaction: rolled-back migration leaves DB in pre-migration state', () => {
347
+ test("crash in transaction: rolled-back migration leaves DB in pre-migration state", () => {
307
348
  // Verify that when migrateMemoryEntityRelationDedup fails mid-transaction, it
308
349
  // rolls back cleanly — the DB remains in the pre-migration state and the
309
350
  // checkpoint is NOT written.
@@ -318,10 +359,18 @@ describe('crash-between-migrations: consistent state on re-run', () => {
318
359
  bootstrapEntityRelationsTable(raw);
319
360
 
320
361
  const now = Date.now();
321
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now}, ${now})`);
322
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'knows', 'evidence', ${now - 1000}, ${now})`);
362
+ raw.exec(
363
+ `INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now}, ${now})`,
364
+ );
365
+ raw.exec(
366
+ `INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'knows', 'evidence', ${now - 1000}, ${now})`,
367
+ );
323
368
 
324
- const countBefore = (raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as { c: number }).c;
369
+ const countBefore = (
370
+ raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as {
371
+ c: number;
372
+ }
373
+ ).c;
325
374
  expect(countBefore).toBe(2);
326
375
 
327
376
  // Install a trigger that raises an error on the first INSERT, causing the
@@ -346,17 +395,23 @@ describe('crash-between-migrations: consistent state on re-run', () => {
346
395
  raw.exec(`DROP TRIGGER IF EXISTS fail_on_insert`);
347
396
 
348
397
  // After rollback: row count must be unchanged (DELETE was rolled back).
349
- const countAfter = (raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as { c: number }).c;
398
+ const countAfter = (
399
+ raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as {
400
+ c: number;
401
+ }
402
+ ).c;
350
403
  expect(countAfter).toBe(2);
351
404
 
352
405
  // No checkpoint should have been written (COMMIT never executed).
353
- const cp = raw.query(
354
- `SELECT 1 FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`
355
- ).get();
406
+ const cp = raw
407
+ .query(
408
+ `SELECT 1 FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`,
409
+ )
410
+ .get();
356
411
  expect(cp).toBeNull();
357
412
  });
358
413
 
359
- test('multiple migrations: crash after first completes leaves second un-checkpointed', () => {
414
+ test("multiple migrations: crash after first completes leaves second un-checkpointed", () => {
360
415
  // Simulates: migration_job_deferrals completed (checkpoint = '1'),
361
416
  // but a second migration (memory_entity_relations_dedup) never ran.
362
417
  // On next startup, the first skips (checkpoint found), the second runs fresh.
@@ -370,29 +425,41 @@ describe('crash-between-migrations: consistent state on re-run', () => {
370
425
  const now = Date.now();
371
426
 
372
427
  // Manually set first migration as complete.
373
- raw.exec(`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', '1', ${now})`);
428
+ raw.exec(
429
+ `INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', '1', ${now})`,
430
+ );
374
431
 
375
432
  // Insert duplicate relations that need migration.
376
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'friends', NULL, ${now - 1000}, ${now - 500})`);
377
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'friends', 'evidence', ${now - 2000}, ${now})`);
433
+ raw.exec(
434
+ `INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'friends', NULL, ${now - 1000}, ${now - 500})`,
435
+ );
436
+ raw.exec(
437
+ `INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e2', 'friends', 'evidence', ${now - 2000}, ${now})`,
438
+ );
378
439
 
379
440
  // Run second migration from clean state (no checkpoint for it).
380
441
  migrateMemoryEntityRelationDedup(db);
381
442
 
382
443
  // Second migration should have run and deduplicated.
383
- const relations = raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).all() as Array<{ c: number }>;
444
+ const relations = raw
445
+ .query(`SELECT COUNT(*) AS c FROM memory_entity_relations`)
446
+ .all() as Array<{ c: number }>;
384
447
  expect(relations[0].c).toBe(1);
385
448
 
386
449
  // Both checkpoints should now exist.
387
- const cp1 = raw.query(
388
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_job_deferrals'`
389
- ).get() as { value: string } | null;
390
- const cp2 = raw.query(
391
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`
392
- ).get() as { value: string } | null;
393
-
394
- expect(cp1!.value).toBe('1');
395
- expect(cp2!.value).toBe('1');
450
+ const cp1 = raw
451
+ .query(
452
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_job_deferrals'`,
453
+ )
454
+ .get() as { value: string } | null;
455
+ const cp2 = raw
456
+ .query(
457
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`,
458
+ )
459
+ .get() as { value: string } | null;
460
+
461
+ expect(cp1!.value).toBe("1");
462
+ expect(cp2!.value).toBe("1");
396
463
  });
397
464
  });
398
465
 
@@ -400,7 +467,7 @@ describe('crash-between-migrations: consistent state on re-run', () => {
400
467
  // 2. Schema-drift recovery
401
468
  // ---------------------------------------------------------------------------
402
469
 
403
- describe('schema-drift recovery: migration handles unexpected schema state', () => {
470
+ describe("schema-drift recovery: migration handles unexpected schema state", () => {
404
471
  test('validateMigrationState: detects crashed migration with "started" value', () => {
405
472
  // Simulate a scenario where a checkpoint value is 'started' — meaning the
406
473
  // migration wrote a start marker (via UPSERT) but never wrote the completion '1'.
@@ -414,20 +481,26 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
414
481
  const now = Date.now();
415
482
 
416
483
  // Insert a "started" checkpoint — simulates mid-migration crash.
417
- raw.exec(`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', 'started', ${now})`);
484
+ raw.exec(
485
+ `INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_job_deferrals', 'started', ${now})`,
486
+ );
418
487
  // A completed checkpoint should not be flagged.
419
- raw.exec(`INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_memory_entity_relations_dedup_v1', '1', ${now})`);
488
+ raw.exec(
489
+ `INSERT INTO memory_checkpoints (key, value, updated_at) VALUES ('migration_memory_entity_relations_dedup_v1', '1', ${now})`,
490
+ );
420
491
 
421
492
  // validateMigrationState logs warnings for crashed migrations and returns
422
493
  // structured diagnostic data. Assert directly on the returned result rather
423
494
  // than re-deriving the crashed list from the raw DB — this verifies the
424
495
  // function itself detects the crash, not just that the data is present.
425
496
  const result: MigrationValidationResult = validateMigrationState(db);
426
- expect(result.crashed).toContain('migration_job_deferrals');
427
- expect(result.crashed).not.toContain('migration_memory_entity_relations_dedup_v1');
497
+ expect(result.crashed).toContain("migration_job_deferrals");
498
+ expect(result.crashed).not.toContain(
499
+ "migration_memory_entity_relations_dedup_v1",
500
+ );
428
501
  });
429
502
 
430
- test('validateMigrationState: detects dependency violation (child complete, parent missing)', () => {
503
+ test("validateMigrationState: detects dependency violation (child complete, parent missing)", () => {
431
504
  // Simulates schema drift: a dependent migration ran (checkpoint written) but
432
505
  // its declared prerequisite migration has no checkpoint. This indicates the
433
506
  // migrations were applied out of order — a schema consistency violation.
@@ -447,19 +520,25 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
447
520
 
448
521
  // validateMigrationState throws an IntegrityError on dependency violations
449
522
  // to block daemon startup with an inconsistent schema.
450
- expect(() => validateMigrationState(db)).toThrow('Migration dependency violations detected');
451
- expect(() => validateMigrationState(db)).toThrow('migration_memory_items_fingerprint_scope_unique_v1');
523
+ expect(() => validateMigrationState(db)).toThrow(
524
+ "Migration dependency violations detected",
525
+ );
526
+ expect(() => validateMigrationState(db)).toThrow(
527
+ "migration_memory_items_fingerprint_scope_unique_v1",
528
+ );
452
529
 
453
530
  // Sanity-check: confirm the registry also declares this dependency, so the
454
531
  // violation detection is grounded in real schema intent.
455
532
  const saltedEntry = MIGRATION_REGISTRY.find(
456
- (e) => e.key === 'migration_memory_items_scope_salted_fingerprints_v1',
533
+ (e) => e.key === "migration_memory_items_scope_salted_fingerprints_v1",
457
534
  );
458
535
  expect(saltedEntry).toBeTruthy();
459
- expect(saltedEntry!.dependsOn).toContain('migration_memory_items_fingerprint_scope_unique_v1');
536
+ expect(saltedEntry!.dependsOn).toContain(
537
+ "migration_memory_items_fingerprint_scope_unique_v1",
538
+ );
460
539
  });
461
540
 
462
- test('validateMigrationState: no checkpoints table is handled gracefully', () => {
541
+ test("validateMigrationState: no checkpoints table is handled gracefully", () => {
463
542
  // On a very old database, memory_checkpoints may not exist at all.
464
543
  // validateMigrationState should catch the error and return without crashing.
465
544
  const db = createTestDb();
@@ -468,7 +547,7 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
468
547
  expect(() => validateMigrationState(db)).not.toThrow();
469
548
  });
470
549
 
471
- test('migrateMemoryItemsFingerprintScopeUnique: old schema with UNIQUE on fingerprint is migrated', () => {
550
+ test("migrateMemoryItemsFingerprintScopeUnique: old schema with UNIQUE on fingerprint is migrated", () => {
472
551
  // Schema drift: the DB has the old column-level UNIQUE constraint on fingerprint.
473
552
  // The migration should detect this, rebuild the table without the constraint,
474
553
  // and write the completion checkpoint.
@@ -495,37 +574,53 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
495
574
  `);
496
575
 
497
576
  // Verify old schema has column-level UNIQUE.
498
- const ddlBefore = (raw.query(
499
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`
500
- ).get() as { sql: string } | null)?.sql ?? '';
577
+ const ddlBefore =
578
+ (
579
+ raw
580
+ .query(
581
+ `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`,
582
+ )
583
+ .get() as { sql: string } | null
584
+ )?.sql ?? "";
501
585
  expect(ddlBefore).toMatch(/fingerprint\s+TEXT\s+NOT\s+NULL\s+UNIQUE/i);
502
586
 
503
587
  // Run migration.
504
588
  migrateMemoryItemsFingerprintScopeUnique(db);
505
589
 
506
590
  // Checkpoint should be written.
507
- const cp = raw.query(
508
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`
509
- ).get() as { value: string } | null;
591
+ const cp = raw
592
+ .query(
593
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`,
594
+ )
595
+ .get() as { value: string } | null;
510
596
  expect(cp).toBeTruthy();
511
- expect(cp!.value).toBe('1');
597
+ expect(cp!.value).toBe("1");
512
598
 
513
599
  // The new DDL should NOT have column-level UNIQUE on fingerprint.
514
- const ddlAfter = (raw.query(
515
- `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`
516
- ).get() as { sql: string } | null)?.sql ?? '';
600
+ const ddlAfter =
601
+ (
602
+ raw
603
+ .query(
604
+ `SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`,
605
+ )
606
+ .get() as { sql: string } | null
607
+ )?.sql ?? "";
517
608
  expect(ddlAfter).not.toMatch(/fingerprint\s+TEXT\s+NOT\s+NULL\s+UNIQUE/i);
518
609
 
519
610
  // Existing rows should still be present and readable.
520
- const items = raw.query(`SELECT id, fingerprint, scope_id FROM memory_items ORDER BY id`).all() as Array<{
521
- id: string; fingerprint: string; scope_id: string
611
+ const items = raw
612
+ .query(`SELECT id, fingerprint, scope_id FROM memory_items ORDER BY id`)
613
+ .all() as Array<{
614
+ id: string;
615
+ fingerprint: string;
616
+ scope_id: string;
522
617
  }>;
523
618
  expect(items).toHaveLength(2);
524
- expect(items[0].id).toBe('item-1');
525
- expect(items[1].id).toBe('item-2');
619
+ expect(items[0].id).toBe("item-1");
620
+ expect(items[1].id).toBe("item-2");
526
621
  });
527
622
 
528
- test('migrateMemoryItemsFingerprintScopeUnique: fresh DB (no column UNIQUE) is handled without rebuilding', () => {
623
+ test("migrateMemoryItemsFingerprintScopeUnique: fresh DB (no column UNIQUE) is handled without rebuilding", () => {
529
624
  // On a fresh install, the table was created without the column-level UNIQUE.
530
625
  // The migration should detect this and just write the checkpoint without
531
626
  // doing any table rebuild.
@@ -561,18 +656,22 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
561
656
  migrateMemoryItemsFingerprintScopeUnique(db);
562
657
 
563
658
  // Checkpoint should be written (short-circuit path).
564
- const cp = raw.query(
565
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`
566
- ).get() as { value: string } | null;
659
+ const cp = raw
660
+ .query(
661
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`,
662
+ )
663
+ .get() as { value: string } | null;
567
664
  expect(cp).toBeTruthy();
568
- expect(cp!.value).toBe('1');
665
+ expect(cp!.value).toBe("1");
569
666
 
570
667
  // Row should still be there.
571
- const item = raw.query(`SELECT id FROM memory_items WHERE id = 'item-modern'`).get();
668
+ const item = raw
669
+ .query(`SELECT id FROM memory_items WHERE id = 'item-modern'`)
670
+ .get();
572
671
  expect(item).toBeTruthy();
573
672
  });
574
673
 
575
- test('migrateMemoryItemsFingerprintScopeUnique: already-migrated DB is idempotent', () => {
674
+ test("migrateMemoryItemsFingerprintScopeUnique: already-migrated DB is idempotent", () => {
576
675
  // If the migration has already completed (checkpoint exists), a second run
577
676
  // must not modify the schema or data.
578
677
  const db = createTestDb();
@@ -604,17 +703,21 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
604
703
 
605
704
  // First run.
606
705
  migrateMemoryItemsFingerprintScopeUnique(db);
607
- const countAfter1 = (raw.query(`SELECT COUNT(*) AS c FROM memory_items`).get() as { c: number }).c;
706
+ const countAfter1 = (
707
+ raw.query(`SELECT COUNT(*) AS c FROM memory_items`).get() as { c: number }
708
+ ).c;
608
709
 
609
710
  // Second run — must be idempotent.
610
711
  migrateMemoryItemsFingerprintScopeUnique(db);
611
- const countAfter2 = (raw.query(`SELECT COUNT(*) AS c FROM memory_items`).get() as { c: number }).c;
712
+ const countAfter2 = (
713
+ raw.query(`SELECT COUNT(*) AS c FROM memory_items`).get() as { c: number }
714
+ ).c;
612
715
 
613
716
  expect(countAfter1).toBe(1);
614
717
  expect(countAfter2).toBe(1);
615
718
  });
616
719
 
617
- test('schema-drift: partial migration left _new table behind — next run handles it', () => {
720
+ test("schema-drift: partial migration left _new table behind — next run handles it", () => {
618
721
  // Simulate schema drift where a previous migration run created a *_new table
619
722
  // (e.g., memory_items_new) but crashed before the DROP + RENAME step.
620
723
  // The next migration run on the same migration will fail because memory_items_new
@@ -644,9 +747,11 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
644
747
  `);
645
748
 
646
749
  // The stale _new table exists.
647
- const newTableBefore = raw.query(
648
- `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_items_new'`
649
- ).get();
750
+ const newTableBefore = raw
751
+ .query(
752
+ `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_items_new'`,
753
+ )
754
+ .get();
650
755
  expect(newTableBefore).toBeTruthy();
651
756
 
652
757
  // Running the migration now will fail because memory_items_new already exists.
@@ -660,15 +765,19 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
660
765
 
661
766
  if (threwError) {
662
767
  // The migration failed — checkpoint should NOT have been written.
663
- const cpAfterFail = raw.query(
664
- `SELECT 1 FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`
665
- ).get();
768
+ const cpAfterFail = raw
769
+ .query(
770
+ `SELECT 1 FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`,
771
+ )
772
+ .get();
666
773
  expect(cpAfterFail).toBeNull();
667
774
 
668
775
  // Original table must still be intact.
669
- const originalTableStillExists = raw.query(
670
- `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`
671
- ).get();
776
+ const originalTableStillExists = raw
777
+ .query(
778
+ `SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'memory_items'`,
779
+ )
780
+ .get();
672
781
  expect(originalTableStillExists).toBeTruthy();
673
782
 
674
783
  // Recovery: drop the stale _new table, then re-run the migration.
@@ -676,22 +785,26 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
676
785
  migrateMemoryItemsFingerprintScopeUnique(db);
677
786
 
678
787
  // After recovery: checkpoint should be written and original table migrated.
679
- const cpAfterRecovery = raw.query(
680
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`
681
- ).get() as { value: string } | null;
788
+ const cpAfterRecovery = raw
789
+ .query(
790
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`,
791
+ )
792
+ .get() as { value: string } | null;
682
793
  expect(cpAfterRecovery).toBeTruthy();
683
- expect(cpAfterRecovery!.value).toBe('1');
794
+ expect(cpAfterRecovery!.value).toBe("1");
684
795
  } else {
685
796
  // If the migration succeeded despite the stale table (e.g., CREATE TABLE IF NOT EXISTS
686
797
  // silently skipped), the checkpoint should be written.
687
- const cp = raw.query(
688
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`
689
- ).get() as { value: string } | null;
798
+ const cp = raw
799
+ .query(
800
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_items_fingerprint_scope_unique_v1'`,
801
+ )
802
+ .get() as { value: string } | null;
690
803
  expect(cp).toBeTruthy();
691
804
  }
692
805
  });
693
806
 
694
- test('MIGRATION_REGISTRY: version numbers are strictly monotonically increasing', () => {
807
+ test("MIGRATION_REGISTRY: version numbers are strictly monotonically increasing", () => {
695
808
  // Registry ordering invariant: each entry's version must be strictly greater
696
809
  // than the previous one. A violation here would mean the ordering guarantees
697
810
  // documented in the migration comments cannot be relied upon.
@@ -702,7 +815,7 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
702
815
  }
703
816
  });
704
817
 
705
- test('MIGRATION_REGISTRY: all dependsOn references point to existing registry keys', () => {
818
+ test("MIGRATION_REGISTRY: all dependsOn references point to existing registry keys", () => {
706
819
  // Schema drift guard: if a migration declares a dependency on a key that
707
820
  // doesn't exist in the registry, the dependency check in validateMigrationState
708
821
  // can never be satisfied. This test ensures all declared dependencies are valid.
@@ -715,7 +828,7 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
715
828
  }
716
829
  });
717
830
 
718
- test('migrateMemoryEntityRelationDedup: idempotent on already-deduplicated table', () => {
831
+ test("migrateMemoryEntityRelationDedup: idempotent on already-deduplicated table", () => {
719
832
  // If no duplicates exist, the migration should run without errors, write
720
833
  // the checkpoint, and leave the data unchanged.
721
834
  const db = createTestDb();
@@ -727,24 +840,40 @@ describe('schema-drift recovery: migration handles unexpected schema state', ()
727
840
  const now = Date.now();
728
841
 
729
842
  // Insert distinct relations (no duplicates).
730
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now}, ${now})`);
731
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e3', 'knows', NULL, ${now}, ${now})`);
732
- raw.exec(`INSERT INTO memory_entity_relations VALUES ('r3', 'e2', 'e3', 'friends', 'evidence', ${now}, ${now})`);
843
+ raw.exec(
844
+ `INSERT INTO memory_entity_relations VALUES ('r1', 'e1', 'e2', 'knows', NULL, ${now}, ${now})`,
845
+ );
846
+ raw.exec(
847
+ `INSERT INTO memory_entity_relations VALUES ('r2', 'e1', 'e3', 'knows', NULL, ${now}, ${now})`,
848
+ );
849
+ raw.exec(
850
+ `INSERT INTO memory_entity_relations VALUES ('r3', 'e2', 'e3', 'friends', 'evidence', ${now}, ${now})`,
851
+ );
733
852
 
734
853
  migrateMemoryEntityRelationDedup(db);
735
854
 
736
- const count = (raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as { c: number }).c;
855
+ const count = (
856
+ raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as {
857
+ c: number;
858
+ }
859
+ ).c;
737
860
  // All 3 rows are distinct and should survive the dedup.
738
861
  expect(count).toBe(3);
739
862
 
740
- const cp = raw.query(
741
- `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`
742
- ).get() as { value: string } | null;
743
- expect(cp!.value).toBe('1');
863
+ const cp = raw
864
+ .query(
865
+ `SELECT value FROM memory_checkpoints WHERE key = 'migration_memory_entity_relations_dedup_v1'`,
866
+ )
867
+ .get() as { value: string } | null;
868
+ expect(cp!.value).toBe("1");
744
869
 
745
870
  // Second run — must be a no-op (checkpoint exists).
746
871
  migrateMemoryEntityRelationDedup(db);
747
- const countAfter2 = (raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as { c: number }).c;
872
+ const countAfter2 = (
873
+ raw.query(`SELECT COUNT(*) AS c FROM memory_entity_relations`).get() as {
874
+ c: number;
875
+ }
876
+ ).c;
748
877
  expect(countAfter2).toBe(3);
749
878
  });
750
879
  });