@vellumai/assistant 0.5.16 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (592) hide show
  1. package/AGENTS.md +4 -0
  2. package/ARCHITECTURE.md +69 -16
  3. package/Dockerfile +2 -5
  4. package/bun.lock +6 -2
  5. package/docker-entrypoint.sh +32 -1
  6. package/docs/architecture/integrations.md +1 -1
  7. package/docs/architecture/memory.md +21 -24
  8. package/knip.json +2 -1
  9. package/openapi.yaml +1198 -83
  10. package/package.json +5 -1
  11. package/src/__tests__/actor-token-service.test.ts +68 -0
  12. package/src/__tests__/agent-loop.test.ts +0 -32
  13. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  14. package/src/__tests__/anthropic-provider.test.ts +217 -98
  15. package/src/__tests__/app-compiler.test.ts +120 -0
  16. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  17. package/src/__tests__/app-executors.test.ts +47 -1
  18. package/src/__tests__/app-source-watcher.test.ts +159 -0
  19. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  20. package/src/__tests__/call-conversation-messages.test.ts +2 -6
  21. package/src/__tests__/call-domain.test.ts +2 -6
  22. package/src/__tests__/call-pointer-messages.test.ts +2 -14
  23. package/src/__tests__/call-recovery.test.ts +2 -6
  24. package/src/__tests__/call-routes-http.test.ts +2 -6
  25. package/src/__tests__/call-store.test.ts +2 -6
  26. package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
  27. package/src/__tests__/canonical-guardian-store.test.ts +2 -6
  28. package/src/__tests__/channel-delivery-store.test.ts +2 -6
  29. package/src/__tests__/channel-retry-sweep.test.ts +2 -6
  30. package/src/__tests__/checker.test.ts +63 -9
  31. package/src/__tests__/clawhub.test.ts +54 -24
  32. package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
  33. package/src/__tests__/config-schema.test.ts +6 -1
  34. package/src/__tests__/config-set-platform-guard.test.ts +302 -0
  35. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
  36. package/src/__tests__/contacts-tools.test.ts +31 -0
  37. package/src/__tests__/context-overflow-reducer.test.ts +86 -0
  38. package/src/__tests__/context-token-estimator.test.ts +175 -10
  39. package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
  40. package/src/__tests__/conversation-agent-loop.test.ts +13 -51
  41. package/src/__tests__/conversation-attachments.test.ts +2 -6
  42. package/src/__tests__/conversation-attention-store.test.ts +2 -6
  43. package/src/__tests__/conversation-clear-safety.test.ts +2 -6
  44. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
  45. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
  46. package/src/__tests__/conversation-disk-view.test.ts +2 -6
  47. package/src/__tests__/conversation-error.test.ts +33 -2
  48. package/src/__tests__/conversation-fork-crud.test.ts +2 -6
  49. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  50. package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +91 -0
  52. package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
  53. package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
  54. package/src/__tests__/conversation-starter-routes.test.ts +20 -11
  55. package/src/__tests__/conversation-store.test.ts +2 -6
  56. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
  57. package/src/__tests__/conversation-usage.test.ts +2 -6
  58. package/src/__tests__/conversation-wipe.test.ts +13 -414
  59. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
  60. package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
  61. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
  62. package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
  63. package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
  64. package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
  65. package/src/__tests__/credential-security-e2e.test.ts +2 -0
  66. package/src/__tests__/date-context.test.ts +76 -210
  67. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
  68. package/src/__tests__/file-list-tool.test.ts +219 -0
  69. package/src/__tests__/first-greeting.test.ts +1 -1
  70. package/src/__tests__/followup-tools.test.ts +2 -6
  71. package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
  72. package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
  73. package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
  74. package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
  75. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
  76. package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
  77. package/src/__tests__/guardian-action-store.test.ts +2 -6
  78. package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
  79. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
  80. package/src/__tests__/guardian-dispatch.test.ts +2 -6
  81. package/src/__tests__/guardian-grant-minting.test.ts +2 -14
  82. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
  83. package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
  84. package/src/__tests__/guardian-routing-state.test.ts +2 -6
  85. package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
  86. package/src/__tests__/heartbeat-service.test.ts +180 -3
  87. package/src/__tests__/identity-routes.test.ts +328 -0
  88. package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
  89. package/src/__tests__/injection-block.test.ts +178 -0
  90. package/src/__tests__/install-meta.test.ts +506 -0
  91. package/src/__tests__/install-skill-routing.test.ts +293 -0
  92. package/src/__tests__/invite-redemption-service.test.ts +2 -6
  93. package/src/__tests__/invite-routes-http.test.ts +2 -6
  94. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
  95. package/src/__tests__/list-messages-attachments.test.ts +2 -6
  96. package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
  97. package/src/__tests__/llm-context-normalization.test.ts +18 -18
  98. package/src/__tests__/llm-context-route-provider.test.ts +103 -6
  99. package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
  100. package/src/__tests__/llm-usage-store.test.ts +2 -6
  101. package/src/__tests__/log-export-workspace.test.ts +74 -111
  102. package/src/__tests__/managed-store.test.ts +38 -11
  103. package/src/__tests__/mcp-abort-signal.test.ts +5 -0
  104. package/src/__tests__/mcp-client-auth.test.ts +5 -0
  105. package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
  106. package/src/__tests__/memory-recall-log-store.test.ts +134 -6
  107. package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
  108. package/src/__tests__/migration-export-streaming.test.ts +304 -0
  109. package/src/__tests__/migration-import-commit-http.test.ts +11 -10
  110. package/src/__tests__/mock-fetch.ts +87 -0
  111. package/src/__tests__/non-member-access-request.test.ts +2 -6
  112. package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
  113. package/src/__tests__/notification-guardian-path.test.ts +2 -6
  114. package/src/__tests__/oauth-cli.test.ts +364 -2
  115. package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
  116. package/src/__tests__/onboarding-template-contract.test.ts +62 -14
  117. package/src/__tests__/outlook-attachments.test.ts +301 -0
  118. package/src/__tests__/outlook-automation-tools.test.ts +425 -0
  119. package/src/__tests__/outlook-categories.test.ts +212 -0
  120. package/src/__tests__/outlook-client-automation.test.ts +246 -0
  121. package/src/__tests__/outlook-compose-tools.test.ts +325 -0
  122. package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
  123. package/src/__tests__/outlook-email-watcher.test.ts +322 -0
  124. package/src/__tests__/outlook-follow-up.test.ts +196 -0
  125. package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
  126. package/src/__tests__/outlook-trash.test.ts +77 -0
  127. package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
  128. package/src/__tests__/parser.test.ts +32 -0
  129. package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
  130. package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
  131. package/src/__tests__/permission-mode-sse.test.ts +418 -0
  132. package/src/__tests__/permission-mode-store.test.ts +277 -0
  133. package/src/__tests__/permission-mode.test.ts +101 -0
  134. package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
  135. package/src/__tests__/platform-callback-registration.test.ts +4 -4
  136. package/src/__tests__/playbook-execution.test.ts +76 -80
  137. package/src/__tests__/playbook-tools.test.ts +5 -7
  138. package/src/__tests__/profiler-routes.test.ts +502 -0
  139. package/src/__tests__/profiler-run-store.test.ts +441 -0
  140. package/src/__tests__/provider-error-scenarios.test.ts +21 -0
  141. package/src/__tests__/proxy-approval-callback.test.ts +4 -75
  142. package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
  143. package/src/__tests__/registry.test.ts +3 -3
  144. package/src/__tests__/require-fresh-approval.test.ts +64 -2
  145. package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
  146. package/src/__tests__/runtime-events-sse.test.ts +2 -6
  147. package/src/__tests__/sandbox-host-parity.test.ts +5 -4
  148. package/src/__tests__/schedule-store.test.ts +2 -6
  149. package/src/__tests__/schedule-tools.test.ts +2 -6
  150. package/src/__tests__/scheduler-recurrence.test.ts +1 -5
  151. package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
  152. package/src/__tests__/scoped-approval-grants.test.ts +2 -6
  153. package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
  154. package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
  155. package/src/__tests__/search-skills-unified.test.ts +422 -0
  156. package/src/__tests__/secret-onetime-send.test.ts +2 -0
  157. package/src/__tests__/send-endpoint-busy.test.ts +44 -9
  158. package/src/__tests__/sequence-store.test.ts +2 -6
  159. package/src/__tests__/server-history-render.test.ts +2 -6
  160. package/src/__tests__/set-permission-mode.test.ts +274 -0
  161. package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
  162. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  163. package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
  164. package/src/__tests__/skill-memory.test.ts +2 -741
  165. package/src/__tests__/skills-uninstall.test.ts +2 -2
  166. package/src/__tests__/skills.test.ts +1 -1
  167. package/src/__tests__/slack-inbound-verification.test.ts +2 -6
  168. package/src/__tests__/strip-memory-injections.test.ts +187 -0
  169. package/src/__tests__/subagent-detail.test.ts +84 -0
  170. package/src/__tests__/subagent-disposal.test.ts +308 -0
  171. package/src/__tests__/subagent-manager-notify.test.ts +19 -10
  172. package/src/__tests__/subagent-notify-parent.test.ts +390 -0
  173. package/src/__tests__/subagent-role-registry.test.ts +108 -0
  174. package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
  175. package/src/__tests__/subagent-tools.test.ts +464 -4
  176. package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
  177. package/src/__tests__/task-compiler.test.ts +2 -6
  178. package/src/__tests__/task-management-tools.test.ts +2 -6
  179. package/src/__tests__/task-memory-cleanup.test.ts +185 -241
  180. package/src/__tests__/task-runner.test.ts +2 -6
  181. package/src/__tests__/task-scheduler.test.ts +2 -6
  182. package/src/__tests__/terminal-tools.test.ts +17 -27
  183. package/src/__tests__/test-preload.ts +7 -0
  184. package/src/__tests__/tool-approval-handler.test.ts +2 -6
  185. package/src/__tests__/tool-executor.test.ts +4 -26
  186. package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
  187. package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
  188. package/src/__tests__/top-level-renderer.test.ts +10 -13
  189. package/src/__tests__/trust-store.test.ts +1 -1
  190. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
  191. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
  192. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
  193. package/src/__tests__/trusted-contact-verification.test.ts +2 -6
  194. package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
  195. package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
  196. package/src/__tests__/usage-routes.test.ts +2 -6
  197. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  198. package/src/__tests__/voice-invite-redemption.test.ts +2 -6
  199. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
  200. package/src/__tests__/voice-session-bridge.test.ts +2 -6
  201. package/src/__tests__/volume-security-guard.test.ts +2 -0
  202. package/src/__tests__/workspace-lifecycle.test.ts +29 -1
  203. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
  204. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
  205. package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
  206. package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
  207. package/src/__tests__/workspace-policy.test.ts +1 -1
  208. package/src/agent/attachments.ts +7 -2
  209. package/src/agent/image-optimize.ts +165 -0
  210. package/src/agent/loop.ts +7 -15
  211. package/src/approvals/guardian-request-resolvers.ts +24 -0
  212. package/src/avatar/traits-png-sync.ts +3 -3
  213. package/src/bundler/app-compiler.ts +179 -2
  214. package/src/bundler/package-resolver.ts +3 -5
  215. package/src/cli/__tests__/notifications.test.ts +1 -2
  216. package/src/cli/__tests__/run-assistant-command.ts +29 -0
  217. package/src/cli/commands/__tests__/email-download.test.ts +245 -0
  218. package/src/cli/commands/__tests__/email-list.test.ts +192 -0
  219. package/src/cli/commands/__tests__/email-register.test.ts +186 -0
  220. package/src/cli/commands/__tests__/email-send.test.ts +291 -0
  221. package/src/cli/commands/__tests__/email-status.test.ts +181 -0
  222. package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
  223. package/src/cli/commands/__tests__/routes.test.ts +562 -0
  224. package/src/cli/commands/avatar.ts +3 -3
  225. package/src/cli/commands/config.ts +26 -13
  226. package/src/cli/commands/conversations.ts +1 -8
  227. package/src/cli/commands/doctor.ts +2 -2
  228. package/src/cli/commands/email.ts +584 -835
  229. package/src/cli/commands/memory.ts +37 -84
  230. package/src/cli/commands/notifications.ts +7 -2
  231. package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
  232. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
  233. package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
  234. package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
  235. package/src/cli/commands/oauth/connect.ts +25 -11
  236. package/src/cli/commands/oauth/mode.ts +7 -0
  237. package/src/cli/commands/oauth/shared.ts +39 -3
  238. package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
  239. package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
  240. package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
  241. package/src/cli/commands/platform/index.ts +16 -16
  242. package/src/cli/commands/routes.ts +396 -0
  243. package/src/cli/commands/skills.ts +218 -36
  244. package/src/cli/commands/trust.ts +2 -2
  245. package/src/cli/lib/daemon-credential-client.ts +2 -3
  246. package/src/cli/program.ts +2 -0
  247. package/src/cli.ts +1 -120
  248. package/src/config/bundled-skills/acp/TOOLS.json +1 -1
  249. package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
  250. package/src/config/bundled-skills/contacts/SKILL.md +0 -1
  251. package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
  252. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
  253. package/src/config/bundled-skills/gmail/SKILL.md +4 -12
  254. package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
  255. package/src/config/bundled-skills/messaging/SKILL.md +17 -18
  256. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
  257. package/src/config/bundled-skills/outlook/SKILL.md +189 -0
  258. package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
  259. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
  260. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
  261. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
  262. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
  263. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
  264. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
  265. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
  266. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
  267. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
  268. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
  269. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
  270. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
  271. package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
  272. package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
  273. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
  274. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
  275. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
  276. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
  277. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
  278. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
  279. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
  280. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
  281. package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
  282. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
  283. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
  284. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
  285. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
  286. package/src/config/bundled-skills/schedule/SKILL.md +22 -2
  287. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  288. package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
  289. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
  290. package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
  291. package/src/config/bundled-skills/slack/SKILL.md +3 -7
  292. package/src/config/bundled-skills/subagent/SKILL.md +43 -3
  293. package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
  294. package/src/config/bundled-tool-registry.ts +56 -4
  295. package/src/config/env-registry.ts +78 -8
  296. package/src/config/feature-flag-registry.json +38 -125
  297. package/src/config/schema.ts +8 -0
  298. package/src/config/schemas/filing.ts +51 -0
  299. package/src/config/schemas/heartbeat.ts +15 -12
  300. package/src/config/schemas/memory-lifecycle.ts +12 -0
  301. package/src/config/schemas/platform.ts +8 -0
  302. package/src/config/schemas/security.ts +14 -0
  303. package/src/config/schemas/timeouts.ts +1 -1
  304. package/src/config/skills.ts +18 -7
  305. package/src/context/token-estimator.ts +25 -18
  306. package/src/context/window-manager.ts +6 -2
  307. package/src/credential-execution/process-manager.ts +3 -1
  308. package/src/daemon/app-source-watcher.ts +93 -0
  309. package/src/daemon/config-watcher.ts +79 -1
  310. package/src/daemon/context-overflow-reducer.ts +46 -2
  311. package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
  312. package/src/daemon/conversation-agent-loop.ts +236 -108
  313. package/src/daemon/conversation-error.ts +31 -8
  314. package/src/daemon/conversation-history.ts +4 -19
  315. package/src/daemon/conversation-lifecycle.ts +36 -9
  316. package/src/daemon/conversation-media-retry.ts +85 -7
  317. package/src/daemon/conversation-notifiers.ts +4 -1
  318. package/src/daemon/conversation-process.ts +13 -7
  319. package/src/daemon/conversation-runtime-assembly.ts +305 -306
  320. package/src/daemon/conversation-tool-setup.ts +44 -14
  321. package/src/daemon/conversation-workspace.ts +1 -2
  322. package/src/daemon/conversation.ts +59 -2
  323. package/src/daemon/daemon-control.ts +8 -2
  324. package/src/daemon/date-context.ts +26 -53
  325. package/src/daemon/first-greeting.ts +1 -1
  326. package/src/daemon/handlers/conversations.ts +4 -7
  327. package/src/daemon/handlers/shared.test.ts +143 -0
  328. package/src/daemon/handlers/shared.ts +85 -17
  329. package/src/daemon/handlers/skills.ts +416 -209
  330. package/src/daemon/lifecycle.ts +212 -131
  331. package/src/daemon/main.ts +5 -1
  332. package/src/daemon/message-types/conversations.ts +29 -7
  333. package/src/daemon/message-types/messages.ts +12 -2
  334. package/src/daemon/message-types/schedules.ts +1 -0
  335. package/src/daemon/message-types/settings.ts +6 -0
  336. package/src/daemon/message-types/skills.ts +97 -36
  337. package/src/daemon/profiler-run-store.ts +557 -0
  338. package/src/daemon/providers-setup.ts +5 -0
  339. package/src/daemon/server.ts +100 -11
  340. package/src/daemon/shutdown-handlers.ts +5 -0
  341. package/src/daemon/tool-side-effects.ts +50 -8
  342. package/src/export/transcript-formatter.ts +148 -0
  343. package/src/filing/filing-service.ts +228 -0
  344. package/src/heartbeat/heartbeat-service.ts +97 -7
  345. package/src/hooks/cli.ts +2 -2
  346. package/src/hooks/runner.ts +15 -38
  347. package/src/inbound/platform-callback-registration.ts +14 -14
  348. package/src/mcp/client.ts +6 -0
  349. package/src/mcp/mcp-oauth-provider.ts +149 -27
  350. package/src/memory/admin.ts +42 -75
  351. package/src/memory/app-store.ts +69 -0
  352. package/src/memory/conversation-bootstrap.ts +3 -1
  353. package/src/memory/conversation-crud.ts +211 -288
  354. package/src/memory/conversation-group-migration.ts +157 -0
  355. package/src/memory/conversation-queries.ts +61 -13
  356. package/src/memory/conversation-title-service.ts +1 -0
  357. package/src/memory/db-init.ts +194 -361
  358. package/src/memory/embed.ts +73 -0
  359. package/src/memory/embedding-backend.ts +8 -14
  360. package/src/memory/embedding-runtime-manager.ts +12 -114
  361. package/src/memory/fingerprint.ts +2 -2
  362. package/src/memory/graph/bootstrap.ts +521 -0
  363. package/src/memory/graph/capability-seed.ts +449 -0
  364. package/src/memory/graph/consolidation.ts +725 -0
  365. package/src/memory/graph/conversation-graph-memory.ts +659 -0
  366. package/src/memory/graph/decay.test.ts +208 -0
  367. package/src/memory/graph/decay.ts +195 -0
  368. package/src/memory/graph/extraction-job.ts +74 -0
  369. package/src/memory/graph/extraction.test.ts +936 -0
  370. package/src/memory/graph/extraction.ts +1297 -0
  371. package/src/memory/graph/graph-memory-state-store.ts +37 -0
  372. package/src/memory/graph/graph-search.ts +280 -0
  373. package/src/memory/graph/image-ref-utils.ts +29 -0
  374. package/src/memory/graph/injection.test.ts +513 -0
  375. package/src/memory/graph/injection.ts +469 -0
  376. package/src/memory/graph/inspect.ts +543 -0
  377. package/src/memory/graph/narrative.ts +267 -0
  378. package/src/memory/graph/pattern-scan.ts +269 -0
  379. package/src/memory/graph/retriever.ts +1111 -0
  380. package/src/memory/graph/scoring.test.ts +548 -0
  381. package/src/memory/graph/scoring.ts +232 -0
  382. package/src/memory/graph/serendipity.ts +65 -0
  383. package/src/memory/graph/store.test.ts +1098 -0
  384. package/src/memory/graph/store.ts +838 -0
  385. package/src/memory/graph/tool-handlers.ts +301 -0
  386. package/src/memory/graph/tools.ts +97 -0
  387. package/src/memory/graph/triggers.test.ts +487 -0
  388. package/src/memory/graph/triggers.ts +223 -0
  389. package/src/memory/graph/types.ts +295 -0
  390. package/src/memory/group-crud.ts +191 -0
  391. package/src/memory/indexer.ts +37 -19
  392. package/src/memory/job-handlers/cleanup.ts +32 -42
  393. package/src/memory/job-handlers/conversation-starters.ts +91 -53
  394. package/src/memory/job-handlers/embedding.ts +5 -31
  395. package/src/memory/job-handlers/index-maintenance.ts +23 -11
  396. package/src/memory/job-handlers/summarization.ts +32 -17
  397. package/src/memory/job-utils.ts +1 -1
  398. package/src/memory/jobs-store.ts +21 -31
  399. package/src/memory/jobs-worker.ts +180 -129
  400. package/src/memory/llm-request-log-store.ts +96 -12
  401. package/src/memory/memory-recall-log-store.ts +49 -5
  402. package/src/memory/message-content.ts +1 -0
  403. package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
  404. package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
  405. package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
  406. package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
  407. package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
  408. package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
  409. package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
  410. package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
  411. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
  412. package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
  413. package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
  414. package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
  415. package/src/memory/migrations/index.ts +12 -0
  416. package/src/memory/migrations/registry.ts +16 -0
  417. package/src/memory/qdrant-client.ts +44 -17
  418. package/src/memory/schema/conversations.ts +14 -0
  419. package/src/memory/schema/index.ts +1 -0
  420. package/src/memory/schema/infrastructure.ts +8 -1
  421. package/src/memory/schema/memory-core.ts +0 -51
  422. package/src/memory/schema/memory-graph.ts +154 -0
  423. package/src/memory/search/semantic.ts +47 -91
  424. package/src/memory/task-memory-cleanup.ts +58 -61
  425. package/src/messaging/providers/outlook/adapter.ts +8 -1
  426. package/src/messaging/providers/outlook/client.ts +299 -0
  427. package/src/messaging/providers/outlook/types.ts +118 -0
  428. package/src/notifications/adapters/macos.ts +1 -0
  429. package/src/notifications/copy-composer.ts +95 -0
  430. package/src/notifications/decision-engine.ts +35 -0
  431. package/src/notifications/signal.ts +16 -0
  432. package/src/oauth/seed-providers.ts +2 -1
  433. package/src/permissions/checker.ts +36 -4
  434. package/src/permissions/defaults.ts +4 -4
  435. package/src/permissions/permission-mode-store.ts +180 -0
  436. package/src/permissions/permission-mode.ts +31 -0
  437. package/src/permissions/workspace-policy.ts +10 -1
  438. package/src/playbooks/playbook-compiler.ts +19 -18
  439. package/src/playbooks/types.ts +4 -3
  440. package/src/prompts/system-prompt.ts +62 -36
  441. package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
  442. package/src/prompts/templates/BOOTSTRAP.md +70 -165
  443. package/src/prompts/templates/HEARTBEAT.md +3 -1
  444. package/src/prompts/templates/SOUL.md +25 -4
  445. package/src/prompts/templates/UPDATES.md +8 -0
  446. package/src/providers/anthropic/client.ts +136 -220
  447. package/src/providers/gemini/client.ts +1 -1
  448. package/src/providers/openai/client.ts +1 -1
  449. package/src/providers/registry.ts +1 -1
  450. package/src/providers/retry.ts +19 -3
  451. package/src/runtime/actor-trust-resolver.ts +5 -1
  452. package/src/runtime/auth/route-policy.ts +30 -0
  453. package/src/runtime/guardian-reply-router.ts +5 -1
  454. package/src/runtime/http-server.ts +55 -5
  455. package/src/runtime/http-types.ts +12 -1
  456. package/src/runtime/middleware/auth.ts +20 -0
  457. package/src/runtime/migrations/vbundle-builder.ts +389 -3
  458. package/src/runtime/migrations/vbundle-importer.ts +8 -6
  459. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
  460. package/src/runtime/routes/app-management-routes.ts +1 -11
  461. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
  462. package/src/runtime/routes/archive-utils.ts +29 -0
  463. package/src/runtime/routes/attachment-routes.test.ts +106 -0
  464. package/src/runtime/routes/attachment-routes.ts +106 -16
  465. package/src/runtime/routes/avatar-routes.ts +2 -9
  466. package/src/runtime/routes/brain-graph-routes.ts +21 -22
  467. package/src/runtime/routes/btw-routes.ts +22 -1
  468. package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
  469. package/src/runtime/routes/conversation-management-routes.ts +3 -14
  470. package/src/runtime/routes/conversation-query-routes.ts +49 -3
  471. package/src/runtime/routes/conversation-routes.ts +264 -44
  472. package/src/runtime/routes/conversation-starter-routes.ts +2 -2
  473. package/src/runtime/routes/debug-routes.ts +1 -1
  474. package/src/runtime/routes/global-search-routes.ts +21 -19
  475. package/src/runtime/routes/group-routes.ts +207 -0
  476. package/src/runtime/routes/guardian-action-routes.ts +21 -10
  477. package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
  478. package/src/runtime/routes/heartbeat-routes.ts +4 -10
  479. package/src/runtime/routes/identity-routes.ts +53 -18
  480. package/src/runtime/routes/inbound-message-handler.ts +19 -0
  481. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
  482. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
  483. package/src/runtime/routes/llm-context-normalization.ts +14 -10
  484. package/src/runtime/routes/log-export-routes.ts +23 -275
  485. package/src/runtime/routes/memory-item-routes.test.ts +170 -247
  486. package/src/runtime/routes/memory-item-routes.ts +341 -388
  487. package/src/runtime/routes/migration-routes.ts +18 -7
  488. package/src/runtime/routes/profiler-routes.ts +350 -0
  489. package/src/runtime/routes/schedule-routes.ts +28 -11
  490. package/src/runtime/routes/settings-routes.ts +95 -8
  491. package/src/runtime/routes/skills-routes.ts +103 -37
  492. package/src/runtime/routes/subagents-routes.ts +28 -7
  493. package/src/runtime/routes/user-route-dispatcher.ts +223 -0
  494. package/src/runtime/routes/user-routes.ts +41 -0
  495. package/src/runtime/routes/work-items-routes.test.ts +2 -6
  496. package/src/runtime/routes/workspace-routes.ts +0 -1
  497. package/src/schedule/schedule-store.ts +30 -0
  498. package/src/schedule/scheduler.ts +52 -18
  499. package/src/security/oauth2.ts +1 -1
  500. package/src/security/secure-keys.ts +4 -8
  501. package/src/shared/provider-env-vars.ts +19 -0
  502. package/src/skills/catalog-cache.ts +5 -0
  503. package/src/skills/catalog-install.ts +25 -16
  504. package/src/skills/clawhub.ts +134 -154
  505. package/src/skills/install-meta.ts +208 -0
  506. package/src/skills/managed-store.ts +29 -18
  507. package/src/skills/skill-memory.ts +12 -229
  508. package/src/skills/skillssh-registry.ts +19 -17
  509. package/src/subagent/index.ts +13 -3
  510. package/src/subagent/manager.ts +308 -29
  511. package/src/subagent/types.ts +68 -0
  512. package/src/tasks/task-runner.ts +7 -5
  513. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
  514. package/src/tools/apps/executors.ts +29 -4
  515. package/src/tools/browser/runtime-check.ts +3 -1
  516. package/src/tools/filesystem/list.ts +93 -0
  517. package/src/tools/memory/register.ts +63 -46
  518. package/src/tools/permission-checker.ts +85 -1
  519. package/src/tools/registry.ts +4 -0
  520. package/src/tools/schedule/create.ts +3 -0
  521. package/src/tools/schedule/list.ts +1 -0
  522. package/src/tools/schedule/update.ts +6 -0
  523. package/src/tools/shared/filesystem/errors.ts +5 -0
  524. package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
  525. package/src/tools/shared/filesystem/image-read.ts +22 -85
  526. package/src/tools/shared/filesystem/types.ts +17 -0
  527. package/src/tools/shared/shell-output.ts +31 -2
  528. package/src/tools/subagent/abort.ts +12 -2
  529. package/src/tools/subagent/message.ts +9 -2
  530. package/src/tools/subagent/notify-parent.ts +79 -0
  531. package/src/tools/subagent/read.ts +29 -8
  532. package/src/tools/subagent/resolve.ts +21 -0
  533. package/src/tools/subagent/spawn.ts +2 -0
  534. package/src/tools/subagent/status.ts +11 -1
  535. package/src/tools/system/avatar-generator.ts +3 -3
  536. package/src/tools/system/register.ts +23 -0
  537. package/src/tools/system/set-permission-mode.ts +103 -0
  538. package/src/tools/terminal/parser.ts +30 -5
  539. package/src/tools/terminal/safe-env.ts +17 -1
  540. package/src/tools/tool-manifest.ts +9 -3
  541. package/src/tools/types.ts +2 -0
  542. package/src/util/browser.ts +25 -10
  543. package/src/util/bun-runtime.ts +172 -0
  544. package/src/util/logger.ts +1 -1
  545. package/src/util/platform.ts +50 -17
  546. package/src/watcher/providers/outlook-calendar.ts +343 -0
  547. package/src/watcher/providers/outlook.ts +198 -0
  548. package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
  549. package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
  550. package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
  551. package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
  552. package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
  553. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
  554. package/src/workspace/migrations/029-seed-pkb.ts +84 -0
  555. package/src/workspace/migrations/registry.ts +10 -0
  556. package/src/workspace/top-level-renderer.ts +5 -9
  557. package/src/__tests__/cli-memory.test.ts +0 -372
  558. package/src/__tests__/clipboard.test.ts +0 -88
  559. package/src/__tests__/context-memory-e2e.test.ts +0 -415
  560. package/src/__tests__/journal-context.test.ts +0 -268
  561. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
  562. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
  563. package/src/__tests__/memory-query-builder.test.ts +0 -59
  564. package/src/__tests__/memory-recall-quality.test.ts +0 -1046
  565. package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
  566. package/src/__tests__/memory-regressions.test.ts +0 -3696
  567. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
  568. package/src/cli/cli-memory.ts +0 -176
  569. package/src/daemon/conversation-memory.ts +0 -207
  570. package/src/memory/conversation-starters-cadence.ts +0 -74
  571. package/src/memory/items-extractor.ts +0 -860
  572. package/src/memory/job-handlers/batch-extraction.ts +0 -753
  573. package/src/memory/job-handlers/extraction.ts +0 -40
  574. package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
  575. package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
  576. package/src/memory/journal-memory.ts +0 -224
  577. package/src/memory/query-builder.ts +0 -47
  578. package/src/memory/query-expansion.ts +0 -83
  579. package/src/memory/retriever.test.ts +0 -1592
  580. package/src/memory/retriever.ts +0 -1331
  581. package/src/memory/search/formatting.test.ts +0 -140
  582. package/src/memory/search/formatting.ts +0 -262
  583. package/src/memory/search/mmr.ts +0 -139
  584. package/src/memory/search/ranking.ts +0 -15
  585. package/src/memory/search/staleness.ts +0 -40
  586. package/src/memory/search/tier-classifier.ts +0 -18
  587. package/src/memory/search/types.ts +0 -121
  588. package/src/prompts/journal-context.ts +0 -154
  589. package/src/tools/memory/definitions.ts +0 -69
  590. package/src/tools/memory/handlers.test.ts +0 -562
  591. package/src/tools/memory/handlers.ts +0 -434
  592. package/src/util/clipboard.ts +0 -34
