@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae

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 (475) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +263 -121
  12. package/package.json +2 -2
  13. package/src/__tests__/activation-early-marking.test.ts +120 -0
  14. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  15. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  16. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  17. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  18. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  19. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  20. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  21. package/src/__tests__/agent-loop.test.ts +441 -96
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  23. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  24. package/src/__tests__/anthropic-provider.test.ts +23 -8
  25. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/app-executors.test.ts +132 -0
  29. package/src/__tests__/approval-cascade.test.ts +6 -5
  30. package/src/__tests__/approval-routes-http.test.ts +4 -1
  31. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  32. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  33. package/src/__tests__/channel-approvals.test.ts +1 -1
  34. package/src/__tests__/compaction-circuit.test.ts +258 -0
  35. package/src/__tests__/compaction-direct.test.ts +146 -0
  36. package/src/__tests__/compaction-events.test.ts +7 -7
  37. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  38. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  39. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  40. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  41. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  42. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  43. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  44. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  45. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  46. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  47. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  48. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  49. package/src/__tests__/conversation-error.test.ts +15 -1
  50. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  52. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  53. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  55. package/src/__tests__/conversation-queue.test.ts +10 -10
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  57. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  58. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  59. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  60. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  61. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  62. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  65. package/src/__tests__/conversation-undo.test.ts +2 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  67. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/corrected-target.test.ts +93 -0
  71. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  72. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  73. package/src/__tests__/db-acp-history.test.ts +101 -0
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +1 -1
  76. package/src/__tests__/file-write-tool.test.ts +63 -0
  77. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  78. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  79. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  80. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  82. package/src/__tests__/heartbeat-service.test.ts +1 -0
  83. package/src/__tests__/history-repair-hook.test.ts +5 -1
  84. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  85. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  86. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  87. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  88. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  89. package/src/__tests__/injector-background-turn.test.ts +13 -23
  90. package/src/__tests__/injector-chain.test.ts +268 -44
  91. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  92. package/src/__tests__/injector-document-comments.test.ts +97 -114
  93. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  94. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  95. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  96. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  97. package/src/__tests__/llm-resolver.test.ts +73 -0
  98. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  99. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  100. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  101. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  102. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  103. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  104. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  105. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  106. package/src/__tests__/plugin-registry.test.ts +3 -49
  107. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  108. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  109. package/src/__tests__/plugin-types.test.ts +0 -70
  110. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  111. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  112. package/src/__tests__/published-app-updater.test.ts +138 -0
  113. package/src/__tests__/reaction-persistence.test.ts +1 -1
  114. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  115. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  116. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  117. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  118. package/src/__tests__/subagent-detail.test.ts +25 -7
  119. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  120. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  121. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  122. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  123. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  124. package/src/__tests__/title-generate-hook.test.ts +5 -1
  125. package/src/__tests__/tool-error-hook.test.ts +1 -1
  126. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  127. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  128. package/src/__tests__/web-fetch.test.ts +45 -0
  129. package/src/acp/__tests__/agent-process.test.ts +161 -0
  130. package/src/acp/__tests__/client-handler.test.ts +40 -0
  131. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  132. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  133. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  134. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  135. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  136. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  137. package/src/acp/agent-process.ts +61 -1
  138. package/src/acp/auto-install.test.ts +280 -0
  139. package/src/acp/auto-install.ts +232 -0
  140. package/src/acp/client-handler.ts +31 -0
  141. package/src/acp/prepare-agent-env.ts +80 -27
  142. package/src/acp/resolve-agent.test.ts +188 -28
  143. package/src/acp/resolve-agent.ts +119 -42
  144. package/src/acp/resume-hint.ts +23 -0
  145. package/src/acp/session-manager.ts +507 -73
  146. package/src/agent/compaction-circuit.ts +60 -102
  147. package/src/agent/loop.ts +403 -251
  148. package/src/api/responses/conversation-message.ts +22 -2
  149. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  150. package/src/approvals/guardian-request-resolvers.ts +27 -1
  151. package/src/background-wake/next-wake.ts +1 -0
  152. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  153. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  154. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  155. package/src/cli/commands/memory-v3.ts +57 -199
  156. package/src/cli/commands/plugins.ts +43 -37
  157. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  158. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  159. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  160. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  161. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  162. package/src/cli/lib/install-from-github.ts +797 -60
  163. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  164. package/src/cli/lib/plugin-details.ts +416 -0
  165. package/src/cli/lib/plugin-marketplace.ts +215 -0
  166. package/src/cli/lib/search-plugins.ts +201 -29
  167. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  168. package/src/config/acp-defaults.test.ts +10 -0
  169. package/src/config/acp-defaults.ts +9 -3
  170. package/src/config/acp-schema.ts +1 -7
  171. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  172. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  173. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  174. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  175. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  176. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  177. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  178. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  179. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  180. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  181. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  182. package/src/config/bundled-tool-registry.ts +4 -0
  183. package/src/config/call-site-defaults.ts +0 -3
  184. package/src/config/feature-flag-registry.json +10 -16
  185. package/src/config/llm-resolver.ts +39 -7
  186. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  187. package/src/config/schemas/call-site-catalog.ts +0 -21
  188. package/src/config/schemas/heartbeat.ts +9 -0
  189. package/src/config/schemas/llm.ts +17 -3
  190. package/src/config/schemas/memory-v3.ts +58 -8
  191. package/src/config/seed-inference-profiles.ts +18 -0
  192. package/src/context/compactor.ts +22 -4
  193. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  194. package/src/context/strip-injections.ts +8 -2
  195. package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
  196. package/src/daemon/conversation-agent-loop.ts +308 -1297
  197. package/src/daemon/conversation-error.ts +31 -4
  198. package/src/daemon/conversation-history.ts +1 -1
  199. package/src/daemon/conversation-lifecycle.ts +11 -255
  200. package/src/daemon/conversation-media-retry.ts +19 -6
  201. package/src/daemon/conversation-messaging.ts +17 -0
  202. package/src/daemon/conversation-process.ts +22 -141
  203. package/src/daemon/conversation-queue-manager.ts +8 -0
  204. package/src/daemon/conversation-registry.ts +159 -0
  205. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  206. package/src/daemon/conversation-store.ts +9 -90
  207. package/src/daemon/conversation-surfaces.ts +165 -11
  208. package/src/daemon/conversation-workspace.ts +17 -0
  209. package/src/daemon/conversation.ts +444 -62
  210. package/src/daemon/disk-pressure-policy.ts +0 -1
  211. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  212. package/src/daemon/handlers/config-channels.ts +11 -2
  213. package/src/daemon/handlers/conversations.ts +3 -1
  214. package/src/daemon/handlers/skills.ts +4 -1
  215. package/src/daemon/host-app-control-proxy.ts +72 -57
  216. package/src/daemon/host-proxy-preactivation.ts +1 -3
  217. package/src/daemon/lifecycle.ts +21 -7
  218. package/src/daemon/persist-unsendable-image.ts +62 -25
  219. package/src/daemon/process-message.ts +1 -1
  220. package/src/daemon/server.ts +2 -0
  221. package/src/daemon/tool-side-effects.ts +15 -0
  222. package/src/daemon/wake-conversation-ops.ts +269 -0
  223. package/src/embedded/plugin-api.ts +2 -2
  224. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  225. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  226. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  227. package/src/heartbeat/heartbeat-service.ts +26 -0
  228. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  229. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  230. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  231. package/src/ipc/skill-routes/memory.ts +4 -2
  232. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  233. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  234. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  235. package/src/memory/activation-session-store.ts +43 -0
  236. package/src/memory/conversation-crud.ts +29 -19
  237. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  238. package/src/memory/db-init.ts +6 -0
  239. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  240. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  241. package/src/memory/jobs-worker.ts +25 -1
  242. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  243. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  244. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  245. package/src/memory/migrations/index.ts +3 -0
  246. package/src/memory/onboarding-events-store.ts +66 -18
  247. package/src/memory/schema/acp.ts +4 -0
  248. package/src/memory/schema/infrastructure.ts +13 -0
  249. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  250. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  251. package/src/memory/v2/consolidation-job.ts +2 -63
  252. package/src/memory/v2/types.ts +5 -0
  253. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  254. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  255. package/src/notifications/access-request-copy.ts +298 -0
  256. package/src/notifications/adapters/slack.ts +3 -3
  257. package/src/notifications/adapters/telegram.ts +9 -2
  258. package/src/notifications/copy-composer.ts +49 -267
  259. package/src/notifications/decision-engine.ts +16 -35
  260. package/src/notifications/home-feed-side-effect.ts +1 -6
  261. package/src/plugin-api/constants.ts +4 -0
  262. package/src/plugin-api/index.ts +40 -11
  263. package/src/plugin-api/types.ts +108 -0
  264. package/src/plugins/defaults/compaction/compact.ts +106 -0
  265. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  266. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  267. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  268. package/src/plugins/defaults/compaction/package.json +1 -2
  269. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  270. package/src/plugins/defaults/empty-response/package.json +0 -1
  271. package/src/plugins/defaults/history-repair/package.json +0 -1
  272. package/src/plugins/defaults/index.ts +156 -26
  273. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  274. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  275. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  276. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  277. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  278. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  282. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  283. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  284. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  285. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  286. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  287. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  288. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  289. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  290. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  291. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  293. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  294. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  295. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  296. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  297. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  298. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  299. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  300. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  301. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  302. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  303. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  304. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  306. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  307. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  308. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  309. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  310. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  311. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  312. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  313. package/src/plugins/defaults/title-generate/package.json +0 -1
  314. package/src/plugins/defaults/tool-error/package.json +0 -1
  315. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  316. package/src/plugins/external-api.ts +12 -2
  317. package/src/plugins/pipeline.ts +6 -293
  318. package/src/plugins/registry.ts +9 -37
  319. package/src/plugins/types.ts +76 -381
  320. package/src/plugins/user-loader.ts +30 -127
  321. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  322. package/src/prompts/system-prompt.ts +61 -10
  323. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  324. package/src/providers/anthropic/client.ts +9 -10
  325. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  326. package/src/providers/inference/logit-bias.ts +55 -0
  327. package/src/providers/model-catalog.ts +34 -0
  328. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  329. package/src/providers/openai/chat-completions-provider.ts +44 -1
  330. package/src/providers/retry.ts +22 -0
  331. package/src/providers/types.ts +6 -0
  332. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  333. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  334. package/src/runtime/agent-wake.ts +108 -209
  335. package/src/runtime/assistant-event-hub.ts +1 -1
  336. package/src/runtime/channel-approvals.ts +1 -1
  337. package/src/runtime/interactive-ui.ts +1 -1
  338. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  339. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  340. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  341. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  342. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  343. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  344. package/src/runtime/routes/acp-routes.test.ts +185 -32
  345. package/src/runtime/routes/acp-routes.ts +328 -30
  346. package/src/runtime/routes/app-management-routes.ts +3 -0
  347. package/src/runtime/routes/approval-routes.ts +1 -1
  348. package/src/runtime/routes/browser-routes.ts +1 -1
  349. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  350. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  351. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  352. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  354. package/src/runtime/routes/conversation-routes.ts +30 -2
  355. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  356. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  357. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  358. package/src/runtime/routes/host-cu-routes.ts +1 -1
  359. package/src/runtime/routes/identity-routes.ts +18 -3
  360. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  361. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  362. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  363. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  364. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  365. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  366. package/src/runtime/routes/playground/helpers.ts +1 -1
  367. package/src/runtime/routes/plugins-routes.ts +337 -35
  368. package/src/runtime/routes/stt-routes.ts +45 -12
  369. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  370. package/src/runtime/routes/work-items-routes.ts +2 -4
  371. package/src/runtime/routes/workspace-routes.ts +50 -15
  372. package/src/runtime/services/conversation-serializer.ts +1 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/services/published-app-updater.ts +30 -8
  376. package/src/signals/cancel.ts +2 -4
  377. package/src/subagent/manager.ts +21 -5
  378. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  379. package/src/telemetry/activation-funnel.ts +167 -0
  380. package/src/telemetry/types.ts +13 -0
  381. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  382. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  383. package/src/tools/acp/context.ts +20 -0
  384. package/src/tools/acp/list-agents.test.ts +9 -19
  385. package/src/tools/acp/list-agents.ts +3 -15
  386. package/src/tools/acp/spawn.test.ts +173 -202
  387. package/src/tools/acp/spawn.ts +37 -172
  388. package/src/tools/acp/steer.test.ts +105 -8
  389. package/src/tools/acp/steer.ts +48 -17
  390. package/src/tools/apps/executors.ts +166 -50
  391. package/src/tools/browser/browser-execution.ts +12 -2
  392. package/src/tools/filesystem/write.ts +34 -0
  393. package/src/tools/network/web-fetch.ts +65 -24
  394. package/src/tools/skills/load.ts +1 -1
  395. package/src/tools/subagent/spawn.ts +2 -4
  396. package/src/tools/ui-surface/definitions.ts +32 -5
  397. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  398. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  399. package/docs/plugins.md +0 -832
  400. package/examples/plugins/echo/register.ts +0 -143
  401. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  402. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  403. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  404. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  405. package/src/__tests__/pipeline-runner.test.ts +0 -554
  406. package/src/daemon/wake-target-adapter.ts +0 -253
  407. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  408. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  409. package/src/memory/v3/__tests__/core.test.ts +0 -39
  410. package/src/memory/v3/__tests__/health.test.ts +0 -219
  411. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  412. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  413. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  414. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  415. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  416. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  417. package/src/memory/v3/__tests__/router.test.ts +0 -332
  418. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  419. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  420. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  421. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  422. package/src/memory/v3/assign.ts +0 -268
  423. package/src/memory/v3/capabilities.ts +0 -124
  424. package/src/memory/v3/core.ts +0 -26
  425. package/src/memory/v3/health.ts +0 -0
  426. package/src/memory/v3/maintain-job.ts +0 -314
  427. package/src/memory/v3/needle.ts +0 -115
  428. package/src/memory/v3/orchestrate.ts +0 -126
  429. package/src/memory/v3/page-content.ts +0 -34
  430. package/src/memory/v3/provider-blocks.ts +0 -26
  431. package/src/memory/v3/reconcile.ts +0 -523
  432. package/src/memory/v3/router.ts +0 -190
  433. package/src/memory/v3/selection-log-store.ts +0 -84
  434. package/src/memory/v3/selector.ts +0 -226
  435. package/src/memory/v3/shadow-plugin.ts +0 -411
  436. package/src/memory/v3/snapshot.ts +0 -209
  437. package/src/memory/v3/tree.ts +0 -174
  438. package/src/memory/v3/types.ts +0 -59
  439. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  440. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  441. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  442. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  443. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  444. package/src/plugins/defaults/compaction/register.ts +0 -35
  445. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  446. package/src/plugins/defaults/empty-response/register.ts +0 -23
  447. package/src/plugins/defaults/history-repair/register.ts +0 -24
  448. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  449. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  450. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  451. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  452. package/src/plugins/defaults/title-generate/register.ts +0 -35
  453. package/src/plugins/defaults/tool-error/register.ts +0 -23
  454. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  455. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  456. package/src/proactive-artifact/decision.test.ts +0 -226
  457. package/src/proactive-artifact/decision.ts +0 -165
  458. package/src/proactive-artifact/index.ts +0 -7
  459. package/src/proactive-artifact/job.test.ts +0 -962
  460. package/src/proactive-artifact/job.ts +0 -372
  461. package/src/proactive-artifact/message-copy.ts +0 -58
  462. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  463. package/src/proactive-artifact/trigger-state.ts +0 -123
  464. package/src/util/map-limit.ts +0 -27
  465. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  466. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  467. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  468. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  469. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  470. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  471. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  472. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  473. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  474. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  475. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -4,9 +4,9 @@
