mixdog 0.9.63 → 0.9.65

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 (408) 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/turn-snapshot.mjs +184 -0
  187. package/src/runtime/shared/update-checker.mjs +1 -1
  188. package/src/runtime/shared/user-cwd.mjs +3 -3
  189. package/src/runtime/shared/user-data-guard.mjs +4 -4
  190. package/src/runtime/shared/workspace-router.mjs +5 -5
  191. package/src/session-runtime/config-helpers.mjs +2 -3
  192. package/src/session-runtime/config-lifecycle.mjs +1 -1
  193. package/src/session-runtime/hitch-profile.mjs +1 -1
  194. package/src/session-runtime/lifecycle-api.mjs +6 -4
  195. package/src/session-runtime/model-recency.mjs +5 -5
  196. package/src/session-runtime/plugin-mcp.mjs +1 -1
  197. package/src/session-runtime/provider-request-snapshot.mjs +338 -0
  198. package/src/session-runtime/runtime-core.mjs +4 -0
  199. package/src/session-runtime/session-text.mjs +4 -4
  200. package/src/session-runtime/session-turn-api.mjs +7 -0
  201. package/src/session-runtime/tool-catalog-schema.mjs +197 -0
  202. package/src/session-runtime/tool-catalog.mjs +6 -483
  203. package/src/session-runtime/tool-defs.mjs +1 -1
  204. package/src/standalone/agent-task-status.mjs +1 -1
  205. package/src/standalone/agent-tool/helpers.mjs +2 -2
  206. package/src/standalone/channel-admin.mjs +4 -4
  207. package/src/standalone/explore-tool.mjs +3 -3
  208. package/src/standalone/hook-bus/config.mjs +1 -1
  209. package/src/standalone/hook-bus/constants.mjs +1 -1
  210. package/src/standalone/hook-bus/rules.mjs +1 -1
  211. package/src/standalone/projects.mjs +1 -1
  212. package/src/standalone/provider-admin.mjs +2 -2
  213. package/src/tui/App.jsx +1 -1
  214. package/src/tui/app/app-format.mjs +2 -2
  215. package/src/tui/app/clipboard.mjs +3 -3
  216. package/src/tui/app/input-parsers.mjs +1 -1
  217. package/src/tui/app/text-layout.mjs +1 -1
  218. package/src/tui/app/transcript-row-estimate.mjs +360 -0
  219. package/src/tui/app/transcript-window.mjs +5 -347
  220. package/src/tui/app/use-mouse-input.mjs +1 -1
  221. package/src/tui/app/use-prompt-handlers.mjs +1 -1
  222. package/src/tui/components/tool-execution/surface-detail.mjs +9 -9
  223. package/src/tui/components/tool-execution/text-format.mjs +2 -2
  224. package/src/tui/components/tool-output-format.mjs +7 -7
  225. package/src/tui/display-width.mjs +4 -4
  226. package/src/tui/dist/index.mjs +187 -99
  227. package/src/tui/engine/agent-envelope.mjs +5 -5
  228. package/src/tui/engine/live-share.mjs +100 -0
  229. package/src/tui/engine/notification-plan.mjs +1 -1
  230. package/src/tui/engine/queue-helpers.mjs +3 -3
  231. package/src/tui/engine/render-timing.mjs +4 -5
  232. package/src/tui/engine/session-api-ext.mjs +6 -3
  233. package/src/tui/engine/tool-result-status.mjs +5 -5
  234. package/src/tui/engine/tool-result-text.mjs +1 -1
  235. package/src/tui/engine/transcript-spill.mjs +585 -0
  236. package/src/tui/engine/tui-steering-persist.mjs +1 -1
  237. package/src/tui/engine.mjs +29 -474
  238. package/src/tui/lib/voice-setup.mjs +1 -1
  239. package/src/tui/markdown/format-token.mjs +1 -1
  240. package/src/tui/markdown/render-ansi.mjs +1 -1
  241. package/src/tui/markdown/table-layout.mjs +4 -4
  242. package/src/tui/paste-attachments.mjs +1 -1
  243. package/src/tui/prompt-history-store.mjs +3 -3
  244. package/src/tui/statusline-ansi-bridge.mjs +2 -2
  245. package/src/tui/theme.mjs +1 -1
  246. package/src/tui/transcript-tool-failures.mjs +2 -2
  247. package/src/ui/ansi.mjs +0 -9
  248. package/src/ui/statusline-format.mjs +2 -4
  249. package/scripts/_bench-cwc.json +0 -20
  250. package/scripts/_jitter-fuzz.jsx +0 -42
  251. package/scripts/_jitter-fuzz2.jsx +0 -30
  252. package/scripts/_jitter-probe.jsx +0 -35
  253. package/scripts/_jp2.jsx +0 -16
  254. package/scripts/_smoke_wd.mjs +0 -7
  255. package/scripts/abort-recovery-test.mjs +0 -175
  256. package/scripts/agent-dispatch-abort-compose-test.mjs +0 -31
  257. package/scripts/agent-live-arg-guard-smoke.mjs +0 -20
  258. package/scripts/agent-live-path-suffix-smoke.mjs +0 -34
  259. package/scripts/agent-live-toolcall-args-smoke.mjs +0 -45
  260. package/scripts/agent-loop-policy-test.mjs +0 -37
  261. package/scripts/agent-model-liveness-test.mjs +0 -763
  262. package/scripts/agent-parallel-smoke.mjs +0 -435
  263. package/scripts/agent-route-batch-test.mjs +0 -40
  264. package/scripts/agent-tag-reuse-smoke.mjs +0 -441
  265. package/scripts/agent-terminal-reap-test.mjs +0 -252
  266. package/scripts/agent-trace-io-test.mjs +0 -133
  267. package/scripts/ansi-color-capability-test.mjs +0 -90
  268. package/scripts/anthropic-admission-retry-integration-test.mjs +0 -119
  269. package/scripts/anthropic-maxtokens-test.mjs +0 -119
  270. package/scripts/anthropic-oauth-refresh-race-test.mjs +0 -397
  271. package/scripts/anthropic-transport-policy-test.mjs +0 -726
  272. package/scripts/apply-patch-edit-smoke.mjs +0 -71
  273. package/scripts/arg-guard-test.mjs +0 -93
  274. package/scripts/async-notify-settlement-test.mjs +0 -99
  275. package/scripts/atomic-lock-tryonce-test.mjs +0 -125
  276. package/scripts/background-task-meta-smoke.mjs +0 -38
  277. package/scripts/bench-run.mjs +0 -508
  278. package/scripts/boot-smoke.mjs +0 -137
  279. package/scripts/build-runtime-windows.ps1 +0 -242
  280. package/scripts/channel-daemon-smoke.mjs +0 -1103
  281. package/scripts/code-graph-aggregate-cwd-test.mjs +0 -158
  282. package/scripts/code-graph-disk-hit-test.mjs +0 -290
  283. package/scripts/code-graph-dispatch-test.mjs +0 -96
  284. package/scripts/code-graph-root-federation-test.mjs +0 -273
  285. package/scripts/compact-active-turn-test.mjs +0 -68
  286. package/scripts/compact-file-reattach-test.mjs +0 -88
  287. package/scripts/compact-pressure-test.mjs +0 -788
  288. package/scripts/compact-prior-context-flatten-test.mjs +0 -252
  289. package/scripts/compact-recall-digest-test.mjs +0 -57
  290. package/scripts/compact-smoke.mjs +0 -1017
  291. package/scripts/compact-trigger-migration-smoke.mjs +0 -261
  292. package/scripts/compacted-placeholder-scrub-test.mjs +0 -63
  293. package/scripts/context-mcp-metering-test.mjs +0 -1406
  294. package/scripts/debounced-skills-async-save-test.mjs +0 -57
  295. package/scripts/deferred-tool-loading-test.mjs +0 -250
  296. package/scripts/desktop-session-bridge-test.mjs +0 -1013
  297. package/scripts/dispatch-persist-recovery-test.mjs +0 -141
  298. package/scripts/embedding-worker-exit-test.mjs +0 -76
  299. package/scripts/execution-completion-dedup-test.mjs +0 -205
  300. package/scripts/execution-pending-resume-kick-test.mjs +0 -151
  301. package/scripts/execution-resume-esc-integration-test.mjs +0 -176
  302. package/scripts/explore-bench-tmp.mjs +0 -36
  303. package/scripts/explore-bench.mjs +0 -248
  304. package/scripts/explore-prompt-policy-test.mjs +0 -256
  305. package/scripts/explore-timeout-cancel-test.mjs +0 -345
  306. package/scripts/find-fuzzy-hidden-test.mjs +0 -267
  307. package/scripts/forwarder-rebind-tail-test.mjs +0 -67
  308. package/scripts/freevar-smoke.mjs +0 -98
  309. package/scripts/gemini-provider-test.mjs +0 -1448
  310. package/scripts/generate-oc-icons.mjs +0 -11
  311. package/scripts/grok-oauth-refresh-race-test.mjs +0 -273
  312. package/scripts/headless-pristine-execution-test.mjs +0 -614
  313. package/scripts/hook-bus-test.mjs +0 -552
  314. package/scripts/ingest-pure-conversation-smoke.mjs +0 -175
  315. package/scripts/internal-comms-bench-test.mjs +0 -226
  316. package/scripts/internal-comms-bench.mjs +0 -853
  317. package/scripts/internal-comms-smoke.mjs +0 -277
  318. package/scripts/internal-tools-normalization-test.mjs +0 -62
  319. package/scripts/interrupted-turn-history-test.mjs +0 -399
  320. package/scripts/lead-workflow-smoke.mjs +0 -592
  321. package/scripts/lifecycle-api-test.mjs +0 -137
  322. package/scripts/live-share-test.mjs +0 -148
  323. package/scripts/live-worker-smoke.mjs +0 -333
  324. package/scripts/log-writer-guard-smoke.mjs +0 -131
  325. package/scripts/maintenance-default-routes-test.mjs +0 -164
  326. package/scripts/max-output-recovery-persist-test.mjs +0 -81
  327. package/scripts/max-output-recovery-test.mjs +0 -368
  328. package/scripts/mcp-client-normalization-test.mjs +0 -45
  329. package/scripts/mcp-grace-deferred-test.mjs +0 -225
  330. package/scripts/memory-core-input-test.mjs +0 -167
  331. package/scripts/memory-cycle-routing-test.mjs +0 -111
  332. package/scripts/memory-meta-concurrency-test.mjs +0 -20
  333. package/scripts/memory-pg-recovery-test.mjs +0 -59
  334. package/scripts/memory-rule-contract-test.mjs +0 -93
  335. package/scripts/model-list-sanitize-test.mjs +0 -37
  336. package/scripts/mouse-tracking-restore-smoke.mjs +0 -107
  337. package/scripts/native-edit-wire-test.mjs +0 -152
  338. package/scripts/notify-completion-mirror-test.mjs +0 -73
  339. package/scripts/openai-oauth-refresh-race-test.mjs +0 -120
  340. package/scripts/openai-oauth-ws-1006-retry-test.mjs +0 -954
  341. package/scripts/openai-ws-early-settle-test.mjs +0 -216
  342. package/scripts/output-style-bench.mjs +0 -292
  343. package/scripts/output-style-smoke.mjs +0 -145
  344. package/scripts/parent-abort-link-test.mjs +0 -90
  345. package/scripts/patch-binary-cache-test.mjs +0 -181
  346. package/scripts/path-suffix-test.mjs +0 -57
  347. package/scripts/pending-completion-drop-test.mjs +0 -239
  348. package/scripts/pending-messages-lock-nonblocking-test.mjs +0 -62
  349. package/scripts/pretool-ask-runtime-test.mjs +0 -54
  350. package/scripts/process-lifecycle-test.mjs +0 -461
  351. package/scripts/prompt-immediate-render-test.mjs +0 -89
  352. package/scripts/prompt-input-parity-test.mjs +0 -145
  353. package/scripts/provider-admission-scheduler-test.mjs +0 -681
  354. package/scripts/provider-contract-test.mjs +0 -632
  355. package/scripts/provider-stream-stall-test.mjs +0 -276
  356. package/scripts/provider-toolcall-test.mjs +0 -3063
  357. package/scripts/reactive-compact-persist-smoke.mjs +0 -203
  358. package/scripts/recall-bench.mjs +0 -359
  359. package/scripts/resource-admission-test.mjs +0 -792
  360. package/scripts/result-classification-test.mjs +0 -75
  361. package/scripts/rg-runner-test.mjs +0 -240
  362. package/scripts/routing-corpus-test.mjs +0 -349
  363. package/scripts/sanitize-tool-pairs-test.mjs +0 -260
  364. package/scripts/session-bench-cache-break-test.mjs +0 -102
  365. package/scripts/session-bench.mjs +0 -1708
  366. package/scripts/session-context-bench.mjs +0 -344
  367. package/scripts/session-heartbeat-lifecycle-test.mjs +0 -68
  368. package/scripts/session-ingest-compaction-smoke.mjs +0 -279
  369. package/scripts/session-ingest-smoke.mjs +0 -177
  370. package/scripts/session-orphan-sweep-test.mjs +0 -109
  371. package/scripts/set-effort-config-test.mjs +0 -41
  372. package/scripts/shell-failure-diagnostics-test.mjs +0 -280
  373. package/scripts/shell-hardening-test.mjs +0 -209
  374. package/scripts/shell-jobs-windows-hide-test.mjs +0 -164
  375. package/scripts/ship-mode-test.mjs +0 -98
  376. package/scripts/smoke-loop-failure-summary-test.mjs +0 -38
  377. package/scripts/smoke-loop-failure-summary.mjs +0 -16
  378. package/scripts/smoke-loop-report.mjs +0 -221
  379. package/scripts/smoke-loop.mjs +0 -202
  380. package/scripts/smoke-runtime-negative.ps1 +0 -106
  381. package/scripts/statusline-quota-hysteresis-test.mjs +0 -62
  382. package/scripts/steering-drain-buckets-test.mjs +0 -467
  383. package/scripts/steering-fold-provenance-test.mjs +0 -71
  384. package/scripts/streaming-tail-window-test.mjs +0 -175
  385. package/scripts/submit-commandbusy-race-test.mjs +0 -257
  386. package/scripts/task-bench.mjs +0 -205
  387. package/scripts/terminal-bench-isolation-guards-test.mjs +0 -102
  388. package/scripts/termio-input-smoke.mjs +0 -199
  389. package/scripts/tool-result-hook-test.mjs +0 -48
  390. package/scripts/tool-smoke.mjs +0 -2453
  391. package/scripts/tool-tui-presentation-test.mjs +0 -286
  392. package/scripts/toolcall-args-test.mjs +0 -239
  393. package/scripts/tui-ambiguous-width-test.mjs +0 -113
  394. package/scripts/tui-background-failure-smoke.mjs +0 -73
  395. package/scripts/tui-perf-run.ps1 +0 -26
  396. package/scripts/tui-render-smoke.mjs +0 -90
  397. package/scripts/tui-runtime-load-bench-entry.jsx +0 -608
  398. package/scripts/tui-runtime-load-bench.mjs +0 -50
  399. package/scripts/tui-store-frame-batch-test.mjs +0 -99
  400. package/scripts/tui-transcript-jitter-harness-entry.jsx +0 -383
  401. package/scripts/tui-transcript-perf-test.mjs +0 -934
  402. package/scripts/usage-metrics-epoch-smoke.mjs +0 -114
  403. package/scripts/verify-release-assets-test.mjs +0 -281
  404. package/scripts/web-fetch-routing-test.mjs +0 -158
  405. package/scripts/webhook-smoke.mjs +0 -201
  406. package/scripts/windows-hide-spawn-options-test.mjs +0 -19
  407. package/scripts/worker-notify-rejection-test.mjs +0 -51
  408. package/scripts/write-backpressure-test.mjs +0 -147