@@ -11,7 +11,7 @@
11
11
  * 4. activated — when the trusted contact successfully verifies
12
12
  * 5. denied — when the guardian denies the request
13
13
  */
14
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
14
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
15
15
 
16
16
  // ---------------------------------------------------------------------------
17
17
  // Test isolation: in-memory SQLite via temp directory
@@ -70,17 +70,13 @@ import {
70
70
  createGuardianBinding,
71
71
  upsertContactChannel,
72
72
  } from "../contacts/contacts-write.js";
73
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
73
+ import { getDb, initializeDb } from "../memory/db.js";
74
74
  import { createApprovalRequest } from "../memory/guardian-approvals.js";
75
75
  import { createOutboundSession } from "../runtime/channel-verification-service.js";
76
76
  import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
77
77
 
78
78
  initializeDb();
79
79
 
80
- afterAll(() => {
81
- resetDb();
82
- });
83
-
84
80
  // ---------------------------------------------------------------------------
85
81
  // Helpers
86
82
  // ---------------------------------------------------------------------------
@@ -137,7 +133,7 @@ describe("trusted contact lifecycle notification signals", () => {
137
133
  resetState();
138
134
  });
139
135
 
140
- test("guardian deny emits guardian_decision and denied signals", async () => {
136
+ test("guardian deny emits guardian_decision and denied signals with display names", async () => {
141
137
  // Set up guardian binding and member record (guardians must pass ACL)
142
138
  createGuardianBinding({
143
139
  channel: "telegram",
@@ -152,6 +148,17 @@ describe("trusted contact lifecycle notification signals", () => {
152
148
  externalChatId: "guardian-chat-789",
153
149
  status: "active",
154
150
  policy: "allow",
151
+ displayName: "Guardian Bob",
152
+ });
153
+
154
+ // Set up requester contact with a display name so payloads are enriched
155
+ upsertContactChannel({
156
+ sourceChannel: "telegram",
157
+ externalUserId: "requester-user-456",
158
+ externalChatId: "requester-chat-456",
159
+ status: "pending",
160
+ policy: "ask",
161
+ displayName: "Alice Requester",
155
162
  });
156
163
 
157
164
  const testRequestId = `req-deny-${Date.now()}`;
@@ -203,11 +210,15 @@ describe("trusted contact lifecycle notification signals", () => {
203
210
  expect(gdPayload.decision).toBe("denied");
204
211
  expect(gdPayload.requesterExternalUserId).toBe("requester-user-456");
205
212
  expect(gdPayload.decidedByExternalUserId).toBe("guardian-user-789");
213
+ expect(gdPayload.requesterDisplayName).toBe("Alice Requester");
214
+ expect(gdPayload.decidedByDisplayName).toBe("Guardian Bob");
206
215
 
207
216
  // Verify denied payload
208
217
  const dPayload = deniedSignals[0].contextPayload as Record<string, unknown>;
209
218
  expect(dPayload.decision).toBe("denied");
210
219
  expect(dPayload.requesterExternalUserId).toBe("requester-user-456");
220
+ expect(dPayload.requesterDisplayName).toBe("Alice Requester");
221
+ expect(dPayload.decidedByDisplayName).toBe("Guardian Bob");
211
222
 
212
223
  // Verify deduplication keys are distinct
213
224
  expect(guardianDecisionSignals[0].dedupeKey).toContain(
@@ -216,7 +227,7 @@ describe("trusted contact lifecycle notification signals", () => {
216
227
  expect(deniedSignals[0].dedupeKey).toContain("trusted-contact:denied:");
217
228
  });
218
229
 
219
- test("guardian approve emits guardian_decision and verification_sent signals", async () => {
230
+ test("guardian approve emits guardian_decision and verification_sent signals with display names", async () => {
220
231
  // Set up guardian binding and member record (guardians must pass ACL)
221
232
  createGuardianBinding({
222
233
  channel: "telegram",
@@ -231,6 +242,17 @@ describe("trusted contact lifecycle notification signals", () => {
231
242
  externalChatId: "guardian-chat-789",
232
243
  status: "active",
233
244
  policy: "allow",
245
+ displayName: "Guardian Bob",
246
+ });
247
+
248
+ // Set up requester contact with a display name
249
+ upsertContactChannel({
250
+ sourceChannel: "telegram",
251
+ externalUserId: "requester-user-456",
252
+ externalChatId: "requester-chat-456",
253
+ status: "pending",
254
+ policy: "ask",
255
+ displayName: "Alice Requester",
234
256
  });
235
257
 
236
258
  const testRequestId = `req-approve-${Date.now()}`;
@@ -280,6 +302,8 @@ describe("trusted contact lifecycle notification signals", () => {
280
302
  const vsPayload = vsSignal.contextPayload as Record<string, unknown>;
281
303
  expect(vsPayload.requesterExternalUserId).toBe("requester-user-456");
282
304
  expect(vsPayload.verificationSessionId).toBeDefined();
305
+ expect(vsPayload.requesterDisplayName).toBe("Alice Requester");
306
+ expect(vsPayload.decidedByDisplayName).toBe("Guardian Bob");
283
307
  expect(
284
308
  (vsSignal.attentionHints as Record<string, unknown>).visibleInSourceNow,
285
309
  ).toBe(true);
@@ -344,6 +368,92 @@ describe("trusted contact lifecycle notification signals", () => {
344
368
  // guardian_decision and denied — both keyed on approval.id
345
369
  expect(signals.length).toBe(2);
346
370
  });
371
+
372
+ test("display name fields fall back to null when contacts have no display name", async () => {
373
+ // Set up guardian binding — createGuardianBinding creates a contact with
374
+ // displayName defaulting to the externalUserId. We need to verify the
375
+ // null-fallback path for display name resolution, so we use a guardian
376
+ // whose external user ID does NOT have a matching contact_channels row.
377
+ //
378
+ // Strategy: create the guardian binding normally (so the sender is
379
+ // classified as trustClass="guardian"), then use a DIFFERENT external
380
+ // user ID in the approval request's guardianExternalUserId field. The
381
+ // decidedByExternalUserId comes from actorExternalId (the real guardian),
382
+ // which DOES have a contact. To truly get null, we clear the guardian
383
+ // contact's displayName to empty string after creation — the signal
384
+ // enrichment code treats empty string the same as null for display
385
+ // purposes.
386
+ createGuardianBinding({
387
+ channel: "telegram",
388
+ guardianExternalUserId: "guardian-noname-111",
389
+ guardianDeliveryChatId: "guardian-chat-111",
390
+ guardianPrincipalId: "guardian-noname-111",
391
+ verifiedVia: "test",
392
+ });
393
+
394
+ // Clear the guardian contact's displayName to empty string so the
395
+ // display name resolution returns a falsy value. createGuardianBinding
396
+ // defaults displayName to the externalUserId, which would be a non-empty
397
+ // string and defeat the purpose of this test.
398
+ const db = getDb();
399
+ db.run("UPDATE contacts SET display_name = '' WHERE role = 'guardian'");
400
+
401
+ // Do NOT create a requester contact — display name should resolve to null
402
+
403
+ const testRequestId = `req-noname-${Date.now()}`;
404
+
405
+ createApprovalRequest({
406
+ runId: `ingress-access-request-${Date.now()}`,
407
+ requestId: testRequestId,
408
+ conversationId: "access-req-telegram-requester-noname-222",
409
+ channel: "telegram",
410
+ requesterExternalUserId: "requester-noname-222",
411
+ requesterChatId: "requester-chat-222",
412
+ guardianExternalUserId: "guardian-noname-111",
413
+ guardianChatId: "guardian-chat-111",
414
+ toolName: "ingress_access_request",
415
+ riskLevel: "access_request",
416
+ reason: "Unknown user requesting access",
417
+ expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
418
+ });
419
+
420
+ // Guardian denies via callback button
421
+ const guardianReq = buildInboundRequest({
422
+ conversationExternalId: "guardian-chat-111",
423
+ actorExternalId: "guardian-noname-111",
424
+ actorDisplayName: "Guardian",
425
+ content: "",
426
+ callbackData: `apr:${testRequestId}:reject`,
427
+ });
428
+
429
+ await handleChannelInbound(guardianReq, undefined, TEST_BEARER_TOKEN);
430
+
431
+ const guardianDecisionSignals = emitSignalCalls.filter(
432
+ (c) => c.sourceEventName === "ingress.trusted_contact.guardian_decision",
433
+ );
434
+ const deniedSignals = emitSignalCalls.filter(
435
+ (c) => c.sourceEventName === "ingress.trusted_contact.denied",
436
+ );
437
+
438
+ expect(guardianDecisionSignals.length).toBe(1);
439
+ expect(deniedSignals.length).toBe(1);
440
+
441
+ // Verify display names fall back to null/empty when contacts have no
442
+ // display name set.
443
+ const gdPayload = guardianDecisionSignals[0].contextPayload as Record<
444
+ string,
445
+ unknown
446
+ >;
447
+ expect(gdPayload.requesterDisplayName).toBeNull();
448
+ // Guardian contact exists but displayName was cleared to empty string.
449
+ // The signal enrichment resolves displayName from the contact record,
450
+ // so decidedByDisplayName will be "" (empty string) rather than null.
451
+ expect(gdPayload.decidedByDisplayName).toBe("");
452
+
453
+ const dPayload = deniedSignals[0].contextPayload as Record<string, unknown>;
454
+ expect(dPayload.requesterDisplayName).toBeNull();
455
+ expect(dPayload.decidedByDisplayName).toBe("");
456
+ });
347
457
  });
348
458
 
349
459
  // ---------------------------------------------------------------------------
@@ -6,7 +6,7 @@
6
6
  * These tests confirm no channel-specific assumptions leaked into the
7
7
  * trusted contact code paths.
8
8
  */
9
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
9
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
10
10
 
11
11
  // ---------------------------------------------------------------------------
12
12
  // Test isolation: in-memory SQLite via temp directory
@@ -78,7 +78,7 @@ import {
78
78
  createGuardianBinding,
79
79
  upsertContactChannel,
80
80
  } from "../contacts/contacts-write.js";
81
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
81
+ import { getDb, initializeDb } from "../memory/db.js";
82
82
  import {
83
83
  createOutboundSession,
84
84
  validateAndConsumeVerification,
@@ -87,10 +87,6 @@ import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
87
87
 
88
88
  initializeDb();
89
89
 
90
- afterAll(() => {
91
- resetDb();
92
- });
93
-
94
90
  // ---------------------------------------------------------------------------
95
91
  // Helpers
96
92
  // ---------------------------------------------------------------------------
@@ -9,7 +9,7 @@
9
9
  * 4. Reactivate previously revoked members on re-verification
10
10
  * 5. NOT create a guardian binding (trusted contacts are not guardians)
11
11
  */
12
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
12
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
13
13
 
14
14
  // ---------------------------------------------------------------------------
15
15
  // Test isolation: in-memory SQLite via temp directory
@@ -31,7 +31,7 @@ import {
31
31
  revokeMember,
32
32
  upsertContactChannel,
33
33
  } from "../contacts/contacts-write.js";
34
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
34
+ import { getDb, initializeDb } from "../memory/db.js";
35
35
  import { resolveActorTrust } from "../runtime/actor-trust-resolver.js";
36
36
  import {
37
37
  createOutboundSession,
@@ -40,10 +40,6 @@ import {
40
40
 
41
41
  initializeDb();
42
42
 
43
- afterAll(() => {
44
- resetDb();
45
- });
46
-
47
43
  // ---------------------------------------------------------------------------
48
44
  // Helpers
49
45
  // ---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  mock.module("../util/logger.js", () => ({
4
4
  getLogger: () =>
@@ -23,7 +23,7 @@ import {
23
23
  createConversation,
24
24
  getAssistantMessageIdsInTurn,
25
25
  } from "../memory/conversation-crud.js";
26
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
26
+ import { getDb, initializeDb } from "../memory/db.js";
27
27
  import { llmRequestLogs, toolInvocations } from "../memory/schema.js";
28
28
 
29
29
  initializeDb();
@@ -49,10 +49,6 @@ function toolResultContent(toolUseIds: string[]): string {
49
49
  );
50
50
  }
51
51
 
52
- afterAll(() => {
53
- resetDb();
54
- });
55
-
56
52
  describe("getAssistantMessageIdsInTurn", () => {
57
53
  beforeEach(() => {
58
54
  resetTables();
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  let mockPricingOverrides: Array<{
4
4
  provider: string;
@@ -26,7 +26,6 @@ import {
26
26
  initializeDb,
27
27
  rawGet,
28
28
  rawRun,
29
- resetDb,
30
29
  } from "../memory/db.js";
31
30
  import { migrateBackfillUsageCacheAccounting } from "../memory/migrations/140-backfill-usage-cache-accounting.js";
32
31
  import type { PricingUsage } from "../usage/types.js";
@@ -145,10 +144,6 @@ function foreignResponsePayload(): string {
145
144
  });
146
145
  }
147
146
 
148
- afterAll(() => {
149
- resetDb();
150
- });
151
-
152
147
  describe("migrateBackfillUsageCacheAccounting", () => {
153
148
  beforeEach(() => {
154
149
  getSqlite().run(`DELETE FROM llm_request_logs`);
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  mock.module("../util/logger.js", () => ({
4
4
  getLogger: () =>
@@ -7,16 +7,12 @@ mock.module("../util/logger.js", () => ({
7
7
  }),
8
8
  }));
9
9
 
10
- import { getSqlite, initializeDb, resetDb } from "../memory/db.js";
10
+ import { getSqlite, initializeDb } from "../memory/db.js";
11
11
  import { recordUsageEvent } from "../memory/llm-usage-store.js";
12
12
  import { usageRouteDefinitions } from "../runtime/routes/usage-routes.js";
13
13
 
14
14
  initializeDb();
15
15
 
16
- afterAll(() => {
17
- resetDb();
18
- });
19
-
20
16
  function clearUsageEvents() {
21
17
  getSqlite().run("DELETE FROM llm_usage_events");
22
18
  }
@@ -129,14 +129,12 @@ function makePrompter(): PermissionPrompter {
129
129
  } as unknown as PermissionPrompter;
130
130
  }
131
131
 
132
- import { resetDb } from "../memory/db.js";
133
132
  import { initializeDb } from "../memory/db-init.js";
134
133
 
135
134
  beforeAll(() => {
136
135
  initializeDb();
137
136
  });
138
137
  afterAll(() => {
139
- resetDb();
140
138
  mock.restore();
141
139
  });
142
140
 
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  mock.module("../util/logger.js", () => ({
4
4
  getLogger: () =>
@@ -13,17 +13,13 @@ import {
13
13
  upsertContact,
14
14
  } from "../contacts/contact-store.js";
15
15
  import { upsertContactChannel } from "../contacts/contacts-write.js";
16
- import { getSqlite, initializeDb, resetDb } from "../memory/db.js";
16
+ import { getSqlite, initializeDb } from "../memory/db.js";
17
17
  import { createInvite, revokeInvite } from "../memory/invite-store.js";
18
18
  import { redeemVoiceInviteCode } from "../runtime/invite-redemption-service.js";
19
19
  import { generateVoiceCode, hashVoiceCode } from "../util/voice-code.js";
20
20
 
21
21
  initializeDb();
22
22
 
23
- afterAll(() => {
24
- resetDb();
25
- });
26
-
27
23
  function resetTables() {
28
24
  getSqlite().run("DELETE FROM assistant_ingress_invites");
29
25
  getSqlite().run("DELETE FROM contact_channels");
@@ -16,7 +16,7 @@
16
16
  * 4. Grants are revoked on call end (controller.destroy).
17
17
  */
18
18
 
19
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
19
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
20
20
 
21
21
  // ── Platform + logger mocks (must come before any source imports) ────
22
22
 
@@ -82,7 +82,7 @@ import {
82
82
  } from "../calls/voice-session-bridge.js";
83
83
  import type { TrustContext } from "../daemon/conversation-runtime-assembly.js";
84
84
  import type { ServerMessage } from "../daemon/message-protocol.js";
85
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
85
+ import { getDb, initializeDb } from "../memory/db.js";
86
86
  import { scopedApprovalGrants } from "../memory/schema.js";
87
87
  import {
88
88
  _internal,
@@ -95,10 +95,6 @@ import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
95
95
 
96
96
  initializeDb();
97
97
 
98
- afterAll(() => {
99
- resetDb();
100
- });
101
-
102
98
  // ---------------------------------------------------------------------------
103
99
  // Mock session that triggers a confirmation_request on processMessage
104
100
  // ---------------------------------------------------------------------------
@@ -1,4 +1,4 @@
1
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { Conversation } from "../daemon/conversation.js";
4
4
  import type { ServerMessage } from "../daemon/message-protocol.js";
@@ -32,7 +32,7 @@ import {
32
32
  startVoiceTurn,
33
33
  } from "../calls/voice-session-bridge.js";
34
34
  import { createConversation } from "../memory/conversation-crud.js";
35
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
35
+ import { getDb, initializeDb } from "../memory/db.js";
36
36
 
37
37
  initializeDb();
38
38
 
@@ -1017,7 +1017,3 @@ describe("voice-session-bridge", () => {
1017
1017
  expect(abortCalled).toBe(true);
1018
1018
  });
1019
1019
  });
1020
-
1021
- afterAll(() => {
1022
- resetDb();
1023
- });
@@ -38,6 +38,8 @@ const ALLOWED_FILES = new Set([
38
38
  "assistant/src/cli/commands/trust.ts",
39
39
  // Auth middleware documentation comment (not a file access)
40
40
  "assistant/src/runtime/auth/middleware.ts",
41
+ // Permission checker: classifies file_read of signing key as High risk
42
+ "assistant/src/permissions/checker.ts",
41
43
  ]);
42
44
 
43
45
  // ---------------------------------------------------------------------------
@@ -6,7 +6,13 @@
6
6
  * in the same flow a real daemon conversation would follow.
7
7
  */
8
8
  import { execFileSync } from "node:child_process";
9
- import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
9
+ import {
10
+ existsSync,
11
+ mkdirSync,
12
+ rmSync,
13
+ unlinkSync,
14
+ writeFileSync,
15
+ } from "node:fs";
10
16
  import { tmpdir } from "node:os";
11
17
  import { join } from "node:path";
12
18
  import {
@@ -23,6 +29,7 @@ import {
23
29
  getEnrichmentService,
24
30
  } from "../workspace/commit-message-enrichment-service.js";
25
31
  import {
32
+ _resetBreaker,
26
33
  _resetGitServiceRegistry,
27
34
  getWorkspaceGitService,
28
35
  WorkspaceGitService,
@@ -184,6 +191,27 @@ describe("Workspace git lifecycle (integration)", () => {
184
191
  await commitTurnChanges(testDir, conversationId, 3);
185
192
  expect(commitCount(testDir)).toBe(3); // Still 3
186
193
 
194
+ // Drain fire-and-forget enrichment from turn commits before heartbeat
195
+ // testing. Enrichment's writeNote() can leave a stale index.lock on
196
+ // some git versions (see heartbeat-service.ts:240-242), causing the
197
+ // heartbeat commit to fail with "index.lock: File exists".
198
+ await getEnrichmentService().shutdown();
199
+ _resetEnrichmentService();
200
+
201
+ // On CI, the enrichment service's spawned git child processes may still
202
+ // be alive briefly after the queue drains, holding index.lock. Remove it
203
+ // unconditionally and reset the circuit breaker so the heartbeat portion
204
+ // starts clean.
205
+ const lockPath = join(testDir, ".git", "index.lock");
206
+ if (existsSync(lockPath)) {
207
+ try {
208
+ unlinkSync(lockPath);
209
+ } catch {
210
+ /* race: already gone */
211
+ }
212
+ }
213
+ _resetBreaker(service);
214
+
187
215
  // ----------------------------------------------------------------
188
216
  // Step 5: Heartbeat safety net — simulate uncommitted changes
189
217
  // that linger past the age threshold
@@ -7,7 +7,7 @@ import {
7
7
  writeFileSync,
8
8
  } from "node:fs";
9
9
  import { join } from "node:path";
10
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
11
 
12
12
  // ---------------------------------------------------------------------------
13
13
  // Mocks — must come before any imports that depend on them
@@ -40,7 +40,7 @@ mock.module("../config/loader.js", () => ({
40
40
  // ---------------------------------------------------------------------------
41
41
 
42
42
  import { getConversationDirPath } from "../memory/conversation-disk-view.js";
43
- import { getDb, initializeDb, resetDb } from "../memory/db.js";
43
+ import { getDb, initializeDb } from "../memory/db.js";
44
44
  import {
45
45
  attachments,
46
46
  conversations,
@@ -51,10 +51,6 @@ import { backfillConversationDiskViewMigration } from "../workspace/migrations/0
51
51
 
52
52
  initializeDb();
53
53
 
54
- afterAll(() => {
55
- resetDb();
56
- });
57
-
58
54
  function resetTables() {
59
55
  const db = getDb();
60
56
  db.run("DELETE FROM message_attachments");
@@ -7,7 +7,7 @@ import {
7
7
  writeFileSync,
8
8
  } from "node:fs";
9
9
  import { join } from "node:path";
10
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
10
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
11
11
 
12
12
  // ---------------------------------------------------------------------------
13
13
  // Mocks — must come before any imports that depend on them
@@ -40,7 +40,7 @@ mock.module("../config/loader.js", () => ({
40
40
  // ---------------------------------------------------------------------------
41
41
 
42
42
  import { getConversationDirPath } from "../memory/conversation-disk-view.js";
43
- import { getDb, initializeDb, rawRun, resetDb } from "../memory/db.js";
43
+ import { getDb, initializeDb, rawRun } from "../memory/db.js";
44
44
  import {
45
45
  attachments,
46
46
  conversations,
@@ -51,10 +51,6 @@ import { repairConversationDiskViewMigration } from "../workspace/migrations/013
51
51
 
52
52
  initializeDb();
53
53
 
54
- afterAll(() => {
55
- resetDb();
56
- });
57
-
58
54
  function resetTables() {
59
55
  const db = getDb();
60
56
  db.run("DELETE FROM message_attachments");