4
4
  * SCOPE / ALTITUDE. A full daemon-assembly integration (plugin registry → flag
5
5
  * read → runtime assembly → provider call) is too heavy and too mock-fragile
6
6
  * for a unit test. Instead this composes the REAL v3 live-path units with a
7
- * mocked routing/selection provider and synthetic fixtures:
7
+ * mocked select provider + stubbed dense lane and synthetic fixtures:
8
8
  *
9
- * orchestrate (routeL1 + selectAcrossLeaves over a shared WorkingSet)
9
+ * orchestrate (needle ∪ dense ∪ edge → selectPool over a shared WorkingSet)
10
10
  * → renderMemoryBlock (the rendered `<memory>` working-set block)
11
11
  * → stripAllMemoryInjections (all-turns history strip)
12
12
  *
@@ -16,108 +16,103 @@
16
16
  * message so exactly one block exists. Driving these real units across turns
17
17
  * exercises carry-forward, eviction, single-source, and strip-all end-to-end at
18
18
  * the v3 layer without the daemon. The provider is stubbed (no network).
19
- *
20
- * Mock-leak safety: the only `mock.module` here stub the provider + logger,
21
- * which are pure inputs to orchestrate and carry no real behavior siblings
22
- * depend on (orchestrate.test.ts installs the identical stubs). No
23
- * snapshot-real-modules dance is needed because nothing is partially stubbed.
24
19
  */