@@ -91,7 +91,7 @@ function projectFromRoot(root, marker) {
91
91
  };
92
92
  }
93
93
 
94
- export function findNearestProjectRoot(start) {
94
+ function findNearestProjectRoot(start) {
95
95
  const initial = safeResolve(start);
96
96
  if (!initial || !safeIsDirectory(initial)) return null;
97
97
  let cur = initial;
@@ -108,7 +108,7 @@ function shouldIgnoreDir(name) {
108
108
  return IGNORE_DIRS.has(name) || name.startsWith('$') || name.endsWith('.tmp');
109
109
  }
110
110
 
111
- export function discoverProjectCandidates(base, {
111
+ function discoverProjectCandidates(base, {
112
112
  maxDepth = DEFAULT_MAX_DEPTH,
113
113
  maxDirs = DEFAULT_MAX_DIRS,
114
114
  maxCandidates = DEFAULT_MAX_CANDIDATES,
@@ -179,7 +179,7 @@ function scanBaseFor(currentCwd, activeProject) {
179
179
  return currentCwd;
180
180
  }
181
181
 
182
- export function createWorkspaceRouter({
182
+ function createWorkspaceRouter({
183
183
  entryCwd = process.cwd(),
184
184
  maxDepth = DEFAULT_MAX_DEPTH,
185
185
  maxDirs = DEFAULT_MAX_DIRS,
@@ -227,7 +227,7 @@ export function createWorkspaceRouter({
227
227
  return { snapshot };
228
228
  }
229
229
 
230
- export function formatWorkspaceSessionContext(snapshot) {
230
+ function formatWorkspaceSessionContext(snapshot) {
231
231
  if (!snapshot) return '';
232
232
  const candidates = (snapshot.candidates || []).slice(0, 20);
233
233
  const lines = ['# Workspace'];
@@ -252,7 +252,7 @@ export function formatWorkspaceSessionContext(snapshot) {
252
252
  return lines.join('\n');
253
253
  }
254
254
 
255
- export function resolveWorkspaceCwd(baseCwd, value) {
255
+ function resolveWorkspaceCwd(baseCwd, value) {
256
256
  const raw = String(value || '').trim();
257
257
  if (!raw) return resolve(baseCwd || process.cwd());
258
258
  return isAbsolute(raw) ? resolve(raw) : resolve(baseCwd || process.cwd(), raw);
@@ -138,10 +138,9 @@ export const AUTO_CLEAR_PROVIDER_IDLE_MS = Object.freeze({
138
138
  'mistral': 60 * 60 * 1000,
139
139
  'default': AUTO_CLEAR_DEFAULT_IDLE_MS,
140
140
  });
141
- export const AUTO_CLEAR_PROVIDER_IDS = Object.freeze(Object.keys(AUTO_CLEAR_PROVIDER_IDLE_MS));
142
- export const AUTO_CLEAR_UNKNOWN_PROVIDER_IDLE_MS = AUTO_CLEAR_PROVIDER_IDLE_MS.default;
141
+ const AUTO_CLEAR_PROVIDER_IDS = Object.freeze(Object.keys(AUTO_CLEAR_PROVIDER_IDLE_MS));
143
142
 
144
- export function normalizeAutoClearProviderIdleMs(value = {}) {
143
+ function normalizeAutoClearProviderIdleMs(value = {}) {
145
144
  const raw = value && typeof value === 'object' ? value : {};
146
145
  const out = {};
147
146
  for (const [key, ms] of Object.entries(raw)) {
@@ -16,7 +16,7 @@
16
16
  // only serializes agent-section fields, so a top-level
17
17
  // outputStyle would never reach disk via that path)
18
18
 
19
- export const CONFIG_SAVE_DEBOUNCE_MS = 150;
19
+ const CONFIG_SAVE_DEBOUNCE_MS = 150;
20
20
 
21
21
  export function createConfigLifecycle({
22
22
  // config mutable-state injection
@@ -10,7 +10,7 @@ function positiveNumberEnv(name, fallback) {
10
10
 
11
11
  // The histogram and sampling timer are never constructed unless explicitly
12
12
  // enabled, leaving the normal runtime with no event-loop profiling work.
13
- export function installHitchProfiler() {
13
+ function installHitchProfiler() {
14
14
  if (!HITCH_PROFILE_ENABLED) return null;
15
15
 
16
16
  const thresholdMs = positiveNumberEnv('MIXDOG_HITCH_THRESHOLD_MS', 100);
@@ -94,10 +94,12 @@ export function createLifecycleApi(deps) {
94
94
  provider: s.provider,
95
95
  messageCount,
96
96
  preview,
97
- heartbeatAt: Math.max(
98
- Number(s.lastHeartbeatAt) || 0,
99
- Number(heartbeatMtimes.get(s.id)) || 0,
100
- ),
97
+ // Working indicator: the .hb sidecar ALONE is the liveness signal. Its
98
+ // deletion at turn end IS the completion signal, so the persisted
99
+ // lastHeartbeatAt JSON field (refreshed by the final save) must not be
100
+ // folded in — it pinned desktop spinners on for the full 2-minute TTL
101
+ // after a turn had already finished.
102
+ heartbeatAt: Number(heartbeatMtimes.get(s.id)) || 0,
101
103
  desktopSession: s.desktopSession || null,
102
104
  };
103
105
  }).filter(Boolean);
@@ -3,7 +3,7 @@
3
3
  // injected route provider (for sort priority) and searchCapableFor predicate.
4
4
  import { clean } from './session-text.mjs';
5
5
 
6
- export function parsedProviderModelVersion(id) {
6
+ function parsedProviderModelVersion(id) {
7
7
  const text = clean(id).toLowerCase();
8
8
  const claude = text.match(/^claude-[a-z]+-(\d+)(?:[-.](\d+))?/);
9
9
  if (claude) return [Number(claude[1]) || 0, Number(claude[2]) || 0];
@@ -13,7 +13,7 @@ export function parsedProviderModelVersion(id) {
13
13
  return generic ? generic.slice(1).filter((v) => v != null).map((v) => Number(v) || 0) : [];
14
14
  }
15
15
 
16
- export function compareProviderModelVersion(a, b) {
16
+ function compareProviderModelVersion(a, b) {
17
17
  const va = parsedProviderModelVersion(a.id || a.display || a.name);
18
18
  const vb = parsedProviderModelVersion(b.id || b.display || b.name);
19
19
  if (va.length === 0 && vb.length === 0) return 0;
@@ -26,7 +26,7 @@ export function compareProviderModelVersion(a, b) {
26
26
  return 0;
27
27
  }
28
28
 
29
- export function providerModelReleaseTime(model) {
29
+ function providerModelReleaseTime(model) {
30
30
  if (model?.releaseDate) {
31
31
  const t = Date.parse(model.releaseDate);
32
32
  if (Number.isFinite(t)) return t;
@@ -39,12 +39,12 @@ export function providerModelReleaseTime(model) {
39
39
  return dated ? (Date.parse(`${dated[1]}-${dated[2]}-${dated[3]}`) || 0) : 0;
40
40
  }
41
41
 
42
- export function isClaudeProviderModel(model) {
42
+ function isClaudeProviderModel(model) {
43
43
  return clean(model?.provider).toLowerCase().includes('anthropic')
44
44
  && /^claude-[a-z]+-/.test(clean(model?.id).toLowerCase());
45
45
  }
46
46
 
47
- export function compareProviderModelRecency(a, b) {
47
+ function compareProviderModelRecency(a, b) {
48
48
  if (isClaudeProviderModel(a) && isClaudeProviderModel(b)) {
49
49
  if (a.latest !== b.latest) return a.latest ? -1 : 1;
50
50
  const versionDelta = compareProviderModelVersion(a, b);
@@ -131,7 +131,7 @@ function isSkillMdFile(name) {
131
131
  return /^(SKILL|skill)\.md$/i.test(name);
132
132
  }
133
133
 
134
- export const PLUGIN_INLINE_MCP_SCRIPT = 'plugin.json';
134
+ const PLUGIN_INLINE_MCP_SCRIPT = 'plugin.json';
135
135
 
136
136
  export function countSkillFiles(root) {
137
137
  let count = 0;
@@ -0,0 +1,338 @@
1
+ // Provider request-tool resolution + JSON-safe snapshot machinery, extracted from tool-catalog.mjs.
2
+ import { clean, LATE_TOOL_ANNOUNCEMENT_SENTINEL } from './session-text.mjs';
3
+ import { estimateToolSchemaTokens, toolSchemaSignature } from '../runtime/agent/orchestrator/session/context-utils.mjs';
4
+ import {
5
+ applyInitialDeferredToolManifestToBp1,
6
+ buildDeferredToolManifest,
7
+ stripDeferredToolManifestBlock,
8
+ } from '../runtime/agent/orchestrator/context/collect.mjs';
9
+ import { getMcpServerInstructionsMap } from '../runtime/agent/orchestrator/mcp/client.mjs';
10
+ import {
11
+ isResponsesFreeformTool,
12
+ toResponsesCustomTool,
13
+ } from '../runtime/agent/orchestrator/providers/custom-tool-wire.mjs';
14
+ import {
15
+ finalizeProviderRequestTools,
16
+ providerNativeToolPrefixCount,
17
+ } from './provider-request-tools.mjs';
18
+ import {
19
+ DEFERRED_DEFAULT_FULL_TOOLS,
20
+ DEFERRED_DEFAULT_LEAD_TOOLS,
21
+ DEFERRED_DEFAULT_READONLY_TOOLS,
22
+ DEFERRED_SELECT_ALIASES,
23
+ MEASURED_TOOL_ORDER,
24
+ MEASURED_TOOL_USAGE,
25
+ READONLY_TOOL_NAMES,
26
+ } from './tool-catalog-data.mjs';
27
+ import { parseToolSelection, ANTHROPIC_NATIVE_PROVIDERS } from './tool-catalog-schema.mjs';
28
+
29
+ export function resolveProviderRequestTools({
30
+ provider,
31
+ tools,
32
+ messages,
33
+ session,
34
+ } = {}) {
35
+ const activeTools = Array.isArray(tools) ? tools : [];
36
+ const normalizedProvider = clean(provider || session?.provider).toLowerCase();
37
+ if (!ANTHROPIC_NATIVE_PROVIDERS.has(normalizedProvider)
38
+ || session?.deferredNativeTools !== true
39
+ || activeTools.length === 0) {
40
+ return activeTools;
41
+ }
42
+ const discovered = new Set(
43
+ parseToolSelection(session?.deferredDiscoveredTools),
44
+ );
45
+ for (const message of Array.isArray(messages) ? messages : []) {
46
+ const native = message?.nativeToolSearch;
47
+ const source = clean(native?.provider).toLowerCase();
48
+ if (source && source !== normalizedProvider
49
+ && !(ANTHROPIC_NATIVE_PROVIDERS.has(source)
50
+ && ANTHROPIC_NATIVE_PROVIDERS.has(normalizedProvider))) continue;
51
+ for (const name of parseToolSelection(native?.toolReferences)) discovered.add(name);
52
+ }
53
+ if (discovered.size === 0) return activeTools;
54
+ const activeNames = new Set(activeTools.map((tool) => clean(tool?.name)).filter(Boolean));
55
+ const catalog = Array.isArray(session?.deferredToolCatalog) ? session.deferredToolCatalog : [];
56
+ const deferredTools = catalog
57
+ .filter((tool) => {
58
+ const name = clean(tool?.name);
59
+ return name && discovered.has(name) && !activeNames.has(name);
60
+ })
61
+ .map((tool) => ({ ...tool, deferLoading: true }));
62
+ return deferredTools.length ? [...activeTools, ...deferredTools] : activeTools;
63
+ }
64
+
65
+ const OMIT_REQUEST_TOOL_VALUE = Symbol('omit-request-tool-value');
66
+ const MAX_PROVIDER_SNAPSHOT_ARRAY_LENGTH = 1_000_000;
67
+
68
+ function defineEnumerableDataProperty(target, key, value) {
69
+ Object.defineProperty(target, key, {
70
+ value,
71
+ enumerable: true,
72
+ configurable: false,
73
+ writable: false,
74
+ });
75
+ }
76
+
77
+ function boxedJsonPrimitive(value) {
78
+ try { return { matched: true, value: Number.prototype.valueOf.call(value) }; } catch {}
79
+ try { return { matched: true, value: String.prototype.valueOf.call(value) }; } catch {}
80
+ try { return { matched: true, value: Boolean.prototype.valueOf.call(value) }; } catch {}
81
+ try { return { matched: true, value: BigInt.prototype.valueOf.call(value) }; } catch {}
82
+ return { matched: false, value: null };
83
+ }
84
+
85
+ function providerSnapshotLengthPrimitive(value) {
86
+ if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return value;
87
+ const exotic = value[Symbol.toPrimitive];
88
+ if (exotic !== undefined && exotic !== null) {
89
+ if (typeof exotic !== 'function') throw new TypeError('invalid length primitive');
90
+ const primitive = exotic.call(value, 'number');
91
+ if ((typeof primitive === 'object' && primitive !== null) || typeof primitive === 'function') {
92
+ throw new TypeError('invalid length primitive');
93
+ }
94
+ return primitive;
95
+ }
96
+ for (const methodName of ['valueOf', 'toString']) {
97
+ const method = value[methodName];
98
+ if (typeof method !== 'function') continue;
99
+ const primitive = method.call(value);
100
+ if ((typeof primitive !== 'object' || primitive === null) && typeof primitive !== 'function') {
101
+ return primitive;
102
+ }
103
+ }
104
+ throw new TypeError('invalid length primitive');
105
+ }
106
+
107
+ function providerSnapshotArrayLength(rawLength) {
108
+ let primitive;
109
+ let numeric;
110
+ try {
111
+ primitive = providerSnapshotLengthPrimitive(rawLength);
112
+ if (typeof primitive === 'bigint' || typeof primitive === 'symbol') {
113
+ throw new TypeError('invalid length primitive');
114
+ }
115
+ numeric = Number(primitive);
116
+ } catch {
117
+ throw new TypeError('provider tool snapshot: invalid array length');
118
+ }
119
+ if (Number.isNaN(numeric) || numeric <= 0) return 0;
120
+ if (!Number.isFinite(numeric)) {
121
+ throw new RangeError(
122
+ `provider tool snapshot: array length exceeds safe limit ${MAX_PROVIDER_SNAPSHOT_ARRAY_LENGTH}`,
123
+ );
124
+ }
125
+ const effectiveLength = Math.floor(numeric);
126
+ if (effectiveLength > MAX_PROVIDER_SNAPSHOT_ARRAY_LENGTH) {
127
+ throw new RangeError(
128
+ `provider tool snapshot: array length exceeds safe limit ${MAX_PROVIDER_SNAPSHOT_ARRAY_LENGTH}`,
129
+ );
130
+ }
131
+ return effectiveLength;
132
+ }
133
+
134
+ function normalizeRequestToolJson(value, state, {
135
+ arrayEntry = false,
136
+ key = '',
137
+ applyToJSON = true,
138
+ seededProperties = null,
139
+ } = {}) {
140
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;
141
+ if (typeof value === 'number') return Number.isFinite(value) ? value : null;
142
+ if (typeof value === 'bigint') {
143
+ throw new TypeError('provider tool snapshot: BigInt is not JSON-serializable');
144
+ }
145
+ if (value === undefined || typeof value === 'function' || typeof value === 'symbol') {
146
+ return arrayEntry ? null : OMIT_REQUEST_TOOL_VALUE;
147
+ }
148
+ if (typeof value !== 'object') {
149
+ throw new TypeError(`provider tool snapshot: unsupported JSON value type ${typeof value}`);
150
+ }
151
+ if (state.active.has(value)) {
152
+ throw new TypeError('provider tool snapshot: cyclic value is not JSON-serializable');
153
+ }
154
+ if (state.memo.has(value)) return state.memo.get(value);
155
+
156
+ let capturedProperties = seededProperties;
157
+ if (applyToJSON) {
158
+ // JSON reads `toJSON` once before serializing an object. Preserve that
159
+ // single observation for an own-enumerable non-function (and for a
160
+ // callable that returns `this`) so property traversal cannot invoke a
161
+ // stateful accessor a second time.
162
+ const toJSONDescriptor = Object.getOwnPropertyDescriptor(value, 'toJSON');
163
+ const toJSON = value.toJSON;
164
+ if (typeof toJSON === 'function') {
165
+ // Keep the source guarded through both hook execution and replacement
166
+ // normalization. A hook returning itself, or any replacement graph that
167
+ // points back to its source, is a JSON cycle rather than another hook
168
+ // invocation.
169
+ state.active.add(value);
170
+ try {
171
+ const replacement = toJSON.call(value, key);
172
+ const normalized = normalizeRequestToolJson(replacement, state, {
173
+ arrayEntry,
174
+ key,
175
+ applyToJSON: false,
176
+ seededProperties: null,
177
+ });
178
+ state.memo.set(value, normalized);
179
+ return normalized;
180
+ } finally {
181
+ state.active.delete(value);
182
+ }
183
+ }
184
+ if (toJSONDescriptor?.enumerable) {
185
+ capturedProperties = { ...(seededProperties || {}), toJSON };
186
+ }
187
+ }
188
+ const boxed = boxedJsonPrimitive(value);
189
+ if (boxed.matched) {
190
+ return normalizeRequestToolJson(boxed.value, state, { arrayEntry, key });
191
+ }
192
+
193
+ const isArray = Array.isArray(value);
194
+ const normalized = isArray ? [] : {};
195
+ state.active.add(value);
196
+ try {
197
+ if (isArray) {
198
+ // JSON.stringify captures array length once. Accessors may mutate the
199
+ // source array, but they cannot extend or shorten this iteration bound.
200
+ const rawLength = value.length;
201
+ const length = providerSnapshotArrayLength(rawLength);
202
+ for (let index = 0; index < length; index += 1) {
203
+ const entry = value[index];
204
+ normalized.push(normalizeRequestToolJson(entry, state, {
205
+ arrayEntry: true,
206
+ key: String(index),
207
+ }));
208
+ }
209
+ } else {
210
+ // JSON-compatible request schemas are own-enumerable data. Normalize class
211
+ // instances/accessors to a plain record, ignore inherited mutable fields,
212
+ // and define keys explicitly so an own "__proto__" remains ordinary data.
213
+ for (const key of Reflect.ownKeys(value)) {
214
+ if (typeof key !== 'string') continue;
215
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
216
+ if (!descriptor?.enumerable) continue;
217
+ // Deferred catalog selection captures `name` once before touching the
218
+ // candidate schema. Seed that captured value here so a stateful/throwing
219
+ // getter is never observed a second time during JSON normalization.
220
+ const entry = capturedProperties && Object.hasOwn(capturedProperties, key)
221
+ ? capturedProperties[key]
222
+ : value[key];
223
+ const child = normalizeRequestToolJson(entry, state, { key });
224
+ if (child !== OMIT_REQUEST_TOOL_VALUE) defineEnumerableDataProperty(normalized, key, child);
225
+ }
226
+ }
227
+ } finally {
228
+ state.active.delete(value);
229
+ }
230
+ Object.freeze(normalized);
231
+ state.memo.set(value, normalized);
232
+ return normalized;
233
+ }
234
+
235
+ // Establish one immutable request-attempt snapshot. Nested schema records are
236
+ // cloned before freezing, so a catalog refresh or in-place schema mutation
237
+ // after this boundary cannot change either provider bytes or their signature.
238
+ export function snapshotProviderRequestTools(options = {}) {
239
+ const {
240
+ provider,
241
+ tools,
242
+ nativeTools,
243
+ messages,
244
+ session,
245
+ } = options;
246
+ const activeTools = Array.isArray(tools) ? tools : [];
247
+ const state = { active: new WeakSet(), memo: new WeakMap() };
248
+ const snapshots = [];
249
+ const names = new Set();
250
+ const activeCandidateRefs = new WeakSet();
251
+ // Anthropic native definitions are already provider-wire objects. Preserve
252
+ // their prior prepend order and duplicate behavior, but freeze the exact
253
+ // bytes into the same request snapshot used for accounting and retries.
254
+ if (ANTHROPIC_NATIVE_PROVIDERS.has(clean(provider || session?.provider).toLowerCase())) {
255
+ for (const nativeTool of Array.isArray(nativeTools) ? nativeTools : []) {
256
+ if (!nativeTool || typeof nativeTool !== 'object') continue;
257
+ const normalized = normalizeRequestToolJson(nativeTool, state);
258
+ if (normalized && typeof normalized === 'object' && !Array.isArray(normalized)) {
259
+ snapshots.push(normalized);
260
+ }
261
+ }
262
+ }
263
+ const nativePrefixCount = snapshots.length;
264
+ const finish = () => finalizeProviderRequestTools(snapshots, nativePrefixCount);
265
+ const appendSnapshot = (candidate, selectedName = null, deferred = false) => {
266
+ const normalized = normalizeRequestToolJson(candidate, state, {
267
+ seededProperties: selectedName === null ? null : { name: selectedName },
268
+ });
269
+ if (deferred && (
270
+ !normalized
271
+ || typeof normalized !== 'object'
272
+ || Array.isArray(normalized)
273
+ || typeof normalized.name !== 'string'
274
+ || !clean(normalized.name)
275
+ || normalized.name !== selectedName
276
+ )) {
277
+ throw new TypeError(`provider tool snapshot: selected tool identity mismatch for ${JSON.stringify(selectedName)}`);
278
+ }
279
+ if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) return;
280
+ const name = clean(normalized.name);
281
+ if (!name || names.has(name)) return;
282
+ names.add(name);
283
+ if (!deferred) {
284
+ snapshots.push(normalized);
285
+ return;
286
+ }
287
+ const deferredSnapshot = {};
288
+ for (const key of Object.keys(normalized)) {
289
+ if (key === 'deferLoading' || key === 'defer_loading') continue;
290
+ defineEnumerableDataProperty(deferredSnapshot, key, normalized[key]);
291
+ }
292
+ defineEnumerableDataProperty(deferredSnapshot, 'deferLoading', true);
293
+ snapshots.push(Object.freeze(deferredSnapshot));
294
+ };
295
+
296
+ // Active candidates are provider-visible by definition: normalize each once,
297
+ // then perform all validation/dedupe from the plain snapshot only.
298
+ for (const tool of activeTools) {
299
+ if (tool && typeof tool === 'object') activeCandidateRefs.add(tool);
300
+ appendSnapshot(tool);
301
+ }
302
+
303
+ const normalizedProvider = clean(provider || session?.provider).toLowerCase();
304
+ if (!ANTHROPIC_NATIVE_PROVIDERS.has(normalizedProvider)
305
+ || session?.deferredNativeTools !== true
306
+ // Native definitions preserve their historical prepend behavior, but they
307
+ // do not make an otherwise all-deferred catalog eligible for expansion.
308
+ || names.size === 0) {
309
+ return finish();
310
+ }
311
+ const discovered = new Set(parseToolSelection(session?.deferredDiscoveredTools));
312
+ for (const message of Array.isArray(messages) ? messages : []) {
313
+ const native = message?.nativeToolSearch;
314
+ const source = clean(native?.provider).toLowerCase();
315
+ if (source && source !== normalizedProvider
316
+ && !(ANTHROPIC_NATIVE_PROVIDERS.has(source)
317
+ && ANTHROPIC_NATIVE_PROVIDERS.has(normalizedProvider))) continue;
318
+ for (const name of parseToolSelection(native?.toolReferences)) discovered.add(name);
319
+ }
320
+ if (discovered.size === 0) return finish();
321
+
322
+ // Catalog arrays have no separate key map, so `name` is their explicit
323
+ // selection key contract: capture it once, skip undiscovered/duplicate
324
+ // entries without touching schemas, and seed selected normalization with the
325
+ // captured value to avoid a second getter evaluation.
326
+ const seenCatalogRefs = new WeakSet();
327
+ for (const tool of Array.isArray(session?.deferredToolCatalog) ? session.deferredToolCatalog : []) {
328
+ if (tool && typeof tool === 'object') {
329
+ if (activeCandidateRefs.has(tool) || seenCatalogRefs.has(tool)) continue;
330
+ seenCatalogRefs.add(tool);
331
+ }
332
+ const capturedName = tool?.name;
333
+ const selectionName = typeof capturedName === 'string' ? clean(capturedName) : '';
334
+ if (!selectionName || !discovered.has(selectionName) || names.has(selectionName)) continue;
335
+ appendSnapshot(tool, capturedName, true);
336
+ }
337
+ return finish();
338
+ }
@@ -231,6 +231,7 @@ import { attachSessionHooks } from './session-hooks.mjs';
231
231
  import { createQuickModelRows } from './quick-model-rows.mjs';
232
232
  import { createWarmupSchedulers } from './warmup-schedulers.mjs';
233
233
  import { createPrewarmSchedulers } from './prewarm.mjs';
234
+ import { getTurnReviewDiff as getTurnSnapshotReviewDiff } from '../runtime/shared/turn-snapshot.mjs';
234
235
  import { createMcpGlue } from './mcp-glue.mjs';
235
236
  import { createCwdPlugins } from './cwd-plugins.mjs';
236
237
  import { createSettingsApi } from './settings-api.mjs';
@@ -2303,6 +2304,9 @@ export async function createMixdogSessionRuntime({
2303
2304
  ...settingsApi,
2304
2305
  ...channelConfigApi,
2305
2306
  ...providerAuthApi,
2307
+ // Turn-scoped worktree diff (shadow snapshot): everything changed since
2308
+ // the current turn's base tree, regardless of which agent/process wrote it.
2309
+ getTurnReviewDiff: () => getTurnSnapshotReviewDiff(currentCwd, session?.id),
2306
2310
  get id() {
2307
2311
  return session?.id || null;
2308
2312
  },
@@ -42,14 +42,14 @@ const SYNTHETIC_SESSION_TEXT_PATTERNS = Object.freeze([
42
42
  /^the async (?:agent|shell) task\b/i,
43
43
  ]);
44
44
 
45
- export function stripSessionDisplayEnvelope(value) {
45
+ function stripSessionDisplayEnvelope(value) {
46
46
  return String(value ?? '')
47
47
  .replace(/^# Session\r?\n(?:(?:Cwd|Model|Workflow):[^\r\n]*(?:\r?\n|$))+(?:\r?\n)?/i, '')
48
48
  .replace(/^#\s*Session\s+Cwd:\s+.*?\s+Model:\s+.*?\s+Workflow:\s+\S+\s*/i, '')
49
49
  .replace(/^#\s*Session\s+Cwd:\s+\S+(?:\s+Model:\s+\S*)?(?:\s+Workflow:\s+\S*)?\s*/i, '');
50
50
  }
51
51
 
52
- export function stripInjectedSessionText(value) {
52
+ function stripInjectedSessionText(value) {
53
53
  let text = String(value ?? '');
54
54
  for (const tag of INJECTED_DISPLAY_BLOCK_TAGS) {
55
55
  const block = new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?(?:<\\/${tag}\\s*>|$)`, 'gi');
@@ -59,7 +59,7 @@ export function stripInjectedSessionText(value) {
59
59
  return text;
60
60
  }
61
61
 
62
- export function isSyntheticSessionText(text) {
62
+ function isSyntheticSessionText(text) {
63
63
  const value = String(text || '').trim();
64
64
  return SYNTHETIC_SESSION_TEXT_PATTERNS.some((pattern) => pattern.test(value));
65
65
  }
@@ -102,7 +102,7 @@ export function isLateToolAnnouncement(text) {
102
102
  // "MCP tools available: UnityMCP (12 tools)". MCP tool entries in the manifest
103
103
  // are `- mcp__<server>__<tool>: ...` lines; the server name is the segment
104
104
  // after the `mcp__` prefix. Returns '' for non-announcement text.
105
- export function summarizeLateToolAnnouncement(text) {
105
+ function summarizeLateToolAnnouncement(text) {
106
106
  const value = String(text || '');
107
107
  if (!isLateToolAnnouncement(value)) return '';
108
108
  const block = value.match(/<available-deferred-tools>([\s\S]*?)<\/available-deferred-tools>/i);
@@ -10,6 +10,7 @@ import {
10
10
  refreshInitialDeferredMcpSurface,
11
11
  } from './tool-catalog.mjs';
12
12
  import { getMcpTools } from '../runtime/agent/orchestrator/mcp/client.mjs';
13
+ import { beginTurnSnapshot } from '../runtime/shared/turn-snapshot.mjs';
13
14
 
14
15
  export function splitToolStatusCounts(rows) {
15
16
  const list = Array.isArray(rows) ? rows : [];
@@ -107,6 +108,12 @@ export function createSessionTurnApi(deps) {
107
108
  }
108
109
  }
109
110
  const session0 = getSession();
111
+ // Turn-review base: capture the pre-turn worktree tree in the shadow
112
+ // snapshot repo so the desktop review bar can diff EVERYTHING this
113
+ // turn changes — subagent and background-job edits included. The wait
114
+ // is capped so a cold first snapshot never stalls the turn; a late
115
+ // base still lands through the shared promise.
116
+ try { await beginTurnSnapshot(getCurrentCwd(), session0?.id); } catch { /* never blocks a turn */ }
110
117
  if (session0.deferredInitialRefreshPending) {
111
118
  // FIRST TURN of a FRESH session (session-local gate, NOT the
112
119
  // process-wide firstTurnCompleted): an MCP server may have finished its