mixdog 0.9.63 → 0.9.64

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 (403) hide show
  1. package/README.md +3 -0
  2. package/package.json +9 -2
  3. package/scripts/code-graph-description-contract.mjs +3 -3
  4. package/scripts/verify-release-assets.mjs +2 -2
  5. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +11 -14
  6. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +6 -6
  7. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -2
  8. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  9. package/src/runtime/agent/orchestrator/config.mjs +19 -124
  10. package/src/runtime/agent/orchestrator/context/collect.mjs +6 -6
  11. package/src/runtime/agent/orchestrator/dispatch-persist.mjs +2 -2
  12. package/src/runtime/agent/orchestrator/internal-agents.mjs +2 -2
  13. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +1 -1
  14. package/src/runtime/agent/orchestrator/mcp/client.mjs +4 -4
  15. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +2 -2
  16. package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +4 -4
  17. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +2 -2
  18. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +4 -4
  19. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +333 -0
  20. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +2 -2
  21. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -4
  22. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +1 -1
  23. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -277
  24. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +2 -2
  25. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +1 -1
  26. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +2 -2
  27. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +6 -6
  28. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +196 -0
  29. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +460 -0
  30. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +14 -593
  31. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +1 -1
  32. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +1 -1
  33. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +1 -1
  34. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +4 -4
  35. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2 -2
  36. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +5 -280
  37. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +357 -0
  38. package/src/runtime/agent/orchestrator/providers/openai-ws-headers.mjs +216 -0
  39. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +2 -188
  40. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -2
  41. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -2
  42. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +1 -1
  43. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/registry.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +2 -2
  46. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/session/cache/prefetch-cache.mjs +1 -1
  48. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +3 -3
  49. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +2 -2
  50. package/src/runtime/agent/orchestrator/session/compact/file-reattach.mjs +2 -2
  51. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +1 -1
  52. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +1 -1
  53. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +2 -2
  54. package/src/runtime/agent/orchestrator/session/context-utils.mjs +4 -4
  55. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +1 -1
  56. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +17 -0
  57. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +1 -1
  58. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +18 -26
  59. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +1 -1
  60. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +3 -3
  61. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +1 -0
  62. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  63. package/src/runtime/agent/orchestrator/session/manager/delivered-completions.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +1 -1
  65. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +49 -0
  66. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +49 -0
  67. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +260 -0
  68. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +72 -0
  69. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +163 -0
  70. package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +1 -1
  71. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +4 -1
  73. package/src/runtime/agent/orchestrator/session/store.mjs +9 -561
  74. package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +1 -1
  75. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +2 -2
  76. package/src/runtime/agent/orchestrator/stall-policy.mjs +11 -11
  77. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/tools/bash-session.mjs +2 -2
  79. package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +2 -2
  81. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +1 -1
  82. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +2 -154
  83. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/tools/builtin/cwd-utils.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/tools/builtin/fs-reachability.mjs +1 -1
  86. package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
  87. package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/tools/builtin/path-locks.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +2 -2
  91. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +2 -3
  92. package/src/runtime/agent/orchestrator/tools/builtin/read-image-resize.mjs +4 -4
  93. package/src/runtime/agent/orchestrator/tools/builtin/read-open.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +2 -2
  96. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +5 -5
  97. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +2 -2
  99. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-spawn.mjs +519 -0
  101. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +5 -449
  102. package/src/runtime/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +212 -0
  104. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -1
  105. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +1 -7
  106. package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +9 -36
  107. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +15 -3
  108. package/src/runtime/agent/orchestrator/tools/code-graph/search-references.mjs +429 -0
  109. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +2 -395
  110. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +2 -2
  111. package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +1 -1
  112. package/src/runtime/agent/orchestrator/tools/code-graph/trusted-roots.mjs +1 -1
  113. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  114. package/src/runtime/agent/orchestrator/tools/code-graph-state.mjs +3 -3
  115. package/src/runtime/agent/orchestrator/tools/mutation-planner.mjs +5 -5
  116. package/src/runtime/agent/orchestrator/tools/next-call-utils.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +7 -7
  119. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +72 -9
  120. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +4 -4
  121. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +1 -1
  122. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +4 -4
  124. package/src/runtime/agent/orchestrator/tools/patch.mjs +1 -1
  125. package/src/runtime/agent/orchestrator/tools/result-compression.mjs +3 -3
  126. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +2 -444
  127. package/src/runtime/agent/orchestrator/tools/shell-exec-output.mjs +505 -0
  128. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +2 -2
  129. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +1 -1
  130. package/src/runtime/channels/lib/backend-dispatch.mjs +20 -5
  131. package/src/runtime/channels/lib/scheduler.mjs +1 -1
  132. package/src/runtime/channels/lib/telegram-format.mjs +1 -1
  133. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +4 -4
  134. package/src/runtime/channels/tool-defs.mjs +2 -3
  135. package/src/runtime/memory/index.mjs +1 -5
  136. package/src/runtime/memory/lib/core-memory-candidates.mjs +357 -0
  137. package/src/runtime/memory/lib/core-memory-store.mjs +7 -357
  138. package/src/runtime/memory/lib/cycle-signatures.mjs +1 -1
  139. package/src/runtime/memory/lib/embedding-model-config.mjs +1 -1
  140. package/src/runtime/memory/lib/embedding-provider.mjs +1 -5
  141. package/src/runtime/memory/lib/embedding-worker.mjs +1 -5
  142. package/src/runtime/memory/lib/ko-morph.mjs +2 -2
  143. package/src/runtime/memory/lib/memory-config-flags.mjs +2 -5
  144. package/src/runtime/memory/lib/memory-cycle-requests.mjs +3 -7
  145. package/src/runtime/memory/lib/memory-cycle1.mjs +4 -8
  146. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +1 -1
  147. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +1 -1
  148. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +2 -5
  149. package/src/runtime/memory/lib/memory-cycle3.mjs +1 -5
  150. package/src/runtime/memory/lib/memory-embed.mjs +2 -6
  151. package/src/runtime/memory/lib/memory-log.mjs +8 -0
  152. package/src/runtime/memory/lib/memory-ops-policy.mjs +4 -8
  153. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +1 -1
  154. package/src/runtime/memory/lib/memory-recall-store.mjs +2 -193
  155. package/src/runtime/memory/lib/memory-score.mjs +1 -1
  156. package/src/runtime/memory/lib/memory-text-utils.mjs +2 -2
  157. package/src/runtime/memory/lib/memory.mjs +2 -6
  158. package/src/runtime/memory/lib/pg/adapter.mjs +2 -6
  159. package/src/runtime/memory/lib/pg/process.mjs +1 -5
  160. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -5
  161. package/src/runtime/memory/lib/recall-format.mjs +2 -2
  162. package/src/runtime/memory/lib/recall-scoring.mjs +195 -0
  163. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -5
  164. package/src/runtime/memory/lib/trace-store.mjs +2 -6
  165. package/src/runtime/search/lib/http-fetch.mjs +6 -6
  166. package/src/runtime/search/lib/web-tools.mjs +2 -2
  167. package/src/runtime/shared/buffered-appender.mjs +1 -1
  168. package/src/runtime/shared/child-guardian.mjs +1 -1
  169. package/src/runtime/shared/child-spawn-gate.mjs +1 -1
  170. package/src/runtime/shared/config.mjs +4 -4
  171. package/src/runtime/shared/launcher-control.mjs +9 -10
  172. package/src/runtime/shared/llm/index.mjs +5 -20
  173. package/src/runtime/shared/markdown-frontmatter.mjs +1 -1
  174. package/src/runtime/shared/memory-snapshot.mjs +4 -4
  175. package/src/runtime/shared/pristine-execution.mjs +1 -1
  176. package/src/runtime/shared/process-lifecycle.mjs +0 -1
  177. package/src/runtime/shared/process-shutdown.mjs +1 -1
  178. package/src/runtime/shared/resource-admission.mjs +2 -2
  179. package/src/runtime/shared/schedule-session-run.mjs +1 -1
  180. package/src/runtime/shared/schedules-db.mjs +1 -1
  181. package/src/runtime/shared/service-discovery.mjs +2 -2
  182. package/src/runtime/shared/staged-update.mjs +6 -6
  183. package/src/runtime/shared/tool-execution-contract.mjs +1 -1
  184. package/src/runtime/shared/tool-primitives.mjs +1 -1
  185. package/src/runtime/shared/tool-surface.mjs +2 -2
  186. package/src/runtime/shared/update-checker.mjs +1 -1
  187. package/src/runtime/shared/user-cwd.mjs +3 -3
  188. package/src/runtime/shared/user-data-guard.mjs +4 -4
  189. package/src/runtime/shared/workspace-router.mjs +5 -5
  190. package/src/session-runtime/config-helpers.mjs +2 -3
  191. package/src/session-runtime/config-lifecycle.mjs +1 -1
  192. package/src/session-runtime/hitch-profile.mjs +1 -1
  193. package/src/session-runtime/lifecycle-api.mjs +6 -4
  194. package/src/session-runtime/model-recency.mjs +5 -5
  195. package/src/session-runtime/plugin-mcp.mjs +1 -1
  196. package/src/session-runtime/provider-request-snapshot.mjs +338 -0
  197. package/src/session-runtime/session-text.mjs +4 -4
  198. package/src/session-runtime/tool-catalog-schema.mjs +197 -0
  199. package/src/session-runtime/tool-catalog.mjs +6 -483
  200. package/src/session-runtime/tool-defs.mjs +1 -1
  201. package/src/standalone/agent-task-status.mjs +1 -1
  202. package/src/standalone/agent-tool/helpers.mjs +2 -2
  203. package/src/standalone/channel-admin.mjs +4 -4
  204. package/src/standalone/explore-tool.mjs +3 -3
  205. package/src/standalone/hook-bus/config.mjs +1 -1
  206. package/src/standalone/hook-bus/constants.mjs +1 -1
  207. package/src/standalone/hook-bus/rules.mjs +1 -1
  208. package/src/standalone/projects.mjs +1 -1
  209. package/src/standalone/provider-admin.mjs +2 -2
  210. package/src/tui/app/app-format.mjs +2 -2
  211. package/src/tui/app/clipboard.mjs +3 -3
  212. package/src/tui/app/input-parsers.mjs +1 -1
  213. package/src/tui/app/text-layout.mjs +1 -1
  214. package/src/tui/app/transcript-row-estimate.mjs +360 -0
  215. package/src/tui/app/transcript-window.mjs +5 -347
  216. package/src/tui/app/use-mouse-input.mjs +1 -1
  217. package/src/tui/app/use-prompt-handlers.mjs +1 -1
  218. package/src/tui/components/tool-execution/surface-detail.mjs +9 -9
  219. package/src/tui/components/tool-execution/text-format.mjs +2 -2
  220. package/src/tui/components/tool-output-format.mjs +7 -7
  221. package/src/tui/display-width.mjs +4 -4
  222. package/src/tui/dist/index.mjs +63 -97
  223. package/src/tui/engine/agent-envelope.mjs +5 -5
  224. package/src/tui/engine/notification-plan.mjs +1 -1
  225. package/src/tui/engine/queue-helpers.mjs +3 -3
  226. package/src/tui/engine/render-timing.mjs +4 -5
  227. package/src/tui/engine/session-api-ext.mjs +3 -3
  228. package/src/tui/engine/tool-result-status.mjs +5 -5
  229. package/src/tui/engine/tool-result-text.mjs +1 -1
  230. package/src/tui/engine/transcript-spill.mjs +585 -0
  231. package/src/tui/engine/tui-steering-persist.mjs +1 -1
  232. package/src/tui/engine.mjs +2 -474
  233. package/src/tui/lib/voice-setup.mjs +1 -1
  234. package/src/tui/markdown/format-token.mjs +1 -1
  235. package/src/tui/markdown/render-ansi.mjs +1 -1
  236. package/src/tui/markdown/table-layout.mjs +4 -4
  237. package/src/tui/paste-attachments.mjs +1 -1
  238. package/src/tui/prompt-history-store.mjs +3 -3
  239. package/src/tui/statusline-ansi-bridge.mjs +2 -2
  240. package/src/tui/theme.mjs +1 -1
  241. package/src/tui/transcript-tool-failures.mjs +2 -2
  242. package/src/ui/ansi.mjs +0 -9
  243. package/src/ui/statusline-format.mjs +2 -4
  244. package/scripts/_bench-cwc.json +0 -20
  245. package/scripts/_jitter-fuzz.jsx +0 -42
  246. package/scripts/_jitter-fuzz2.jsx +0 -30
  247. package/scripts/_jitter-probe.jsx +0 -35
  248. package/scripts/_jp2.jsx +0 -16
  249. package/scripts/_smoke_wd.mjs +0 -7
  250. package/scripts/abort-recovery-test.mjs +0 -175
  251. package/scripts/agent-dispatch-abort-compose-test.mjs +0 -31
  252. package/scripts/agent-live-arg-guard-smoke.mjs +0 -20
  253. package/scripts/agent-live-path-suffix-smoke.mjs +0 -34
  254. package/scripts/agent-live-toolcall-args-smoke.mjs +0 -45
  255. package/scripts/agent-loop-policy-test.mjs +0 -37
  256. package/scripts/agent-model-liveness-test.mjs +0 -763
  257. package/scripts/agent-parallel-smoke.mjs +0 -435
  258. package/scripts/agent-route-batch-test.mjs +0 -40
  259. package/scripts/agent-tag-reuse-smoke.mjs +0 -441
  260. package/scripts/agent-terminal-reap-test.mjs +0 -252
  261. package/scripts/agent-trace-io-test.mjs +0 -133
  262. package/scripts/ansi-color-capability-test.mjs +0 -90
  263. package/scripts/anthropic-admission-retry-integration-test.mjs +0 -119
  264. package/scripts/anthropic-maxtokens-test.mjs +0 -119
  265. package/scripts/anthropic-oauth-refresh-race-test.mjs +0 -397
  266. package/scripts/anthropic-transport-policy-test.mjs +0 -726
  267. package/scripts/apply-patch-edit-smoke.mjs +0 -71
  268. package/scripts/arg-guard-test.mjs +0 -93
  269. package/scripts/async-notify-settlement-test.mjs +0 -99
  270. package/scripts/atomic-lock-tryonce-test.mjs +0 -125
  271. package/scripts/background-task-meta-smoke.mjs +0 -38
  272. package/scripts/bench-run.mjs +0 -508
  273. package/scripts/boot-smoke.mjs +0 -137
  274. package/scripts/build-runtime-windows.ps1 +0 -242
  275. package/scripts/channel-daemon-smoke.mjs +0 -1103
  276. package/scripts/code-graph-aggregate-cwd-test.mjs +0 -158
  277. package/scripts/code-graph-disk-hit-test.mjs +0 -290
  278. package/scripts/code-graph-dispatch-test.mjs +0 -96
  279. package/scripts/code-graph-root-federation-test.mjs +0 -273
  280. package/scripts/compact-active-turn-test.mjs +0 -68
  281. package/scripts/compact-file-reattach-test.mjs +0 -88
  282. package/scripts/compact-pressure-test.mjs +0 -788
  283. package/scripts/compact-prior-context-flatten-test.mjs +0 -252
  284. package/scripts/compact-recall-digest-test.mjs +0 -57
  285. package/scripts/compact-smoke.mjs +0 -1017
  286. package/scripts/compact-trigger-migration-smoke.mjs +0 -261
  287. package/scripts/compacted-placeholder-scrub-test.mjs +0 -63
  288. package/scripts/context-mcp-metering-test.mjs +0 -1406
  289. package/scripts/debounced-skills-async-save-test.mjs +0 -57
  290. package/scripts/deferred-tool-loading-test.mjs +0 -250
  291. package/scripts/desktop-session-bridge-test.mjs +0 -1013
  292. package/scripts/dispatch-persist-recovery-test.mjs +0 -141
  293. package/scripts/embedding-worker-exit-test.mjs +0 -76
  294. package/scripts/execution-completion-dedup-test.mjs +0 -205
  295. package/scripts/execution-pending-resume-kick-test.mjs +0 -151
  296. package/scripts/execution-resume-esc-integration-test.mjs +0 -176
  297. package/scripts/explore-bench-tmp.mjs +0 -36
  298. package/scripts/explore-bench.mjs +0 -248
  299. package/scripts/explore-prompt-policy-test.mjs +0 -256
  300. package/scripts/explore-timeout-cancel-test.mjs +0 -345
  301. package/scripts/find-fuzzy-hidden-test.mjs +0 -267
  302. package/scripts/forwarder-rebind-tail-test.mjs +0 -67
  303. package/scripts/freevar-smoke.mjs +0 -98
  304. package/scripts/gemini-provider-test.mjs +0 -1448
  305. package/scripts/generate-oc-icons.mjs +0 -11
  306. package/scripts/grok-oauth-refresh-race-test.mjs +0 -273
  307. package/scripts/headless-pristine-execution-test.mjs +0 -614
  308. package/scripts/hook-bus-test.mjs +0 -552
  309. package/scripts/ingest-pure-conversation-smoke.mjs +0 -175
  310. package/scripts/internal-comms-bench-test.mjs +0 -226
  311. package/scripts/internal-comms-bench.mjs +0 -853
  312. package/scripts/internal-comms-smoke.mjs +0 -277
  313. package/scripts/internal-tools-normalization-test.mjs +0 -62
  314. package/scripts/interrupted-turn-history-test.mjs +0 -399
  315. package/scripts/lead-workflow-smoke.mjs +0 -592
  316. package/scripts/lifecycle-api-test.mjs +0 -137
  317. package/scripts/live-share-test.mjs +0 -148
  318. package/scripts/live-worker-smoke.mjs +0 -333
  319. package/scripts/log-writer-guard-smoke.mjs +0 -131
  320. package/scripts/maintenance-default-routes-test.mjs +0 -164
  321. package/scripts/max-output-recovery-persist-test.mjs +0 -81
  322. package/scripts/max-output-recovery-test.mjs +0 -368
  323. package/scripts/mcp-client-normalization-test.mjs +0 -45
  324. package/scripts/mcp-grace-deferred-test.mjs +0 -225
  325. package/scripts/memory-core-input-test.mjs +0 -167
  326. package/scripts/memory-cycle-routing-test.mjs +0 -111
  327. package/scripts/memory-meta-concurrency-test.mjs +0 -20
  328. package/scripts/memory-pg-recovery-test.mjs +0 -59
  329. package/scripts/memory-rule-contract-test.mjs +0 -93
  330. package/scripts/model-list-sanitize-test.mjs +0 -37
  331. package/scripts/mouse-tracking-restore-smoke.mjs +0 -107
  332. package/scripts/native-edit-wire-test.mjs +0 -152
  333. package/scripts/notify-completion-mirror-test.mjs +0 -73
  334. package/scripts/openai-oauth-refresh-race-test.mjs +0 -120
  335. package/scripts/openai-oauth-ws-1006-retry-test.mjs +0 -954
  336. package/scripts/openai-ws-early-settle-test.mjs +0 -216
  337. package/scripts/output-style-bench.mjs +0 -292
  338. package/scripts/output-style-smoke.mjs +0 -145
  339. package/scripts/parent-abort-link-test.mjs +0 -90
  340. package/scripts/patch-binary-cache-test.mjs +0 -181
  341. package/scripts/path-suffix-test.mjs +0 -57
  342. package/scripts/pending-completion-drop-test.mjs +0 -239
  343. package/scripts/pending-messages-lock-nonblocking-test.mjs +0 -62
  344. package/scripts/pretool-ask-runtime-test.mjs +0 -54
  345. package/scripts/process-lifecycle-test.mjs +0 -461
  346. package/scripts/prompt-immediate-render-test.mjs +0 -89
  347. package/scripts/prompt-input-parity-test.mjs +0 -145
  348. package/scripts/provider-admission-scheduler-test.mjs +0 -681
  349. package/scripts/provider-contract-test.mjs +0 -632
  350. package/scripts/provider-stream-stall-test.mjs +0 -276
  351. package/scripts/provider-toolcall-test.mjs +0 -3063
  352. package/scripts/reactive-compact-persist-smoke.mjs +0 -203
  353. package/scripts/recall-bench.mjs +0 -359
  354. package/scripts/resource-admission-test.mjs +0 -792
  355. package/scripts/result-classification-test.mjs +0 -75
  356. package/scripts/rg-runner-test.mjs +0 -240
  357. package/scripts/routing-corpus-test.mjs +0 -349
  358. package/scripts/sanitize-tool-pairs-test.mjs +0 -260
  359. package/scripts/session-bench-cache-break-test.mjs +0 -102
  360. package/scripts/session-bench.mjs +0 -1708
  361. package/scripts/session-context-bench.mjs +0 -344
  362. package/scripts/session-heartbeat-lifecycle-test.mjs +0 -68
  363. package/scripts/session-ingest-compaction-smoke.mjs +0 -279
  364. package/scripts/session-ingest-smoke.mjs +0 -177
  365. package/scripts/session-orphan-sweep-test.mjs +0 -109
  366. package/scripts/set-effort-config-test.mjs +0 -41
  367. package/scripts/shell-failure-diagnostics-test.mjs +0 -280
  368. package/scripts/shell-hardening-test.mjs +0 -209
  369. package/scripts/shell-jobs-windows-hide-test.mjs +0 -164
  370. package/scripts/ship-mode-test.mjs +0 -98
  371. package/scripts/smoke-loop-failure-summary-test.mjs +0 -38
  372. package/scripts/smoke-loop-failure-summary.mjs +0 -16
  373. package/scripts/smoke-loop-report.mjs +0 -221
  374. package/scripts/smoke-loop.mjs +0 -202
  375. package/scripts/smoke-runtime-negative.ps1 +0 -106
  376. package/scripts/statusline-quota-hysteresis-test.mjs +0 -62
  377. package/scripts/steering-drain-buckets-test.mjs +0 -467
  378. package/scripts/steering-fold-provenance-test.mjs +0 -71
  379. package/scripts/streaming-tail-window-test.mjs +0 -175
  380. package/scripts/submit-commandbusy-race-test.mjs +0 -257
  381. package/scripts/task-bench.mjs +0 -205
  382. package/scripts/terminal-bench-isolation-guards-test.mjs +0 -102
  383. package/scripts/termio-input-smoke.mjs +0 -199
  384. package/scripts/tool-result-hook-test.mjs +0 -48
  385. package/scripts/tool-smoke.mjs +0 -2453
  386. package/scripts/tool-tui-presentation-test.mjs +0 -286
  387. package/scripts/toolcall-args-test.mjs +0 -239
  388. package/scripts/tui-ambiguous-width-test.mjs +0 -113
  389. package/scripts/tui-background-failure-smoke.mjs +0 -73
  390. package/scripts/tui-perf-run.ps1 +0 -26
  391. package/scripts/tui-render-smoke.mjs +0 -90
  392. package/scripts/tui-runtime-load-bench-entry.jsx +0 -608
  393. package/scripts/tui-runtime-load-bench.mjs +0 -50
  394. package/scripts/tui-store-frame-batch-test.mjs +0 -99
  395. package/scripts/tui-transcript-jitter-harness-entry.jsx +0 -383
  396. package/scripts/tui-transcript-perf-test.mjs +0 -934
  397. package/scripts/usage-metrics-epoch-smoke.mjs +0 -114
  398. package/scripts/verify-release-assets-test.mjs +0 -281
  399. package/scripts/web-fetch-routing-test.mjs +0 -158
  400. package/scripts/webhook-smoke.mjs +0 -201
  401. package/scripts/windows-hide-spawn-options-test.mjs +0 -19
  402. package/scripts/worker-notify-rejection-test.mjs +0 -51
  403. package/scripts/write-backpressure-test.mjs +0 -147