25
20
 
26
- import { beforeEach, describe, expect, mock, test } from "bun:test";
21
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
27
22
 
23
+ import { stripAllMemoryInjections } from "../../../../memory/graph/conversation-graph-memory.js";
24
+ import type { PageIndexEntry } from "../../../../memory/v2/page-index.js";
28
25
  import type {
29
26
  ContentBlock,
30
27
  Message,
31
28
  Provider,
32
29
  ProviderResponse,
33
- } from "../../../providers/types.js";
34
- import { stripAllMemoryInjections } from "../../graph/conversation-graph-memory.js";
35
- import type { NeedleIndex } from "../needle.js";
36
- import type {
37
- LeafNode,
38
- LeafPath,
39
- LeafTree,
40
- Slug,
41
- TurnContext,
42
- } from "../types.js";
43
- import liveTurns from "./fixtures/live-turns.json" with { type: "json" };
30
+ } from "../../../../providers/types.js";
31
+ import type { EdgeGraph } from "../edge.js";
32
+ import { buildEdgeGraph } from "../edge.js";
33
+ import { buildSectionNeedle } from "../section-needle.js";
34
+ import { buildSectionIndex } from "../sections.js";
35
+ import type { MemoryRoutingTurn, SectionIndex, Slug } from "../types.js";
44
36
 
