@vellumai/assistant 0.8.6 → 0.8.7-dev.202606052118.34cd356

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 (1078) hide show
  1. package/AGENTS.md +4 -4
  2. package/Dockerfile +21 -4
  3. package/bun.lock +13 -4
  4. package/docker-entrypoint.sh +12 -8
  5. package/docker-init-apt-root.sh +3 -1
  6. package/docker-kata-apt-env.sh +3 -1
  7. package/docker-kata-runtime-family.sh +12 -0
  8. package/docs/architecture/memory.md +1 -1
  9. package/docs/plugins.md +110 -83
  10. package/examples/plugins/echo/README.md +13 -12
  11. package/examples/plugins/echo/register.ts +0 -54
  12. package/knip.json +1 -0
  13. package/node_modules/@vellumai/environments/bun.lock +24 -0
  14. package/node_modules/@vellumai/environments/package.json +18 -0
  15. package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +95 -0
  16. package/node_modules/@vellumai/environments/src/index.ts +11 -0
  17. package/node_modules/@vellumai/environments/src/seeds.ts +73 -0
  18. package/node_modules/@vellumai/environments/src/types.ts +70 -0
  19. package/node_modules/@vellumai/environments/tsconfig.json +20 -0
  20. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +11 -0
  21. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +3 -4
  22. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  23. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +13 -8
  24. package/openapi.yaml +6964 -539
  25. package/package.json +8 -4
  26. package/scripts/generate-openapi.ts +88 -54
  27. package/src/__tests__/agent-loop-callsite-precedence.test.ts +42 -80
  28. package/src/__tests__/agent-loop-exit-reason.test.ts +188 -45
  29. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +141 -0
  30. package/src/__tests__/agent-loop-override-profile.test.ts +19 -32
  31. package/src/__tests__/agent-loop-provider-error-recording.test.ts +7 -5
  32. package/src/__tests__/agent-loop-thinking.test.ts +17 -12
  33. package/src/__tests__/agent-loop.test.ts +238 -422
  34. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +6 -2
  35. package/src/__tests__/agent-wake-override-profile.test.ts +22 -40
  36. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  37. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  38. package/src/__tests__/anthropic-provider.test.ts +296 -57
  39. package/src/__tests__/app-builder-skill-instructions.test.ts +22 -0
  40. package/src/__tests__/app-control-flow.test.ts +6 -1
  41. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  42. package/src/__tests__/approval-cascade.test.ts +4 -11
  43. package/src/__tests__/approval-routes-http.test.ts +8 -3
  44. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  45. package/src/__tests__/assistant-event.test.ts +15 -0
  46. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  47. package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
  48. package/src/__tests__/assistant-stream-state.test.ts +645 -0
  49. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  50. package/src/__tests__/avatar-e2e.test.ts +7 -37
  51. package/src/__tests__/avatar-generator.test.ts +12 -42
  52. package/src/__tests__/avatar-identity-sync.test.ts +28 -3
  53. package/src/__tests__/background-shell-bash.test.ts +3 -7
  54. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  55. package/src/__tests__/btw-routes.test.ts +69 -15
  56. package/src/__tests__/build-persisted-content.test.ts +184 -0
  57. package/src/__tests__/call-pointer-messages.test.ts +5 -3
  58. package/src/__tests__/call-site-routing-provider.test.ts +22 -40
  59. package/src/__tests__/catalog-files.test.ts +1 -0
  60. package/src/__tests__/channel-approval-routes.test.ts +49 -21
  61. package/src/__tests__/channel-approvals.test.ts +4 -2
  62. package/src/__tests__/channel-invite-transport.test.ts +1 -5
  63. package/src/__tests__/channel-readiness-routes.test.ts +0 -4
  64. package/src/__tests__/channel-readiness-slack-remote.test.ts +2 -7
  65. package/src/__tests__/channel-retry-sweep.test.ts +71 -79
  66. package/src/__tests__/clawhub-files.test.ts +1 -0
  67. package/src/__tests__/compaction-circuit.test.ts +258 -0
  68. package/src/__tests__/compaction-direct.test.ts +132 -0
  69. package/src/__tests__/compaction-events.test.ts +5 -17
  70. package/src/__tests__/compaction-trail-store.test.ts +1 -79
  71. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  72. package/src/__tests__/compactor-image-manifest-trust.test.ts +112 -0
  73. package/src/__tests__/computer-use-tools.test.ts +2 -2
  74. package/src/__tests__/config-watcher.test.ts +28 -0
  75. package/src/__tests__/context-search-agent-runner.test.ts +6 -3
  76. package/src/__tests__/context-token-estimator.test.ts +34 -0
  77. package/src/__tests__/context-window-manager-compact-retry.test.ts +291 -0
  78. package/src/__tests__/conversation-abort-tool-results.test.ts +70 -25
  79. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +9 -7
  80. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -34
  81. package/src/__tests__/conversation-agent-loop-overflow.test.ts +476 -963
  82. package/src/__tests__/conversation-agent-loop.test.ts +823 -1321
  83. package/src/__tests__/conversation-analysis-routes.test.ts +7 -3
  84. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
  85. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  86. package/src/__tests__/conversation-clear-safety.test.ts +20 -10
  87. package/src/__tests__/conversation-confirmation-signals.test.ts +15 -45
  88. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  89. package/src/__tests__/conversation-disk-view.test.ts +10 -17
  90. package/src/__tests__/conversation-fork-crud.test.ts +86 -172
  91. package/src/__tests__/conversation-fork-route.test.ts +16 -14
  92. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  93. package/src/__tests__/conversation-init.benchmark.test.ts +6 -6
  94. package/src/__tests__/conversation-lifecycle.test.ts +3 -2
  95. package/src/__tests__/conversation-load-history-repair.test.ts +3 -2
  96. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -1
  97. package/src/__tests__/conversation-message-sync-tags.test.ts +3 -4
  98. package/src/__tests__/conversation-pairing.test.ts +10 -7
  99. package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
  100. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +10 -0
  101. package/src/__tests__/conversation-process-callsite.test.ts +27 -30
  102. package/src/__tests__/conversation-provider-retry-repair.test.ts +80 -51
  103. package/src/__tests__/conversation-queue.test.ts +272 -164
  104. package/src/__tests__/conversation-routes-disk-view.test.ts +6 -2
  105. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  106. package/src/__tests__/conversation-routes-slash-commands.test.ts +8 -7
  107. package/src/__tests__/conversation-runtime-assembly.test.ts +317 -313
  108. package/src/__tests__/conversation-runtime-workspace.test.ts +114 -36
  109. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  110. package/src/__tests__/conversation-slash-queue.test.ts +42 -31
  111. package/src/__tests__/conversation-slash-unknown.test.ts +13 -15
  112. package/src/__tests__/conversation-speed-override.test.ts +8 -22
  113. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  114. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +90 -15
  115. package/src/__tests__/conversation-surfaces-app-control.test.ts +32 -4
  116. package/src/__tests__/conversation-surfaces-state-update.test.ts +5 -2
  117. package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -15
  118. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  119. package/src/__tests__/conversation-title-service.test.ts +135 -2
  120. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +23 -11
  121. package/src/__tests__/conversation-unread-route.test.ts +14 -2
  122. package/src/__tests__/conversation-usage.test.ts +0 -2
  123. package/src/__tests__/conversation-wipe.test.ts +1 -1
  124. package/src/__tests__/conversation-workspace-cache-state.test.ts +20 -17
  125. package/src/__tests__/conversation-workspace-injection.test.ts +114 -23
  126. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +34 -13
  127. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  128. package/src/__tests__/credential-execution-tools.test.ts +1 -2
  129. package/src/__tests__/credential-security-invariants.test.ts +0 -1
  130. package/src/__tests__/cross-provider-web-search.test.ts +220 -3
  131. package/src/__tests__/cu-unified-flow.test.ts +26 -1
  132. package/src/__tests__/db-acp-history.test.ts +101 -0
  133. package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -0
  134. package/src/__tests__/disk-pressure-guard.test.ts +66 -0
  135. package/src/__tests__/disk-pressure-routes.test.ts +9 -2
  136. package/src/__tests__/dm-persistence.test.ts +12 -3
  137. package/src/__tests__/dynamic-page-surface.test.ts +99 -0
  138. package/src/__tests__/edit-propagation.test.ts +1 -2
  139. package/src/__tests__/empty-response-hook.test.ts +304 -0
  140. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  141. package/src/__tests__/file-write-tool.test.ts +63 -0
  142. package/src/__tests__/filing-service.test.ts +2 -2
  143. package/src/__tests__/first-greeting.test.ts +55 -14
  144. package/src/__tests__/gemini-image-service.test.ts +13 -0
  145. package/src/__tests__/gemini-inline-media.test.ts +78 -0
  146. package/src/__tests__/gemini-provider.test.ts +351 -28
  147. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  148. package/src/__tests__/guardian-routing-invariants.test.ts +2 -4
  149. package/src/__tests__/guardian-routing-state.test.ts +60 -71
  150. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +10 -8
  151. package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
  152. package/src/__tests__/heartbeat-service.test.ts +3 -1
  153. package/src/__tests__/helpers/mock-provider.ts +110 -0
  154. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  155. package/src/__tests__/history-repair-hook.test.ts +162 -0
  156. package/src/__tests__/history-repair-observability.test.ts +1 -1
  157. package/src/__tests__/history-repair.test.ts +2 -1
  158. package/src/__tests__/host-app-control-proxy.test.ts +2 -0
  159. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  160. package/src/__tests__/host-cu-proxy.test.ts +2 -0
  161. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  162. package/src/__tests__/host-file-edit-tool.test.ts +4 -2
  163. package/src/__tests__/host-file-proxy.test.ts +31 -0
  164. package/src/__tests__/host-file-read-tool.test.ts +4 -2
  165. package/src/__tests__/host-file-write-tool.test.ts +9 -3
  166. package/src/__tests__/host-proxy-preactivation.test.ts +53 -14
  167. package/src/__tests__/host-shell-tool.test.ts +9 -4
  168. package/src/__tests__/http-user-message-parity.test.ts +2 -2
  169. package/src/__tests__/identity-intro-cache.test.ts +47 -114
  170. package/src/__tests__/identity-routes.test.ts +248 -7
  171. package/src/__tests__/inbound-slack-persistence.test.ts +12 -3
  172. package/src/__tests__/injector-background-turn.test.ts +3 -9
  173. package/src/__tests__/injector-chain.test.ts +139 -275
  174. package/src/__tests__/injector-disk-pressure.test.ts +75 -41
  175. package/src/__tests__/injector-document-comments.test.ts +3 -3
  176. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  177. package/src/__tests__/injector-v3-suppression.test.ts +214 -0
  178. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  179. package/src/__tests__/list-messages-attachments.test.ts +7 -8
  180. package/src/__tests__/list-messages-hidden-metadata.test.ts +55 -15
  181. package/src/__tests__/list-messages-page-latest.test.ts +60 -1
  182. package/src/__tests__/list-messages-tool-merge.test.ts +56 -6
  183. package/src/__tests__/llm-request-log-turn-query.test.ts +42 -86
  184. package/src/__tests__/llm-resolver.test.ts +23 -47
  185. package/src/__tests__/llm-usage-store.test.ts +268 -1
  186. package/src/__tests__/log-export-routes.test.ts +59 -0
  187. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -8
  188. package/src/__tests__/mcp-auth-routes.test.ts +15 -10
  189. package/src/__tests__/mcp-health-check.test.ts +18 -13
  190. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  191. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  192. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  193. package/src/__tests__/migration-export-http.test.ts +12 -12
  194. package/src/__tests__/migration-import-commit-http.test.ts +8 -8
  195. package/src/__tests__/migration-import-preflight-http.test.ts +7 -7
  196. package/src/__tests__/migration-validate-http.test.ts +3 -3
  197. package/src/__tests__/native-web-search.test.ts +205 -20
  198. package/src/__tests__/notification-decision-identity.test.ts +9 -18
  199. package/src/__tests__/notification-decision-recipient-context.test.ts +3 -6
  200. package/src/__tests__/oauth-commands-routes.test.ts +1 -1
  201. package/src/__tests__/onboarding-template-contract.test.ts +12 -0
  202. package/src/__tests__/openai-image-service.test.ts +17 -0
  203. package/src/__tests__/openai-provider.test.ts +97 -71
  204. package/src/__tests__/openai-responses-provider.test.ts +21 -77
  205. package/src/__tests__/outbound-slack-persistence.test.ts +2 -1
  206. package/src/__tests__/{overflow-reduce-pipeline.test.ts → overflow-reduction-loop.test.ts} +64 -286
  207. package/src/__tests__/parallel-tool.benchmark.test.ts +24 -36
  208. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  209. package/src/__tests__/persistence-secret-redaction.test.ts +3 -1
  210. package/src/__tests__/pipeline-runner.test.ts +31 -43
  211. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  212. package/src/__tests__/plugin-bootstrap.test.ts +62 -51
  213. package/src/__tests__/plugin-registry.test.ts +0 -27
  214. package/src/__tests__/plugin-route-contribution.test.ts +6 -16
  215. package/src/__tests__/plugin-skill-contribution.test.ts +7 -17
  216. package/src/__tests__/plugin-tool-contribution.test.ts +10 -26
  217. package/src/__tests__/plugin-types.test.ts +8 -173
  218. package/src/__tests__/prechat-onboarding-contract.test.ts +23 -0
  219. package/src/__tests__/process-message-background-slack.test.ts +17 -16
  220. package/src/__tests__/process-message-display-content.test.ts +36 -44
  221. package/src/__tests__/provider-commit-message-generator.test.ts +19 -14
  222. package/src/__tests__/provider-error-scenarios.test.ts +7 -6
  223. package/src/__tests__/provider-platform-proxy-integration.test.ts +3 -8
  224. package/src/__tests__/provider-send-message-override-profile.test.ts +9 -25
  225. package/src/__tests__/provider-streaming.benchmark.test.ts +12 -22
  226. package/src/__tests__/provider-usage-tracking.test.ts +0 -6
  227. package/src/__tests__/ratelimit.test.ts +9 -4
  228. package/src/__tests__/reaction-persistence.test.ts +1 -1
  229. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  230. package/src/__tests__/relay-server.test.ts +20 -13
  231. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  232. package/src/__tests__/retry-openrouter-only-normalization.test.ts +5 -8
  233. package/src/__tests__/retry-thinking-tool-choice.test.ts +10 -13
  234. package/src/__tests__/retry-verbosity-normalization.test.ts +5 -8
  235. package/src/__tests__/runtime-events-sse-reconnect.test.ts +390 -0
  236. package/src/__tests__/schedule-routes.test.ts +683 -12
  237. package/src/__tests__/schedule-store.test.ts +108 -0
  238. package/src/__tests__/schedule-tools.test.ts +160 -0
  239. package/src/__tests__/secret-ingress-http.test.ts +2 -2
  240. package/src/__tests__/secret-prompt-log-hygiene.test.ts +11 -7
  241. package/src/__tests__/secret-prompter-channel-fallback.test.ts +11 -9
  242. package/src/__tests__/secret-response-routing.test.ts +13 -11
  243. package/src/__tests__/send-endpoint-busy.test.ts +6 -2
  244. package/src/__tests__/server-history-render.test.ts +314 -1
  245. package/src/__tests__/shell-observability.test.ts +249 -0
  246. package/src/__tests__/skill-feature-flags-integration.test.ts +44 -11
  247. package/src/__tests__/skill-feature-flags.test.ts +6 -6
  248. package/src/__tests__/skill-load-feature-flag.test.ts +10 -10
  249. package/src/__tests__/skills-files-catalog-fallback.test.ts +10 -0
  250. package/src/__tests__/skillssh-files.test.ts +1 -0
  251. package/src/__tests__/starter-task-flow.test.ts +6 -6
  252. package/src/__tests__/strip-memory-injections.test.ts +102 -14
  253. package/src/__tests__/subagent-call-site-routing.test.ts +3 -3
  254. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  255. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  256. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  257. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  258. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  259. package/src/__tests__/suggestion-routes.test.ts +3 -3
  260. package/src/__tests__/sync-message-contract.test.ts +19 -16
  261. package/src/__tests__/system-prompt.test.ts +74 -0
  262. package/src/__tests__/task-scheduler.test.ts +162 -1
  263. package/src/__tests__/terminal-tools.test.ts +9 -25
  264. package/src/__tests__/thread-backfill.test.ts +4 -9
  265. package/src/__tests__/title-generate-hook.test.ts +319 -0
  266. package/src/__tests__/tool-error-hook.test.ts +278 -0
  267. package/src/__tests__/tool-preview-lifecycle.test.ts +481 -16
  268. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  269. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  270. package/src/__tests__/tool-result-truncation.test.ts +1 -1
  271. package/src/__tests__/tools-audio-read.test.ts +113 -0
  272. package/src/__tests__/turn-boundary-resolution.test.ts +44 -84
  273. package/src/__tests__/turn-events-store.test.ts +11 -7
  274. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  275. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  276. package/src/__tests__/usage-routes.test.ts +285 -1
  277. package/src/__tests__/user-plugin-loader.test.ts +2 -2
  278. package/src/__tests__/voice-scoped-grant-consumer.test.ts +8 -6
  279. package/src/__tests__/voice-session-bridge.test.ts +19 -10
  280. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  281. package/src/acp/__tests__/agent-process.test.ts +161 -0
  282. package/src/acp/__tests__/client-handler.test.ts +40 -0
  283. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  284. package/src/acp/__tests__/helpers/exec-file-stub.ts +101 -0
  285. package/src/acp/__tests__/prepare-agent-env.test.ts +143 -31
  286. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  287. package/src/acp/__tests__/session-manager-resume.test.ts +695 -0
  288. package/src/acp/agent-process.ts +61 -1
  289. package/src/acp/auto-install.test.ts +125 -0
  290. package/src/acp/auto-install.ts +174 -0
  291. package/src/acp/client-handler.ts +31 -0
  292. package/src/acp/feature-gate.test.ts +48 -0
  293. package/src/acp/feature-gate.ts +34 -0
  294. package/src/acp/prepare-agent-env.ts +52 -11
  295. package/src/acp/resolve-agent.test.ts +147 -6
  296. package/src/acp/resolve-agent.ts +81 -7
  297. package/src/acp/resume-hint.ts +22 -0
  298. package/src/acp/session-manager.ts +487 -71
  299. package/src/agent/compaction-circuit.ts +98 -0
  300. package/src/agent/loop.ts +651 -450
  301. package/src/api/README.md +19 -17
  302. package/src/api/constants/tool-execution.ts +21 -0
  303. package/src/api/events/assistant-activity-state.ts +75 -0
  304. package/src/api/events/assistant-outbound-attachment.ts +25 -27
  305. package/src/api/events/assistant-text-delta.ts +6 -8
  306. package/src/api/events/assistant-thinking-delta.ts +33 -0
  307. package/src/api/events/assistant-turn-start.ts +5 -7
  308. package/src/api/events/avatar-updated.ts +24 -0
  309. package/src/api/events/compaction-circuit-closed.ts +26 -0
  310. package/src/api/events/compaction-circuit-open.ts +28 -0
  311. package/src/api/events/confirmation-request.ts +114 -0
  312. package/src/api/events/contact-request.ts +33 -0
  313. package/src/api/events/conversation-error.ts +77 -0
  314. package/src/api/events/conversation-list-invalidated.ts +38 -0
  315. package/src/api/events/conversation-title-updated.ts +24 -0
  316. package/src/api/events/disk-pressure-status-changed.ts +61 -0
  317. package/src/api/events/document-comment-created.ts +24 -28
  318. package/src/api/events/document-comment-deleted.ts +6 -8
  319. package/src/api/events/document-comment-reopened.ts +6 -8
  320. package/src/api/events/document-comment-resolved.ts +8 -10
  321. package/src/api/events/document-editor-update.ts +27 -0
  322. package/src/api/events/error.ts +32 -0
  323. package/src/api/events/generation-cancelled.ts +4 -6
  324. package/src/api/events/generation-handoff.ts +13 -15
  325. package/src/api/events/home-feed-updated.ts +26 -0
  326. package/src/api/events/identity-changed.ts +32 -0
  327. package/src/api/events/interaction-resolved.ts +50 -0
  328. package/src/api/events/message-complete.ts +10 -12
  329. package/src/api/events/message-dequeued.ts +21 -0
  330. package/src/api/events/message-queued-deleted.ts +23 -0
  331. package/src/api/events/message-queued.ts +22 -0
  332. package/src/api/events/message-request-complete.ts +29 -0
  333. package/src/api/events/navigate-settings.ts +20 -0
  334. package/src/api/events/notification-intent.ts +33 -0
  335. package/src/api/events/open-url.ts +6 -8
  336. package/src/api/events/question-request.ts +67 -0
  337. package/src/api/events/relationship-state-updated.ts +4 -6
  338. package/src/api/events/secret-request.ts +42 -0
  339. package/src/api/events/subagent-event.ts +79 -0
  340. package/src/api/events/subagent-spawned.ts +40 -0
  341. package/src/api/events/subagent-status-changed.ts +65 -0
  342. package/src/api/events/sync-changed.ts +29 -0
  343. package/src/api/events/tool-output-chunk.ts +45 -0
  344. package/src/api/events/tool-result.ts +129 -0
  345. package/src/api/events/tool-use-preview-start.ts +32 -0
  346. package/src/api/events/tool-use-start.ts +8 -10
  347. package/src/api/events/trace-event.ts +69 -0
  348. package/src/api/events/turn-profile-auto-routed.ts +28 -0
  349. package/src/api/events/ui-surface-complete.ts +30 -0
  350. package/src/api/events/ui-surface-dismiss.ts +22 -0
  351. package/src/api/events/ui-surface-show.ts +67 -0
  352. package/src/api/events/ui-surface-update.ts +26 -0
  353. package/src/api/events/usage-update.ts +34 -0
  354. package/src/api/events/user-message-echo.ts +35 -0
  355. package/src/api/index.ts +389 -0
  356. package/src/api/requests/dictation.ts +45 -0
  357. package/src/api/responses/conversation-message.ts +374 -0
  358. package/src/api/responses/disk-pressure-status.ts +26 -0
  359. package/src/api/responses/home.ts +217 -0
  360. package/src/api/responses/llm-context-response.ts +2 -0
  361. package/src/api/responses/memory-v3-selection-log.ts +50 -0
  362. package/src/api/responses/subagent-detail.ts +48 -0
  363. package/src/approvals/guardian-decision-primitive.ts +7 -15
  364. package/src/approvals/guardian-request-resolvers.ts +7 -10
  365. package/src/avatar/__tests__/avatar-manifest.test.ts +236 -0
  366. package/src/avatar/__tests__/avatar-store.test.ts +198 -0
  367. package/src/avatar/avatar-manifest.ts +195 -0
  368. package/src/avatar/avatar-store.ts +113 -0
  369. package/src/avatar/traits-png-sync.ts +8 -2
  370. package/src/background-wake/next-wake.test.ts +31 -1
  371. package/src/background-wake/next-wake.ts +5 -1
  372. package/src/calls/call-conversation-messages.ts +6 -4
  373. package/src/calls/guardian-action-sweep.ts +6 -4
  374. package/src/calls/relay-server.ts +12 -8
  375. package/src/calls/voice-session-bridge.ts +13 -27
  376. package/src/cli/commands/__tests__/memory-v3.test.ts +245 -0
  377. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  378. package/src/cli/commands/avatar.ts +17 -11
  379. package/src/cli/commands/conversations.ts +15 -1
  380. package/src/cli/commands/db/__tests__/repair.test.ts +540 -0
  381. package/src/cli/commands/db/__tests__/status.test.ts +253 -0
  382. package/src/cli/commands/db/format.ts +48 -0
  383. package/src/cli/commands/db/index.ts +29 -0
  384. package/src/cli/commands/db/repair-step-conversation-backfill.ts +345 -0
  385. package/src/cli/commands/db/repair-step-integrity.ts +146 -0
  386. package/src/cli/commands/db/repair-steps.ts +164 -0
  387. package/src/cli/commands/db/repair.ts +141 -0
  388. package/src/cli/commands/db/status.ts +366 -0
  389. package/src/cli/commands/memory-v3.ts +159 -445
  390. package/src/cli/commands/notifications.ts +112 -60
  391. package/src/cli/lib/cli-colors.ts +24 -6
  392. package/src/cli/program.ts +4 -5
  393. package/src/config/__tests__/feature-flag-registry-guard.test.ts +4 -4
  394. package/src/config/acp-defaults.test.ts +10 -0
  395. package/src/config/acp-defaults.ts +6 -0
  396. package/src/config/assistant-feature-flags.ts +24 -13
  397. package/src/config/bundled-skills/acp/SKILL.md +64 -30
  398. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  399. package/src/config/bundled-skills/app-builder/SKILL.md +224 -387
  400. package/src/config/bundled-skills/app-builder/TOOLS.json +29 -0
  401. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  402. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  403. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  404. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  405. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  406. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  407. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  408. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  409. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  410. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  411. package/src/config/bundled-skills/media-processing/services/reduce.ts +6 -9
  412. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  413. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +7 -2
  414. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  415. package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
  416. package/src/config/bundled-tool-registry.ts +2 -0
  417. package/src/config/call-site-defaults.ts +2 -7
  418. package/src/config/feature-flag-cache.ts +3 -3
  419. package/src/config/feature-flag-registry.json +68 -12
  420. package/src/config/schemas/__tests__/memory-v2.test.ts +2 -226
  421. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  422. package/src/config/schemas/call-site-catalog.ts +8 -15
  423. package/src/config/schemas/heartbeat.ts +9 -0
  424. package/src/config/schemas/llm.ts +3 -3
  425. package/src/config/schemas/memory-lifecycle.ts +24 -0
  426. package/src/config/schemas/memory-v2.ts +8 -253
  427. package/src/config/schemas/memory-v3.ts +47 -0
  428. package/src/config/schemas/memory.ts +6 -1
  429. package/src/config/schemas/platform.ts +8 -0
  430. package/src/config/schemas/timeouts.ts +3 -1
  431. package/src/config/seed-inference-profiles.ts +2 -2
  432. package/src/config/skills.ts +13 -0
  433. package/src/context/compactor.ts +55 -32
  434. package/src/context/strip-injections.ts +128 -0
  435. package/src/context/token-estimator.ts +42 -0
  436. package/src/context/tool-result-truncation.ts +1 -66
  437. package/src/context/window-manager.ts +141 -26
  438. package/src/credential-execution/executable-discovery.ts +16 -0
  439. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  440. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +2 -2
  441. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  442. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  443. package/src/daemon/__tests__/web-search-status-text.test.ts +10 -6
  444. package/src/daemon/approval-generators.ts +4 -4
  445. package/src/daemon/assistant-attachments.ts +1 -1
  446. package/src/daemon/config-watcher.ts +7 -1
  447. package/src/daemon/context-overflow-reducer.ts +0 -1
  448. package/src/daemon/conversation-agent-loop-handlers.ts +793 -215
  449. package/src/daemon/conversation-agent-loop.ts +487 -1478
  450. package/src/daemon/conversation-error.ts +7 -7
  451. package/src/daemon/conversation-history.ts +27 -10
  452. package/src/daemon/conversation-launch.ts +4 -8
  453. package/src/daemon/conversation-lifecycle.ts +13 -42
  454. package/src/daemon/conversation-messaging.ts +8 -9
  455. package/src/daemon/conversation-notifiers.ts +7 -5
  456. package/src/daemon/conversation-process.ts +109 -93
  457. package/src/daemon/conversation-registry.ts +159 -0
  458. package/src/daemon/conversation-runtime-assembly.ts +209 -382
  459. package/src/daemon/conversation-slash.ts +6 -25
  460. package/src/daemon/conversation-store.ts +15 -95
  461. package/src/daemon/conversation-surfaces.ts +277 -73
  462. package/src/daemon/conversation-tool-setup.ts +5 -29
  463. package/src/daemon/conversation-workspace.ts +17 -0
  464. package/src/daemon/conversation.ts +123 -146
  465. package/src/daemon/daemon-skill-host.ts +2 -6
  466. package/src/daemon/disk-pressure-guard.ts +35 -29
  467. package/src/daemon/external-plugins-bootstrap.ts +53 -32
  468. package/src/daemon/first-greeting.ts +26 -4
  469. package/src/daemon/guardian-action-generators.ts +2 -2
  470. package/src/daemon/handlers/config-a2a.ts +51 -36
  471. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  472. package/src/daemon/handlers/config-telegram.ts +16 -2
  473. package/src/daemon/handlers/conversations.ts +9 -23
  474. package/src/daemon/handlers/shared.ts +158 -82
  475. package/src/daemon/handlers/skills.ts +53 -20
  476. package/src/daemon/host-app-control-proxy.ts +54 -1
  477. package/src/daemon/host-cu-proxy.ts +46 -22
  478. package/src/daemon/host-file-proxy.ts +25 -1
  479. package/src/daemon/host-proxy-preactivation.ts +25 -6
  480. package/src/daemon/lifecycle.ts +53 -55
  481. package/src/daemon/message-protocol.ts +2 -3
  482. package/src/daemon/message-provenance.ts +49 -0
  483. package/src/daemon/message-types/apps.ts +1 -29
  484. package/src/daemon/message-types/contacts.ts +3 -20
  485. package/src/daemon/message-types/conversations.ts +13 -111
  486. package/src/daemon/message-types/documents.ts +3 -9
  487. package/src/daemon/message-types/home.ts +4 -17
  488. package/src/daemon/message-types/integrations.ts +2 -6
  489. package/src/daemon/message-types/messages.ts +37 -400
  490. package/src/daemon/message-types/notifications.ts +2 -32
  491. package/src/daemon/message-types/settings.ts +3 -8
  492. package/src/daemon/message-types/skills.ts +4 -0
  493. package/src/daemon/message-types/surfaces.ts +138 -3
  494. package/src/daemon/message-types/sync.ts +12 -25
  495. package/src/daemon/message-types/workspace.ts +3 -11
  496. package/src/daemon/now-scratchpad.ts +21 -0
  497. package/src/daemon/orphan-reaper.test.ts +210 -0
  498. package/src/daemon/orphan-reaper.ts +240 -0
  499. package/src/daemon/overflow-reduction-loop.ts +230 -0
  500. package/src/daemon/persist-unsendable-image.ts +117 -0
  501. package/src/daemon/process-message.ts +50 -49
  502. package/src/daemon/server.ts +14 -0
  503. package/src/daemon/tool-side-effects.ts +10 -7
  504. package/src/daemon/trace-emitter.ts +6 -4
  505. package/src/daemon/trust-context.ts +32 -0
  506. package/src/daemon/wake-target-adapter.ts +14 -2
  507. package/src/heartbeat/__tests__/heartbeat-service.test.ts +6 -1
  508. package/src/heartbeat/heartbeat-run-store.ts +54 -1
  509. package/src/heartbeat/heartbeat-service.ts +42 -0
  510. package/src/home/feed-types.ts +36 -221
  511. package/src/home/home-greeting-cache.ts +24 -1
  512. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  513. package/src/ipc/__tests__/email-ipc.test.ts +0 -9
  514. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  515. package/src/ipc/gateway-client.test.ts +2 -2
  516. package/src/ipc/gateway-client.ts +3 -3
  517. package/src/ipc/routes/__tests__/route-adapter.test.ts +244 -0
  518. package/src/ipc/routes/route-adapter.ts +45 -6
  519. package/src/ipc/skill-routes/__tests__/memory.test.ts +33 -9
  520. package/src/ipc/skill-routes/__tests__/providers.test.ts +10 -10
  521. package/src/ipc/skill-routes/__tests__/registries.test.ts +28 -18
  522. package/src/ipc/skill-routes/memory.ts +29 -14
  523. package/src/ipc/skill-routes/providers.ts +5 -6
  524. package/src/ipc/skill-routes/registries.ts +13 -61
  525. package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -11
  526. package/src/media/gemini-image-service.ts +15 -0
  527. package/src/media/openai-image-service.ts +14 -0
  528. package/src/media/types.ts +34 -0
  529. package/src/memory/__tests__/conversation-queries.test.ts +192 -8
  530. package/src/memory/__tests__/db-maintenance.test.ts +128 -0
  531. package/src/memory/__tests__/jobs-store-job-classes.test.ts +5 -4
  532. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  533. package/src/memory/__tests__/memory-retrospective-job.test.ts +10 -6
  534. package/src/memory/__tests__/memory-v3-selections-migration.test.ts +103 -0
  535. package/src/memory/auth-fallback-events-store.ts +94 -0
  536. package/src/memory/context-search/agent-runner.ts +2 -4
  537. package/src/memory/conversation-crud.ts +39 -8
  538. package/src/memory/conversation-queries.ts +78 -22
  539. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  540. package/src/memory/conversation-title-service.ts +65 -41
  541. package/src/memory/db-init.ts +14 -0
  542. package/src/memory/db-maintenance.ts +18 -2
  543. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  544. package/src/memory/graph/consolidation.ts +8 -11
  545. package/src/memory/graph/conversation-graph-memory.ts +106 -8
  546. package/src/memory/graph/extraction.ts +6 -9
  547. package/src/memory/graph/narrative.ts +2 -2
  548. package/src/memory/graph/pattern-scan.ts +2 -2
  549. package/src/memory/graph/retriever.ts +20 -26
  550. package/src/memory/graph/tools.ts +4 -4
  551. package/src/memory/job-handlers/conversation-starters.ts +45 -34
  552. package/src/memory/job-handlers/summarization.ts +1 -2
  553. package/src/memory/jobs-store.ts +36 -1
  554. package/src/memory/jobs-worker.ts +82 -43
  555. package/src/memory/llm-request-log-source-clickhouse.ts +5 -31
  556. package/src/memory/llm-request-log-source-local.ts +0 -11
  557. package/src/memory/llm-request-log-source.ts +9 -25
  558. package/src/memory/llm-request-log-store.ts +0 -41
  559. package/src/memory/llm-usage-store.ts +234 -50
  560. package/src/memory/memory-marker.ts +17 -0
  561. package/src/memory/memory-retrospective-job.ts +6 -2
  562. package/src/memory/memory-v2-activation-log-store.ts +1 -83
  563. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  564. package/src/memory/migrations/267-llm-usage-events-add-assistant-version.ts +46 -0
  565. package/src/memory/migrations/268-add-memory-v3-selections.ts +28 -0
  566. package/src/memory/migrations/269-schedule-script-timeout.ts +11 -0
  567. package/src/memory/migrations/270-messages-role-created-at-index.ts +18 -0
  568. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  569. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  570. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  571. package/src/memory/migrations/__tests__/267-llm-usage-events-add-assistant-version.test.ts +117 -0
  572. package/src/memory/migrations/index.ts +7 -0
  573. package/src/memory/pkb/autoinject.ts +61 -0
  574. package/src/memory/pkb/context.ts +50 -0
  575. package/src/memory/pkb/types.ts +14 -0
  576. package/src/memory/schedule-attribution-sql.ts +104 -0
  577. package/src/memory/schema/acp.ts +4 -0
  578. package/src/memory/schema/infrastructure.ts +27 -0
  579. package/src/memory/usage-grouped-buckets.ts +6 -1
  580. package/src/memory/v2/__tests__/consolidation-job.test.ts +125 -1
  581. package/src/memory/v2/__tests__/migration.test.ts +11 -3
  582. package/src/memory/v2/__tests__/page-index.test.ts +37 -1
  583. package/src/memory/v2/__tests__/router.test.ts +14 -4
  584. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -5
  585. package/src/memory/v2/backfill-jobs.ts +6 -0
  586. package/src/memory/v2/consolidation-job.ts +99 -10
  587. package/src/memory/v2/migration.ts +5 -3
  588. package/src/memory/v2/page-index.ts +11 -0
  589. package/src/memory/v2/router.ts +8 -11
  590. package/src/memory/v2/sweep-job.ts +8 -11
  591. package/src/memory/v2/types.ts +1 -0
  592. package/src/messaging/providers/slack/render-transcript.test.ts +1 -1
  593. package/src/messaging/providers/slack/render-transcript.ts +2 -2
  594. package/src/messaging/style-analyzer.ts +8 -11
  595. package/src/notifications/conversation-pairing.ts +8 -13
  596. package/src/notifications/decision-engine.ts +16 -16
  597. package/src/notifications/home-feed-side-effect.ts +12 -1
  598. package/src/notifications/preference-extractor.ts +11 -14
  599. package/src/permissions/prompter.ts +46 -36
  600. package/src/permissions/question-prompter.test.ts +35 -26
  601. package/src/permissions/question-prompter.ts +6 -10
  602. package/src/plugin-api/constants.ts +4 -0
  603. package/src/plugin-api/index.ts +10 -1
  604. package/src/plugin-api/types.ts +176 -4
  605. package/src/plugins/defaults/compaction/compact.ts +59 -0
  606. package/src/plugins/defaults/compaction/package.json +15 -0
  607. package/src/plugins/defaults/compaction/register.ts +24 -0
  608. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  609. package/src/plugins/defaults/empty-response/package.json +15 -0
  610. package/src/plugins/defaults/empty-response/register.ts +23 -0
  611. package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +35 -0
  612. package/src/plugins/defaults/history-repair/package.json +15 -0
  613. package/src/plugins/defaults/history-repair/register.ts +24 -0
  614. package/src/{daemon/history-repair.ts → plugins/defaults/history-repair/terminal.ts} +48 -35
  615. package/src/plugins/defaults/index.ts +22 -49
  616. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +95 -0
  617. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  618. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  619. package/src/plugins/defaults/{injectors.ts → memory-retrieval/injectors.ts} +295 -112
  620. package/src/plugins/defaults/memory-v3-shadow/__tests__/assign.test.ts +242 -0
  621. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +118 -0
  622. package/src/plugins/defaults/memory-v3-shadow/__tests__/core.test.ts +39 -0
  623. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/eval-turns.json +36 -0
  624. package/src/plugins/defaults/memory-v3-shadow/__tests__/fixtures/live-turns.json +37 -0
  625. package/src/plugins/defaults/memory-v3-shadow/__tests__/health.test.ts +219 -0
  626. package/src/plugins/defaults/memory-v3-shadow/__tests__/live-integration.test.ts +330 -0
  627. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +288 -0
  628. package/src/plugins/defaults/memory-v3-shadow/__tests__/needle.test.ts +107 -0
  629. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +436 -0
  630. package/src/plugins/defaults/memory-v3-shadow/__tests__/provider-blocks.test.ts +13 -0
  631. package/src/plugins/defaults/memory-v3-shadow/__tests__/reconcile.test.ts +274 -0
  632. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +61 -0
  633. package/src/plugins/defaults/memory-v3-shadow/__tests__/router.test.ts +332 -0
  634. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +179 -0
  635. package/src/plugins/defaults/memory-v3-shadow/__tests__/selector.test.ts +470 -0
  636. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +432 -0
  637. package/src/plugins/defaults/memory-v3-shadow/__tests__/snapshot.test.ts +168 -0
  638. package/src/plugins/defaults/memory-v3-shadow/__tests__/tree.test.ts +192 -0
  639. package/src/plugins/defaults/memory-v3-shadow/__tests__/types.test.ts +54 -0
  640. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-eviction.test.ts +106 -0
  641. package/src/plugins/defaults/memory-v3-shadow/__tests__/working-set-skeleton.test.ts +44 -0
  642. package/src/plugins/defaults/memory-v3-shadow/assign.ts +268 -0
  643. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +124 -0
  644. package/src/plugins/defaults/memory-v3-shadow/core.ts +26 -0
  645. package/src/plugins/defaults/memory-v3-shadow/data/README.md +84 -0
  646. package/src/plugins/defaults/memory-v3-shadow/data/assignments.json +5 -0
  647. package/src/plugins/defaults/memory-v3-shadow/data/core.json +1 -0
  648. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-x.md +9 -0
  649. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-a/topic-y.md +9 -0
  650. package/src/plugins/defaults/memory-v3-shadow/data/leaves/domain-b/topic-z.md +9 -0
  651. package/src/plugins/defaults/memory-v3-shadow/health.ts +0 -0
  652. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  653. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  654. package/src/plugins/defaults/memory-v3-shadow/injector.ts +75 -0
  655. package/src/plugins/defaults/memory-v3-shadow/llm-retry.ts +32 -0
  656. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +314 -0
  657. package/src/plugins/defaults/memory-v3-shadow/needle.ts +115 -0
  658. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +126 -0
  659. package/src/plugins/defaults/memory-v3-shadow/package.json +15 -0
  660. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +34 -0
  661. package/src/plugins/defaults/memory-v3-shadow/provider-blocks.ts +26 -0
  662. package/src/plugins/defaults/memory-v3-shadow/reconcile.ts +523 -0
  663. package/src/plugins/defaults/memory-v3-shadow/register.ts +26 -0
  664. package/src/plugins/defaults/memory-v3-shadow/render-injection.ts +32 -0
  665. package/src/plugins/defaults/memory-v3-shadow/router.ts +190 -0
  666. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +84 -0
  667. package/src/plugins/defaults/memory-v3-shadow/selector.ts +226 -0
  668. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +349 -0
  669. package/src/plugins/defaults/memory-v3-shadow/snapshot.ts +209 -0
  670. package/src/plugins/defaults/memory-v3-shadow/tree.ts +174 -0
  671. package/src/plugins/defaults/memory-v3-shadow/types.ts +59 -0
  672. package/src/plugins/defaults/memory-v3-shadow/working-set.ts +88 -0
  673. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  674. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  675. package/src/plugins/defaults/title-generate/package.json +15 -0
  676. package/src/plugins/defaults/title-generate/register.ts +35 -0
  677. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  678. package/src/plugins/defaults/tool-error/package.json +15 -0
  679. package/src/plugins/defaults/tool-error/register.ts +23 -0
  680. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  681. package/src/plugins/defaults/tool-result-truncate/package.json +15 -0
  682. package/src/plugins/defaults/tool-result-truncate/register.ts +24 -0
  683. package/src/plugins/defaults/tool-result-truncate/terminal.ts +132 -0
  684. package/src/plugins/external-plugin-loader.ts +2 -2
  685. package/src/plugins/pipeline.ts +8 -35
  686. package/src/plugins/registry.ts +8 -25
  687. package/src/plugins/types.ts +62 -721
  688. package/src/plugins/user-loader.ts +4 -3
  689. package/src/proactive-artifact/aux-message-injector.ts +4 -5
  690. package/src/proactive-artifact/job.test.ts +28 -21
  691. package/src/proactive-artifact/job.ts +3 -1
  692. package/src/prompts/__tests__/system-prompt.test.ts +42 -0
  693. package/src/prompts/sections.ts +20 -7
  694. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +64 -0
  695. package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +2 -2
  696. package/src/prompts/templates/BOOTSTRAP.md +7 -3
  697. package/src/prompts/templates/system-sections.ts +21 -0
  698. package/src/providers/__tests__/retry-callsite.test.ts +25 -25
  699. package/src/providers/__tests__/satellite-connection-routing.test.ts +7 -21
  700. package/src/providers/anthropic/client.ts +61 -34
  701. package/src/providers/call-site-routing.ts +1 -9
  702. package/src/providers/gemini/client.ts +152 -34
  703. package/src/providers/gemini/inline-media.ts +74 -0
  704. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -2
  705. package/src/providers/openai/chat-completions-provider.ts +45 -4
  706. package/src/providers/openai/responses-provider.ts +1 -4
  707. package/src/providers/openrouter/client.ts +2 -6
  708. package/src/providers/placeholder-sentinels.ts +35 -0
  709. package/src/providers/provider-send-message.ts +6 -6
  710. package/src/providers/ratelimit.ts +1 -9
  711. package/src/providers/retry.ts +0 -5
  712. package/src/providers/types.ts +11 -2
  713. package/src/providers/usage-tracking.ts +1 -9
  714. package/src/runtime/__tests__/agent-wake.test.ts +141 -32
  715. package/src/runtime/__tests__/background-job-runner.test.ts +1 -3
  716. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  717. package/src/runtime/agent-wake.ts +95 -23
  718. package/src/runtime/assistant-event-hub.ts +38 -8
  719. package/src/runtime/assistant-stream-state.ts +368 -0
  720. package/src/runtime/auth/__tests__/guard-tests.test.ts +75 -109
  721. package/src/runtime/auth/__tests__/route-policy.test.ts +153 -170
  722. package/src/runtime/auth/route-policy.ts +42 -1079
  723. package/src/runtime/background-job-runner.ts +1 -4
  724. package/src/runtime/btw-sidechain.ts +3 -1
  725. package/src/runtime/channel-approvals.ts +4 -15
  726. package/src/runtime/channel-invite-transport.ts +5 -6
  727. package/src/runtime/channel-readiness-service.ts +2 -5
  728. package/src/runtime/channel-retry-sweep.ts +12 -16
  729. package/src/runtime/http-router.ts +35 -43
  730. package/src/runtime/http-types.ts +23 -71
  731. package/src/runtime/interactive-ui.ts +1 -1
  732. package/src/runtime/invite-instruction-generator.ts +3 -3
  733. package/src/runtime/pending-interactions.ts +3 -2
  734. package/src/runtime/routes/__tests__/acp-routes.test.ts +253 -55
  735. package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +565 -0
  736. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  737. package/src/runtime/routes/__tests__/content-source-routes.test.ts +4 -4
  738. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +62 -32
  739. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +237 -0
  740. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  741. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -22
  742. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  743. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +7 -2
  744. package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -6
  745. package/src/runtime/routes/__tests__/stt-routes.test.ts +3 -3
  746. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +5 -2
  747. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  748. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  749. package/src/runtime/routes/__tests__/tts-routes.test.ts +9 -5
  750. package/src/runtime/routes/acp-routes.test.ts +186 -100
  751. package/src/runtime/routes/acp-routes.ts +110 -35
  752. package/src/runtime/routes/app-management-routes.ts +93 -131
  753. package/src/runtime/routes/app-routes.ts +38 -20
  754. package/src/runtime/routes/approval-routes.ts +17 -5
  755. package/src/runtime/routes/attachment-routes.ts +51 -16
  756. package/src/runtime/routes/audio-routes.ts +1 -0
  757. package/src/runtime/routes/audit-routes.ts +5 -0
  758. package/src/runtime/routes/auth-routes.ts +5 -0
  759. package/src/runtime/routes/avatar-routes.ts +264 -59
  760. package/src/runtime/routes/background-tool-routes.ts +9 -0
  761. package/src/runtime/routes/background-wake-routes.ts +13 -3
  762. package/src/runtime/routes/backup-routes.ts +45 -0
  763. package/src/runtime/routes/bookmark-routes.ts +13 -0
  764. package/src/runtime/routes/brain-graph-routes.ts +9 -0
  765. package/src/runtime/routes/browser-routes.ts +6 -1
  766. package/src/runtime/routes/browser-tabs-routes.ts +11 -10
  767. package/src/runtime/routes/btw-routes.ts +34 -24
  768. package/src/runtime/routes/cache-routes.ts +13 -0
  769. package/src/runtime/routes/call-routes.ts +21 -10
  770. package/src/runtime/routes/channel-availability-routes.ts +5 -1
  771. package/src/runtime/routes/channel-readiness-routes.ts +37 -4
  772. package/src/runtime/routes/channel-route-definitions.ts +21 -0
  773. package/src/runtime/routes/channel-verification-routes.ts +21 -0
  774. package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +9 -2
  775. package/src/runtime/routes/client-routes.ts +9 -0
  776. package/src/runtime/routes/consolidation-routes.ts +133 -25
  777. package/src/runtime/routes/contact-prompt-routes.ts +9 -0
  778. package/src/runtime/routes/contact-routes.ts +90 -23
  779. package/src/runtime/routes/content-source-routes.ts +5 -1
  780. package/src/runtime/routes/conversation-analysis-routes.ts +5 -1
  781. package/src/runtime/routes/conversation-attention-routes.ts +5 -0
  782. package/src/runtime/routes/conversation-cli-routes.ts +54 -7
  783. package/src/runtime/routes/conversation-compaction-routes.ts +54 -25
  784. package/src/runtime/routes/conversation-list-routes.ts +81 -12
  785. package/src/runtime/routes/conversation-management-routes.ts +57 -14
  786. package/src/runtime/routes/conversation-query-routes.ts +90 -41
  787. package/src/runtime/routes/conversation-routes.ts +446 -204
  788. package/src/runtime/routes/conversation-starter-routes.ts +35 -20
  789. package/src/runtime/routes/conversations-import-routes.ts +30 -8
  790. package/src/runtime/routes/credential-prompt-routes.ts +5 -0
  791. package/src/runtime/routes/credential-routes.ts +25 -6
  792. package/src/runtime/routes/debug-bash-routes.ts +5 -0
  793. package/src/runtime/routes/debug-routes.ts +11 -2
  794. package/src/runtime/routes/defer-routes.ts +13 -0
  795. package/src/runtime/routes/diagnostics-routes.ts +37 -46
  796. package/src/runtime/routes/disk-pressure-routes.ts +17 -31
  797. package/src/runtime/routes/document-comments-routes.ts +46 -27
  798. package/src/runtime/routes/documents-routes.ts +25 -10
  799. package/src/runtime/routes/domain-routes.ts +98 -51
  800. package/src/runtime/routes/email-routes.ts +33 -0
  801. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  802. package/src/runtime/routes/events-routes.ts +107 -8
  803. package/src/runtime/routes/filing-routes.ts +9 -4
  804. package/src/runtime/routes/gateway-log-routes.ts +31 -4
  805. package/src/runtime/routes/global-search-routes.ts +53 -50
  806. package/src/runtime/routes/group-routes.ts +21 -5
  807. package/src/runtime/routes/guardian-action-routes.ts +9 -0
  808. package/src/runtime/routes/guardian-approval-interception.ts +0 -31
  809. package/src/runtime/routes/heartbeat-routes.ts +57 -21
  810. package/src/runtime/routes/home-feed-routes.ts +23 -19
  811. package/src/runtime/routes/home-state-routes.ts +8 -40
  812. package/src/runtime/routes/host-app-control-routes.ts +6 -1
  813. package/src/runtime/routes/host-bash-routes.ts +5 -0
  814. package/src/runtime/routes/host-browser-routes.ts +13 -0
  815. package/src/runtime/routes/host-cu-routes.ts +6 -1
  816. package/src/runtime/routes/host-file-routes.ts +26 -6
  817. package/src/runtime/routes/host-transfer-routes.ts +13 -2
  818. package/src/runtime/routes/http-adapter.ts +1 -2
  819. package/src/runtime/routes/identity-intro-cache.ts +28 -40
  820. package/src/runtime/routes/identity-routes.ts +236 -20
  821. package/src/runtime/routes/image-generation-routes.ts +45 -2
  822. package/src/runtime/routes/inbound-message-handler.ts +16 -12
  823. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -12
  824. package/src/runtime/routes/inbound-stages/background-dispatch.ts +15 -19
  825. package/src/runtime/routes/index.ts +2 -0
  826. package/src/runtime/routes/inference-profile-session-routes.ts +13 -3
  827. package/src/runtime/routes/inference-provider-connection-routes.ts +21 -5
  828. package/src/runtime/routes/inference-send-routes.ts +11 -11
  829. package/src/runtime/routes/integrations/a2a.ts +32 -7
  830. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  831. package/src/runtime/routes/integrations/slack/channel.ts +23 -3
  832. package/src/runtime/routes/integrations/slack/share.ts +36 -8
  833. package/src/runtime/routes/integrations/telegram.ts +34 -9
  834. package/src/runtime/routes/integrations/twilio.ts +77 -7
  835. package/src/runtime/routes/integrations/vercel.ts +3 -3
  836. package/src/runtime/routes/internal-oauth-routes.ts +5 -0
  837. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  838. package/src/runtime/routes/internal-twilio-routes.ts +13 -0
  839. package/src/runtime/routes/llm-call-sites-routes.ts +39 -4
  840. package/src/runtime/routes/log-export-routes.ts +36 -10
  841. package/src/runtime/routes/mcp-auth-routes.ts +25 -0
  842. package/src/runtime/routes/memory-item-routes.ts +21 -10
  843. package/src/runtime/routes/memory-v2-routes.ts +105 -44
  844. package/src/runtime/routes/memory-v3-routes.ts +306 -408
  845. package/src/runtime/routes/migration-rollback-routes.ts +5 -1
  846. package/src/runtime/routes/migration-routes.ts +29 -0
  847. package/src/runtime/routes/notification-routes.ts +17 -1
  848. package/src/runtime/routes/oauth-apps.ts +99 -23
  849. package/src/runtime/routes/oauth-commands-routes.ts +37 -14
  850. package/src/runtime/routes/oauth-connect-routes.ts +9 -0
  851. package/src/runtime/routes/oauth-lifecycle-routes.ts +5 -1
  852. package/src/runtime/routes/oauth-providers.ts +79 -15
  853. package/src/runtime/routes/platform-routes.ts +102 -5
  854. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +9 -6
  855. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +37 -16
  856. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +7 -3
  857. package/src/runtime/routes/playground/__tests__/state.test.ts +10 -3
  858. package/src/runtime/routes/playground/force-compact.ts +2 -2
  859. package/src/runtime/routes/playground/helpers.ts +1 -2
  860. package/src/runtime/routes/playground/inject-failures.ts +13 -8
  861. package/src/runtime/routes/playground/reset-circuit.ts +14 -9
  862. package/src/runtime/routes/playground/seed-conversation.ts +1 -1
  863. package/src/runtime/routes/playground/seeded-conversations.ts +3 -3
  864. package/src/runtime/routes/playground/state.ts +4 -3
  865. package/src/runtime/routes/plugins-routes.ts +22 -19
  866. package/src/runtime/routes/profiler-routes.ts +17 -4
  867. package/src/runtime/routes/ps-routes.ts +5 -0
  868. package/src/runtime/routes/publish-routes.ts +13 -3
  869. package/src/runtime/routes/question-routes.ts +5 -0
  870. package/src/runtime/routes/recording-routes.ts +25 -12
  871. package/src/runtime/routes/rename-conversation-routes.ts +10 -0
  872. package/src/runtime/routes/sanity-routes.ts +9 -2
  873. package/src/runtime/routes/schedule-routes.ts +288 -88
  874. package/src/runtime/routes/secret-routes.ts +31 -6
  875. package/src/runtime/routes/sequence-routes.ts +33 -0
  876. package/src/runtime/routes/settings-routes.ts +65 -19
  877. package/src/runtime/routes/skills-routes.ts +166 -73
  878. package/src/runtime/routes/slack-channel-routes.ts +5 -0
  879. package/src/runtime/routes/stt-routes.ts +13 -6
  880. package/src/runtime/routes/subagents-routes.ts +24 -18
  881. package/src/runtime/routes/suggest-trust-rule-routes.ts +7 -2
  882. package/src/runtime/routes/surface-action-routes.ts +9 -0
  883. package/src/runtime/routes/surface-content-routes.ts +10 -2
  884. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  885. package/src/runtime/routes/task-routes.ts +37 -0
  886. package/src/runtime/routes/telemetry-routes.ts +9 -0
  887. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  888. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  889. package/src/runtime/routes/trace-event-routes.ts +42 -1
  890. package/src/runtime/routes/trust-rules-routes.ts +31 -2
  891. package/src/runtime/routes/tts-routes.ts +48 -6
  892. package/src/runtime/routes/types.ts +83 -16
  893. package/src/runtime/routes/ui-request-routes.ts +5 -0
  894. package/src/runtime/routes/upgrade-broadcast-routes.ts +5 -0
  895. package/src/runtime/routes/usage-routes.ts +118 -42
  896. package/src/runtime/routes/user-routes-cli.ts +9 -0
  897. package/src/runtime/routes/user-routes.ts +5 -1
  898. package/src/runtime/routes/wake-conversation-routes.ts +5 -0
  899. package/src/runtime/routes/watcher-routes.ts +21 -0
  900. package/src/runtime/routes/webhook-routes.ts +50 -2
  901. package/src/runtime/routes/wipe-conversation-routes.ts +5 -0
  902. package/src/runtime/routes/work-items-routes.ts +49 -23
  903. package/src/runtime/routes/workspace-commit-routes.ts +5 -0
  904. package/src/runtime/routes/workspace-routes.test.ts +42 -0
  905. package/src/runtime/routes/workspace-routes.ts +124 -9
  906. package/src/runtime/services/__tests__/analyze-conversation.test.ts +8 -4
  907. package/src/runtime/services/analyze-conversation.ts +5 -8
  908. package/src/runtime/services/conversation-serializer.ts +24 -2
  909. package/src/runtime/sync/resource-sync-events.ts +16 -2
  910. package/src/runtime/sync/sync-publisher.ts +2 -2
  911. package/src/schedule/run-script.ts +28 -3
  912. package/src/schedule/schedule-store.ts +28 -1
  913. package/src/schedule/schedule-usage-store.ts +83 -0
  914. package/src/schedule/scheduler.ts +15 -6
  915. package/src/signals/cancel.ts +2 -4
  916. package/src/signals/user-message.ts +5 -8
  917. package/src/skills/catalog-files.ts +4 -1
  918. package/src/skills/catalog-install.ts +3 -0
  919. package/src/skills/categories-cache.ts +118 -0
  920. package/src/skills/clawhub-files.ts +1 -0
  921. package/src/skills/skillssh-files.ts +1 -0
  922. package/src/subagent/manager.ts +20 -11
  923. package/src/telemetry/types.ts +55 -1
  924. package/src/telemetry/usage-telemetry-reporter.test.ts +250 -4
  925. package/src/telemetry/usage-telemetry-reporter.ts +88 -2
  926. package/src/tools/acp/context.ts +20 -0
  927. package/src/tools/acp/list-agents.test.ts +7 -1
  928. package/src/tools/acp/spawn.test.ts +198 -93
  929. package/src/tools/acp/spawn.ts +32 -70
  930. package/src/tools/acp/steer.test.ts +105 -8
  931. package/src/tools/acp/steer.ts +48 -17
  932. package/src/tools/apps/definitions.ts +8 -4
  933. package/src/tools/apps/executors.ts +13 -8
  934. package/src/tools/ask-question/ask-question-tool.test.ts +120 -105
  935. package/src/tools/ask-question/ask-question-tool.ts +85 -90
  936. package/src/tools/computer-use/definitions.ts +28 -24
  937. package/src/tools/credential-execution/make-authenticated-request.ts +56 -51
  938. package/src/tools/credential-execution/manage-secure-command-tool.ts +2 -2
  939. package/src/tools/credential-execution/run-authenticated-command.ts +82 -77
  940. package/src/tools/credentials/vault.ts +112 -111
  941. package/src/tools/execution-target.ts +1 -1
  942. package/src/tools/execution-timeout.ts +3 -4
  943. package/src/tools/executor.ts +1 -53
  944. package/src/tools/filesystem/edit.ts +45 -42
  945. package/src/tools/filesystem/list.ts +33 -30
  946. package/src/tools/filesystem/read.ts +54 -35
  947. package/src/tools/filesystem/write.ts +69 -32
  948. package/src/tools/host-filesystem/edit.ts +44 -42
  949. package/src/tools/host-filesystem/read.ts +49 -35
  950. package/src/tools/host-filesystem/transfer.ts +121 -108
  951. package/src/tools/host-filesystem/write.ts +33 -31
  952. package/src/tools/host-terminal/host-shell.ts +50 -48
  953. package/src/tools/memory/register.ts +23 -24
  954. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  955. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  956. package/src/tools/network/web-fetch.ts +49 -46
  957. package/src/tools/network/web-search-error.test.ts +248 -0
  958. package/src/tools/network/web-search-error.ts +267 -0
  959. package/src/tools/network/web-search.ts +223 -61
  960. package/src/tools/registry.ts +39 -16
  961. package/src/tools/schedule/create.ts +13 -0
  962. package/src/tools/schedule/update.ts +16 -0
  963. package/src/tools/shared/filesystem/audio-read.ts +122 -0
  964. package/src/tools/shared/filesystem/image-read.ts +1 -1
  965. package/src/tools/skills/execute.ts +34 -31
  966. package/src/tools/skills/load.ts +29 -23
  967. package/src/tools/subagent/notify-parent.ts +35 -32
  968. package/src/tools/subagent/spawn.ts +2 -4
  969. package/src/tools/system/avatar-generator.ts +13 -22
  970. package/src/tools/system/request-permission.ts +30 -27
  971. package/src/tools/terminal/safe-env.ts +10 -1
  972. package/src/tools/terminal/shell.ts +190 -61
  973. package/src/tools/tool-defaults.ts +20 -9
  974. package/src/tools/tool-manifest.ts +4 -4
  975. package/src/tools/types.ts +74 -23
  976. package/src/tools/ui-surface/definitions.ts +99 -10
  977. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  978. package/src/tts/provider-catalog.ts +76 -1
  979. package/src/usage/types.ts +10 -0
  980. package/src/util/errors.ts +2 -2
  981. package/src/util/map-limit.ts +27 -0
  982. package/src/util/mutex.ts +47 -0
  983. package/src/util/platform.ts +15 -12
  984. package/src/work-items/work-item-runner.ts +7 -2
  985. package/src/workspace/git-service.ts +1 -42
  986. package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +7 -20
  987. package/src/workspace/migrations/092-backfill-v3-leaves.ts +169 -0
  988. package/src/workspace/migrations/093-backfill-leaf-ids.ts +144 -0
  989. package/src/workspace/migrations/094-seed-avatar-manifest.ts +155 -0
  990. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  991. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  992. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +117 -0
  993. package/src/workspace/migrations/__tests__/094-seed-avatar-manifest.test.ts +136 -0
  994. package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +175 -0
  995. package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +124 -0
  996. package/src/workspace/migrations/registry.ts +12 -0
  997. package/src/workspace/provider-commit-message-generator.ts +15 -17
  998. package/tsconfig.json +4 -1
  999. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  1000. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  1001. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  1002. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -262
  1003. package/src/__tests__/empty-response-pipeline.test.ts +0 -301
  1004. package/src/__tests__/history-repair-pipeline.test.ts +0 -396
  1005. package/src/__tests__/llm-call-pipeline.test.ts +0 -281
  1006. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  1007. package/src/__tests__/persistence-pipeline.test.ts +0 -514
  1008. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  1009. package/src/__tests__/token-estimate-pipeline.test.ts +0 -481
  1010. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  1011. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  1012. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -344
  1013. package/src/cli/commands/__tests__/memory-v3-render.test.ts +0 -340
  1014. package/src/cli/commands/memory-v3-render.ts +0 -491
  1015. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  1016. package/src/daemon/message-types/disk-pressure.ts +0 -9
  1017. package/src/email/feature-gate.ts +0 -23
  1018. package/src/gallery/default-gallery.ts +0 -1359
  1019. package/src/gallery/gallery-manifest.ts +0 -28
  1020. package/src/memory/v3/__tests__/coactivation-store.test.ts +0 -422
  1021. package/src/memory/v3/__tests__/consolidation-job.test.ts +0 -466
  1022. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +0 -270
  1023. package/src/memory/v3/__tests__/edge-learning-job.test.ts +0 -324
  1024. package/src/memory/v3/__tests__/edges.test.ts +0 -706
  1025. package/src/memory/v3/__tests__/filter.test.ts +0 -560
  1026. package/src/memory/v3/__tests__/gate.test.ts +0 -637
  1027. package/src/memory/v3/__tests__/index-composition.test.ts +0 -291
  1028. package/src/memory/v3/__tests__/loop.test.ts +0 -775
  1029. package/src/memory/v3/__tests__/retriever.test.ts +0 -226
  1030. package/src/memory/v3/__tests__/scouts.test.ts +0 -489
  1031. package/src/memory/v3/__tests__/shadow-diff.test.ts +0 -225
  1032. package/src/memory/v3/__tests__/shadow-middleware.test.ts +0 -398
  1033. package/src/memory/v3/__tests__/system-prompts.test.ts +0 -154
  1034. package/src/memory/v3/__tests__/traversal.test.ts +0 -508
  1035. package/src/memory/v3/__tests__/tree-index.test.ts +0 -280
  1036. package/src/memory/v3/__tests__/tree-store.test.ts +0 -529
  1037. package/src/memory/v3/__tests__/tree-walk.test.ts +0 -784
  1038. package/src/memory/v3/__tests__/validate.test.ts +0 -277
  1039. package/src/memory/v3/auto-edges.ts +0 -223
  1040. package/src/memory/v3/coactivation-store.ts +0 -124
  1041. package/src/memory/v3/consolidation-job.ts +0 -323
  1042. package/src/memory/v3/coretrieval-seed.ts +0 -240
  1043. package/src/memory/v3/edge-learning-job.ts +0 -160
  1044. package/src/memory/v3/edges.ts +0 -286
  1045. package/src/memory/v3/filter.ts +0 -286
  1046. package/src/memory/v3/gate.ts +0 -349
  1047. package/src/memory/v3/index-composition.ts +0 -126
  1048. package/src/memory/v3/llm-capture.ts +0 -46
  1049. package/src/memory/v3/loop.ts +0 -430
  1050. package/src/memory/v3/maintenance.ts +0 -144
  1051. package/src/memory/v3/prompt-context.ts +0 -33
  1052. package/src/memory/v3/prompts/consolidation.ts +0 -458
  1053. package/src/memory/v3/prompts/system-prompts.ts +0 -196
  1054. package/src/memory/v3/retriever.ts +0 -33
  1055. package/src/memory/v3/scouts.ts +0 -431
  1056. package/src/memory/v3/shadow-diff.ts +0 -287
  1057. package/src/memory/v3/shadow-middleware.ts +0 -347
  1058. package/src/memory/v3/traversal.ts +0 -211
  1059. package/src/memory/v3/tree-index.ts +0 -237
  1060. package/src/memory/v3/tree-store.ts +0 -394
  1061. package/src/memory/v3/tree-walk.ts +0 -356
  1062. package/src/memory/v3/types.ts +0 -65
  1063. package/src/memory/v3/validate.ts +0 -323
  1064. package/src/plugins/defaults/circuit-breaker.ts +0 -141
  1065. package/src/plugins/defaults/compaction.ts +0 -141
  1066. package/src/plugins/defaults/empty-response.ts +0 -124
  1067. package/src/plugins/defaults/history-repair.ts +0 -83
  1068. package/src/plugins/defaults/llm-call.ts +0 -77
  1069. package/src/plugins/defaults/memory-retrieval.ts +0 -219
  1070. package/src/plugins/defaults/overflow-reduce.ts +0 -185
  1071. package/src/plugins/defaults/persistence.ts +0 -146
  1072. package/src/plugins/defaults/title-generate.ts +0 -90
  1073. package/src/plugins/defaults/token-estimate.ts +0 -101
  1074. package/src/plugins/defaults/tool-error.ts +0 -119
  1075. package/src/plugins/defaults/tool-execute.ts +0 -87
  1076. package/src/plugins/defaults/tool-result-truncate.ts +0 -84
  1077. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +0 -35
  1078. package/src/skills/category-inference.ts +0 -111
