@vellumai/assistant 0.5.16 → 0.6.0

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 (407) hide show
  1. package/ARCHITECTURE.md +1 -1
  2. package/Dockerfile +0 -3
  3. package/knip.json +2 -1
  4. package/openapi.yaml +660 -80
  5. package/package.json +1 -1
  6. package/src/__tests__/actor-token-service.test.ts +68 -0
  7. package/src/__tests__/agent-loop.test.ts +0 -32
  8. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  9. package/src/__tests__/anthropic-provider.test.ts +57 -3
  10. package/src/__tests__/app-compiler.test.ts +120 -0
  11. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  12. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  13. package/src/__tests__/call-domain.test.ts +2 -6
  14. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  15. package/src/__tests__/call-recovery.test.ts +2 -6
  16. package/src/__tests__/call-routes-http.test.ts +2 -6
  17. package/src/__tests__/call-store.test.ts +2 -6
  18. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  19. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  20. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  21. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  22. package/src/__tests__/checker.test.ts +25 -3
  23. package/src/__tests__/clawhub.test.ts +54 -24
  24. package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
  25. package/src/__tests__/cli-memory.test.ts +74 -69
  26. package/src/__tests__/config-schema.test.ts +1 -1
  27. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  28. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  29. package/src/__tests__/contacts-tools.test.ts +31 -0
  30. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  31. package/src/__tests__/context-token-estimator.test.ts +175 -10
  32. package/src/__tests__/conversation-agent-loop-overflow.test.ts +9 -0
  33. package/src/__tests__/conversation-agent-loop.test.ts +9 -0
  34. package/src/__tests__/conversation-attachments.test.ts +2 -6
  35. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  36. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  37. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  38. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  39. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  40. package/src/__tests__/conversation-error.test.ts +33 -2
  41. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  42. package/src/__tests__/conversation-history-web-search.test.ts +5 -0
  43. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  44. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  45. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  46. package/src/__tests__/conversation-store.test.ts +2 -6
  47. package/src/__tests__/conversation-usage.test.ts +2 -6
  48. package/src/__tests__/conversation-wipe.test.ts +11 -408
  49. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  50. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  51. package/src/__tests__/credential-security-e2e.test.ts +2 -0
  52. package/src/__tests__/followup-tools.test.ts +2 -6
  53. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  54. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  55. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  56. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  57. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  58. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  59. package/src/__tests__/guardian-action-store.test.ts +2 -6
  60. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  61. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  62. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  63. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  64. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  65. package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
  66. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  67. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  68. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  69. package/src/__tests__/injection-block.test.ts +154 -0
  70. package/src/__tests__/install-meta.test.ts +506 -0
  71. package/src/__tests__/install-skill-routing.test.ts +292 -0
  72. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  73. package/src/__tests__/invite-routes-http.test.ts +2 -6
  74. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +2 -14
  75. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  76. package/src/__tests__/llm-context-route-provider.test.ts +2 -6
  77. package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
  78. package/src/__tests__/llm-usage-store.test.ts +2 -6
  79. package/src/__tests__/log-export-workspace.test.ts +2 -6
  80. package/src/__tests__/managed-store.test.ts +38 -11
  81. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  82. package/src/__tests__/memory-recall-log-store.test.ts +2 -6
  83. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  84. package/src/__tests__/non-member-access-request.test.ts +2 -6
  85. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  86. package/src/__tests__/oauth-cli.test.ts +364 -2
  87. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  88. package/src/__tests__/outlook-attachments.test.ts +301 -0
  89. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  90. package/src/__tests__/outlook-categories.test.ts +212 -0
  91. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  92. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  93. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  94. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  95. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  96. package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
  97. package/src/__tests__/outlook-trash.test.ts +77 -0
  98. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  99. package/src/__tests__/platform-callback-registration.test.ts +4 -4
  100. package/src/__tests__/playbook-execution.test.ts +76 -80
  101. package/src/__tests__/playbook-tools.test.ts +5 -7
  102. package/src/__tests__/provider-error-scenarios.test.ts +21 -0
  103. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  104. package/src/__tests__/registry.test.ts +2 -2
  105. package/src/__tests__/require-fresh-approval.test.ts +64 -2
  106. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  107. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  108. package/src/__tests__/schedule-store.test.ts +2 -6
  109. package/src/__tests__/schedule-tools.test.ts +2 -6
  110. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  111. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  112. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  113. package/src/__tests__/search-skills-unified.test.ts +421 -0
  114. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  115. package/src/__tests__/send-endpoint-busy.test.ts +2 -6
  116. package/src/__tests__/sequence-store.test.ts +2 -6
  117. package/src/__tests__/server-history-render.test.ts +2 -6
  118. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  119. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  120. package/src/__tests__/skill-load-feature-flag.test.ts +11 -11
  121. package/src/__tests__/skill-memory.test.ts +140 -98
  122. package/src/__tests__/skills-uninstall.test.ts +2 -2
  123. package/src/__tests__/skills.test.ts +1 -1
  124. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  125. package/src/__tests__/task-compiler.test.ts +2 -6
  126. package/src/__tests__/task-management-tools.test.ts +2 -6
  127. package/src/__tests__/task-memory-cleanup.test.ts +173 -229
  128. package/src/__tests__/task-runner.test.ts +2 -6
  129. package/src/__tests__/task-scheduler.test.ts +2 -6
  130. package/src/__tests__/test-preload.ts +3 -0
  131. package/src/__tests__/tool-approval-handler.test.ts +2 -6
  132. package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
  133. package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
  134. package/src/__tests__/trust-store.test.ts +1 -1
  135. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
  136. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -6
  137. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
  138. package/src/__tests__/trusted-contact-verification.test.ts +2 -6
  139. package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
  140. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
  141. package/src/__tests__/usage-routes.test.ts +2 -6
  142. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  143. package/src/__tests__/voice-invite-redemption.test.ts +2 -6
  144. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
  145. package/src/__tests__/voice-session-bridge.test.ts +2 -6
  146. package/src/__tests__/volume-security-guard.test.ts +2 -0
  147. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  148. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
  149. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
  150. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  151. package/src/__tests__/workspace-policy.test.ts +1 -1
  152. package/src/agent/attachments.ts +7 -2
  153. package/src/agent/image-optimize.ts +165 -0
  154. package/src/agent/loop.ts +1 -15
  155. package/src/bundler/app-compiler.ts +179 -2
  156. package/src/bundler/package-resolver.ts +3 -5
  157. package/src/cli/__tests__/notifications.test.ts +1 -2
  158. package/src/cli/cli-memory.ts +67 -64
  159. package/src/cli/commands/avatar.ts +3 -3
  160. package/src/cli/commands/config.ts +26 -13
  161. package/src/cli/commands/doctor.ts +2 -2
  162. package/src/cli/commands/memory.ts +41 -55
  163. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  164. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  165. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  166. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  167. package/src/cli/commands/oauth/connect.ts +11 -6
  168. package/src/cli/commands/oauth/mode.ts +7 -0
  169. package/src/cli/commands/oauth/shared.ts +39 -3
  170. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  171. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  172. package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
  173. package/src/cli/commands/platform/index.ts +16 -16
  174. package/src/cli/commands/skills.ts +88 -16
  175. package/src/cli/commands/trust.ts +2 -2
  176. package/src/cli/lib/daemon-credential-client.ts +2 -3
  177. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  178. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  179. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  180. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  181. package/src/config/bundled-skills/gmail/SKILL.md +2 -10
  182. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  183. package/src/config/bundled-skills/messaging/SKILL.md +10 -18
  184. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  185. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  186. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  187. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  188. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  189. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  190. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  191. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  192. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  193. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  194. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  195. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  196. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  197. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  198. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  199. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  200. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  201. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  202. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  203. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  204. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  205. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  206. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  207. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  208. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  209. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  210. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  211. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  212. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  213. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  214. package/src/config/bundled-skills/slack/SKILL.md +1 -7
  215. package/src/config/bundled-tool-registry.ts +56 -4
  216. package/src/config/env-registry.ts +15 -8
  217. package/src/config/feature-flag-registry.json +21 -124
  218. package/src/config/schemas/platform.ts +8 -0
  219. package/src/config/schemas/timeouts.ts +1 -1
  220. package/src/config/skills.ts +18 -7
  221. package/src/context/token-estimator.ts +25 -18
  222. package/src/context/window-manager.ts +6 -2
  223. package/src/credential-execution/process-manager.ts +3 -1
  224. package/src/daemon/context-overflow-reducer.ts +46 -2
  225. package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
  226. package/src/daemon/conversation-agent-loop.ts +96 -61
  227. package/src/daemon/conversation-error.ts +31 -8
  228. package/src/daemon/conversation-lifecycle.ts +33 -0
  229. package/src/daemon/conversation-media-retry.ts +85 -7
  230. package/src/daemon/conversation-notifiers.ts +4 -1
  231. package/src/daemon/conversation-runtime-assembly.ts +5 -0
  232. package/src/daemon/conversation.ts +41 -2
  233. package/src/daemon/daemon-control.ts +8 -2
  234. package/src/daemon/handlers/shared.ts +22 -12
  235. package/src/daemon/handlers/skills.ts +416 -202
  236. package/src/daemon/lifecycle.ts +40 -1
  237. package/src/daemon/main.ts +5 -1
  238. package/src/daemon/message-types/conversations.ts +4 -1
  239. package/src/daemon/message-types/messages.ts +3 -1
  240. package/src/daemon/message-types/skills.ts +97 -36
  241. package/src/daemon/providers-setup.ts +5 -0
  242. package/src/daemon/server.ts +11 -2
  243. package/src/daemon/tool-side-effects.ts +27 -5
  244. package/src/heartbeat/heartbeat-service.ts +1 -0
  245. package/src/hooks/cli.ts +2 -2
  246. package/src/hooks/runner.ts +15 -38
  247. package/src/inbound/platform-callback-registration.ts +14 -14
  248. package/src/memory/admin.ts +11 -45
  249. package/src/memory/conversation-bootstrap.ts +2 -0
  250. package/src/memory/conversation-crud.ts +242 -348
  251. package/src/memory/conversation-group-migration.ts +157 -0
  252. package/src/memory/conversation-queries.ts +4 -2
  253. package/src/memory/db-init.ts +30 -3
  254. package/src/memory/embed.ts +73 -0
  255. package/src/memory/embedding-backend.ts +8 -14
  256. package/src/memory/embedding-runtime-manager.ts +12 -114
  257. package/src/memory/fingerprint.ts +2 -2
  258. package/src/memory/graph/bootstrap.ts +512 -0
  259. package/src/memory/graph/capability-seed.ts +297 -0
  260. package/src/memory/graph/consolidation.ts +691 -0
  261. package/src/memory/graph/conversation-graph-memory.ts +630 -0
  262. package/src/memory/graph/decay.test.ts +208 -0
  263. package/src/memory/graph/decay.ts +195 -0
  264. package/src/memory/graph/extraction-job.ts +69 -0
  265. package/src/memory/graph/extraction.test.ts +936 -0
  266. package/src/memory/graph/extraction.ts +1254 -0
  267. package/src/memory/graph/graph-search.ts +266 -0
  268. package/src/memory/graph/image-ref-utils.ts +29 -0
  269. package/src/memory/graph/injection.test.ts +513 -0
  270. package/src/memory/graph/injection.ts +439 -0
  271. package/src/memory/graph/inspect.ts +534 -0
  272. package/src/memory/graph/narrative.ts +267 -0
  273. package/src/memory/graph/pattern-scan.ts +269 -0
  274. package/src/memory/graph/retriever.ts +1008 -0
  275. package/src/memory/graph/scoring.test.ts +548 -0
  276. package/src/memory/graph/scoring.ts +232 -0
  277. package/src/memory/graph/serendipity.ts +65 -0
  278. package/src/memory/graph/store.test.ts +1050 -0
  279. package/src/memory/graph/store.ts +699 -0
  280. package/src/memory/graph/tool-handlers.ts +426 -0
  281. package/src/memory/graph/tools.ts +141 -0
  282. package/src/memory/graph/triggers.test.ts +487 -0
  283. package/src/memory/graph/triggers.ts +223 -0
  284. package/src/memory/graph/types.ts +271 -0
  285. package/src/memory/group-crud.ts +191 -0
  286. package/src/memory/indexer.ts +37 -19
  287. package/src/memory/job-handlers/cleanup.ts +0 -53
  288. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  289. package/src/memory/job-handlers/embedding.ts +5 -31
  290. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  291. package/src/memory/job-handlers/summarization.ts +32 -17
  292. package/src/memory/job-utils.ts +1 -1
  293. package/src/memory/jobs-store.ts +50 -70
  294. package/src/memory/jobs-worker.ts +147 -112
  295. package/src/memory/message-content.ts +1 -0
  296. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  297. package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -0
  298. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  299. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  300. package/src/memory/migrations/index.ts +4 -0
  301. package/src/memory/migrations/registry.ts +8 -0
  302. package/src/memory/qdrant-client.ts +44 -17
  303. package/src/memory/schema/index.ts +1 -0
  304. package/src/memory/schema/memory-graph.ts +139 -0
  305. package/src/memory/search/semantic.ts +47 -91
  306. package/src/memory/task-memory-cleanup.ts +28 -50
  307. package/src/messaging/providers/outlook/adapter.ts +8 -1
  308. package/src/messaging/providers/outlook/client.ts +299 -0
  309. package/src/messaging/providers/outlook/types.ts +118 -0
  310. package/src/notifications/adapters/macos.ts +1 -0
  311. package/src/notifications/copy-composer.ts +9 -0
  312. package/src/notifications/signal.ts +16 -0
  313. package/src/oauth/seed-providers.ts +2 -1
  314. package/src/permissions/checker.ts +24 -3
  315. package/src/permissions/defaults.ts +4 -4
  316. package/src/permissions/workspace-policy.ts +1 -1
  317. package/src/playbooks/playbook-compiler.ts +19 -18
  318. package/src/playbooks/types.ts +4 -3
  319. package/src/prompts/system-prompt.ts +3 -29
  320. package/src/providers/anthropic/client.ts +47 -19
  321. package/src/providers/gemini/client.ts +1 -1
  322. package/src/providers/openai/client.ts +1 -1
  323. package/src/providers/registry.ts +1 -1
  324. package/src/providers/retry.ts +19 -3
  325. package/src/runtime/actor-trust-resolver.ts +5 -1
  326. package/src/runtime/auth/route-policy.ts +7 -0
  327. package/src/runtime/guardian-reply-router.ts +5 -1
  328. package/src/runtime/http-server.ts +23 -3
  329. package/src/runtime/middleware/auth.ts +20 -0
  330. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  331. package/src/runtime/routes/attachment-routes.ts +106 -16
  332. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  333. package/src/runtime/routes/btw-routes.ts +8 -0
  334. package/src/runtime/routes/conversation-management-routes.ts +2 -0
  335. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  336. package/src/runtime/routes/debug-routes.ts +1 -1
  337. package/src/runtime/routes/global-search-routes.ts +21 -19
  338. package/src/runtime/routes/group-routes.ts +207 -0
  339. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  340. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  341. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  342. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  343. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  344. package/src/runtime/routes/memory-item-routes.test.ts +2 -14
  345. package/src/runtime/routes/memory-item-routes.ts +341 -388
  346. package/src/runtime/routes/schedule-routes.ts +2 -0
  347. package/src/runtime/routes/skills-routes.ts +103 -37
  348. package/src/runtime/routes/work-items-routes.test.ts +2 -6
  349. package/src/schedule/scheduler.ts +8 -1
  350. package/src/security/oauth2.ts +1 -1
  351. package/src/security/secure-keys.ts +4 -8
  352. package/src/shared/provider-env-vars.ts +19 -0
  353. package/src/skills/catalog-cache.ts +5 -0
  354. package/src/skills/catalog-install.ts +15 -14
  355. package/src/skills/clawhub.ts +134 -154
  356. package/src/skills/install-meta.ts +208 -0
  357. package/src/skills/managed-store.ts +27 -16
  358. package/src/skills/skill-memory.ts +152 -77
  359. package/src/skills/skillssh-registry.ts +19 -17
  360. package/src/tasks/task-runner.ts +3 -1
  361. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  362. package/src/tools/browser/runtime-check.ts +3 -1
  363. package/src/tools/memory/register.ts +63 -46
  364. package/src/tools/permission-checker.ts +7 -1
  365. package/src/tools/shared/filesystem/image-read.ts +22 -85
  366. package/src/tools/terminal/safe-env.ts +1 -0
  367. package/src/tools/tool-manifest.ts +3 -3
  368. package/src/util/browser.ts +25 -10
  369. package/src/util/bun-runtime.ts +172 -0
  370. package/src/watcher/providers/outlook-calendar.ts +343 -0
  371. package/src/watcher/providers/outlook.ts +198 -0
  372. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  373. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  374. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  375. package/src/workspace/migrations/registry.ts +6 -0
  376. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  377. package/src/__tests__/journal-context.test.ts +0 -268
  378. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  379. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  380. package/src/__tests__/memory-query-builder.test.ts +0 -59
  381. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  382. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  383. package/src/__tests__/memory-regressions.test.ts +0 -3696
  384. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  385. package/src/daemon/conversation-memory.ts +0 -207
  386. package/src/memory/conversation-starters-cadence.ts +0 -74
  387. package/src/memory/items-extractor.ts +0 -860
  388. package/src/memory/job-handlers/batch-extraction.ts +0 -753
  389. package/src/memory/job-handlers/extraction.ts +0 -40
  390. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
  391. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  392. package/src/memory/journal-memory.ts +0 -224
  393. package/src/memory/query-builder.ts +0 -47
  394. package/src/memory/query-expansion.ts +0 -83
  395. package/src/memory/retriever.test.ts +0 -1592
  396. package/src/memory/retriever.ts +0 -1331
  397. package/src/memory/search/formatting.test.ts +0 -140
  398. package/src/memory/search/formatting.ts +0 -262
  399. package/src/memory/search/mmr.ts +0 -139
  400. package/src/memory/search/ranking.ts +0 -15
  401. package/src/memory/search/staleness.ts +0 -40
  402. package/src/memory/search/tier-classifier.ts +0 -18
  403. package/src/memory/search/types.ts +0 -121
  404. package/src/prompts/journal-context.ts +0 -154
  405. package/src/tools/memory/definitions.ts +0 -69
  406. package/src/tools/memory/handlers.test.ts +0 -562
  407. package/src/tools/memory/handlers.ts +0 -434
