mixdog 0.9.62 → 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,216 +0,0 @@
1
- // Regression: OpenAI OAuth WS early tool-call settle.
2
- //
3
- // A tool-call response can be fully formed (function_call_arguments.done +
4
- // output_item.done) yet the server never emits the terminal
5
- // response.completed/response.done frame. Before the fix _streamResponse
6
- // coasted on that silence until a stall error (gated out of the loop via
7
- // pendingToolUse) or the 30-min agent watchdog, and -- because the socket was
8
- // still pooled -- the missing terminal frame later leaked onto the NEXT request
9
- // as orphan bytes (http_status=0 wedge). The fix resolves early with the
10
- // captured tool call and flags `closeSocket` so the pool discards the socket.
11
- import test from 'node:test';
12
- import assert from 'node:assert/strict';
13
- import { EventEmitter } from 'node:events';
14
- import { _streamResponse } from '../src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs';
15
- import { classifyMidstreamError, MIDSTREAM_RETRY_POLICY } from '../src/runtime/agent/orchestrator/providers/retry-classifier.mjs';
16
-
17
- // Minimal fake WS: matches the .on/.off/.close/.ping surface _streamResponse
18
- // uses. close() is a no-op here -- the early-settle path sets done=true before
19
- // calling it, so the real closeHandler would short-circuit anyway.
20
- class FakeSocket extends EventEmitter {
21
- constructor() {
22
- super();
23
- this.readyState = 1;
24
- this.closed = null;
25
- }
26
- close(code, reason) { this.closed = { code, reason }; }
27
- ping() {}
28
- feed(events) { for (const e of events) this.emit('message', JSON.stringify(e)); }
29
- }
30
-
31
- const FAST_TIMEOUTS = { interChunkMs: 40, preResponseCreatedMs: 5000, firstMeaningfulMs: 5000 };
32
-
33
- const TOOL_CALL_EVENTS = [
34
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
35
- { type: 'response.output_item.added', item: { type: 'function_call', id: 'fc_1', name: 'explore', call_id: 'call_1' } },
36
- { type: 'response.function_call_arguments.delta', item_id: 'fc_1', delta: '{"query"' },
37
- { type: 'response.function_call_arguments.done', item_id: 'fc_1', arguments: '{"query":"x"}', call_id: 'call_1', name: 'explore' },
38
- { type: 'response.output_item.done', item: { type: 'function_call', id: 'fc_1', name: 'explore', call_id: 'call_1', arguments: '{"query":"x"}' } },
39
- ];
40
-
41
- test('ws early settle: complete tool call resolves without response.completed and flags closeSocket', async () => {
42
- const socket = new FakeSocket();
43
- const state = {};
44
- const emitted = [];
45
- const p = _streamResponse({
46
- entry: { socket },
47
- state,
48
- onToolCall: (c) => emitted.push(c),
49
- _timeouts: FAST_TIMEOUTS,
50
- });
51
- socket.feed(TOOL_CALL_EVENTS);
52
- const result = await p;
53
- assert.equal(result.closeSocket, true, 'socket must be dropped, not pooled');
54
- assert.ok(Array.isArray(result.toolCalls) && result.toolCalls.length === 1);
55
- assert.equal(result.toolCalls[0].id, 'call_1');
56
- assert.equal(result.toolCalls[0].name, 'explore');
57
- assert.deepEqual(result.toolCalls[0].arguments, { query: 'x' });
58
- assert.equal(emitted.length, 1, 'tool call dispatched exactly once');
59
- assert.equal(state.wsEarlySettle, 'inter_chunk');
60
- assert.ok(socket.closed, 'socket.close() invoked so it is never reused');
61
- });
62
-
63
- test('ws early settle: normal response.completed path keeps the socket (no closeSocket)', async () => {
64
- const socket = new FakeSocket();
65
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
66
- socket.feed([
67
- ...TOOL_CALL_EVENTS,
68
- {
69
- type: 'response.completed',
70
- response: {
71
- id: 'resp_1',
72
- model: 'gpt-5.5',
73
- output: [{ type: 'function_call', id: 'fc_1', name: 'explore', call_id: 'call_1', arguments: '{"query":"x"}' }],
74
- },
75
- },
76
- ]);
77
- const result = await p;
78
- assert.equal(result.closeSocket, undefined, 'normal completion must not mark closeSocket');
79
- assert.equal(result.toolCalls.length, 1);
80
- });
81
-
82
- test('ws early settle: deferred salvage still pending does NOT early-settle (fails as stall)', async () => {
83
- const socket = new FakeSocket();
84
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
85
- // No output_item.added -> pendingCalls empty; args.done carries no call_id/name
86
- // -> a deferred placeholder that only response.completed could salvage.
87
- socket.feed([
88
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
89
- { type: 'response.function_call_arguments.delta', item_id: 'fc_1', delta: '{"query"' },
90
- { type: 'response.function_call_arguments.done', item_id: 'fc_1', arguments: '{"query":"x"}' },
91
- ]);
92
- await assert.rejects(p, /inter-chunk inactivity/);
93
- });
94
-
95
- test('ws early settle: complete tool then partial second tool does NOT early-settle', async () => {
96
- const socket = new FakeSocket();
97
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
98
- socket.feed([
99
- ...TOOL_CALL_EVENTS,
100
- { type: 'response.output_item.added', item: { type: 'function_call', id: 'fc_2', name: 'grep', call_id: 'call_2' } },
101
- { type: 'response.function_call_arguments.delta', item_id: 'fc_2', delta: '{"pattern"' },
102
- ]);
103
- await assert.rejects(p, /inter-chunk inactivity/);
104
- assert.equal(socket.closed?.reason, 'inter_chunk_timeout', 'partial second tool must use stall path, not early settle');
105
- });
106
-
107
- test('ws early settle: complete tool_search_call clears in-flight and can early-settle', async () => {
108
- const socket = new FakeSocket();
109
- const state = {};
110
- const p = _streamResponse({ entry: { socket }, state, _timeouts: FAST_TIMEOUTS });
111
- socket.feed([
112
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
113
- { type: 'response.output_item.added', item: { type: 'tool_search_call', id: 'ts_1' } },
114
- { type: 'response.output_item.done', item: { type: 'tool_search_call', id: 'ts_1', arguments: '{"query":"fetch"}' } },
115
- ]);
116
- const result = await p;
117
- assert.equal(result.closeSocket, true);
118
- assert.equal(result.toolCalls[0].id, 'ts_1');
119
- assert.equal(result.toolCalls[0].name, 'load_tool');
120
- assert.deepEqual(result.toolCalls[0].arguments, { query: 'fetch' });
121
- assert.equal(state.wsEarlySettle, 'inter_chunk');
122
- });
123
-
124
- test('ws early settle: complete tool_search_call plus partial custom tool does NOT early-settle', async () => {
125
- const socket = new FakeSocket();
126
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
127
- socket.feed([
128
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
129
- { type: 'response.output_item.added', item: { type: 'tool_search_call', id: 'ts_1' } },
130
- { type: 'response.output_item.done', item: { type: 'tool_search_call', id: 'ts_1', arguments: '{"query":"fetch"}' } },
131
- { type: 'response.output_item.added', item: { type: 'custom_tool_call', id: 'ct_2', call_id: 'call_custom_2', name: 'apply_patch' } },
132
- { type: 'response.custom_tool_call_input.delta', item_id: 'ct_2', delta: '*** Begin Patch' },
133
- ]);
134
- await assert.rejects(p, /inter-chunk inactivity/);
135
- assert.equal(socket.closed?.reason, 'inter_chunk_timeout', 'partial custom tool must keep stall path');
136
- });
137
-
138
- test('ws early settle: output_item.done salvages deferred function_call and can early-settle', async () => {
139
- const socket = new FakeSocket();
140
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
141
- socket.feed([
142
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
143
- { type: 'response.function_call_arguments.delta', item_id: 'fc_salvage', delta: '{"query"' },
144
- { type: 'response.function_call_arguments.done', item_id: 'fc_salvage', arguments: '{"query":"x"}' },
145
- { type: 'response.output_item.done', item: { type: 'function_call', id: 'fc_salvage', name: 'explore', call_id: 'call_salvage', arguments: '{"query":"x"}' } },
146
- ]);
147
- const result = await p;
148
- assert.equal(result.closeSocket, true);
149
- assert.equal(result.toolCalls[0].id, 'call_salvage');
150
- assert.equal(result.toolCalls[0].name, 'explore');
151
- assert.deepEqual(result.toolCalls[0].arguments, { query: 'x' });
152
- });
153
-
154
- test('ws early settle: call_id-only tool_search done clears id-tracked active item', async () => {
155
- const socket = new FakeSocket();
156
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
157
- socket.feed([
158
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
159
- { type: 'response.output_item.added', item: { type: 'tool_search_call', id: 'ts_added', call_id: 'ts_call' } },
160
- { type: 'response.output_item.done', item: { type: 'tool_search_call', call_id: 'ts_call', arguments: '{"query":"fetch"}' } },
161
- ]);
162
- const result = await p;
163
- assert.equal(result.closeSocket, true);
164
- assert.equal(result.toolCalls[0].id, 'ts_call');
165
- });
166
-
167
- test('ws early settle: function args.done without item.done does NOT early-settle', async () => {
168
- const socket = new FakeSocket();
169
- const p = _streamResponse({ entry: { socket }, state: {}, _timeouts: FAST_TIMEOUTS });
170
- socket.feed([
171
- { type: 'response.created', response: { id: 'resp_1', model: 'gpt-5.5' } },
172
- { type: 'response.output_item.added', item: { type: 'function_call', id: 'fc_empty', name: 'explore', call_id: 'call_empty' } },
173
- { type: 'response.function_call_arguments.done', item_id: 'fc_empty', arguments: '{}', call_id: 'call_empty', name: 'explore' },
174
- ]);
175
- await assert.rejects(p, /inter-chunk inactivity/);
176
- assert.equal(socket.closed?.reason, 'inter_chunk_timeout', 'function item must stay active until output_item.done');
177
- });
178
-
179
- test('OpenAI WS rejects an oversized Buffer before UTF-8 conversion and marks it retryable', async () => {
180
- const socket = new FakeSocket();
181
- const state = { attemptIndex: 0 };
182
- const payload = Buffer.alloc(33);
183
- payload.toString = () => { throw new Error('oversized Buffer was decoded'); };
184
- const p = _streamResponse({
185
- entry: { socket },
186
- state,
187
- _timeouts: { ...FAST_TIMEOUTS, maxIncomingFrameBytes: 32 },
188
- });
189
- socket.emit('message', payload);
190
- await assert.rejects(p, (error) => {
191
- assert.equal(error.code, 'EOPENAIWSFRAMETOOLARGE');
192
- assert.equal(error.retryable, true);
193
- assert.match(error.message, /33 bytes; limit 32 bytes.*retryable/);
194
- assert.equal(
195
- classifyMidstreamError(error, state, MIDSTREAM_RETRY_POLICY.ws),
196
- 'ws_frame_too_large',
197
- );
198
- return true;
199
- });
200
- assert.deepEqual(socket.closed, { code: 1009, reason: 'frame_too_large' });
201
- });
202
-
203
- test('OpenAI WS preserves normal-size Buffer handling', async () => {
204
- const socket = new FakeSocket();
205
- const p = _streamResponse({
206
- entry: { socket },
207
- state: {},
208
- _timeouts: { ...FAST_TIMEOUTS, maxIncomingFrameBytes: 1024 },
209
- });
210
- socket.emit('message', Buffer.from(JSON.stringify({
211
- type: 'response.completed',
212
- response: { id: 'resp_normal', model: 'gpt-5.5', output: [] },
213
- })));
214
- const result = await p;
215
- assert.equal(result.responseId, 'resp_normal');
216
- });
@@ -1,292 +0,0 @@
1
- #!/usr/bin/env node
2
- // Lead output-style verbosity bench (default >= simple >= minimal >= extreme-minimal).
3
- import { createRequire } from 'node:module';
4
- import { execFileSync } from 'node:child_process';
5
- import {
6
- copyFileSync,
7
- existsSync,
8
- mkdirSync,
9
- mkdtempSync,
10
- readdirSync,
11
- readFileSync,
12
- rmSync,
13
- writeFileSync,
14
- } from 'node:fs';
15
- import { homedir } from 'node:os';
16
- import { dirname, join, resolve } from 'node:path';
17
- import { fileURLToPath, pathToFileURL } from 'node:url';
18
-
19
- const __dir = dirname(fileURLToPath(import.meta.url));
20
- const REPO_ROOT = resolve(__dir, '..');
21
- const PLUGIN_ROOT = join(REPO_ROOT, 'src');
22
- const STYLES = ['default', 'simple', 'minimal', 'extreme-minimal'];
23
- const DEFAULT_PROMPT =
24
- 'Reply in plain English only. What is 2+2? Give a short summary suitable for a status report (no tools, no file reads).';
25
- const MODEL_ALIASES = {
26
- opus: { provider: 'anthropic-oauth', model: 'claude-opus-4-8' },
27
- sonnet: { provider: 'anthropic-oauth', model: 'claude-sonnet-5' },
28
- gpt: { provider: 'openai-oauth', model: 'gpt-5.5' },
29
- 'gpt-5.5': { provider: 'openai-oauth', model: 'gpt-5.5' },
30
- grok: { provider: 'grok-oauth', model: 'grok-composer-2.5-fast' },
31
- };
32
- // Filenames verified in provider ensureAuth / token paths (resolvePluginData / getPluginData).
33
- const AUTH_ARTIFACT_BY_PROVIDER = {
34
- 'grok-oauth': ['grok-oauth.json', 'grok-oauth-models.json'],
35
- 'anthropic-oauth': ['anthropic-oauth-credentials.json', 'anthropic-oauth-models.json'],
36
- 'openai-oauth': ['openai-oauth.json', 'openai-oauth-models.json'],
37
- };
38
-
39
- function argValue(name, fallback = null) {
40
- const idx = process.argv.indexOf(name);
41
- if (idx >= 0 && idx + 1 < process.argv.length) return process.argv[idx + 1];
42
- const pref = `${name}=`;
43
- const hit = process.argv.find((a) => a.startsWith(pref));
44
- return hit ? hit.slice(pref.length) : fallback;
45
- }
46
- function hasFlag(name) { return process.argv.includes(name); }
47
- function resolveModelOpts(modelArg, providerArg) {
48
- const key = String(modelArg || '').trim().toLowerCase();
49
- if (MODEL_ALIASES[key] && !providerArg) return { ...MODEL_ALIASES[key] };
50
- return { provider: providerArg || null, model: modelArg || null };
51
- }
52
- function defaultUserDataDir() {
53
- return process.env.MIXDOG_DATA_DIR || join(process.env.MIXDOG_HOME || join(homedir(), '.mixdog'), 'data');
54
- }
55
- function readUnifiedConfig(dataDir) {
56
- try {
57
- const unified = JSON.parse(readFileSync(join(dataDir, 'mixdog-config.json'), 'utf8'));
58
- return unified && typeof unified === 'object' ? unified : {};
59
- } catch { return {}; }
60
- }
61
- function outputStyleBodyFromMeta(meta) {
62
- const marker = '# Output Style';
63
- const idx = String(meta || '').lastIndexOf(marker);
64
- return idx < 0 ? '' : String(meta).slice(idx).trim();
65
- }
66
- function measureOutputText(text) {
67
- const trimmed = String(text || '').trim();
68
- const lines = trimmed ? trimmed.split(/\r?\n/) : [];
69
- const bullets = lines.filter((l) => /^\s*[-*•]\s+/.test(l)).length;
70
- const withoutCode = trimmed.replace(/`[^`]*`/g, '');
71
- const sentenceMarks = withoutCode.match(/[.!?。!?]+(?=\s|$)/g) || [];
72
- return {
73
- chars: trimmed.length,
74
- lines: lines.length,
75
- bullets,
76
- sentences: sentenceMarks.length || (trimmed ? 1 : 0),
77
- text: trimmed,
78
- };
79
- }
80
- function runInjectionScaffold() {
81
- const rulesBuilder = createRequire(import.meta.url)(join(PLUGIN_ROOT, 'lib', 'rules-builder.cjs'));
82
- const baseDir = mkdtempSync(join(REPO_ROOT, '.tmp-output-style-bench-'));
83
- const templatePath = join(PLUGIN_ROOT, 'defaults', 'mixdog-config.template.json');
84
- const baseConfig = existsSync(templatePath)
85
- ? JSON.parse(readFileSync(templatePath, 'utf8'))
86
- : { outputStyle: 'default' };
87
- const markers = {
88
- default: 'most detailed style',
89
- simple: 'Practical concise',
90
- minimal: 'a very short summary',
91
- 'extreme-minimal': 'exactly one sentence',
92
- };
93
- const snippets = {};
94
- try {
95
- for (const styleId of STYLES) {
96
- const dataDir = join(baseDir, styleId);
97
- mkdirSync(dataDir, { recursive: true });
98
- writeFileSync(join(dataDir, 'mixdog-config.json'), JSON.stringify({ ...baseConfig, outputStyle: styleId }, null, 2));
99
- snippets[styleId] = outputStyleBodyFromMeta(rulesBuilder.buildLeadMetaContent({ PLUGIN_ROOT, DATA_DIR: dataDir }));
100
- if (!snippets[styleId].includes(markers[styleId])) throw new Error(`${styleId} injection marker missing`);
101
- }
102
- if (new Set(STYLES.map((id) => snippets[id])).size !== STYLES.length) throw new Error('injection bodies not distinct');
103
- return { snippets };
104
- } finally {
105
- rmSync(baseDir, { recursive: true, force: true });
106
- }
107
- }
108
- function authArtifactNamesForSandbox(realDataDir, provider) {
109
- const names = new Set();
110
- for (const file of AUTH_ARTIFACT_BY_PROVIDER[provider] || []) names.add(file);
111
- try {
112
- for (const entry of readdirSync(realDataDir, { withFileTypes: true })) {
113
- if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
114
- if (/oauth/i.test(entry.name) || /credentials/i.test(entry.name)) names.add(entry.name);
115
- }
116
- } catch { /* missing real data dir */ }
117
- return [...names];
118
- }
119
- function copyAuthArtifacts(realDataDir, sandboxDataDir, provider) {
120
- const copied = [];
121
- const skipped = [];
122
- for (const name of authArtifactNamesForSandbox(realDataDir, provider)) {
123
- const src = join(realDataDir, name);
124
- const dest = join(sandboxDataDir, name);
125
- if (!existsSync(src)) {
126
- skipped.push(name);
127
- continue;
128
- }
129
- try {
130
- copyFileSync(src, dest);
131
- copied.push(name);
132
- } catch {
133
- skipped.push(name);
134
- }
135
- }
136
- return { copied, skipped };
137
- }
138
- function prepareStyleSandbox(baseSandbox, styleId, userUnified, realDataDir, provider) {
139
- const dataDir = join(baseSandbox, styleId);
140
- mkdirSync(dataDir, { recursive: true });
141
- writeFileSync(join(dataDir, 'mixdog-config.json'), JSON.stringify({ ...userUnified, outputStyle: styleId }, null, 2));
142
- copyAuthArtifacts(realDataDir, dataDir, provider);
143
- return dataDir;
144
- }
145
- function findPresetRoute(config, key) {
146
- const wanted = String(key || '').trim().toLowerCase();
147
- if (!wanted) return null;
148
- const presets = Array.isArray(config?.presets) ? config.presets : [];
149
- return presets.find((p) => {
150
- const id = String(p?.id || '').trim().toLowerCase();
151
- const name = String(p?.name || '').trim().toLowerCase();
152
- return id === wanted || name === wanted;
153
- }) || null;
154
- }
155
- function resolveLeadProviderModel(userUnified, cli) {
156
- if (cli.provider && cli.model) return { provider: cli.provider, model: cli.model };
157
- const leadPreset = findPresetRoute(userUnified, 'workflow-lead')
158
- || findPresetRoute(userUnified, userUnified.default)
159
- || findPresetRoute(userUnified, 'gpt-5.5');
160
- if (leadPreset?.provider && leadPreset?.model) return { provider: leadPreset.provider, model: leadPreset.model };
161
- const alias = MODEL_ALIASES.gpt;
162
- return { provider: cli.provider || alias.provider, model: cli.model || alias.model };
163
- }
164
- function runLiveLeadTurn({ dataDir, prompt, provider, model, cwd, effort, fast }) {
165
- const cfgUrl = pathToFileURL(join(PLUGIN_ROOT, 'runtime/agent/orchestrator/config.mjs')).href;
166
- const regUrl = pathToFileURL(join(PLUGIN_ROOT, 'runtime/agent/orchestrator/providers/registry.mjs')).href;
167
- const mgrUrl = pathToFileURL(join(PLUGIN_ROOT, 'runtime/agent/orchestrator/session/manager.mjs')).href;
168
- const driver = [
169
- `import * as cfgMod from ${JSON.stringify(cfgUrl)};`,
170
- `import * as reg from ${JSON.stringify(regUrl)};`,
171
- `import { createSession, askSession, closeSession } from ${JSON.stringify(mgrUrl)};`,
172
- `const config = cfgMod.loadConfig({ secrets: true });`,
173
- `await reg.initProviders(config.providers || {});`,
174
- `const sessionOpts = { provider: ${JSON.stringify(provider)}, model: ${JSON.stringify(model)},`,
175
- ` owner: 'cli', agent: 'lead', lane: 'cli', sourceType: 'lead', sourceName: 'output-style-bench',`,
176
- ` cwd: ${JSON.stringify(cwd)}, tools: 'full', fast: ${fast ? 'true' : 'false'} };`,
177
- effort ? `sessionOpts.effort = ${JSON.stringify(effort)};` : '',
178
- `const session = createSession(sessionOpts);`,
179
- `let result;`,
180
- `try { result = await askSession(session.id, ${JSON.stringify(prompt)}, null, null, ${JSON.stringify(cwd)}); }`,
181
- `finally { try { closeSession(session.id, 'output-style-bench'); } catch {} }`,
182
- // Pooled provider sockets (e.g. openai-oauth WS, 20-min idle TTL) keep the
183
- // child alive after the turn; flush JSON then force-exit so execFileSync
184
- // returns as soon as the turn completes.
185
- `const payload = JSON.stringify({ text: String(result?.text || result?.content || '').trim(), sessionId: session.id });`,
186
- `await new Promise((r) => process.stdout.write(payload, r));`,
187
- `process.exit(0);`,
188
- ].filter(Boolean).join('\n');
189
- const raw = execFileSync('node', ['--input-type=module', '-e', driver], {
190
- encoding: 'utf8',
191
- maxBuffer: 64 * 1024 * 1024,
192
- timeout: Number(process.env.OUTPUT_STYLE_BENCH_TURN_TIMEOUT_MS || 10 * 60_000),
193
- killSignal: 'SIGKILL',
194
- env: { ...process.env, MIXDOG_ROOT: PLUGIN_ROOT, MIXDOG_DATA_DIR: dataDir },
195
- });
196
- const jsonStart = raw.lastIndexOf('{');
197
- if (jsonStart < 0) throw new Error(`live driver failed: ${raw.slice(0, 400)}`);
198
- return JSON.parse(raw.slice(jsonStart));
199
- }
200
- function styleCharCountsFromResults(results) {
201
- return Object.fromEntries(
202
- STYLES.map((id) => [id, results.find((r) => r.style === id)?.metrics.chars ?? 0]),
203
- );
204
- }
205
- function evaluateVerbosityOrdering(results) {
206
- const counts = STYLES.map((id) => results.find((r) => r.style === id)?.metrics.chars ?? 0);
207
- let orderingOk = true;
208
- for (let i = 1; i < counts.length; i += 1) {
209
- if (counts[i - 1] < counts[i]) orderingOk = false;
210
- }
211
- const chain = STYLES.map((id, i) => `${id}=${counts[i]}`).join(' ');
212
- const passLabel = STYLES.map((id) => `chars(${id})`).join(' >= ');
213
- const verdict = orderingOk
214
- ? `PASS ${passLabel}`
215
- : `WARN ordering violated: ${chain}`;
216
- return { orderingOk, verdict, counts: styleCharCountsFromResults(results) };
217
- }
218
- function printUsage() {
219
- process.stdout.write(`output-style-bench — Lead verbosity ladder (default >= simple >= minimal >= extreme-minimal).
220
-
221
- Output style is Lead-only (buildLeadMetaContent when owner is not agent).
222
- runHeadlessRole worker paths (owner=agent) do NOT inject outputStyle.
223
-
224
- Usage:
225
- node scripts/output-style-bench.mjs [--json]
226
- node scripts/output-style-bench.mjs --run [--model gpt] [--provider P] [--effort E] [--fast] [--prompt "..."] [--json]
227
-
228
- --run required for live calls. Temp MIXDOG_DATA_DIR: outputStyle override + read-only copy of OAuth/credential JSON from your real data dir.
229
- `);
230
- }
231
- function main() {
232
- const jsonMode = hasFlag('--json');
233
- const doRun = hasFlag('--run');
234
- const prompt = argValue('--prompt', DEFAULT_PROMPT);
235
- const cli = resolveModelOpts(argValue('--model', null), argValue('--provider', null));
236
- const effort = argValue('--effort', null);
237
- const fast = hasFlag('--fast');
238
- const cwd = process.cwd();
239
- let scaffold;
240
- try { scaffold = runInjectionScaffold(); }
241
- catch (e) { process.stderr.write(`[output-style-bench] scaffold FAILED: ${e.message}\n`); process.exit(1); }
242
- if (!doRun) {
243
- printUsage();
244
- const charCounts = Object.fromEntries(STYLES.map((id) => [id, scaffold.snippets[id].length]));
245
- if (jsonMode) {
246
- console.log(JSON.stringify({ mode: 'scaffold', role: 'lead', owner: 'cli', charCounts, liveCommand: 'node scripts/output-style-bench.mjs --run --model gpt' }, null, 2));
247
- } else {
248
- process.stdout.write(`[output-style-bench] scaffold ok: ${STYLES.map((id) => `${id}=${charCounts[id]}`).join(', ')}\n`);
249
- }
250
- process.exit(0);
251
- }
252
- const realDataDir = defaultUserDataDir();
253
- const userUnified = readUnifiedConfig(realDataDir);
254
- const route = resolveLeadProviderModel(userUnified, cli);
255
- const baseSandbox = mkdtempSync(join(REPO_ROOT, '.tmp-output-style-bench-live-'));
256
- const results = [];
257
- try {
258
- for (const styleId of STYLES) {
259
- const dataDir = prepareStyleSandbox(baseSandbox, styleId, userUnified, realDataDir, route.provider);
260
- process.stderr.write(`[output-style-bench] style=${styleId} ${route.provider}/${route.model}\n`);
261
- try {
262
- const live = runLiveLeadTurn({ dataDir, prompt, ...route, cwd, effort, fast });
263
- const metrics = measureOutputText(live.text);
264
- results.push({ style: styleId, ok: true, sessionId: live.sessionId, metrics, raw: metrics.text });
265
- } catch (err) {
266
- results.push({
267
- style: styleId,
268
- ok: false,
269
- error: String(err.stdout || err.stderr || err.message).slice(0, 2000),
270
- metrics: measureOutputText(''),
271
- });
272
- }
273
- }
274
- } finally {
275
- rmSync(baseSandbox, { recursive: true, force: true });
276
- }
277
- const { orderingOk, verdict } = evaluateVerbosityOrdering(results);
278
- if (jsonMode) {
279
- console.log(JSON.stringify({ mode: 'live', role: 'lead', prompt, route, results, verdict, orderingOk }, null, 2));
280
- } else {
281
- console.log(`live role=lead ${route.provider}/${route.model}`);
282
- for (const r of results) {
283
- const m = r.metrics;
284
- console.log(`- ${r.style}: ${r.ok ? 'ok' : 'FAIL'} chars=${m.chars} lines=${m.lines} bullets=${m.bullets} sentences=${m.sentences}`);
285
- if (r.ok) console.log(` ${m.text}`);
286
- else console.log(` error: ${String(r.error || '').slice(0, 300)}`);
287
- }
288
- console.log(verdict);
289
- }
290
- process.exit(results.every((r) => r.ok) ? 0 : 1);
291
- }
292
- main();
@@ -1,145 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createRequire } from 'node:module';
3
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
4
- import { tmpdir } from 'node:os';
5
- import { dirname, join, resolve } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
-
8
- const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
9
- const require = createRequire(import.meta.url);
10
- const rulesBuilder = require('../src/lib/rules-builder.cjs');
11
-
12
- function assert(condition, message) {
13
- if (!condition) throw new Error(message);
14
- }
15
-
16
- const DEFAULT_REPORT_LABELS = new Set(['Changes', 'Verification', 'Risks / next steps', '\uBC14\uB010 \uC810', '\uD655\uC778\uD55C \uAC83', '\uB0A8\uC740 \uB9AC\uC2A4\uD06C/\uB2E4\uC74C \uB2E8\uACC4', '\uB2E4\uC74C \uB2E8\uACC4']);
17
-
18
- function assertCleanOutput(name, value, { maxLines = 3, maxBullets = 3, allowedLabels = new Set() } = {}) {
19
- const text = String(value || '').trim();
20
- assert(text, `${name}: empty output`);
21
- assert(!/\n\s*\n/.test(text), `${name}: multiple paragraphs are not compact`);
22
- assert(!/^\s*#{1,6}\s/m.test(text), `${name}: heading found`);
23
- assert(!/^\s*\d+[.)]\s/m.test(text), `${name}: numbered list found`);
24
- assert(!/^\s{2,}[-*]\s/m.test(text), `${name}: nested bullet found`);
25
- for (const line of text.split(/\r?\n/)) {
26
- const match = line.match(/^\s*(?:[-*]\s+)?([\p{L}\p{N}][\p{L}\p{N} _/-]{0,30}):\s/u);
27
- if (match) assert(allowedLabels.has(match[1]), `${name}: disallowed report label found`);
28
- }
29
- assert(!/\b(?:tool trace|session metadata|model metadata|searched-path list)\b/i.test(text), `${name}: tool/meta trace found`);
30
- assert(!/\b(?:Mapped|Searched|Read|Called) for \d/i.test(text), `${name}: timing/tool status found`);
31
- assert(!/^(?:\uB124|\uC608|\uB9DE\uC544\uC694|\uC88B\uC544\uC694|\uC54C\uACA0\uC2B5\uB2C8\uB2E4|Sure|Okay|Understood)[,.\s]/i.test(text), `${name}: acknowledgment preface found`);
32
- assert(!/(.+)(?:\n|\s{2,})\1/.test(text), `${name}: repeated conclusion found`);
33
-
34
- const lines = text.split(/\r?\n/).filter((line) => line.trim());
35
- const bulletLines = lines.filter((line) => /^\s*[-*]\s+/.test(line));
36
- if (bulletLines.length > 0) {
37
- assert(bulletLines.length === lines.length, `${name}: mixed prose and bullets`);
38
- assert(bulletLines.length <= maxBullets, `${name}: too many bullets`);
39
- return;
40
- }
41
- assert(lines.length <= maxLines, `${name}: too many lines`);
42
-
43
- const withoutCode = text.replace(/`[^`]*`/g, '');
44
- const sentenceMarks = withoutCode.match(/[.!?。!?]|\uB2E4\.|\uC694\./g) || [];
45
- assert(sentenceMarks.length <= 2, `${name}: too many sentences`);
46
- }
47
-
48
- const defaultStyle = readFileSync(join(root, 'src', 'output-styles', 'default.md'), 'utf8');
49
- for (const required of [
50
- 'name: default',
51
- 'Concise engineering summaries',
52
- 'Mixdog default — the most detailed style',
53
- 'State conclusions, not reasoning',
54
- 'Use labels such as',
55
- '`Changes`, `Verification`,',
56
- 'Synthesize agent or retrieval results',
57
- 'Do not hide blockers',
58
- ]) {
59
- assert(defaultStyle.includes(required), `default.md missing: ${required}`);
60
- }
61
- assert(!defaultStyle.includes('Claude Code-compact'), 'default.md must not reference the old compact style name');
62
- assert(!defaultStyle.includes('Hard cap user-visible replies'), 'default.md must not hard-cap replies to two short sentences');
63
- assert(!defaultStyle.includes('Be short and direct.'), 'default.md must not keep the old generic concise preset');
64
- assert(!defaultStyle.includes('Practical concise — outcome-first handoffs'), 'default.md must not use the simple preset body');
65
-
66
- const simpleStyle = readFileSync(join(root, 'src', 'output-styles', 'simple.md'), 'utf8');
67
- for (const required of [
68
- 'name: simple',
69
- 'Outcome-first concise handoffs for coding work',
70
- 'Practical concise — outcome-first handoffs',
71
- 'file_path:line_number',
72
- 'Controlled detail',
73
- 'Synthesize agent or retrieval results',
74
- 'Do not hide blockers',
75
- 'verification was not run, say so once',
76
- ]) {
77
- assert(simpleStyle.includes(required), `simple.md missing: ${required}`);
78
- }
79
- assert(!simpleStyle.includes('Mixdog default — the most detailed of the three styles'), 'simple.md must not duplicate default preset body');
80
- for (const [name, style] of Object.entries({
81
- default: defaultStyle,
82
- simple: simpleStyle,
83
- minimal: readFileSync(join(root, 'src', 'output-styles', 'minimal.md'), 'utf8'),
84
- 'extreme-minimal': readFileSync(join(root, 'src', 'output-styles', 'extreme-minimal.md'), 'utf8'),
85
- })) {
86
- assert(!style.includes('pre-tool preamble'), `${name} output style must not own language preamble rules`);
87
- assert(!style.includes('selected/default user language'), `${name} output style must not duplicate profile language rules`);
88
- }
89
-
90
- const dataDir = mkdtempSync(join(tmpdir(), 'mixdog-output-style-smoke-'));
91
- try {
92
- writeFileSync(join(dataDir, 'user-workflow.md'), 'workflow context should not override output style\n');
93
- const leadRules = rulesBuilder.buildInjectionContent({ PLUGIN_ROOT: join(root, 'src'), DATA_DIR: dataDir });
94
- const outputStyleIndex = leadRules.lastIndexOf('# Output Style');
95
- assert(outputStyleIndex >= 0, 'Lead output style missing');
96
- assert(outputStyleIndex > leadRules.lastIndexOf('# User Workflow'), 'Lead output style must be injected after workflow/user context');
97
-
98
- mkdirSync(join(dataDir, 'output-styles'), { recursive: true });
99
- writeFileSync(join(dataDir, 'mixdog-config.json'), JSON.stringify({
100
- agent: { profile: { title: '\uD64D\uAE38\uB3D9\uB2D8', language: 'system' } },
101
- outputStyle: 'custom-smoke',
102
- }));
103
- writeFileSync(join(dataDir, 'output-styles', 'custom-smoke.md'), '---\nname: custom-smoke\n---\n\n# Custom Output Style\n\ncustom smoke style\n');
104
- const customRules = rulesBuilder.buildInjectionContent({ PLUGIN_ROOT: join(root, 'src'), DATA_DIR: dataDir });
105
- assert(customRules.includes('# Custom Output Style'), 'configured outputStyle must select custom style');
106
- assert(!customRules.includes('Mixdog default — the most detailed of the three styles'), 'custom outputStyle should not append default style');
107
- const profileMeta = rulesBuilder.buildLeadMetaContent({ PLUGIN_ROOT: join(root, 'src'), DATA_DIR: dataDir });
108
- assert(profileMeta.includes('Use "\uD64D\uAE38\uB3D9\uB2D8" when directly addressing the user'), 'profile title must inject into Lead BP3 meta');
109
- assert(profileMeta.includes('do not repeat it in routine progress updates or pre-tool preambles'), 'profile title must not encourage title in preambles');
110
- assert(/Default user-facing response language from system locale/.test(profileMeta), 'system profile language must resolve from system locale');
111
- assert(profileMeta.includes('pre-tool preambles (even single-line)'), 'profile language must cover pre-tool preambles');
112
- } finally {
113
- rmSync(dataDir, { recursive: true, force: true });
114
- }
115
-
116
- // assertCleanOutput encodes the Simple style compact contract (not Default, which may be longer).
117
- const goodOutputs = {
118
- explanation: 'Simple \uC2A4\uD0C0\uC77C\uC740 \uACB0\uACFC \uD55C \uC904\uACFC \uADFC\uAC70 \uD55C \uAC00\uC9C0\uB85C \uB05D\uB0B4\uACE0, \uCD5C\uC885 handoff\uB9CC \uC9E7\uC740 bullet \uB77C\uBCA8\uC744 \uC501\uB2C8\uB2E4.',
119
- implementation: '- \uBC14\uB010 \uC810: `scripts/output-style-smoke.mjs`\uC758 default/simple \uBB38\uC790\uC5F4 \uAC80\uC99D\uC744 \uD604\uC7AC \uD504\uB9AC\uC14B\uC5D0 \uB9DE\uCDC4\uC2B5\uB2C8\uB2E4.\n- \uD655\uC778\uD55C \uAC83: `node scripts/output-style-smoke.mjs`\uB97C \uC2E4\uD589\uD588\uC2B5\uB2C8\uB2E4.',
120
- crowded: '- \uBC14\uB010 \uC810: compact guardrail\uC740 Simple handoff\uC6A9 controlled detail\uC744 \uAC80\uC99D\uD569\uB2C8\uB2E4.\n- \uD655\uC778\uD55C \uAC83: bad \uC0D8\uD50C \uAC70\uBD80 \uADDC\uCE59\uC740 \uADF8\uB300\uB85C\uC785\uB2C8\uB2E4.',
121
- blocker: '`scripts/output-style-smoke.mjs`\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uBCC0\uACBD\uC774 \uB9C9\uD614\uC2B5\uB2C8\uB2E4.',
122
- semicolon: '\uC2A4\uBAA8\uD06C \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uAC31\uC2E0\uD588\uACE0; Simple \uACC4\uC57D\uC5D0 \uB9DE\uB294 \uC608\uC2DC \uC751\uB2F5\uB9CC \uD1B5\uACFC\uD569\uB2C8\uB2E4.',
123
- };
124
- for (const [name, output] of Object.entries(goodOutputs)) assertCleanOutput(name, output, { allowedLabels: DEFAULT_REPORT_LABELS });
125
-
126
- const badOutputs = {
127
- heading: '## Summary\nDone.',
128
- label: 'Changed: updated default style.',
129
- koreanLabel: '\uBCC0\uACBD: default \uC2A4\uD0C0\uC77C\uC744 \uC218\uC815\uD588\uC2B5\uB2C8\uB2E4.\n\uAC80\uC99D: \uC2A4\uBAA8\uD06C\uB97C \uD1B5\uACFC\uD588\uC2B5\uB2C8\uB2E4.',
130
- numbered: '1. Updated style\n2. Ran smoke',
131
- paragraphs: 'Done.\n\nDone again.',
132
- nested: '- Updated\n - Nested detail',
133
- ack: '\uB124, default \uC2A4\uD0C0\uC77C\uC744 \uC218\uC815\uD588\uC2B5\uB2C8\uB2E4.',
134
- timing: 'Mapped for 2m 32s\n\ndefault \uC2A4\uD0C0\uC77C\uC744 \uC218\uC815\uD588\uC2B5\uB2C8\uB2E4.',
135
- tooManySentences: '\uC218\uC815\uD588\uC2B5\uB2C8\uB2E4. \uAC80\uC99D\uD588\uC2B5\uB2C8\uB2E4. \uBCF4\uACE0\uD588\uC2B5\uB2C8\uB2E4.',
136
- mixed: '\uC218\uC815\uD588\uC2B5\uB2C8\uB2E4.\n- \uAC80\uC99D\uD588\uC2B5\uB2C8\uB2E4.',
137
- tooManyBullets: '- \uBC14\uB010 \uC810: A\n- \uD655\uC778\uD55C \uAC83: B\n- \uB2E4\uC74C \uB2E8\uACC4: C\n- \uB0A8\uC740 \uB9AC\uC2A4\uD06C/\uB2E4\uC74C \uB2E8\uACC4: D',
138
- };
139
- for (const [name, output] of Object.entries(badOutputs)) {
140
- let failed = false;
141
- try { assertCleanOutput(`bad:${name}`, output, { allowedLabels: DEFAULT_REPORT_LABELS }); } catch { failed = true; }
142
- assert(failed, `bad sample unexpectedly passed: ${name}`);
143
- }
144
-
145
- process.stdout.write(`output style smoke passed samples=${Object.keys(goodOutputs).length}\n`);