@@ -1,6 +1,6 @@
1
1
  import { VALID_CATEGORY } from './memory.mjs'
2
2
 
3
- export function buildCategoryFilterClause(offset, categories, { tableAlias = '' } = {}) {
3
+ function buildCategoryFilterClause(offset, categories, { tableAlias = '' } = {}) {
4
4
  const cats = (Array.isArray(categories) ? categories : [categories])
5
5
  .map(c => String(c ?? '').trim().toLowerCase())
6
6
  .filter(c => VALID_CATEGORY.has(c))
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from './memory-log.mjs';
6
2
 
7
3
  import { buildFtsQuery, buildFtsPrefixQuery } from './memory-text-utils.mjs'
8
4
  import { VALID_CATEGORY, embeddingToSql } from './memory.mjs'
@@ -12,194 +8,7 @@ import { recallReadQuery } from './memory-recall-read-query.mjs'
12
8
 
13
9
  // Per-db cache of mv_hot_active populated state. The main recall path currently
14
10
  // uses entries directly; this guard remains for explicit useHotActive callers.
15
- const _MV_HOT_ACTIVE_TTL_MS = 60_000
16
- const _mvHotActiveCache = new WeakMap() // db → { populated: boolean, ts: number }
17
- const SEMANTIC_ONLY_MIN_SIM = 0.72
18
- // Member-hit time gate: a chunk MEMBER whose own ts falls inside the requested
19
- // [ts_from, ts_to] window is an in-window match even when its ROOT's ts sits
20
- // outside it. Returns true when the member ts is within the (open-ended) window.
21
- function memberTsInWindow(row, tsFrom, tsTo) {
22
- const ts = Number(row?.ts)
23
- if (!Number.isFinite(ts)) return true // undated member: don't drop on window
24
- if (tsFrom != null && ts < tsFrom) return false
25
- if (tsTo != null && ts > tsTo) return false
26
- return true
27
- }
28
- // Cross-language semantic rescue: a query in one language against rows in
29
- // another rarely clears SEMANTIC_ONLY_MIN_SIM on a small (384-dim) embedding
30
- // model, yet the TOP dense ranks are still overwhelmingly relevant. Accept
31
- // semantic-only rows that are both top-ranked in the dense leg AND above a
32
- // softer floor, instead of dropping everything below 0.72.
33
- const SEMANTIC_TOP_RANK_MAX = 3
34
- // Floor for the top-rank rescue. 384-dim MiniLM-class embeddings put UNRELATED
35
- // text at ~0.65-0.75 sim (measured: gibberish query "zzqqxx ... 999" scored
36
- // 0.749 against real rows), so anything below ~0.70 is noise regardless of
37
- // rank; cross-language relevant pairs measured 0.67-0.74. 0.70 keeps most of
38
- // the cross-language rescue while rejecting pure-noise top ranks.
39
- // The softer 0.70 floor SITS INSIDE the noise band (noise peaked at 0.749), so
40
- // it only rescues rows that ALSO carry a lexical leg as corroboration. A
41
- // semantic-only row (no sparse/trgm/exact) must clear SEMANTIC_TOP_RANK_STRICT_SIM
42
- // instead — set above the measured 0.749 noise ceiling so unrelated top ranks
43
- // (e.g. old narration surfacing for "embedding worker crash") stop leaking in.
44
- const SEMANTIC_TOP_RANK_MIN_SIM = 0.70
45
- const SEMANTIC_TOP_RANK_STRICT_SIM = 0.78
46
- const SHORT_QUERY_TOKEN_MAX = 2
47
- // Dense-similarity weighting for retrievalScore. Lexical RRF sums 1/(K+rank)
48
- // per matching leg (K=60), so a row hitting 2 lexical legs at rank 1 scores
49
- // rrf ≈ 2/(60+1) = 0.0328 — enough to bury a single semantically-close dense
50
- // hit that never shares lexical terms. We add a normalized dense-similarity
51
- // term so a strong dense-only match can outrank stale multi-leg lexical hits:
52
- // denseTerm = W_DENSE * max(0, sim - SIM_FLOOR) / (1 - SIM_FLOOR) * freshness
53
- // At sim=0.85: (0.85-0.60)/(1-0.60) = 0.625, so denseTerm = 0.04 * 0.625 = 0.025
54
- // with freshness=1. That alone doesn't beat 0.0328, but combined with the
55
- // row's own rrf contribution (a dense-only row still has 1/(60+rank) from its
56
- // dense rank, e.g. rank 1 → 0.0164) the total ≈ 0.0164 + 0.025 = 0.0414,
57
- // which clears the 0.0328 two-leg lexical baseline. W_DENSE=0.04 was chosen
58
- // as the smallest round value satisfying this at sim=0.85; SIM_FLOOR=0.60
59
- // matches the noise floor used elsewhere for MiniLM-class embeddings.
60
- const SIM_FLOOR = 0.60
61
- const W_DENSE = 0.04
62
- // Recency nudge applied ONLY when a [ts_from, ts_to] window is active. Inside a
63
- // fixed window absolute-age freshness is often disabled (applyFreshness=false)
64
- // or too flat to separate early-window from late-window rows, so a 07-04 row
65
- // could outrank a 07-05 row of comparable relevance under a 24h period. This
66
- // term is a normalized position-in-window score (newest→1) scaled small enough
67
- // to break comparable-relevance ties toward newer rows without overriding a
68
- // clearly stronger lexical/semantic match.
69
- // Kept below a single rank-1 RRF leg (~0.016) so it only breaks ties between
70
- // comparable-relevance rows and never overrides a clearly stronger match.
71
- const W_WINDOW_RECENCY = 0.008
72
- // Rare-token display boost. A query token that appears in the RENDERED display
73
- // of only a small fraction of the candidate set (an IDF-style rarity signal) is
74
- // strong evidence a row is genuinely about that term — even for a
75
- // cross-language row whose only lexical tie is one distinctive English token
76
- // (e.g. "embedding" inside otherwise-Korean content). We add a boost when such
77
- // a rare token is present in the fields that actually render (element/summary
78
- // for roots, content for member-hit turns), so a low-lexical row surfaces above
79
- // common-token neighbours. Scoped to display fields so we never promote a row
80
- // whose match hides in un-rendered body text. RARE_DF_MAX gates "rare": tokens
81
- // present in >34% of candidates are common and earn nothing.
82
- // Scaled to at most one rank-1 RRF leg (1/(K+1) ≈ 0.0164 at K=60): a rare
83
- // display token is a genuine relevance signal, but the IDF boost should only
84
- // carry the weight of a single extra retrieval-leg agreement — enough to break
85
- // ties toward the distinctive-token row without overriding a clearly stronger
86
- // multi-leg lexical/semantic match. W_RARE * (1 - df/N) peaks below this cap.
87
- const W_RARE = 0.016
88
- const RARE_DF_MAX = 0.34
89
-
90
- // Lowercased, de-duplicated query tokens (>= 2 chars) for DF/boost/gate use.
91
- // Capped at 12 (mirrors buildExactTerms) so a paragraph-length query can't
92
- // turn the per-row DF scan into O(tokens × candidateWindow) on display text.
93
- function queryTokensLower(query) {
94
- const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
95
- const toks = (clean.match(/[\p{L}\p{N}_./:-]+/gu) || [])
96
- .map(t => t.toLowerCase())
97
- .filter(t => Array.from(t).length >= 2)
98
- return [...new Set(toks)].slice(0, 12)
99
- }
100
-
101
- // The text that actually renders as a result LINE for a row: element+summary
102
- // for a root (its members render on their own lines), plus content for a
103
- // member-hit turn (its own content is the rendered line). Deliberately excludes
104
- // a ROOT's body content, which never renders when the row is shown as a summary
105
- // line — matching there is incidental, not topical.
106
- function rowDisplayText(row) {
107
- const base = `${row?.element ?? ''} ${row?.summary ?? ''}`
108
- const withBody = Number(row?.is_root) === 0 ? `${base} ${row?.content ?? ''}` : base
109
- return withBody.toLowerCase()
110
- }
111
-
112
- function windowRecencyFactor(ts, tsFrom, tsTo, nowMs) {
113
- const t = Number(ts)
114
- if (!Number.isFinite(t)) return 0
115
- const hi = tsTo != null ? tsTo : nowMs
116
- const lo = tsFrom != null ? tsFrom : hi - 86_400_000 // default 24h span when open-started
117
- if (!(hi > lo)) return 0
118
- return Math.max(0, Math.min(1, (t - lo) / (hi - lo)))
119
- }
120
-
121
- function buildExactTerms(query) {
122
- const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
123
- if (!clean) return []
124
- const terms = []
125
- const add = (value) => {
126
- const term = String(value ?? '').trim()
127
- .replace(/^[^\p{L}\p{N}_./:-]+|[^\p{L}\p{N}_./:-]+$/gu, '')
128
- if (!term) return
129
- const hasIdentifierShape = /[_./:-]/.test(term)
130
- if (!hasIdentifierShape && /^[\d\s]+$/.test(term)) return
131
- const symbolCount = Array.from(term).length
132
- if (!hasIdentifierShape && symbolCount < 2) return
133
- terms.push(term.slice(0, 80))
134
- }
135
- if (clean.length <= 80) add(clean)
136
- const tokens = clean.match(/[\p{L}\p{N}_./:-]+/gu) || []
137
- for (const token of tokens) add(token)
138
- for (let i = 0; i < tokens.length - 1; i++) {
139
- add(`${tokens[i]} ${tokens[i + 1]}`)
140
- }
141
- return [...new Set(terms.map(t => t.toLowerCase()))].slice(0, 12)
142
- }
143
-
144
- function countQueryTokens(query) {
145
- const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
146
- if (!clean) return 0
147
- return (clean.match(/[\p{L}\p{N}_./:-]+/gu) || [])
148
- .filter(token => String(token ?? '').trim().length > 0)
149
- .length
150
- }
151
-
152
- function hasFullQueryTextMatch(query, row) {
153
- const clean = String(query ?? '').replace(/\s+/g, ' ').trim().toLowerCase()
154
- if (!clean || clean.length > 160) return false
155
- const element = String(row?.element ?? '').toLowerCase()
156
- const summary = String(row?.summary ?? '').toLowerCase()
157
- const content = String(row?.content ?? '').toLowerCase()
158
- return (element && element.includes(clean))
159
- || (summary && summary.includes(clean))
160
- || (content && content.includes(clean))
161
- }
162
-
163
- function hasQueryTokenCoverage(row, queryTokenCount) {
164
- if (queryTokenCount <= SHORT_QUERY_TOKEN_MAX) return true
165
- const hits = Number(row?.exact_hits)
166
- // Majority coverage, not full coverage. Requiring EVERY query token to hit
167
- // made mixed-language queries (English "usage spike" plus a Korean noun for
168
- // "cause") return nothing when one
169
- // token has no lexical counterpart in the row — ~60% of tokens matching is
170
- // strong enough lexical evidence alongside the semantic leg.
171
- const required = Math.max(2, Math.ceil(queryTokenCount * 0.6))
172
- return Number.isFinite(hits) && hits >= required
173
- }
174
-
175
- function exactTextBoost(query, row, exactHits) {
176
- const clean = String(query ?? '').trim().toLowerCase()
177
- if (!clean) return 0
178
- const element = String(row?.element ?? '').toLowerCase()
179
- const summary = String(row?.summary ?? '').toLowerCase()
180
- const content = String(row?.content ?? '').toLowerCase()
181
- let boost = 0
182
- if (element && element.includes(clean)) boost += 0.035
183
- if (summary && summary.includes(clean)) boost += 0.025
184
- if (content && content.includes(clean)) boost += 0.015
185
- const hits = Number(exactHits)
186
- if (Number.isFinite(hits) && hits > 0) boost += Math.min(0.03, hits * 0.008)
187
- return boost
188
- }
189
-
190
- async function _checkMvHotActivePopulated(db) {
191
- const cached = _mvHotActiveCache.get(db)
192
- const now = Date.now()
193
- if (cached && now - cached.ts < _MV_HOT_ACTIVE_TTL_MS) return cached.populated
194
- const r = await recallReadQuery(
195
- db,
196
- `SELECT relispopulated FROM pg_class WHERE relname = 'mv_hot_active' LIMIT 1`,
197
- )
198
- if (!r.rows?.length) throw new Error('mv_hot_active not found in pg_class')
199
- const populated = Boolean(r.rows[0].relispopulated)
200
- _mvHotActiveCache.set(db, { populated, ts: now })
201
- return populated
202
- }
11
+ import { SEMANTIC_ONLY_MIN_SIM, memberTsInWindow, SEMANTIC_TOP_RANK_MAX, SEMANTIC_TOP_RANK_MIN_SIM, SEMANTIC_TOP_RANK_STRICT_SIM, SHORT_QUERY_TOKEN_MAX, SIM_FLOOR, W_DENSE, W_WINDOW_RECENCY, W_RARE, RARE_DF_MAX, queryTokensLower, rowDisplayText, windowRecencyFactor, buildExactTerms, countQueryTokens, hasFullQueryTextMatch, hasQueryTokenCoverage, exactTextBoost, _checkMvHotActivePopulated } from './recall-scoring.mjs';
203
12
 
204
13
  export async function searchRelevantHybrid(db, query, options = {}) {
205
14
  const clean = String(query ?? '').trim()
@@ -23,7 +23,7 @@ export const CATEGORY_GRADE = {
23
23
  issue: 1.0,
24
24
  }
25
25
 
26
- export const CATEGORY_DECAY = {
26
+ const CATEGORY_DECAY = {
27
27
  rule: 0.0,
28
28
  constraint: 0.06,
29
29
  decision: 0.15,
@@ -13,7 +13,7 @@ const MEMORY_TOKEN_STOPWORDS = new Set([
13
13
  '\uC0AC\uC6A9\uC790', '\uC720\uC800', '\uC694\uCCAD', '\uC9C8\uBB38', '\uB2F5\uBCC0', '\uC5B8\uAE09', '\uB9D0\uC500', '\uC124\uBA85', '\uBCF4\uACE0', '\uBB34\uC2A8', '\uBB50\uC57C', '\uD588\uC9C0', 'user', 'asks', 'asked', 'request', 'requested', 'question', 'answer', 'reply', 'said', 'mentioned', 'explained', 'reported', 'what', 'huh',
14
14
  ])
15
15
 
16
- export function normalizeMemoryToken(token) {
16
+ function normalizeMemoryToken(token) {
17
17
  let normalized = String(token ?? '').trim().toLowerCase()
18
18
  if (!normalized) return ''
19
19
 
@@ -36,7 +36,7 @@ export function normalizeMemoryToken(token) {
36
36
  return normalized
37
37
  }
38
38
 
39
- export function tokenizeMemoryText(text) {
39
+ function tokenizeMemoryText(text) {
40
40
  return cleanMemoryText(text)
41
41
  .toLowerCase()
42
42
  .split(/[^\p{L}\p{N}_]+/u)
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from './memory-log.mjs';
6
2
 
7
3
  // Native-PG-backed memory store. Schema, helpers, and lifecycle.
8
4
 
@@ -371,7 +367,7 @@ async function resetEmbeddingColumnsForDims(db, dimCount) {
371
367
  // Validate that the halfvec column dimension stored in the DB matches
372
368
  // dimCount from the current model config. Call after schema is confirmed
373
369
  // complete and before any embedding operations.
374
- export async function validateEmbeddingDims(db, dimCount) {
370
+ async function validateEmbeddingDims(db, dimCount) {
375
371
  const colDims = await getEmbeddingColumnDims(db, 'entries')
376
372
  if (colDims == null) return // column absent — pre-schema DB; bootstrapSchema will handle
377
373
  // pgvector halfvec stores dimension as atttypmod directly (unlike varchar which uses dims+4).
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from '../memory-log.mjs';
6
2
 
7
3
  const _poolClientErrorHandlers = new WeakMap()
8
4
 
@@ -112,7 +108,7 @@ const _bootstrapped = new Set()
112
108
 
113
109
  const ADVISORY_LOCK_CLASSID = 0x6d696478 // "midx" — mixdog bootstrap namespace
114
110
  const ADVISORY_OBJID_CREATE_DB = 1 // CREATE DATABASE mixdog
115
- export const ADVISORY_OBJID_SCHEMA_BOOTSTRAP = 2 // extensions + schema DDL
111
+ const ADVISORY_OBJID_SCHEMA_BOOTSTRAP = 2 // extensions + schema DDL
116
112
 
117
113
  // ---------------------------------------------------------------------------
118
114
  // In-process cache
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from '../memory-log.mjs';
6
2
 
7
3
  // pg-process.mjs — lower-level PG lifecycle helpers for mixdog 0.4.0
8
4
  // Track B can wire these into the supervisor; pg-adapter calls them directly.
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from '../memory-log.mjs';
6
2
 
7
3
  /**
8
4
  * supervisor-pg — PG child process lifecycle wired into the mixdog supervisor.
@@ -109,7 +109,7 @@ export function formatTs(tsMs) {
109
109
  return String(tsMs ?? '').slice(0, 16)
110
110
  }
111
111
 
112
- export const CORE_RECALL_STOPWORDS = new Set([
112
+ const CORE_RECALL_STOPWORDS = new Set([
113
113
  'about', 'after', 'again', 'before', 'check', 'color', 'decision', 'decided',
114
114
  'earlier', 'memory', 'previous', 'routing', 'stored', 'tell', 'what',
115
115
  ])
@@ -258,7 +258,7 @@ function exactDuplicateKey(r) {
258
258
  // Legacy object-identity-only ingest could mint duplicate rows on JSON reload.
259
259
  // Keep the newest/highest-ranked exact body once, including short acknowledgments
260
260
  // that shingle dedupe intentionally ignores.
261
- export function collapseExactDuplicateRows(rows) {
261
+ function collapseExactDuplicateRows(rows) {
262
262
  if (!Array.isArray(rows) || rows.length < 2) return rows
263
263
  const seen = new Set()
264
264
  const out = []
@@ -0,0 +1,195 @@
1
+ // Hybrid-recall scoring constants and pure helpers, extracted from memory-recall-store.mjs.
2
+ import { buildFtsQuery, buildFtsPrefixQuery } from './memory-text-utils.mjs'
3
+ import { VALID_CATEGORY, embeddingToSql } from './memory.mjs'
4
+ import { freshnessFactor } from './memory-score.mjs'
5
+ import { buildRecallScopeFilter } from './memory-recall-scope-filter.mjs'
6
+ import { recallReadQuery } from './memory-recall-read-query.mjs'
7
+
8
+ const _MV_HOT_ACTIVE_TTL_MS = 60_000
9
+ const _mvHotActiveCache = new WeakMap() // db → { populated: boolean, ts: number }
10
+ export const SEMANTIC_ONLY_MIN_SIM = 0.72
11
+ // Member-hit time gate: a chunk MEMBER whose own ts falls inside the requested
12
+ // [ts_from, ts_to] window is an in-window match even when its ROOT's ts sits
13
+ // outside it. Returns true when the member ts is within the (open-ended) window.
14
+ export function memberTsInWindow(row, tsFrom, tsTo) {
15
+ const ts = Number(row?.ts)
16
+ if (!Number.isFinite(ts)) return true // undated member: don't drop on window
17
+ if (tsFrom != null && ts < tsFrom) return false
18
+ if (tsTo != null && ts > tsTo) return false
19
+ return true
20
+ }
21
+ // Cross-language semantic rescue: a query in one language against rows in
22
+ // another rarely clears SEMANTIC_ONLY_MIN_SIM on a small (384-dim) embedding
23
+ // model, yet the TOP dense ranks are still overwhelmingly relevant. Accept
24
+ // semantic-only rows that are both top-ranked in the dense leg AND above a
25
+ // softer floor, instead of dropping everything below 0.72.
26
+ export const SEMANTIC_TOP_RANK_MAX = 3
27
+ // Floor for the top-rank rescue. 384-dim MiniLM-class embeddings put UNRELATED
28
+ // text at ~0.65-0.75 sim (measured: gibberish query "zzqqxx ... 999" scored
29
+ // 0.749 against real rows), so anything below ~0.70 is noise regardless of
30
+ // rank; cross-language relevant pairs measured 0.67-0.74. 0.70 keeps most of
31
+ // the cross-language rescue while rejecting pure-noise top ranks.
32
+ // The softer 0.70 floor SITS INSIDE the noise band (noise peaked at 0.749), so
33
+ // it only rescues rows that ALSO carry a lexical leg as corroboration. A
34
+ // semantic-only row (no sparse/trgm/exact) must clear SEMANTIC_TOP_RANK_STRICT_SIM
35
+ // instead — set above the measured 0.749 noise ceiling so unrelated top ranks
36
+ // (e.g. old narration surfacing for "embedding worker crash") stop leaking in.
37
+ export const SEMANTIC_TOP_RANK_MIN_SIM = 0.70
38
+ export const SEMANTIC_TOP_RANK_STRICT_SIM = 0.78
39
+ export const SHORT_QUERY_TOKEN_MAX = 2
40
+ // Dense-similarity weighting for retrievalScore. Lexical RRF sums 1/(K+rank)
41
+ // per matching leg (K=60), so a row hitting 2 lexical legs at rank 1 scores
42
+ // rrf ≈ 2/(60+1) = 0.0328 — enough to bury a single semantically-close dense
43
+ // hit that never shares lexical terms. We add a normalized dense-similarity
44
+ // term so a strong dense-only match can outrank stale multi-leg lexical hits:
45
+ // denseTerm = W_DENSE * max(0, sim - SIM_FLOOR) / (1 - SIM_FLOOR) * freshness
46
+ // At sim=0.85: (0.85-0.60)/(1-0.60) = 0.625, so denseTerm = 0.04 * 0.625 = 0.025
47
+ // with freshness=1. That alone doesn't beat 0.0328, but combined with the
48
+ // row's own rrf contribution (a dense-only row still has 1/(60+rank) from its
49
+ // dense rank, e.g. rank 1 → 0.0164) the total ≈ 0.0164 + 0.025 = 0.0414,
50
+ // which clears the 0.0328 two-leg lexical baseline. W_DENSE=0.04 was chosen
51
+ // as the smallest round value satisfying this at sim=0.85; SIM_FLOOR=0.60
52
+ // matches the noise floor used elsewhere for MiniLM-class embeddings.
53
+ export const SIM_FLOOR = 0.60
54
+ export const W_DENSE = 0.04
55
+ // Recency nudge applied ONLY when a [ts_from, ts_to] window is active. Inside a
56
+ // fixed window absolute-age freshness is often disabled (applyFreshness=false)
57
+ // or too flat to separate early-window from late-window rows, so a 07-04 row
58
+ // could outrank a 07-05 row of comparable relevance under a 24h period. This
59
+ // term is a normalized position-in-window score (newest→1) scaled small enough
60
+ // to break comparable-relevance ties toward newer rows without overriding a
61
+ // clearly stronger lexical/semantic match.
62
+ // Kept below a single rank-1 RRF leg (~0.016) so it only breaks ties between
63
+ // comparable-relevance rows and never overrides a clearly stronger match.
64
+ export const W_WINDOW_RECENCY = 0.008
65
+ // Rare-token display boost. A query token that appears in the RENDERED display
66
+ // of only a small fraction of the candidate set (an IDF-style rarity signal) is
67
+ // strong evidence a row is genuinely about that term — even for a
68
+ // cross-language row whose only lexical tie is one distinctive English token
69
+ // (e.g. "embedding" inside otherwise-Korean content). We add a boost when such
70
+ // a rare token is present in the fields that actually render (element/summary
71
+ // for roots, content for member-hit turns), so a low-lexical row surfaces above
72
+ // common-token neighbours. Scoped to display fields so we never promote a row
73
+ // whose match hides in un-rendered body text. RARE_DF_MAX gates "rare": tokens
74
+ // present in >34% of candidates are common and earn nothing.
75
+ // Scaled to at most one rank-1 RRF leg (1/(K+1) ≈ 0.0164 at K=60): a rare
76
+ // display token is a genuine relevance signal, but the IDF boost should only
77
+ // carry the weight of a single extra retrieval-leg agreement — enough to break
78
+ // ties toward the distinctive-token row without overriding a clearly stronger
79
+ // multi-leg lexical/semantic match. W_RARE * (1 - df/N) peaks below this cap.
80
+ export const W_RARE = 0.016
81
+ export const RARE_DF_MAX = 0.34
82
+
83
+ // Lowercased, de-duplicated query tokens (>= 2 chars) for DF/boost/gate use.
84
+ // Capped at 12 (mirrors buildExactTerms) so a paragraph-length query can't
85
+ // turn the per-row DF scan into O(tokens × candidateWindow) on display text.
86
+ export function queryTokensLower(query) {
87
+ const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
88
+ const toks = (clean.match(/[\p{L}\p{N}_./:-]+/gu) || [])
89
+ .map(t => t.toLowerCase())
90
+ .filter(t => Array.from(t).length >= 2)
91
+ return [...new Set(toks)].slice(0, 12)
92
+ }
93
+
94
+ // The text that actually renders as a result LINE for a row: element+summary
95
+ // for a root (its members render on their own lines), plus content for a
96
+ // member-hit turn (its own content is the rendered line). Deliberately excludes
97
+ // a ROOT's body content, which never renders when the row is shown as a summary
98
+ // line — matching there is incidental, not topical.
99
+ export function rowDisplayText(row) {
100
+ const base = `${row?.element ?? ''} ${row?.summary ?? ''}`
101
+ const withBody = Number(row?.is_root) === 0 ? `${base} ${row?.content ?? ''}` : base
102
+ return withBody.toLowerCase()
103
+ }
104
+
105
+ export function windowRecencyFactor(ts, tsFrom, tsTo, nowMs) {
106
+ const t = Number(ts)
107
+ if (!Number.isFinite(t)) return 0
108
+ const hi = tsTo != null ? tsTo : nowMs
109
+ const lo = tsFrom != null ? tsFrom : hi - 86_400_000 // default 24h span when open-started
110
+ if (!(hi > lo)) return 0
111
+ return Math.max(0, Math.min(1, (t - lo) / (hi - lo)))
112
+ }
113
+
114
+ export function buildExactTerms(query) {
115
+ const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
116
+ if (!clean) return []
117
+ const terms = []
118
+ const add = (value) => {
119
+ const term = String(value ?? '').trim()
120
+ .replace(/^[^\p{L}\p{N}_./:-]+|[^\p{L}\p{N}_./:-]+$/gu, '')
121
+ if (!term) return
122
+ const hasIdentifierShape = /[_./:-]/.test(term)
123
+ if (!hasIdentifierShape && /^[\d\s]+$/.test(term)) return
124
+ const symbolCount = Array.from(term).length
125
+ if (!hasIdentifierShape && symbolCount < 2) return
126
+ terms.push(term.slice(0, 80))
127
+ }
128
+ if (clean.length <= 80) add(clean)
129
+ const tokens = clean.match(/[\p{L}\p{N}_./:-]+/gu) || []
130
+ for (const token of tokens) add(token)
131
+ for (let i = 0; i < tokens.length - 1; i++) {
132
+ add(`${tokens[i]} ${tokens[i + 1]}`)
133
+ }
134
+ return [...new Set(terms.map(t => t.toLowerCase()))].slice(0, 12)
135
+ }
136
+
137
+ export function countQueryTokens(query) {
138
+ const clean = String(query ?? '').replace(/\s+/g, ' ').trim()
139
+ if (!clean) return 0
140
+ return (clean.match(/[\p{L}\p{N}_./:-]+/gu) || [])
141
+ .filter(token => String(token ?? '').trim().length > 0)
142
+ .length
143
+ }
144
+
145
+ export function hasFullQueryTextMatch(query, row) {
146
+ const clean = String(query ?? '').replace(/\s+/g, ' ').trim().toLowerCase()
147
+ if (!clean || clean.length > 160) return false
148
+ const element = String(row?.element ?? '').toLowerCase()
149
+ const summary = String(row?.summary ?? '').toLowerCase()
150
+ const content = String(row?.content ?? '').toLowerCase()
151
+ return (element && element.includes(clean))
152
+ || (summary && summary.includes(clean))
153
+ || (content && content.includes(clean))
154
+ }
155
+
156
+ export function hasQueryTokenCoverage(row, queryTokenCount) {
157
+ if (queryTokenCount <= SHORT_QUERY_TOKEN_MAX) return true
158
+ const hits = Number(row?.exact_hits)
159
+ // Majority coverage, not full coverage. Requiring EVERY query token to hit
160
+ // made mixed-language queries (English "usage spike" plus a Korean noun for
161
+ // "cause") return nothing when one
162
+ // token has no lexical counterpart in the row — ~60% of tokens matching is
163
+ // strong enough lexical evidence alongside the semantic leg.
164
+ const required = Math.max(2, Math.ceil(queryTokenCount * 0.6))
165
+ return Number.isFinite(hits) && hits >= required
166
+ }
167
+
168
+ export function exactTextBoost(query, row, exactHits) {
169
+ const clean = String(query ?? '').trim().toLowerCase()
170
+ if (!clean) return 0
171
+ const element = String(row?.element ?? '').toLowerCase()
172
+ const summary = String(row?.summary ?? '').toLowerCase()
173
+ const content = String(row?.content ?? '').toLowerCase()
174
+ let boost = 0
175
+ if (element && element.includes(clean)) boost += 0.035
176
+ if (summary && summary.includes(clean)) boost += 0.025
177
+ if (content && content.includes(clean)) boost += 0.015
178
+ const hits = Number(exactHits)
179
+ if (Number.isFinite(hits) && hits > 0) boost += Math.min(0.03, hits * 0.008)
180
+ return boost
181
+ }
182
+
183
+ export async function _checkMvHotActivePopulated(db) {
184
+ const cached = _mvHotActiveCache.get(db)
185
+ const now = Date.now()
186
+ if (cached && now - cached.ts < _MV_HOT_ACTIVE_TTL_MS) return cached.populated
187
+ const r = await recallReadQuery(
188
+ db,
189
+ `SELECT relispopulated FROM pg_class WHERE relname = 'mv_hot_active' LIMIT 1`,
190
+ )
191
+ if (!r.rows?.length) throw new Error('mv_hot_active not found in pg_class')
192
+ const populated = Boolean(r.rows[0].relispopulated)
193
+ _mvHotActiveCache.set(db, { populated, ts: now })
194
+ return populated
195
+ }
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from './memory-log.mjs';
6
2
 
7
3
  // runtime-fetcher.mjs — P1 runtime fetcher for mixdog 0.4.0
8
4
  // runtime-fetcher.mjs
@@ -1,8 +1,4 @@
1
- const __mixdogMemoryStderrWrite = process.stderr.write.bind(process.stderr);
2
- function __mixdogMemoryLog(...args) {
3
- if (process.env.MIXDOG_QUIET_MEMORY_LOG) return true;
4
- return __mixdogMemoryStderrWrite(...args);
5
- }
1
+ import { __mixdogMemoryLog } from './memory-log.mjs';
6
2
 
7
3
  // trace-store.mjs — native-PG trace analytics store for mixdog 0.4.0.
8
4
  // Uses pg-adapter (schema='trace') so trace_events live in the trace schema.
@@ -173,7 +169,7 @@ async function migrateSchemaDrift(client) {
173
169
  // Called once per openTraceDatabase boot, inside the BOOTSTRAP advisory-lock
174
170
  // scope (see openTraceDatabase) so concurrent first-boot processes don't race
175
171
  // this DDL. All statements remain IF NOT EXISTS as a second line of defense.
176
- export async function initAgentTables(client) {
172
+ async function initAgentTables(client) {
177
173
  // Repair schema drift on already-created tables before anything else
178
174
  // (trace_events already exists at this point via init(); agent_sessions
179
175
  // is created just below in this same function).
@@ -19,8 +19,8 @@ export function buildHeaders() {
19
19
  }
20
20
  }
21
21
 
22
- export const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])
23
- export const MAX_REDIRECTS = 5
22
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])
23
+ const MAX_REDIRECTS = 5
24
24
  // Hard cap on response body size (10 MB) to prevent memory DoS from a
25
25
  // hostile / misconfigured URL returning a huge body. Applied in two places:
26
26
  // 1. Content-Length pre-check (cheap reject before reading bytes).
@@ -39,7 +39,7 @@ export function isFatalHttpPathPolicyError(error) {
39
39
  return false
40
40
  }
41
41
 
42
- export async function readBodyWithCap(response, maxBytes) {
42
+ async function readBodyWithCap(response, maxBytes) {
43
43
  // Reject non-text content-types early; decode by content-type charset.
44
44
  const contentType = (response.headers.get('content-type') || '').toLowerCase()
45
45
  if (contentType) {
@@ -96,7 +96,7 @@ export async function readBodyWithCap(response, maxBytes) {
96
96
  }
97
97
 
98
98
  /** Binary-safe body reader for CDP Fetch fulfillment (no text-only filter). */
99
- export async function readBodyBytesWithCap(response, maxBytes) {
99
+ async function readBodyBytesWithCap(response, maxBytes) {
100
100
  const contentLength = Number(response.headers.get('content-length') || 0)
101
101
  if (contentLength > maxBytes) {
102
102
  try { await response.body?.cancel() } catch {}
@@ -214,7 +214,7 @@ async function pinnedLoopbackFetch(url, options = {}) {
214
214
  })
215
215
  }
216
216
 
217
- export function assertLoopbackUrl(url) {
217
+ function assertLoopbackUrl(url) {
218
218
  const parsed = new URL(url)
219
219
  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
220
220
  throw new Error(`Blocked non-HTTP protocol: ${parsed.protocol}`)
@@ -289,7 +289,7 @@ const CDP_FORBIDDEN_RESPONSE_HEADERS = new Set([
289
289
  'content-encoding',
290
290
  ])
291
291
 
292
- export function headersToCdpPairs(headers) {
292
+ function headersToCdpPairs(headers) {
293
293
  const out = []
294
294
  headers.forEach((value, name) => {
295
295
  const lower = name.toLowerCase()
@@ -564,7 +564,7 @@ async function mapWithPuppeteer(url, options, timeoutMs, signal) {
564
564
  })
565
565
  }
566
566
 
567
- export async function scrapeUrl(url, timeoutMs, usageState, signal) {
567
+ async function scrapeUrl(url, timeoutMs, usageState, signal) {
568
568
  const normalizedUrl = normalizeUrl(url)
569
569
  const host = new URL(normalizedUrl).host
570
570
  const extractors = rankScrapeExtractors(host, usageState, DEFAULT_EXTRACTORS)
@@ -646,7 +646,7 @@ async function mapSite(url, { limit = 50, sameDomainOnly = true, search }, timeo
646
646
  return mapWithPuppeteer(url, options, timeoutMs, signal)
647
647
  }
648
648
 
649
- export async function crawlSite(
649
+ async function crawlSite(
650
650
  startUrl,
651
651
  { maxPages = 10, maxDepth = 1, sameDomainOnly = true },
652
652
  timeoutMs,
@@ -182,7 +182,7 @@ export function getBufferedAppenderStats(path) {
182
182
  * Synchronously drain any remaining buffered bytes for every known path.
183
183
  * Intended for process exit hooks only — best-effort, never throws.
184
184
  */
185
- export function drainAllSync() {
185
+ function drainAllSync() {
186
186
  for (const [path, q] of queues) {
187
187
  drainPathSync(path);
188
188
  }
@@ -43,7 +43,7 @@ let killing = false;
43
43
  let orphanedAt = 0;
44
44
  const timer = setInterval(() => {
45
45
  if (!alive(childPid)) process.exit(0);
46
- // Orphaned when the parent PID dies. Matches Claude Code / pi: no console
46
+ // Orphaned when the parent PID dies. Matches mainstream CLIs: no console
47
47
  // probe — a hidden shell spawn (windowsHide) plus tree-kill on cleanup, so
48
48
  // orphan detection is pure parent-liveness.
49
49
  if (alive(parentPid)) {
@@ -144,7 +144,7 @@ export function hasSpareCapacity() {
144
144
  * @param {AbortSignal | null} [signal]
145
145
  * @returns {Promise<T>}
146
146
  */
147
- export async function withGate(fn, signal = null) {
147
+ async function withGate(fn, signal = null) {
148
148
  const release = await acquire(signal);
149
149
  try {
150
150
  return await fn({ signal: signal || null });