@@ -170,17 +170,39 @@ describe("Permission Checker", () => {
170
170
  // ── classifyRisk ────────────────────────────────────────────────
171
171
 
172
172
  describe("classifyRisk", () => {
173
- // file_read is always low
173
+ // file_read is low risk except for signing-key material
174
174
  describe("file_read", () => {
175
- test("file_read is always low risk", async () => {
175
+ test("file_read is low risk for regular files", async () => {
176
176
  const risk = await classifyRisk("file_read", { path: "/etc/passwd" });
177
177
  expect(risk).toBe(RiskLevel.Low);
178
178
  });
179
179
 
180
- test("file_read with any path is low risk", async () => {
180
+ test("file_read with arbitrary non-key path is low risk", async () => {
181
181
  const risk = await classifyRisk("file_read", { path: "/tmp/safe.txt" });
182
182
  expect(risk).toBe(RiskLevel.Low);
183
183
  });
184
+
185
+ test("file_read of workspace signing key path is high risk", async () => {
186
+ const workspaceDir = join(checkerTestDir, "workspace");
187
+ const risk = await classifyRisk(
188
+ "file_read",
189
+ { path: "deprecated/actor-token-signing-key" },
190
+ workspaceDir,
191
+ );
192
+ expect(risk).toBe(RiskLevel.High);
193
+ });
194
+
195
+ test("file_read of legacy protected signing key path is high risk", async () => {
196
+ const risk = await classifyRisk("file_read", {
197
+ path: join(
198
+ homedir(),
199
+ ".vellum",
200
+ "protected",
201
+ "actor-token-signing-key",
202
+ ),
203
+ });
204
+ expect(risk).toBe(RiskLevel.High);
205
+ });
184
206
  });
185
207
 
186
208
  // file_write is always low (sandboxed)
@@ -1,4 +1,10 @@
1
- import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ rmSync,
6
+ writeFileSync,
7
+ } from "node:fs";
2
8
  import { join } from "node:path";
3
9
  import { describe, expect, test } from "bun:test";
4
10
  import { mock } from "bun:test";
@@ -15,9 +21,9 @@ mock.module("../util/logger.js", () => ({
15
21
  import {
16
22
  clawhubInspect,
17
23
  clawhubInstall,
18
- loadIntegrityManifest,
19
24
  verifyAndRecordSkillHash,
20
25
  } from "../skills/clawhub.js";
26
+ import type { SkillInstallMeta } from "../skills/install-meta.js";
21
27
 
22
28
  // ---------------------------------------------------------------------------
23
29
  // Slug validation (exercised through public API)
@@ -92,58 +98,65 @@ describe("clawhubInspect slug validation", () => {
92
98
  });
93
99
 
94
100
  // ---------------------------------------------------------------------------
95
- // Integrity manifest edge cases — tested via verifyAndRecordSkillHash
96
- // which is the code path that reads/writes the manifest.
101
+ // Content hash verification — tested via verifyAndRecordSkillHash
102
+ // which reads legacy .integrity.json but always writes to install-meta.json.
97
103
  // ---------------------------------------------------------------------------
98
104
 
99
- describe("integrity manifest", () => {
105
+ describe("content hash verification", () => {
100
106
  function createSkillFiles(slug: string): void {
101
107
  const skillDir = join(TEST_DIR, "skills", slug);
102
108
  mkdirSync(skillDir, { recursive: true });
103
109
  writeFileSync(join(skillDir, "SKILL.md"), "# Test Skill\n", "utf-8");
104
110
  }
105
111
 
112
+ function readSkillInstallMeta(slug: string): SkillInstallMeta {
113
+ const metaPath = join(TEST_DIR, "skills", slug, "install-meta.json");
114
+ return JSON.parse(readFileSync(metaPath, "utf-8")) as SkillInstallMeta;
115
+ }
116
+
106
117
  test("malformed integrity JSON is handled gracefully", () => {
107
118
  mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
108
119
  const integrityPath = join(TEST_DIR, "skills", ".integrity.json");
109
120
  writeFileSync(integrityPath, "{not valid json!!!", "utf-8");
110
121
  createSkillFiles("valid-slug");
111
122
 
112
- // Should not throw — malformed manifest is replaced with a fresh one
123
+ // Should not throw — malformed legacy manifest is ignored; install-meta.json is created
113
124
  verifyAndRecordSkillHash("valid-slug");
114
125
 
115
- // Manifest should now contain a valid entry
116
- const manifest = loadIntegrityManifest();
117
- expect(manifest["valid-slug"]).toBeDefined();
118
- expect(manifest["valid-slug"].sha256).toMatch(/^v2:[0-9a-f]{64}$/);
126
+ // install-meta.json should now contain a valid hash
127
+ const meta = readSkillInstallMeta("valid-slug");
128
+ expect(meta.contentHash).toMatch(/^v2:[0-9a-f]{64}$/);
129
+ expect(meta.origin).toBe("clawhub");
130
+ expect(meta.slug).toBe("valid-slug");
119
131
  });
120
132
 
121
- test("missing integrity manifest is created on first install", () => {
133
+ test("install-meta.json is created on first hash verification for skills without one", () => {
122
134
  const skillsDir = join(TEST_DIR, "skills");
123
135
  mkdirSync(skillsDir, { recursive: true });
124
- const integrityPath = join(skillsDir, ".integrity.json");
125
- // Remove any manifest left by earlier tests so we test the fresh-creation path
126
- rmSync(integrityPath, { force: true });
127
- expect(existsSync(integrityPath)).toBe(false);
128
136
  createSkillFiles("new-skill");
137
+ const metaPath = join(skillsDir, "new-skill", "install-meta.json");
138
+ // Remove any install-meta left by earlier tests
139
+ rmSync(metaPath, { force: true });
140
+ expect(existsSync(metaPath)).toBe(false);
129
141
 
130
142
  verifyAndRecordSkillHash("new-skill");
131
143
 
132
- // Manifest should now exist with the skill's hash
133
- expect(existsSync(integrityPath)).toBe(true);
134
- const manifest = loadIntegrityManifest();
135
- expect(manifest["new-skill"]).toBeDefined();
136
- expect(manifest["new-skill"].sha256).toMatch(/^v2:[0-9a-f]{64}$/);
144
+ // install-meta.json should now exist with the skill's hash
145
+ expect(existsSync(metaPath)).toBe(true);
146
+ const meta = readSkillInstallMeta("new-skill");
147
+ expect(meta.contentHash).toMatch(/^v2:[0-9a-f]{64}$/);
148
+ expect(meta.origin).toBe("clawhub");
149
+ expect(meta.slug).toBe("new-skill");
137
150
  });
138
151
 
139
152
  test("re-install with same content preserves hash", () => {
140
153
  createSkillFiles("stable-skill");
141
154
 
142
155
  verifyAndRecordSkillHash("stable-skill");
143
- const first = loadIntegrityManifest()["stable-skill"].sha256;
156
+ const first = readSkillInstallMeta("stable-skill").contentHash;
144
157
 
145
158
  verifyAndRecordSkillHash("stable-skill");
146
- const second = loadIntegrityManifest()["stable-skill"].sha256;
159
+ const second = readSkillInstallMeta("stable-skill").contentHash;
147
160
 
148
161
  expect(first).toBe(second);
149
162
  });
@@ -151,7 +164,7 @@ describe("integrity manifest", () => {
151
164
  test("re-install with changed content updates hash", () => {
152
165
  createSkillFiles("changing-skill");
153
166
  verifyAndRecordSkillHash("changing-skill");
154
- const first = loadIntegrityManifest()["changing-skill"].sha256;
167
+ const first = readSkillInstallMeta("changing-skill").contentHash;
155
168
 
156
169
  // Modify skill content
157
170
  writeFileSync(
@@ -160,8 +173,25 @@ describe("integrity manifest", () => {
160
173
  "utf-8",
161
174
  );
162
175
  verifyAndRecordSkillHash("changing-skill");
163
- const second = loadIntegrityManifest()["changing-skill"].sha256;
176
+ const second = readSkillInstallMeta("changing-skill").contentHash;
164
177
 
165
178
  expect(first).not.toBe(second);
166
179
  });
180
+
181
+ test(".integrity.json is never written to", () => {
182
+ const skillsDir = join(TEST_DIR, "skills");
183
+ mkdirSync(skillsDir, { recursive: true });
184
+ const integrityPath = join(skillsDir, ".integrity.json");
185
+ // Remove any legacy manifest
186
+ rmSync(integrityPath, { force: true });
187
+ createSkillFiles("no-integrity-write");
188
+
189
+ verifyAndRecordSkillHash("no-integrity-write");
190
+
191
+ // .integrity.json should NOT have been created
192
+ expect(existsSync(integrityPath)).toBe(false);
193
+ // But install-meta.json should exist
194
+ const metaPath = join(skillsDir, "no-integrity-write", "install-meta.json");
195
+ expect(existsSync(metaPath)).toBe(true);
196
+ });
167
197
  });
@@ -208,6 +208,20 @@ describe("CLI command risk guard: elevated assistant subcommands", () => {
208
208
  }
209
209
  });
210
210
 
211
+ test("--help used as option value does not downgrade credentials reveal risk", async () => {
212
+ const risk = await classifyRisk("bash", {
213
+ command: "assistant credentials reveal 123 --service --help",
214
+ });
215
+ expect(risk).toBe(RiskLevel.High);
216
+ });
217
+
218
+ test("-h used as option value does not downgrade oauth mode --set risk", async () => {
219
+ const risk = await classifyRisk("bash", {
220
+ command: "assistant oauth mode --set -h",
221
+ });
222
+ expect(risk).toBe(RiskLevel.High);
223
+ });
224
+
211
225
  test("non-sensitive oauth subcommands remain Low risk", async () => {
212
226
  const lowRiskOauthCommands = [
213
227
  "assistant oauth apps",
@@ -2,7 +2,7 @@ import { rmSync } from "node:fs";
2
2
  import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
3
3
 
4
4
  import { Command } from "commander";
5
- import { eq } from "drizzle-orm";
5
+ import { eq, like } from "drizzle-orm";
6
6
 
7
7
  mock.module("../util/logger.js", () => ({
8
8
  getLogger: () =>
@@ -64,7 +64,7 @@ import {
64
64
  upsertCliCapabilityMemory,
65
65
  } from "../cli/cli-memory.js";
66
66
  import { getDb, initializeDb, resetDb } from "../memory/db.js";
67
- import { memoryItems, memoryJobs } from "../memory/schema.js";
67
+ import { memoryGraphNodes, memoryJobs } from "../memory/schema.js";
68
68
  import { ensureDataDir, getDbPath } from "../util/platform.js";
69
69
 
70
70
  ensureDataDir();
@@ -76,9 +76,8 @@ afterAll(() => {
76
76
 
77
77
  function resetTables() {
78
78
  const db = getDb();
79
- db.run("DELETE FROM memory_item_sources");
80
79
  db.run("DELETE FROM memory_embeddings");
81
- db.run("DELETE FROM memory_items");
80
+ db.run("DELETE FROM memory_graph_nodes");
82
81
  db.run("DELETE FROM memory_jobs");
83
82
  }
84
83
 
@@ -103,62 +102,62 @@ describe("buildCliCapabilityStatement", () => {
103
102
  describe("upsertCliCapabilityMemory", () => {
104
103
  beforeEach(resetTables);
105
104
 
106
- test("inserts with correct kind, subject, confidence, importance", () => {
105
+ test("inserts with correct type, content, confidence, significance", () => {
107
106
  upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
108
107
 
109
108
  const db = getDb();
110
- const items = db.select().from(memoryItems).all();
109
+ const items = db.select().from(memoryGraphNodes).all();
111
110
  expect(items).toHaveLength(1);
112
- expect(items[0].kind).toBe("capability");
113
- expect(items[0].subject).toBe("cli:doctor");
111
+ expect(items[0].type).toBe("procedural");
112
+ expect(items[0].content).toMatch(/^cli:doctor\n/);
114
113
  expect(items[0].confidence).toBe(1.0);
115
- expect(items[0].importance).toBe(0.7);
116
- expect(items[0].status).toBe("active");
114
+ expect(items[0].significance).toBe(0.7);
115
+ expect(items[0].fidelity).toBe("vivid");
117
116
  expect(items[0].scopeId).toBe("default");
118
117
 
119
- // Should also enqueue an embed_item job
118
+ // Should also enqueue an embed_graph_node job
120
119
  const jobs = db.select().from(memoryJobs).all();
121
120
  expect(jobs).toHaveLength(1);
122
- expect(jobs[0].type).toBe("embed_item");
121
+ expect(jobs[0].type).toBe("embed_graph_node");
123
122
  });
124
123
 
125
- test("is idempotent (same entry only touches lastSeenAt)", () => {
124
+ test("is idempotent (same entry only touches lastAccessed)", () => {
126
125
  upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
127
126
 
128
127
  const db = getDb();
129
- const before = db.select().from(memoryItems).all();
128
+ const before = db.select().from(memoryGraphNodes).all();
130
129
  expect(before).toHaveLength(1);
131
- const originalLastSeen = before[0].lastSeenAt;
130
+ const originalLastAccessed = before[0].lastAccessed;
132
131
 
133
132
  // Upsert again
134
133
  upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
135
134
 
136
- const after = db.select().from(memoryItems).all();
135
+ const after = db.select().from(memoryGraphNodes).all();
137
136
  expect(after).toHaveLength(1);
138
- // Fingerprint should be the same, so only lastSeenAt changes
139
- expect(after[0].fingerprint).toBe(before[0].fingerprint);
140
- expect(after[0].lastSeenAt).toBeGreaterThanOrEqual(originalLastSeen);
137
+ // Same content, so only lastAccessed changes
138
+ expect(after[0].content).toBe(before[0].content);
139
+ expect(after[0].lastAccessed).toBeGreaterThanOrEqual(originalLastAccessed);
141
140
 
142
141
  // Should NOT enqueue a second embed job (only 1 from initial insert)
143
142
  const jobs = db.select().from(memoryJobs).all();
144
143
  expect(jobs).toHaveLength(1);
145
144
  });
146
145
 
147
- test("updates statement when description changes", () => {
146
+ test("updates content when description changes", () => {
148
147
  upsertCliCapabilityMemory("doctor", "Original description");
149
148
 
150
149
  const db = getDb();
151
- const before = db.select().from(memoryItems).all();
150
+ const before = db.select().from(memoryGraphNodes).all();
152
151
  expect(before).toHaveLength(1);
153
- expect(before[0].statement).toContain("Original description");
152
+ expect(before[0].content).toContain("Original description");
154
153
 
155
154
  // Change description
156
155
  upsertCliCapabilityMemory("doctor", "Updated description");
157
156
 
158
- const after = db.select().from(memoryItems).all();
157
+ const after = db.select().from(memoryGraphNodes).all();
159
158
  expect(after).toHaveLength(1);
160
- expect(after[0].statement).toContain("Updated description");
161
- expect(after[0].fingerprint).not.toBe(before[0].fingerprint);
159
+ expect(after[0].content).toContain("Updated description");
160
+ expect(after[0].content).not.toBe(before[0].content);
162
161
 
163
162
  // Should enqueue a second embed job
164
163
  const jobs = db.select().from(memoryJobs).all();
@@ -170,13 +169,13 @@ describe("upsertCliCapabilityMemory", () => {
170
169
 
171
170
  const db = getDb();
172
171
  // Soft-delete the item
173
- db.update(memoryItems)
174
- .set({ status: "deleted" })
175
- .where(eq(memoryItems.subject, "cli:doctor"))
172
+ db.update(memoryGraphNodes)
173
+ .set({ fidelity: "gone" })
174
+ .where(like(memoryGraphNodes.content, "cli:doctor\n%"))
176
175
  .run();
177
176
 
178
- const deleted = db.select().from(memoryItems).all();
179
- expect(deleted[0].status).toBe("deleted");
177
+ const deleted = db.select().from(memoryGraphNodes).all();
178
+ expect(deleted[0].fidelity).toBe("gone");
180
179
 
181
180
  // Clear jobs from initial insert
182
181
  db.run("DELETE FROM memory_jobs");
@@ -184,20 +183,20 @@ describe("upsertCliCapabilityMemory", () => {
184
183
  // Upsert again — should reactivate
185
184
  upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
186
185
 
187
- const reactivated = db.select().from(memoryItems).all();
186
+ const reactivated = db.select().from(memoryGraphNodes).all();
188
187
  expect(reactivated).toHaveLength(1);
189
- expect(reactivated[0].status).toBe("active");
188
+ expect(reactivated[0].fidelity).toBe("vivid");
190
189
 
191
190
  // Should enqueue embed job for reactivated item
192
191
  const jobs = db.select().from(memoryJobs).all();
193
192
  expect(jobs).toHaveLength(1);
194
- expect(jobs[0].type).toBe("embed_item");
193
+ expect(jobs[0].type).toBe("embed_graph_node");
195
194
  });
196
195
 
197
196
  test("does not throw on DB error", () => {
198
197
  resetDb();
199
198
  const db = getDb();
200
- db.run("DROP TABLE IF EXISTS memory_items");
199
+ db.run("DROP TABLE IF EXISTS memory_graph_nodes");
201
200
 
202
201
  expect(() => {
203
202
  upsertCliCapabilityMemory("doctor", "Run diagnostic checks");
@@ -234,21 +233,21 @@ describe("seedCliCommandMemories", () => {
234
233
  const db = getDb();
235
234
  const items = db
236
235
  .select()
237
- .from(memoryItems)
238
- .where(eq(memoryItems.kind, "capability"))
236
+ .from(memoryGraphNodes)
237
+ .where(eq(memoryGraphNodes.type, "procedural"))
239
238
  .all();
240
239
  expect(items).toHaveLength(3);
241
240
 
242
- const subjects = items.map((i) => i.subject).sort();
243
- expect(subjects).toEqual([
241
+ const contentPrefixes = items.map((i) => i.content.split("\n")[0]).sort();
242
+ expect(contentPrefixes).toEqual([
244
243
  "cli:config",
245
244
  "cli:doctor",
246
245
  "cli:keys",
247
246
  ]);
248
247
 
249
- // All should be active
248
+ // All should be vivid
250
249
  for (const item of items) {
251
- expect(item.status).toBe("active");
250
+ expect(item.fidelity).toBe("vivid");
252
251
  }
253
252
  });
254
253
 
@@ -264,11 +263,11 @@ describe("seedCliCommandMemories", () => {
264
263
  const db = getDb();
265
264
  const beforeItems = db
266
265
  .select()
267
- .from(memoryItems)
268
- .where(eq(memoryItems.kind, "capability"))
266
+ .from(memoryGraphNodes)
267
+ .where(eq(memoryGraphNodes.type, "procedural"))
269
268
  .all();
270
269
  expect(beforeItems).toHaveLength(3);
271
- expect(beforeItems.every((i) => i.status === "active")).toBe(true);
270
+ expect(beforeItems.every((i) => i.fidelity === "vivid")).toBe(true);
272
271
 
273
272
  // Now seed with only doctor — config and keys should be pruned
274
273
  mockCommands = [
@@ -278,20 +277,20 @@ describe("seedCliCommandMemories", () => {
278
277
 
279
278
  const afterItems = db
280
279
  .select()
281
- .from(memoryItems)
282
- .where(eq(memoryItems.kind, "capability"))
280
+ .from(memoryGraphNodes)
281
+ .where(eq(memoryGraphNodes.type, "procedural"))
283
282
  .all();
284
283
  expect(afterItems).toHaveLength(3); // still 3 rows, but 2 are soft-deleted
285
284
 
286
- const active = afterItems.filter((i) => i.status === "active");
287
- const deleted = afterItems.filter((i) => i.status === "deleted");
285
+ const active = afterItems.filter((i) => i.fidelity === "vivid");
286
+ const deleted = afterItems.filter((i) => i.fidelity === "gone");
288
287
 
289
288
  expect(active).toHaveLength(1);
290
- expect(active[0].subject).toBe("cli:doctor");
289
+ expect(active[0].content).toMatch(/^cli:doctor\n/);
291
290
 
292
291
  expect(deleted).toHaveLength(2);
293
- const deletedSubjects = deleted.map((i) => i.subject).sort();
294
- expect(deletedSubjects).toEqual(["cli:config", "cli:keys"]);
292
+ const deletedPrefixes = deleted.map((i) => i.content.split("\n")[0]).sort();
293
+ expect(deletedPrefixes).toEqual(["cli:config", "cli:keys"]);
295
294
  });
296
295
 
297
296
  test("handles empty command list without errors", () => {
@@ -299,38 +298,44 @@ describe("seedCliCommandMemories", () => {
299
298
  upsertCliCapabilityMemory("old-command", "An old command");
300
299
 
301
300
  const db = getDb();
302
- const beforeItems = db.select().from(memoryItems).all();
301
+ const beforeItems = db.select().from(memoryGraphNodes).all();
303
302
  expect(beforeItems).toHaveLength(1);
304
- expect(beforeItems[0].status).toBe("active");
303
+ expect(beforeItems[0].fidelity).toBe("vivid");
305
304
 
306
305
  // Seed with empty commands
307
306
  mockCommands = [];
308
307
  seedCliCommandMemories();
309
308
 
310
309
  // The existing command should be pruned (soft-deleted)
311
- const afterItems = db.select().from(memoryItems).all();
310
+ const afterItems = db.select().from(memoryGraphNodes).all();
312
311
  expect(afterItems).toHaveLength(1);
313
- expect(afterItems[0].status).toBe("deleted");
312
+ expect(afterItems[0].fidelity).toBe("gone");
314
313
  });
315
314
 
316
315
  test("does not prune non-cli capability memories", () => {
317
316
  // Pre-insert a skill capability memory directly into the DB
318
317
  const db = getDb();
319
318
  const now = Date.now();
320
- db.insert(memoryItems)
319
+ db.insert(memoryGraphNodes)
321
320
  .values({
322
321
  id: "skill-test-item",
323
- kind: "capability",
324
- subject: "skill:test-skill",
325
- statement: "The test skill does things.",
326
- status: "active",
322
+ type: "procedural",
323
+ content: "skill:test-skill\nThe test skill does things.",
324
+ fidelity: "vivid",
327
325
  confidence: 1.0,
328
- importance: 0.7,
329
- fingerprint: "skill-test-fp",
330
- sourceType: "extraction",
326
+ significance: 0.7,
327
+ sourceType: "inferred",
331
328
  scopeId: "default",
332
- firstSeenAt: now,
333
- lastSeenAt: now,
329
+ created: now,
330
+ lastAccessed: now,
331
+ lastConsolidated: now,
332
+ emotionalCharge: '{"valence":0,"intensity":0.1,"decayCurve":"linear","decayRate":0.05,"originalIntensity":0.1}',
333
+ stability: 14,
334
+ reinforcementCount: 0,
335
+ lastReinforced: now,
336
+ sourceConversations: "[]",
337
+ narrativeRole: null,
338
+ partOfStory: null,
334
339
  })
335
340
  .run();
336
341
 
@@ -340,11 +345,11 @@ describe("seedCliCommandMemories", () => {
340
345
 
341
346
  const item = db
342
347
  .select()
343
- .from(memoryItems)
344
- .where(eq(memoryItems.subject, "skill:test-skill"))
348
+ .from(memoryGraphNodes)
349
+ .where(like(memoryGraphNodes.content, "skill:test-skill\n%"))
345
350
  .get();
346
351
  expect(item).toBeDefined();
347
- expect(item!.status).toBe("active");
352
+ expect(item!.fidelity).toBe("vivid");
348
353
  });
349
354
 
350
355
  test("does not throw on error", () => {
@@ -352,10 +357,10 @@ describe("seedCliCommandMemories", () => {
352
357
  { name: "doctor", description: "Run diagnostic checks" },
353
358
  ];
354
359
 
355
- // Drop memory_items to force a DB error during the prune phase
360
+ // Drop memory_graph_nodes to force a DB error during the prune phase
356
361
  resetDb();
357
362
  const db = getDb();
358
- db.run("DROP TABLE IF EXISTS memory_items");
363
+ db.run("DROP TABLE IF EXISTS memory_graph_nodes");
359
364
 
360
365
  expect(() => {
361
366
  seedCliCommandMemories();
@@ -105,7 +105,7 @@ describe("AssistantConfigSchema", () => {
105
105
  shellMaxTimeoutSec: 600,
106
106
  permissionTimeoutSec: 300,
107
107
  toolExecutionTimeoutSec: 120,
108
- providerStreamTimeoutSec: 300,
108
+ providerStreamTimeoutSec: 1800,
109
109
  });
110
110
  expect(result.sandbox).toEqual({
111
111
  enabled: false,