45
37
  // ---------------------------------------------------------------------------
46
- // Provider mock installed BEFORE the orchestrator import so router.ts and
47
- // selector.ts observe it at load time. Mirrors orchestrate.test.ts.
38
+ // Module stubs installed BEFORE the orchestrator import.
48
39
  // ---------------------------------------------------------------------------
49
40
 
50
41
  let providerStub: Provider | null = null;
51
42
 
52
- mock.module("../../../providers/provider-send-message.js", () => ({
43
+ mock.module("../../../../providers/provider-send-message.js", () => ({
53
44
  getConfiguredProvider: async () => providerStub,
54
45
  extractToolUse: (response: ProviderResponse) =>
55
46
  response.content.find((b) => b.type === "tool_use"),
56
47
  }));
57
48
 
58
- mock.module("../../../util/logger.js", () => ({
49
+ mock.module("../../../../util/logger.js", () => ({
59
50
  getLogger: () =>
60
51
  new Proxy({} as Record<string, unknown>, {
61
52
  get: (_t, prop) => (prop === "child" ? () => ({}) : () => {}),
62
53
  }),
63
54
  }));
64
55
 
56
+ // The dense lane never hits in this fixture — the needle drives the pool. The
57
+ // stub DELEGATES to the real `denseLane` unless this file's tests are running
58
+ // (`denseMockActive`), so the process-global `mock.module` cannot leak fake
59
+ // behavior into dense.test.ts (which exercises the real lane).
60
+ const realDense = { ...(await import("../dense.js")) };
61
+ let denseMockActive = false;
62
+ mock.module("../dense.js", () => ({
63
+ ...realDense,
64
+ denseLane: async (...args: Parameters<typeof realDense.denseLane>) =>
65
+ denseMockActive ? [] : realDense.denseLane(...args),
66
+ }));
67
+
65
68
  const { orchestrate } = await import("../orchestrate.js");
66
69
  const { WorkingSet } = await import("../working-set.js");
67
70
  const { renderMemoryBlock } = await import("../render-injection.js");
68
71
 
69
72
  // ---------------------------------------------------------------------------
70
- // Fixture types + helpers.
73
+ // Fixtures: a tiny corpus whose section text contains a distinctive term per
74
+ // page so a query selects exactly that page via the needle.
71
75
  // ---------------------------------------------------------------------------
72
76
 
73
- interface LeafSelection {
74
- ids: number[];
75
- pinned_ids: number[];
76
- }
77
- interface LiveTurn {
78
- name: string;
79
- currentMessage: string;
80
- routeIds: number[];
81
- leafSelections: Record<LeafPath, LeafSelection>;
82
- }
83
- const TURNS = (liveTurns as unknown as { turns: LiveTurn[] }).turns;
84
-
85
- function makeLeaf(path: LeafPath, members: Slug[]): LeafNode {
86
- return {
87
- path,
88
- frontmatter: { path, in_core: false },
89
- description: `description for ${path}`,
90
- members,
91
- domain: path.split("/")[0],
92
- };
93
- }
94
-
95
- /**
96
- * Synthetic tree. Sorted leaf order is [domain-a/topic-x, domain-a/topic-y],
97
- * so L1 id 1 → topic-x, id 2 → topic-y.
98
- */
99
- function makeTree(): LeafTree {
100
- const leaves: LeafNode[] = [
101
- makeLeaf("domain-a/topic-x", ["page-a", "page-b"]),
102
- makeLeaf("domain-a/topic-y", ["page-c"]),
103
- ];
104
- const byPage = new Map<Slug, LeafPath[]>();
105
- for (const leaf of leaves) {
106
- for (const slug of leaf.members) {
107
- byPage.set(slug, [...(byPage.get(slug) ?? []), leaf.path]);
108
- }
109
- }
110
- return { leaves: new Map(leaves.map((n) => [n.path, n])), byPage };
77
+ const PAGES: Record<Slug, string> = {
78
+ "page-a": "lead a\n## Body\napple content for page a",
79
+ "page-b": "lead b\n## Body\nbanana content for page b",
80
+ "page-c": "lead c\n## Body\ncherry content for page c",
81
+ };
82
+ const SLUGS = Object.keys(PAGES);
83
+
84
+ function makeEntries(): PageIndexEntry[] {
85
+ return SLUGS.map((slug, i) => ({
86
+ id: i + 1,
87
+ slug,
88
+ summary: `summary of ${slug}`,
89
+ edges: [],
90
+ leaves: [],
91
+ modifiedAt: 0,
92
+ }));
111
93
  }
112
94
 
113
- const summaryOf = async (slug: Slug): Promise<string> => `summary of ${slug}`;
114
- /** Deterministic per-slug body so the rendered `<memory>` block is assertable. */
95
+ const config = {} as never;
115
96
  const contentOf = async (slug: Slug): Promise<string> => `body for ${slug}`;
116
97
 
117
- /** Needle that never hits — routing alone drives the open set in this fixture. */
118
- const emptyNeedle: NeedleIndex = { query: () => [] };
98
+ async function buildLanes(): Promise<{
99
+ sectionIndex: SectionIndex;
100
+ needle: ReturnType<typeof buildSectionNeedle>;
101
+ edgeGraph: EdgeGraph;
102
+ }> {
103
+ const sectionIndex = await buildSectionIndex(SLUGS, async (s) => PAGES[s]!);
104
+ const needle = buildSectionNeedle(sectionIndex);
105
+ const edgeGraph = await buildEdgeGraph(
106
+ makeEntries(),
107
+ async (s) => PAGES[s]!, // no `links:` frontmatter → edge graph is empty
108
+ );
109
+ return { sectionIndex, needle, edgeGraph };
110
+ }
119
111
 
120
- function makeTurn(turnNumber: number, currentMessage: string): TurnContext {
112
+ function makeTurn(
113
+ turnNumber: number,
114
+ currentMessage: string,
115
+ ): MemoryRoutingTurn {
121
116
  return {
122
117
  conversationId: "conv-xyz",
123
118
  turnNumber,
@@ -126,71 +121,72 @@ function makeTurn(turnNumber: number, currentMessage: string): TurnContext {
126
121
  };
127
122
  }
128
123
 
129
- function toolUseResponse(
130
- name: string,
131
- input: Record<string, unknown>,
132
- ): ProviderResponse {
124
+ function toolUseResponse(input: Record<string, unknown>): ProviderResponse {
133
125
  return {
134
126
  model: "stub-model",
135
127
  stopReason: "tool_use",
136
128
  usage: { inputTokens: 0, outputTokens: 0 },
137
- content: [{ type: "tool_use", id: "tu-1", name, input }],
129
+ content: [{ type: "tool_use", id: "tu-1", name: "select_pages", input }],
138
130
  };
139
131
  }
140
132
 
141
- /** Last `<leaf>X</leaf>` tag found in an L2 request, or undefined. */
142
- function leafFromMessages(messages: Message[]): LeafPath | undefined {
133
+ /** Parse the numbered `<candidates>` block into an ordered slug list. */
134
+ function candidateSlugs(messages: Message[]): Slug[] {
143
135
  for (const msg of messages) {
144
136
  for (const block of msg.content) {
145
- if (block.type === "text") {
146
- const m = /<leaf>([^<]+)<\/leaf>/.exec(block.text);
147
- if (m) return m[1];
148
- }
137
+ if (block.type !== "text") continue;
138
+ const m = /<candidates>\n([\s\S]*?)\n<\/candidates>/.exec(block.text);
139
+ if (!m) continue;
140
+ return m[1]
141
+ .split("\n")
142
+ .map((line) => /^\[\d+\] (\S+) —/.exec(line)?.[1])
143
+ .filter((s): s is string => !!s);
149
144
  }
150
145
  }
151
- return undefined;
146
+ return [];
152
147
  }
153
148
 
154
- /**
155
- * Build a provider that answers L1 `open_leaves` with `routeIds` and each L2
156
- * `select_pages` call with the per-leaf selection from the fixture turn.
157
- */
158
- function providerForTurn(turn: LiveTurn): Provider {
149
+ /** Provider that selects (and optionally pins) the pooled candidates in `keep`. */
150
+ function selectProvider(keep: Slug[], pin: Slug[] = []): Provider {
159
151
  return {
160
152
  name: "stub",
161
- sendMessage: async (messages, options) => {
162
- const toolName = options?.tools?.[0]?.name;
163
- if (toolName === "open_leaves") {
164
- return toolUseResponse("open_leaves", { ids: turn.routeIds });
165
- }
166
- const leaf = leafFromMessages(messages);
167
- const sel = (leaf ? turn.leafSelections[leaf] : undefined) ?? {
168
- ids: [],
169
- pinned_ids: [],
170
- };
171
- return toolUseResponse("select_pages", {
172
- ids: sel.ids,
173
- pinned_ids: sel.pinned_ids,
153
+ sendMessage: async (messages) => {
154
+ const pool = candidateSlugs(messages);
155
+ const ids: number[] = [];
156
+ const pinned_ids: number[] = [];
157
+ pool.forEach((slug, i) => {
158
+ if (keep.includes(slug)) ids.push(i + 1);
159
+ if (pin.includes(slug)) pinned_ids.push(i + 1);
174
160
  });
161
+ return toolUseResponse({ ids, pinned_ids });
175
162
  },
176
163
  };
177
164
  }
178
165
 
179
166
  /** Run one turn through orchestrate over the shared working set + render it. */
180
167
  async function runTurn(
181
- turn: LiveTurn,
182
168
  turnNumber: number,
183
- deps: { tree: LeafTree; workingSet: InstanceType<typeof WorkingSet> },
169
+ query: string,
170
+ keep: Slug[],
171
+ pin: Slug[],
172
+ deps: {
173
+ lanes: Awaited<ReturnType<typeof buildLanes>>;
174
+ workingSet: InstanceType<typeof WorkingSet>;
175
+ },
184
176
  ) {
185
- providerStub = providerForTurn(turn);
186
- const result = await orchestrate(makeTurn(turnNumber, turn.currentMessage), {
187
- tree: deps.tree,
188
- core: new Set(),
189
- needle: emptyNeedle,
177
+ providerStub = selectProvider(keep, pin);
178
+ const result = await orchestrate(makeTurn(turnNumber, query), {
179
+ sectionIndex: deps.lanes.sectionIndex,
180
+ needle: deps.lanes.needle,
181
+ denseConfig: config,
182
+ edgeGraph: deps.lanes.edgeGraph,
190
183
  workingSet: deps.workingSet,
191
- pageSummary: summaryOf,
192
184
  });
193
- const block = await renderMemoryBlock(result.finalInjection, contentOf);
185
+ const block = await renderMemoryBlock(
186
+ result.finalInjection,
187
+ result.sectionBySlug,
188
+ contentOf,
189
+ );
194
190
  return { result, block };
195
191
  }
196
192
 
@@ -200,9 +196,14 @@ function countMemoryBlocks(text: string): number {
200
196
  }
201
197
 
202
198
  beforeEach(() => {
199
+ denseMockActive = true;
203
200
  providerStub = null;
204
201
  });
205
202
 
203
+ afterAll(() => {
204
+ denseMockActive = false;
205
+ });
206
+
206
207
  // ---------------------------------------------------------------------------
207
208
  // Carry-forward: a page pinned in turn 1 appears in turn 2's injected block
208
209
  // WITHOUT being re-selected in turn 2 (same WorkingSet reused across turns).
@@ -210,20 +211,23 @@ beforeEach(() => {
210
211
 
211
212
  describe("memory-v3 live — carry-forward across turns", () => {
212
213
  test("a page pinned in turn 1 is injected in turn 2 without re-selection", async () => {
213
- const tree = makeTree();
214
+ const lanes = await buildLanes();
214
215
  const workingSet = new WorkingSet();
215
216
 
216
- const t1 = await runTurn(TURNS[0], 1, { tree, workingSet });
217
- // page-a was selected (and pinned) this turn and rendered into the block.
217
+ const t1 = await runTurn(1, "apple", ["page-a"], ["page-a"], {
218
+ lanes,
219
+ workingSet,
220
+ });
218
221
  expect(t1.result.currentSelections.map((s) => s.slug)).toContain("page-a");
219
222
  expect(t1.block).toContain("body for page-a");
220
223
 
221
- const t2 = await runTurn(TURNS[1], 2, { tree, workingSet });
222
- // Turn 2 opens a DIFFERENT leaf (topic-y) and never re-selects page-a…
224
+ const t2 = await runTurn(2, "cherry", ["page-c"], [], {
225
+ lanes,
226
+ workingSet,
227
+ });
223
228
  expect(t2.result.currentSelections.map((s) => s.slug)).not.toContain(
224
229
  "page-a",
225
230
  );
226
- // …yet page-a carries forward into the injected block via the working set.
227
231
  expect(t2.result.finalInjection).toContain("page-a");
228
232
  expect(t2.block).toContain("body for page-a");
229
233
  });
@@ -236,24 +240,36 @@ describe("memory-v3 live — carry-forward across turns", () => {
236
240
 
237
241
  describe("memory-v3 live — eviction reflected in the injected block", () => {
238
242
  test("a stale non-pinned page drops out; the pinned page persists", async () => {
239
- const tree = makeTree();
243
+ const lanes = await buildLanes();
240
244
  // Small window: a non-pinned entry unseen for >2 turns evicts. page-b is
241
245
  // selected only in turn 1, so by turn 4 (4-1=3 > 2) it ages out; pinned
242
246
  // page-a never evicts; page-c is re-selected every later turn.
243
247
  const workingSet = new WorkingSet(150, 2);
244
248
 
245
- const t1 = await runTurn(TURNS[0], 1, { tree, workingSet });
249
+ const t1 = await runTurn(
250
+ 1,
251
+ "apple banana",
252
+ ["page-a", "page-b"],
253
+ ["page-a"],
254
+ { lanes, workingSet },
255
+ );
246
256
  expect(t1.result.finalInjection).toContain("page-b");
247
257
  expect(t1.block).toContain("body for page-b");
248
258
 
249
- // Turns 2–3 keep page-b inside the window (3-1=2, not > 2).
250
- await runTurn(TURNS[1], 2, { tree, workingSet });
251
- const t3 = await runTurn(TURNS[2], 3, { tree, workingSet });
259
+ // Turns 2–3 keep page-b inside the window (3-1=2, not > 2); re-select page-c.
260
+ await runTurn(2, "cherry", ["page-c"], [], { lanes, workingSet });
261
+ const t3 = await runTurn(3, "cherry", ["page-c"], [], {
262
+ lanes,
263
+ workingSet,
264
+ });
252
265
  expect(t3.result.finalInjection).toContain("page-b");
253
266
 
254
267
  // Turn 4: page-b is now stale (4-1=3 > 2) and must be gone from the block;
255
268
  // pinned page-a and freshly-selected page-c remain.
256
- const t4 = await runTurn(TURNS[3], 4, { tree, workingSet });
269
+ const t4 = await runTurn(4, "cherry", ["page-c"], [], {
270
+ lanes,
271
+ workingSet,
272
+ });
257
273
  expect(t4.result.finalInjection).not.toContain("page-b");
258
274
  expect(t4.block).not.toContain("body for page-b");
259
275
  expect(t4.result.finalInjection).toContain("page-a");
@@ -263,17 +279,20 @@ describe("memory-v3 live — eviction reflected in the injected block", () => {
263
279
 
264
280
  // ---------------------------------------------------------------------------
265
281
  // Single source: orchestrate → render produces exactly one coherent `<memory>`
266
- // block per turn. (Assembly-level v2 suppression is covered by the assembly
267
- // tests; here we assert the v3 producer never emits more than one block.)
282
+ // block per turn.
268
283
  // ---------------------------------------------------------------------------
269
284
 
270
285
  describe("memory-v3 live — single memory source", () => {
271
286
  test("each turn renders exactly one <memory> block", async () => {
272
- const tree = makeTree();
287
+ const lanes = await buildLanes();
273
288
  const workingSet = new WorkingSet();
274
289
 
275
- for (const [i, turn] of TURNS.entries()) {
276
- const { block } = await runTurn(turn, i + 1, { tree, workingSet });
290
+ const queries = ["apple", "banana", "cherry"];
291
+ for (const [i, query] of queries.entries()) {
292
+ const { block } = await runTurn(i + 1, query, [SLUGS[i]!], [], {
293
+ lanes,
294
+ workingSet,
295
+ });
277
296
  expect(countMemoryBlocks(block)).toBe(1);
278
297
  expect(block.startsWith("<memory>\n")).toBe(true);
279
298
  expect(block.endsWith("\n</memory>")).toBe(true);
@@ -288,10 +307,9 @@ describe("memory-v3 live — single memory source", () => {
288
307
 
289
308
  describe("memory-v3 live — all-turns history strip", () => {
290
309
  test("historical <memory> blocks strip back to byte-stable user history", async () => {
291
- const tree = makeTree();
310
+ const lanes = await buildLanes();
292
311
  const workingSet = new WorkingSet();
293
312
 
294
- // The canonical (un-injected) user history the strip must converge to.
295
313
  const baseHistory: Message[] = [
296
314
  { role: "user", content: [{ type: "text", text: "first user message" }] },
297
315
  { role: "assistant", content: [{ type: "text", text: "ok" }] },
@@ -303,17 +321,14 @@ describe("memory-v3 live — all-turns history strip", () => {
303
321
  { role: "user", content: [{ type: "text", text: "third user message" }] },
304
322
  ];
305
323
 
306
- // Simulate prior turns having injected a v3 `<memory>` block onto EVERY
307
- // historical user message (prepended, as the live path does).
308
324
  const memBlock = (text: string): ContentBlock => ({ type: "text", text });
325
+ const queries = ["apple", "banana", "cherry"];
309
326
  let injected: Message[] = baseHistory;
310
- for (let turnNumber = 1; turnNumber <= TURNS.length; turnNumber++) {
311
- const { block } = await runTurn(TURNS[turnNumber - 1], turnNumber, {
312
- tree,
327
+ for (const [i, query] of queries.entries()) {
328
+ const { block } = await runTurn(i + 1, query, [SLUGS[i]!], [], {
329
+ lanes,
313
330
  workingSet,
314
331
  });
315
- // Re-inject this turn's freshly-rendered block onto each user message,
316
- // after stripping the prior turn's block (what the live assembly does).
317
332
  const stripped = stripAllMemoryInjections(injected);
318
333
  injected = stripped.map((m) =>
319
334
  m.role === "user"
@@ -322,8 +337,6 @@ describe("memory-v3 live — all-turns history strip", () => {
322
337
  );
323
338
  }
324
339
 
325
- // After a final all-turns strip, history is byte-identical to the canonical
326
- // base — every injected block was recognized and removed.
327
340
  const finalStripped = stripAllMemoryInjections(injected);
328
341
  expect(finalStripped).toEqual(baseHistory);
329
342
  });