@@ -1,4 +1,6 @@
1
- import { beforeEach, describe, expect, mock, test } from "bun:test";
1
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
4
 
3
5
  // This test exercises v1 PKB injection. `config.memory.v2.enabled` (default
4
6
  // `true`) makes the PKB injector go silent — force it off here so the v1
@@ -33,6 +35,10 @@ mock.module("../memory/pkb/pkb-search.js", () => ({
33
35
  },
34
36
  }));
35
37
 
38
+ import {
39
+ clearConversations,
40
+ setConversation,
41
+ } from "../daemon/conversation-registry.js";
36
42
  import type {
37
43
  ChannelCapabilities,
38
44
  SlackTranscriptInputRow,
@@ -44,7 +50,6 @@ import {
44
50
  assembleSlackChronologicalMessages,
45
51
  buildSubagentStatusBlock,
46
52
  buildUnifiedTurnContextBlock,
47
- findLastInjectedNowContent,
48
53
  getSlackCompactionWatermarkForPrefix,
49
54
  injectChannelCapabilityContext,
50
55
  injectChannelCommandContext,
@@ -58,31 +63,102 @@ import {
58
63
  stripInjectionsForCompaction,
59
64
  stripNowScratchpad,
60
65
  } from "../daemon/conversation-runtime-assembly.js";
66
+ import type { SurfaceData, SurfaceType } from "../daemon/message-protocol.js";
61
67
  import { buildPkbReminder } from "../daemon/pkb-reminder-builder.js";
62
68
  import type { MessageRow } from "../memory/conversation-crud.js";
69
+ import { ConversationGraphMemory } from "../memory/graph/conversation-graph-memory.js";
70
+ import { getPkbRoot } from "../memory/pkb/types.js";
63
71
  import {
64
72
  type SlackMessageMetadata,
65
73
  writeSlackMetadata,
66
74
  } from "../messaging/providers/slack/message-metadata.js";
67
75
  import { parentAlias } from "../messaging/providers/slack/render-transcript.js";
68
- import { defaultInjectorsPlugin } from "../plugins/defaults/injectors.js";
69
- import {
70
- registerPlugin,
71
- resetPluginRegistryForTests,
72
- } from "../plugins/registry.js";
73
76
  import type { Message } from "../providers/types.js";
74
77
  import { wrapUntrustedContent } from "../security/untrusted-content.js";
75
78
  import type { SubagentState } from "../subagent/types.js";
79
+ import { getWorkspacePromptPath } from "../util/platform.js";
80
+
81
+ // The pkb-reminder injector derives PKB-active state from the workspace itself
82
+ // — `readPkbContext()` returning content behind the personal-memory trust gate
83
+ // — rather than from a threaded flag. Tests that need the reminder to fire seed
84
+ // a default auto-injected PKB file under the workspace pkb root; tests that
85
+ // need it suppressed leave the pkb dir empty.
86
+ function seedPkbContent(): void {
87
+ const root = getPkbRoot();
88
+ mkdirSync(root, { recursive: true });
89
+ writeFileSync(join(root, "INDEX.md"), "workspace knowledge index", "utf-8");
90
+ }
76
91
 
77
- // `applyRuntimeInjections` is now driven by the default injector chain
78
- // (PR G2.1). The default-injectors plugin must be registered for the chain
79
- // to emit workspace, PKB, NOW.md, subagent, Slack, and thread-focus blocks.
80
- // Each test gets a clean registry so a test that registers its own plugin
81
- // doesn't leak into the next one.
82
- beforeEach(() => {
83
- resetPluginRegistryForTests();
84
- registerPlugin(defaultInjectorsPlugin);
85
- });
92
+ function clearPkbContent(): void {
93
+ rmSync(getPkbRoot(), { recursive: true, force: true });
94
+ }
95
+
96
+ // The now-md injector derives NOW.md state from the workspace itself —
97
+ // `readNowScratchpad()` returning content behind the personal-memory trust gate
98
+ // and the `scratchpadInjection` config toggle — rather than from a threaded
99
+ // option. Seed the file so the injector fires; clear it so suites that assert
100
+ // NOW.md is absent stay unaffected.
101
+ function seedNowScratchpad(content: string): void {
102
+ const nowPath = getWorkspacePromptPath("NOW.md");
103
+ mkdirSync(dirname(nowPath), { recursive: true });
104
+ writeFileSync(nowPath, content, "utf-8");
105
+ }
106
+
107
+ function clearNowScratchpad(): void {
108
+ rmSync(getWorkspacePromptPath("NOW.md"), { force: true });
109
+ }
110
+
111
+ // The workspace-context injector sources its block off the live `Conversation`
112
+ // looked up by `conversationId`. Register a fake instance carrying both a
113
+ // non-dirty workspace context (non-null content, not dirty) so
114
+ // `resolveWorkspaceTopLevelContext` returns it verbatim without rescanning the
115
+ // filesystem, and an active dynamic-page surface, so `applyRuntimeInjections`
116
+ // resolves the `<workspace>` and `<active_workspace>` blocks from it;
117
+ // `clearConversations()` between tests keeps suites that assert the blocks are
118
+ // absent unaffected.
119
+ function seedActiveSurfaceConversation(
120
+ conversationId: string,
121
+ workspaceText: string,
122
+ surfaceId: string,
123
+ data: SurfaceData,
124
+ channelCapabilities?: ChannelCapabilities,
125
+ ): void {
126
+ setConversation(conversationId, {
127
+ conversationId,
128
+ workingDir: "/sandbox",
129
+ workspaceTopLevelContext: workspaceText,
130
+ workspaceTopLevelDirty: false,
131
+ currentActiveSurfaceId: surfaceId,
132
+ surfaceState: new Map<
133
+ string,
134
+ { surfaceType: SurfaceType; data: SurfaceData }
135
+ >([[surfaceId, { surfaceType: "dynamic_page", data }]]),
136
+ channelCapabilities: channelCapabilities ?? undefined,
137
+ } as never);
138
+ }
139
+
140
+ function clearWorkspaceContext(): void {
141
+ clearConversations();
142
+ }
143
+
144
+ // The `<channel_capabilities>` branch and the Slack gates source the channel
145
+ // capabilities off the live `Conversation` looked up by `conversationId`.
146
+ // Register a fake fallback instance carrying the given capabilities (and a
147
+ // non-dirty empty workspace + empty surface so the other live-sourced branches
148
+ // stay inert) so `applyRuntimeInjections` resolves them; `clearConversations()`
149
+ // between tests keeps suites asserting absence unaffected.
150
+ function seedChannelCapabilitiesConversation(
151
+ caps: ChannelCapabilities | null,
152
+ ): void {
153
+ setConversation("runtime-assembly-fallback", {
154
+ conversationId: "runtime-assembly-fallback",
155
+ workingDir: "/sandbox",
156
+ workspaceTopLevelContext: "",
157
+ workspaceTopLevelDirty: false,
158
+ surfaceState: new Map(),
159
+ channelCapabilities: caps ?? undefined,
160
+ } as never);
161
+ }
86
162
 
87
163
  // ---------------------------------------------------------------------------
88
164
  // resolveChannelCapabilities
@@ -556,6 +632,8 @@ describe("stripChannelCapabilityContext", () => {
556
632
  // ---------------------------------------------------------------------------
557
633
 
558
634
  describe("applyRuntimeInjections with channelCapabilities", () => {
635
+ afterEach(clearConversations);
636
+
559
637
  const baseMessages: Message[] = [
560
638
  {
561
639
  role: "user",
@@ -571,9 +649,8 @@ describe("applyRuntimeInjections with channelCapabilities", () => {
571
649
  supportsVoiceInput: false,
572
650
  };
573
651
 
574
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
575
- channelCapabilities: caps,
576
- });
652
+ seedChannelCapabilitiesConversation(caps);
653
+ const { messages: result } = await applyRuntimeInjections(baseMessages, {});
577
654
 
578
655
  expect(result.length).toBe(1);
579
656
  expect(result[0].content.length).toBe(2);
@@ -584,9 +661,8 @@ describe("applyRuntimeInjections with channelCapabilities", () => {
584
661
  });
585
662
 
586
663
  test("does not inject when channelCapabilities is null", async () => {
587
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
588
- channelCapabilities: null,
589
- });
664
+ seedChannelCapabilitiesConversation(null);
665
+ const { messages: result } = await applyRuntimeInjections(baseMessages, {});
590
666
 
591
667
  expect(result.length).toBe(1);
592
668
  expect(result[0].content.length).toBe(1);
@@ -607,9 +683,8 @@ describe("applyRuntimeInjections with channelCapabilities", () => {
607
683
  supportsVoiceInput: false,
608
684
  };
609
685
 
610
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
611
- channelCapabilities: caps,
612
- });
686
+ seedChannelCapabilitiesConversation(caps);
687
+ const { messages: result } = await applyRuntimeInjections(baseMessages, {});
613
688
 
614
689
  expect(result.length).toBe(1);
615
690
  // channelCapabilities prepends
@@ -736,24 +811,52 @@ describe("applyRuntimeInjections — injection mode", () => {
736
811
  },
737
812
  ];
738
813
 
814
+ const channelCapabilities: ChannelCapabilities = {
815
+ channel: "telegram",
816
+ dashboardCapable: false,
817
+ supportsDynamicUi: false,
818
+ supportsVoiceInput: false,
819
+ };
820
+
739
821
  const fullOptions = {
740
- workspaceTopLevelContext: "<workspace>\nRoot: /sandbox\n</workspace>",
741
822
  channelCommandContext: { type: "start" } as const,
742
- activeSurface: { surfaceId: "sf_1", html: "<div>test</div>" },
743
- channelCapabilities: {
744
- channel: "telegram",
745
- dashboardCapable: false,
746
- supportsDynamicUi: false,
747
- supportsVoiceInput: false,
748
- } as ChannelCapabilities,
749
823
  unifiedTurnContext:
750
824
  "<turn_context>\ncurrent_time: 2026-03-04 (Tuesday) 12:00:00 +00:00 (UTC)\ninterface: telegram\n</turn_context>",
751
- nowScratchpad: "Current focus: shipping PR 3",
752
- pkbContext: "essentials content here",
753
- pkbActive: true,
754
825
  isNonInteractive: true,
826
+ // Guardian trust so the personal-memory gate admits the actor regardless
827
+ // of the telegram channel capabilities under test, letting the reminder
828
+ // gate hinge purely on PKB content presence.
829
+ turnContext: {
830
+ requestId: "injection-mode-req",
831
+ conversationId: "injection-mode-conv",
832
+ turnIndex: 0,
833
+ trust: {
834
+ sourceChannel: "vellum" as const,
835
+ trustClass: "guardian" as const,
836
+ },
837
+ },
755
838
  };
756
839
 
840
+ // The reminder fires only when the workspace has PKB content, and the now-md
841
+ // injector only when NOW.md has content; seed both so the full-mode cases
842
+ // exercise the active branch.
843
+ beforeEach(() => {
844
+ seedPkbContent();
845
+ seedNowScratchpad("Current focus: shipping PR 3");
846
+ seedActiveSurfaceConversation(
847
+ "injection-mode-conv",
848
+ "<workspace>\nRoot: /sandbox\n</workspace>",
849
+ "sf_1",
850
+ { html: "<div>test</div>" },
851
+ channelCapabilities,
852
+ );
853
+ });
854
+ afterEach(() => {
855
+ clearPkbContent();
856
+ clearNowScratchpad();
857
+ clearWorkspaceContext();
858
+ });
859
+
757
860
  test("full mode (default) includes all injections", async () => {
758
861
  const { messages: result } = await applyRuntimeInjections(
759
862
  baseMessages,
@@ -860,12 +963,10 @@ describe("applyRuntimeInjections — injection mode", () => {
860
963
  });
861
964
  });
862
965
 
863
- // The standalone `injectNowScratchpad` helper was removed in G2.1. The
864
- // now-md default injector (registered by `defaultInjectorsPlugin`) emits
865
- // the `<NOW.md>` block as an `after-memory-prefix` placement during
866
- // `applyRuntimeInjections`. The suites below (`applyRuntimeInjections with
867
- // nowScratchpad` and the injection-mode tests) cover that behaviour
868
- // end-to-end.
966
+ // The now-md default injector emits the `<NOW.md>` block as an
967
+ // `after-memory-prefix` placement during `applyRuntimeInjections`. The suites
968
+ // below (`applyRuntimeInjections with nowScratchpad` and the injection-mode
969
+ // tests) cover that behaviour end-to-end.
869
970
 
870
971
  // ---------------------------------------------------------------------------
871
972
  // stripNowScratchpad
@@ -1013,7 +1114,7 @@ describe("stripInjectionsForCompaction preserves persistent blocks", () => {
1013
1114
  ).toContain("<turn_context>");
1014
1115
  });
1015
1116
 
1016
- test("<workspace> blocks are NOT stripped", () => {
1117
+ test("<workspace> blocks ARE stripped so the injector re-sources them post-compaction", () => {
1017
1118
  const messages: Message[] = [
1018
1119
  {
1019
1120
  role: "user",
@@ -1029,10 +1130,10 @@ describe("stripInjectionsForCompaction preserves persistent blocks", () => {
1029
1130
 
1030
1131
  const result = stripInjectionsForCompaction(messages);
1031
1132
  expect(result.length).toBe(1);
1032
- expect(result[0].content.length).toBe(2);
1033
- expect(
1034
- (result[0].content[0] as { type: "text"; text: string }).text,
1035
- ).toContain("<workspace>");
1133
+ expect(result[0].content.length).toBe(1);
1134
+ expect((result[0].content[0] as { type: "text"; text: string }).text).toBe(
1135
+ "Hello",
1136
+ );
1036
1137
  });
1037
1138
 
1038
1139
  test("legacy <workspace_top_level> blocks ARE stripped for backward compat", () => {
@@ -1192,10 +1293,14 @@ describe("applyRuntimeInjections with nowScratchpad", () => {
1192
1293
  },
1193
1294
  ];
1194
1295
 
1195
- test("injects NOW.md block when provided", async () => {
1196
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
1197
- nowScratchpad: "Current focus: fix the bug",
1198
- });
1296
+ // The now-md injector sources NOW.md from the workspace itself rather than
1297
+ // from a threaded option, so seed the file to drive injection and clear it so
1298
+ // the absent-content cases see no block.
1299
+ afterEach(clearNowScratchpad);
1300
+
1301
+ test("injects NOW.md block when the file has content", async () => {
1302
+ seedNowScratchpad("Current focus: fix the bug");
1303
+ const { messages: result } = await applyRuntimeInjections(baseMessages, {});
1199
1304
 
1200
1305
  expect(result.length).toBe(1);
1201
1306
  expect(result[0].content.length).toBe(2);
@@ -1206,9 +1311,8 @@ describe("applyRuntimeInjections with nowScratchpad", () => {
1206
1311
  });
1207
1312
 
1208
1313
  test("scratchpad appears before user's original text content", async () => {
1209
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
1210
- nowScratchpad: "scratchpad notes",
1211
- });
1314
+ seedNowScratchpad("scratchpad notes");
1315
+ const { messages: result } = await applyRuntimeInjections(baseMessages, {});
1212
1316
 
1213
1317
  // Scratchpad comes first (before user content)
1214
1318
  expect(
@@ -1220,16 +1324,7 @@ describe("applyRuntimeInjections with nowScratchpad", () => {
1220
1324
  );
1221
1325
  });
1222
1326
 
1223
- test("does not inject when nowScratchpad is null", async () => {
1224
- const { messages: result } = await applyRuntimeInjections(baseMessages, {
1225
- nowScratchpad: null,
1226
- });
1227
-
1228
- expect(result.length).toBe(1);
1229
- expect(result[0].content.length).toBe(1);
1230
- });
1231
-
1232
- test("does not inject when nowScratchpad is omitted", async () => {
1327
+ test("does not inject when the NOW.md file is absent", async () => {
1233
1328
  const { messages: result } = await applyRuntimeInjections(baseMessages, {});
1234
1329
 
1235
1330
  expect(result.length).toBe(1);
@@ -1237,8 +1332,8 @@ describe("applyRuntimeInjections with nowScratchpad", () => {
1237
1332
  });
1238
1333
 
1239
1334
  test("skipped in minimal mode", async () => {
1335
+ seedNowScratchpad("Current focus: fix the bug");
1240
1336
  const { messages: result } = await applyRuntimeInjections(baseMessages, {
1241
- nowScratchpad: "Current focus: fix the bug",
1242
1337
  mode: "minimal",
1243
1338
  });
1244
1339
 
@@ -1782,85 +1877,6 @@ describe("applyRuntimeInjections blocks.unifiedTurnContext", () => {
1782
1877
  });
1783
1878
  });
1784
1879
 
1785
- // ---------------------------------------------------------------------------
1786
- // findLastInjectedNowContent
1787
- // ---------------------------------------------------------------------------
1788
-
1789
- describe("findLastInjectedNowContent", () => {
1790
- test("extracts NOW.md content from the last user message", () => {
1791
- const messages: Message[] = [
1792
- {
1793
- role: "user",
1794
- content: [
1795
- {
1796
- type: "text",
1797
- text: "<NOW.md Always keep this up to date>\nCurrent focus: fix the bug\n</NOW.md>",
1798
- },
1799
- { type: "text", text: "Hello" },
1800
- ],
1801
- },
1802
- ];
1803
-
1804
- expect(findLastInjectedNowContent(messages)).toBe(
1805
- "Current focus: fix the bug",
1806
- );
1807
- });
1808
-
1809
- test("returns null when no NOW.md injection exists", () => {
1810
- const messages: Message[] = [
1811
- {
1812
- role: "user",
1813
- content: [{ type: "text", text: "Hello" }],
1814
- },
1815
- ];
1816
-
1817
- expect(findLastInjectedNowContent(messages)).toBeNull();
1818
- });
1819
-
1820
- test("returns the most recent injection when multiple exist", () => {
1821
- const messages: Message[] = [
1822
- {
1823
- role: "user",
1824
- content: [
1825
- {
1826
- type: "text",
1827
- text: "<NOW.md Always keep this up to date>\nOld focus\n</NOW.md>",
1828
- },
1829
- ],
1830
- },
1831
- { role: "assistant", content: [{ type: "text", text: "OK" }] },
1832
- {
1833
- role: "user",
1834
- content: [
1835
- {
1836
- type: "text",
1837
- text: "<NOW.md Always keep this up to date>\nNew focus\n</NOW.md>",
1838
- },
1839
- ],
1840
- },
1841
- ];
1842
-
1843
- expect(findLastInjectedNowContent(messages)).toBe("New focus");
1844
- });
1845
-
1846
- test("skips assistant messages", () => {
1847
- const messages: Message[] = [
1848
- {
1849
- role: "user",
1850
- content: [
1851
- {
1852
- type: "text",
1853
- text: "<NOW.md Always keep this up to date>\nUser focus\n</NOW.md>",
1854
- },
1855
- ],
1856
- },
1857
- { role: "assistant", content: [{ type: "text", text: "response" }] },
1858
- ];
1859
-
1860
- expect(findLastInjectedNowContent(messages)).toBe("User focus");
1861
- });
1862
- });
1863
-
1864
1880
  // ---------------------------------------------------------------------------
1865
1881
  // Subagent status injection
1866
1882
  // ---------------------------------------------------------------------------
@@ -2032,21 +2048,33 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2032
2048
 
2033
2049
  const FLAT_REMINDER = buildPkbReminder([]);
2034
2050
 
2035
- // Use a platform-agnostic absolute workspace root so the tests work on
2036
- // macOS and Linux runners alike. `pkbRoot` sits under `pkbWorkingDir` to
2037
- // mirror production, where `pkbRoot = join(workingDir, "pkb")`.
2038
- const pkbWorkingDir = "/tmp/fake-workspace";
2039
- const pkbRoot = `${pkbWorkingDir}/pkb`;
2051
+ // The pkb-reminder injector sources the PKB root itself via `getPkbRoot()`,
2052
+ // so the in-context file paths these tests build must resolve against the
2053
+ // same per-test workspace the injector sees.
2054
+ const pkbRoot = getPkbRoot();
2055
+
2056
+ // The pkb-reminder injector reads the dense/sparse PKB query pair off the
2057
+ // conversation's live graph handle (the memory-retrieval hook records it
2058
+ // there during retrieval), not from the injection options. Register a handle
2059
+ // for the fallback conversation id `applyRuntimeInjections` synthesizes and
2060
+ // seed it with a query vector so the hint-search branch runs.
2061
+ let graphHandle: ConversationGraphMemory;
2062
+ beforeEach(() => {
2063
+ graphHandle = new ConversationGraphMemory("runtime-assembly-fallback");
2064
+ graphHandle.recordPkbQueryVectors([0.1, 0.2, 0.3], undefined);
2065
+ });
2066
+ afterEach(() => {
2067
+ graphHandle.dispose();
2068
+ });
2069
+
2070
+ // PKB content makes `readPkbContext()` non-null so the (vellum/guardian-
2071
+ // equivalent) fallback trust gate admits the reminder; cleared after each
2072
+ // test to avoid leaking into suites that assert the reminder is absent.
2073
+ beforeEach(seedPkbContent);
2074
+ afterEach(clearPkbContent);
2040
2075
 
2041
2076
  function makePkbOptions(overrides: Record<string, unknown> = {}) {
2042
2077
  return {
2043
- pkbActive: true,
2044
- pkbQueryVector: [0.1, 0.2, 0.3],
2045
- pkbScopeId: "scope-1",
2046
- pkbConversation: { messages: baseMessages },
2047
- pkbRoot,
2048
- pkbWorkingDir,
2049
- pkbAutoInjectList: [],
2050
2078
  ...overrides,
2051
2079
  };
2052
2080
  }
@@ -2082,10 +2110,11 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2082
2110
  test("default auto-injected files (from PKB_DEFAULT_FILES) are filtered out of hints", async () => {
2083
2111
  // Regression test: when `_autoinject.md` is missing, `readPkbContext`
2084
2112
  // falls back to PKB_DEFAULT_FILES — so those files ARE in the prompt.
2085
- // The tracker must know about them too, otherwise the reminder would
2086
- // redundantly recommend e.g. `essentials.md` even though its contents
2087
- // are already injected. The agent-loop passes the effective auto-inject
2088
- // list (via `getPkbAutoInjectList`) to `applyRuntimeInjections`.
2113
+ // The injector sources the same fallback via `getPkbAutoInjectList`, so
2114
+ // it must know about them too, otherwise the reminder would redundantly
2115
+ // recommend e.g. `essentials.md` even though its contents are already
2116
+ // injected. The per-test workspace has no `_autoinject.md`, so the
2117
+ // injector resolves PKB_DEFAULT_FILES here.
2089
2118
  pkbSearchResults = [
2090
2119
  { path: "essentials.md", denseScore: 0.95 },
2091
2120
  { path: "topics/alpha.md", denseScore: 0.9 },
@@ -2094,16 +2123,7 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2094
2123
 
2095
2124
  const { messages: result } = await applyRuntimeInjections(
2096
2125
  baseMessages,
2097
- makePkbOptions({
2098
- // Simulate the fallback the agent-loop now threads through:
2099
- // `_autoinject.md` is missing, so defaults are injected.
2100
- pkbAutoInjectList: [
2101
- "INDEX.md",
2102
- "essentials.md",
2103
- "threads.md",
2104
- "buffer.md",
2105
- ],
2106
- }),
2126
+ makePkbOptions(),
2107
2127
  );
2108
2128
  const texts = extractTexts(result);
2109
2129
  const reminder = texts.find((t) => t.startsWith("<system_reminder>"));
@@ -2143,27 +2163,26 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2143
2163
  ];
2144
2164
  pkbSearchThrows = null;
2145
2165
 
2146
- // Build a conversation that has already read topics/beta.md via file_read.
2147
- const conversationWithRead: { messages: Message[] } = {
2148
- messages: [
2149
- ...baseMessages,
2150
- {
2151
- role: "assistant",
2152
- content: [
2153
- {
2154
- type: "tool_use",
2155
- id: "tu_1",
2156
- name: "file_read",
2157
- input: { path: `${pkbRoot}/topics/beta.md` },
2158
- },
2159
- ],
2160
- },
2161
- ],
2162
- };
2166
+ // Working messages where topics/beta.md was already read via file_read on
2167
+ // an earlier turn, followed by the current user prompt as the tail.
2168
+ const conversationWithRead: Message[] = [
2169
+ {
2170
+ role: "assistant",
2171
+ content: [
2172
+ {
2173
+ type: "tool_use",
2174
+ id: "tu_1",
2175
+ name: "file_read",
2176
+ input: { path: `${pkbRoot}/topics/beta.md` },
2177
+ },
2178
+ ],
2179
+ },
2180
+ ...baseMessages,
2181
+ ];
2163
2182
 
2164
2183
  const { messages: result } = await applyRuntimeInjections(
2165
- baseMessages,
2166
- makePkbOptions({ pkbConversation: conversationWithRead }),
2184
+ conversationWithRead,
2185
+ makePkbOptions(),
2167
2186
  );
2168
2187
  const texts = extractTexts(result);
2169
2188
  const reminder = texts.find((t) => t.startsWith("<system_reminder>"));
@@ -2201,10 +2220,13 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2201
2220
 
2202
2221
  test("missing query vector → flat fallback, search is not attempted", async () => {
2203
2222
  pkbSearchThrows = new Error("should not be called");
2223
+ // No dense vector was recorded on the graph handle this turn, so the
2224
+ // injector must skip the hint search entirely.
2225
+ graphHandle.recordPkbQueryVectors(undefined, undefined);
2204
2226
 
2205
2227
  const { messages: result } = await applyRuntimeInjections(
2206
2228
  baseMessages,
2207
- makePkbOptions({ pkbQueryVector: undefined }),
2229
+ makePkbOptions(),
2208
2230
  );
2209
2231
  const texts = extractTexts(result);
2210
2232
  const reminder = texts.find((t) => t.startsWith("<system_reminder>"));
@@ -2318,37 +2340,28 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2318
2340
  ];
2319
2341
  pkbSearchThrows = null;
2320
2342
 
2321
- // Pre-compaction conversation: beta was already read.
2322
- const preCompactionConversation: { messages: Message[] } = {
2323
- messages: [
2324
- ...baseMessages,
2325
- {
2326
- role: "assistant",
2327
- content: [
2328
- {
2329
- type: "tool_use",
2330
- id: "tu_pre",
2331
- name: "file_read",
2332
- input: { path: `${pkbRoot}/topics/beta.md` },
2333
- },
2334
- ],
2335
- },
2336
- ],
2337
- };
2343
+ // Pre-compaction working messages: beta was already read on an earlier
2344
+ // turn, followed by the current user prompt as the tail.
2345
+ const preCompactionMessages: Message[] = [
2346
+ {
2347
+ role: "assistant",
2348
+ content: [
2349
+ {
2350
+ type: "tool_use",
2351
+ id: "tu_pre",
2352
+ name: "file_read",
2353
+ input: { path: `${pkbRoot}/topics/beta.md` },
2354
+ },
2355
+ ],
2356
+ },
2357
+ ...baseMessages,
2358
+ ];
2338
2359
 
2339
2360
  // 1. Initial injection sees the pre-compaction state — beta should be
2340
2361
  // filtered out.
2341
2362
  const { messages: initialResult } = await applyRuntimeInjections(
2342
- baseMessages,
2343
- {
2344
- pkbActive: true,
2345
- pkbQueryVector: [0.1, 0.2],
2346
- pkbScopeId: "scope-1",
2347
- pkbConversation: preCompactionConversation,
2348
- pkbRoot,
2349
- pkbWorkingDir,
2350
- pkbAutoInjectList: [],
2351
- },
2363
+ preCompactionMessages,
2364
+ {},
2352
2365
  );
2353
2366
  // Unwrap the injected reminder from the last user message.
2354
2367
  const initialTexts = extractTexts(initialResult);
@@ -2360,41 +2373,29 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2360
2373
  expect(initialReminder).toBeDefined();
2361
2374
  expect(initialReminder).not.toContain("- topics/beta.md");
2362
2375
 
2363
- // 2. Simulate compaction: strip all runtime injections, rebuild
2364
- // conversation to reflect the post-compaction state (tool_use blocks
2365
- // are serialized into summary text, so the only live file_read is the
2366
- // newly-read gamma).
2367
- const postCompactionConversation: { messages: Message[] } = {
2368
- messages: [
2369
- ...baseMessages,
2370
- {
2371
- role: "assistant",
2372
- content: [
2373
- {
2374
- type: "tool_use",
2375
- id: "tu_post",
2376
- name: "file_read",
2377
- input: { path: `${pkbRoot}/topics/gamma.md` },
2378
- },
2379
- ],
2380
- },
2381
- ],
2382
- };
2383
- const postCompactionMessages = stripInjectionsForCompaction(initialResult);
2376
+ // 2. After compaction the working messages reflect the post-compaction
2377
+ // state: beta's tool_use was serialized into summary text and dropped,
2378
+ // so the only live file_read is the newly-read gamma.
2379
+ const postCompactionMessages: Message[] = [
2380
+ {
2381
+ role: "assistant",
2382
+ content: [
2383
+ {
2384
+ type: "tool_use",
2385
+ id: "tu_post",
2386
+ name: "file_read",
2387
+ input: { path: `${pkbRoot}/topics/gamma.md` },
2388
+ },
2389
+ ],
2390
+ },
2391
+ ...baseMessages,
2392
+ ];
2384
2393
 
2385
- // 3. Re-inject with the new conversation — gamma (now in context)
2394
+ // 3. Re-inject over the post-compaction messages — gamma (now in context)
2386
2395
  // should be filtered, and beta (no longer "in context") should appear.
2387
2396
  const { messages: rebuiltResult } = await applyRuntimeInjections(
2388
2397
  postCompactionMessages,
2389
- {
2390
- pkbActive: true,
2391
- pkbQueryVector: [0.1, 0.2],
2392
- pkbScopeId: "scope-1",
2393
- pkbConversation: postCompactionConversation,
2394
- pkbRoot,
2395
- pkbWorkingDir,
2396
- pkbAutoInjectList: [],
2397
- },
2398
+ {},
2398
2399
  );
2399
2400
  const rebuiltTexts = extractTexts(rebuiltResult);
2400
2401
  const rebuiltReminder = rebuiltTexts.find(
@@ -2414,6 +2415,8 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2414
2415
  // ---------------------------------------------------------------------------
2415
2416
 
2416
2417
  describe("Slack channel chronological rendering — multi-thread", () => {
2418
+ afterEach(clearConversations);
2419
+
2417
2420
  // Slack ts values are seconds-since-epoch with microsecond precision.
2418
2421
  // Pick a few stable anchors so thread aliases (sha-derived) stay
2419
2422
  // predictable across the scenarios.
@@ -2499,8 +2502,8 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2499
2502
  role: "user",
2500
2503
  content: [{ type: "text", text: "current turn" }],
2501
2504
  };
2505
+ seedChannelCapabilitiesConversation(slackChannelCaps);
2502
2506
  const { messages } = await applyRuntimeInjections([lastUserMessage], {
2503
- channelCapabilities: slackChannelCaps,
2504
2507
  slackChronologicalMessages,
2505
2508
  });
2506
2509
  return messages;
@@ -2788,15 +2791,15 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2788
2791
  role: "user",
2789
2792
  content: [{ type: "text", text: "vellum question" }],
2790
2793
  };
2794
+ seedChannelCapabilitiesConversation({
2795
+ channel: "vellum",
2796
+ dashboardCapable: true,
2797
+ supportsDynamicUi: true,
2798
+ supportsVoiceInput: true,
2799
+ });
2791
2800
  const { messages: result } = await applyRuntimeInjections(
2792
2801
  [lastUserMessage],
2793
2802
  {
2794
- channelCapabilities: {
2795
- channel: "vellum",
2796
- dashboardCapable: true,
2797
- supportsDynamicUi: true,
2798
- supportsVoiceInput: true,
2799
- },
2800
2803
  // Even if we accidentally pass a chronological transcript, the
2801
2804
  // branch must be a no-op for non-slack channels.
2802
2805
  slackChronologicalMessages: [
@@ -2826,16 +2829,16 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2826
2829
  role: "user",
2827
2830
  content: [{ type: "text", text: "DM question" }],
2828
2831
  };
2832
+ seedChannelCapabilitiesConversation({
2833
+ channel: "slack",
2834
+ dashboardCapable: false,
2835
+ supportsDynamicUi: false,
2836
+ supportsVoiceInput: false,
2837
+ chatType: "im",
2838
+ });
2829
2839
  const { messages: result } = await applyRuntimeInjections(
2830
2840
  [lastUserMessage],
2831
2841
  {
2832
- channelCapabilities: {
2833
- channel: "slack",
2834
- dashboardCapable: false,
2835
- supportsDynamicUi: false,
2836
- supportsVoiceInput: false,
2837
- chatType: "im",
2838
- },
2839
2842
  slackChronologicalMessages: [
2840
2843
  {
2841
2844
  role: "user",
@@ -2894,10 +2897,10 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2894
2897
  ],
2895
2898
  },
2896
2899
  ];
2900
+ seedChannelCapabilitiesConversation(slackCaps);
2897
2901
  const { messages: result } = await applyRuntimeInjections(
2898
2902
  runMessagesWithMemory,
2899
2903
  {
2900
- channelCapabilities: slackCaps,
2901
2904
  slackChronologicalMessages: [
2902
2905
  {
2903
2906
  role: "user",
@@ -2958,10 +2961,10 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2958
2961
  ],
2959
2962
  },
2960
2963
  ];
2964
+ seedChannelCapabilitiesConversation(slackCaps);
2961
2965
  const { messages: result } = await applyRuntimeInjections(
2962
2966
  runMessagesWithMemory,
2963
2967
  {
2964
- channelCapabilities: slackCaps,
2965
2968
  slackChronologicalMessages: [
2966
2969
  {
2967
2970
  role: "user",
@@ -2997,10 +3000,10 @@ describe("Slack channel chronological rendering — multi-thread", () => {
2997
3000
  supportsVoiceInput: false,
2998
3001
  chatType: "im",
2999
3002
  };
3003
+ seedChannelCapabilitiesConversation(slackCaps);
3000
3004
  const { messages: result } = await applyRuntimeInjections(
3001
3005
  [{ role: "user", content: [{ type: "text", text: "inbound" }] }],
3002
3006
  {
3003
- channelCapabilities: slackCaps,
3004
3007
  slackChronologicalMessages: [
3005
3008
  {
3006
3009
  role: "user",
@@ -3041,10 +3044,10 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3041
3044
  { loader: () => rows, trustClass: "guardian" },
3042
3045
  );
3043
3046
 
3047
+ seedChannelCapabilitiesConversation(slackChannelCaps);
3044
3048
  const { messages: result } = await applyRuntimeInjections(
3045
3049
  [{ role: "user", content: [{ type: "text", text: "current turn" }] }],
3046
3050
  {
3047
- channelCapabilities: slackChannelCaps,
3048
3051
  slackChronologicalMessages,
3049
3052
  transportHints: ["thread context: ..."],
3050
3053
  },
@@ -3071,10 +3074,10 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3071
3074
  chatType: "im",
3072
3075
  };
3073
3076
 
3077
+ seedChannelCapabilitiesConversation(slackDmCaps);
3074
3078
  const { messages: result } = await applyRuntimeInjections(
3075
3079
  [{ role: "user", content: [{ type: "text", text: "hi DM" }] }],
3076
3080
  {
3077
- channelCapabilities: slackDmCaps,
3078
3081
  transportHints: ["dm context: ..."],
3079
3082
  },
3080
3083
  );
@@ -3090,16 +3093,16 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3090
3093
 
3091
3094
  // ── transport_hints kept for non-slack channels ───────────────────────
3092
3095
  test("non-slack conversations still receive <transport_hints>", async () => {
3096
+ seedChannelCapabilitiesConversation({
3097
+ channel: "telegram",
3098
+ dashboardCapable: false,
3099
+ supportsDynamicUi: false,
3100
+ supportsVoiceInput: false,
3101
+ chatType: "private",
3102
+ });
3093
3103
  const { messages: result } = await applyRuntimeInjections(
3094
3104
  [{ role: "user", content: [{ type: "text", text: "hi" }] }],
3095
3105
  {
3096
- channelCapabilities: {
3097
- channel: "telegram",
3098
- dashboardCapable: false,
3099
- supportsDynamicUi: false,
3100
- supportsVoiceInput: false,
3101
- chatType: "private",
3102
- },
3103
3106
  transportHints: ["please answer concisely"],
3104
3107
  },
3105
3108
  );
@@ -3426,8 +3429,8 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3426
3429
  role: "user",
3427
3430
  content: [{ type: "text", text: "current turn" }],
3428
3431
  };
3432
+ seedChannelCapabilitiesConversation(slackChannelCaps);
3429
3433
  const { messages } = await applyRuntimeInjections([lastUserMessage], {
3430
- channelCapabilities: slackChannelCaps,
3431
3434
  slackChronologicalMessages,
3432
3435
  slackActiveThreadFocusBlock: focusBlock,
3433
3436
  });
@@ -3696,8 +3699,8 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3696
3699
  chatType: "channel",
3697
3700
  };
3698
3701
  const newFocus = "<active_thread>\nnewly built\n</active_thread>";
3702
+ seedChannelCapabilitiesConversation(slackChannelCaps);
3699
3703
  const { messages: reInjected } = await applyRuntimeInjections(stripped, {
3700
- channelCapabilities: slackChannelCaps,
3701
3704
  slackActiveThreadFocusBlock: newFocus,
3702
3705
  });
3703
3706
  const reInjectedTexts = reInjected
@@ -3717,15 +3720,15 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3717
3720
  // Defensive: the focus injection is gated on `slackChannel` (i.e.
3718
3721
  // `isSlackChannelConversation`). Even if a caller mistakenly forwards
3719
3722
  // a focus block on a non-Slack channel, it must NOT be appended.
3723
+ seedChannelCapabilitiesConversation({
3724
+ channel: "vellum",
3725
+ dashboardCapable: true,
3726
+ supportsDynamicUi: true,
3727
+ supportsVoiceInput: true,
3728
+ });
3720
3729
  const { messages: result } = await applyRuntimeInjections(
3721
3730
  [{ role: "user", content: [{ type: "text", text: "vellum question" }] }],
3722
3731
  {
3723
- channelCapabilities: {
3724
- channel: "vellum",
3725
- dashboardCapable: true,
3726
- supportsDynamicUi: true,
3727
- supportsVoiceInput: true,
3728
- },
3729
3732
  slackActiveThreadFocusBlock: "<active_thread>\nbogus\n</active_thread>",
3730
3733
  },
3731
3734
  );
@@ -3742,16 +3745,16 @@ describe("Slack channel chronological rendering — multi-thread", () => {
3742
3745
  // Same as above but for Slack DMs (chatType === "im"). The focus
3743
3746
  // injection is keyed on `isSlackChannelConversation` which excludes
3744
3747
  // DMs, so the block must not appear.
3748
+ seedChannelCapabilitiesConversation({
3749
+ channel: "slack",
3750
+ dashboardCapable: false,
3751
+ supportsDynamicUi: false,
3752
+ supportsVoiceInput: false,
3753
+ chatType: "im",
3754
+ });
3745
3755
  const { messages: result } = await applyRuntimeInjections(
3746
3756
  [{ role: "user", content: [{ type: "text", text: "DM question" }] }],
3747
3757
  {
3748
- channelCapabilities: {
3749
- channel: "slack",
3750
- dashboardCapable: false,
3751
- supportsDynamicUi: false,
3752
- supportsVoiceInput: false,
3753
- chatType: "im",
3754
- },
3755
3758
  slackActiveThreadFocusBlock: "<active_thread>\nbogus\n</active_thread>",
3756
3759
  },
3757
3760
  );
@@ -3990,11 +3993,11 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
3990
3993
  expect(result!).not.toContain("Sibling top-level");
3991
3994
  });
3992
3995
 
3993
- test("preserves speaker attribution when flattening to plain text", () => {
3996
+ test("preserves user attribution while leaving assistant text unchanged", () => {
3994
3997
  // The `<active_thread>` block is rendered as newline-joined plain text,
3995
- // discarding `Message.role`. Assistant rows and unnamed user rows must
3996
- // therefore carry an explicit `@assistant` / `@user` label so the model
3997
- // can still tell turns apart inside the flattened block.
3998
+ // discarding `Message.role`. User rows keep explicit Slack attribution,
3999
+ // while assistant rows remain raw to avoid teaching the model a synthetic
4000
+ // reply prefix.
3998
4001
  const rows: SlackTranscriptInputRow[] = [
3999
4002
  buildRow(
4000
4003
  "user",
@@ -4021,17 +4024,16 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
4021
4024
  const result = assembleSlackActiveThreadFocusBlock(rows, SLACK_CAPS);
4022
4025
  expect(result).not.toBeNull();
4023
4026
  expect(result!).toContain("@alice");
4024
- expect(result!).toContain("@assistant");
4027
+ expect(result!).toContain("Assistant reply");
4028
+ expect(result!).not.toContain("@assistant: Assistant reply");
4025
4029
  expect(result!).toContain("@user");
4026
4030
  });
4027
4031
 
4028
4032
  test("assistant reactions are not double-attributed (`@assistant: [... @assistant reacted ...]`)", () => {
4029
4033
  // `renderReaction` bakes `@assistant` into the reaction tag line
4030
4034
  // (`[11/14/23 14:28 @assistant reacted 👍 to Mxxxxxx]`). The
4031
- // post-render step that prepends `@assistant: ` to assistant content
4032
- // lines must skip reaction lines, otherwise the flattened block
4033
- // produces `@assistant: [... @assistant reacted ...]` — two
4034
- // attributions for one event.
4035
+ // flattened block should preserve that renderer-owned attribution without
4036
+ // adding any extra assistant-message prefix.
4035
4037
  const rows: SlackTranscriptInputRow[] = [
4036
4038
  buildRow(
4037
4039
  "user",
@@ -4039,7 +4041,7 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
4039
4041
  1_000,
4040
4042
  buildMeta({ channelTs: PARENT_TS, displayName: "@alice" }),
4041
4043
  ),
4042
- // Assistant reply in the thread — gets an `@assistant:` prefix.
4044
+ // Assistant reply in the thread — stays unchanged.
4043
4045
  buildRow(
4044
4046
  "assistant",
4045
4047
  "Assistant reply",
@@ -4081,12 +4083,13 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
4081
4083
  expect(result).not.toBeNull();
4082
4084
  // Double-attribution anti-pattern must NOT appear anywhere.
4083
4085
  expect(result!).not.toContain("@assistant: [");
4084
- // Both the reaction attribution and the reply prefix are still present.
4086
+ // Reaction attribution remains, and the assistant reply stays raw.
4085
4087
  expect(result!).toContain("@assistant reacted 👍");
4086
- expect(result!).toContain("@assistant: Assistant reply");
4088
+ expect(result!).toContain("Assistant reply");
4089
+ expect(result!).not.toContain("@assistant: Assistant reply");
4087
4090
  });
4088
4091
 
4089
- test("timezone-aware assistant rows keep renderer attribution in active-thread focus block", () => {
4092
+ test("timezone-aware assistant rows stay unchanged in active-thread focus block", () => {
4090
4093
  const rows: SlackTranscriptInputRow[] = [
4091
4094
  buildRow(
4092
4095
  "user",
@@ -4127,15 +4130,12 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
4127
4130
 
4128
4131
  const result = assembleSlackActiveThreadFocusBlock(rows, SLACK_CAPS);
4129
4132
  expect(result).not.toBeNull();
4130
- expect(result!).toContain(
4131
- "[nov 14 2023 3:13 PM MT assistant] Assistant reply",
4132
- );
4133
- expect(result!).not.toContain(
4134
- "@assistant: [nov 14 2023 3:13 PM MT assistant]",
4135
- );
4133
+ expect(result!).toContain("\nAssistant reply\n");
4134
+ expect(result!).not.toContain("[nov 14 2023 3:13 PM MT assistant]");
4135
+ expect(result!).not.toContain("@assistant: Assistant reply");
4136
4136
  });
4137
4137
 
4138
- test("assistant content that only looks like a compact tag still gets active-thread attribution", () => {
4138
+ test("assistant content that only looks like a compact tag stays unchanged", () => {
4139
4139
  const compactLookingContent =
4140
4140
  "[nov 14 2023 3:13 PM MT assistant] Assistant reply";
4141
4141
  const rows: SlackTranscriptInputRow[] = [
@@ -4168,7 +4168,8 @@ describe("assembleSlackActiveThreadFocusBlock", () => {
4168
4168
 
4169
4169
  const result = assembleSlackActiveThreadFocusBlock(rows, SLACK_CAPS);
4170
4170
  expect(result).not.toBeNull();
4171
- expect(result!).toContain(`@assistant: ${compactLookingContent}`);
4171
+ expect(result!).toContain(`\n${compactLookingContent}\n`);
4172
+ expect(result!).not.toContain(`@assistant: ${compactLookingContent}`);
4172
4173
  });
4173
4174
 
4174
4175
  test("assistant reaction overflow trailer is not double-attributed", () => {
@@ -5102,11 +5103,15 @@ describe("applyRuntimeInjections blocks.pkbSystemReminder", () => {
5102
5103
  },
5103
5104
  ];
5104
5105
 
5106
+ // The reminder gate hinges on PKB content presence; clear it after each test
5107
+ // so the "PKB inactive" case starts from an empty workspace pkb dir.
5108
+ afterEach(clearPkbContent);
5109
+
5105
5110
  test("captures exact reminder bytes when full mode and PKB active", async () => {
5111
+ seedPkbContent();
5106
5112
  pkbSearchResults = [];
5107
5113
  pkbSearchThrows = null;
5108
5114
  const { blocks } = await applyRuntimeInjections(baseMessages, {
5109
- pkbActive: true,
5110
5115
  mode: "full",
5111
5116
  });
5112
5117
 
@@ -5115,8 +5120,8 @@ describe("applyRuntimeInjections blocks.pkbSystemReminder", () => {
5115
5120
  });
5116
5121
 
5117
5122
  test("not captured in minimal mode", async () => {
5123
+ seedPkbContent();
5118
5124
  const { blocks } = await applyRuntimeInjections(baseMessages, {
5119
- pkbActive: true,
5120
5125
  mode: "minimal",
5121
5126
  });
5122
5127
 
@@ -5125,7 +5130,6 @@ describe("applyRuntimeInjections blocks.pkbSystemReminder", () => {
5125
5130
 
5126
5131
  test("not captured when PKB inactive", async () => {
5127
5132
  const { blocks } = await applyRuntimeInjections(baseMessages, {
5128
- pkbActive: false,
5129
5133
  mode: "full",
5130
5134
  });
5131
5135