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
@@ -1,853 +0,0 @@
1
- #!/usr/bin/env node
2
- // internal-comms-bench.mjs — live A/B token measurement for internal-comms rules.
3
- //
4
- // Variant A (verbose): prior committed blobs via `git show HEAD:src/<rule>`.
5
- // Variant B (optimized): current on-disk src/ copied into a temp PLUGIN_ROOT.
6
- // Only the listed rule files differ between variants; everything else matches.
7
- //
8
- // node scripts/internal-comms-bench.mjs
9
- // node scripts/internal-comms-bench.mjs --run [--model grok] [--provider P] [--json]
10
- import { execFileSync, spawnSync } from 'node:child_process';
11
- import {
12
- copyFileSync,
13
- cpSync,
14
- existsSync,
15
- mkdirSync,
16
- mkdtempSync,
17
- readFileSync,
18
- readdirSync,
19
- rmSync,
20
- writeFileSync,
21
- } from 'node:fs';
22
- import { homedir } from 'node:os';
23
- import { dirname, join, resolve } from 'node:path';
24
- import { fileURLToPath, pathToFileURL } from 'node:url';
25
-
26
- const __dir = dirname(fileURLToPath(import.meta.url));
27
- const REPO_ROOT = resolve(__dir, '..');
28
- const PLUGIN_ROOT = join(REPO_ROOT, 'src');
29
- const HEADLESS = pathToFileURL(resolve(__dir, '../src/headless-role.mjs')).href;
30
-
31
- const RULE_FILES = [
32
- 'rules/agent/00-core.md',
33
- 'rules/agent/00-common.md',
34
- 'rules/agent/20-skip-protocol.md',
35
- 'agents/worker/AGENT.md',
36
- 'agents/heavy-worker/AGENT.md',
37
- 'agents/reviewer/AGENT.md',
38
- 'agents/debugger/AGENT.md',
39
- 'workflows/default/WORKFLOW.md',
40
- 'workflows/solo/WORKFLOW.md',
41
- 'rules/lead/01-general.md',
42
- 'rules/lead/02-channels.md',
43
- 'rules/lead/lead-tool.md',
44
- 'rules/lead/lead-brief.md',
45
- ];
46
-
47
- const DEFAULT_WORKER_PROMPT =
48
- 'In math.js add an exported function add(a, b) that returns a + b. Keep the existing mul export unchanged. Use apply_patch only. Stop when the function exists; hand off with outcome and file:line.';
49
-
50
- // Lead-mode task: FORCES delegation so the real internal-comms flow runs
51
- // (Lead writes a brief -> worker returns a handoff -> reviewer verifies).
52
- // Identical across variants A/B; only the on-disk rule files differ.
53
- const DEFAULT_LEAD_PROMPT = [
54
- 'You are the Lead in an automation benchmark. A file named math.js already exists in your working directory.',
55
- 'This is the planning turn: give a concise plan only, then wait for a later explicit approval. Do not edit, mutate state, or delegate in this turn.',
56
- 'After approval, do NOT edit any file yourself or call apply_patch yourself. Delegate every implementation step: first a worker adds exported add(a, b) returning a + b to math.js while preserving mul, then a reviewer verifies both exports. Finally reply with a one-line outcome plus math.js:line.',
57
- ].join(' ');
58
- export const DEFAULT_LEAD_APPROVAL_PROMPT = 'Proceed with the latest plan.';
59
- export const CHILD_RESULT_START = '__INTERNAL_COMMS_BENCH_RESULT_START__';
60
- export const CHILD_RESULT_END = '__INTERNAL_COMMS_BENCH_RESULT_END__';
61
-
62
- const MODEL_ALIASES = {
63
- opus: { provider: 'anthropic-oauth', model: 'claude-opus-4-8' },
64
- sonnet: { provider: 'anthropic-oauth', model: 'claude-sonnet-5' },
65
- gpt: { provider: 'openai-oauth', model: 'gpt-5.5' },
66
- 'gpt-5.5': { provider: 'openai-oauth', model: 'gpt-5.5' },
67
- grok: { provider: 'grok-oauth', model: 'grok-composer-2.5-fast' },
68
- };
69
-
70
- const AUTH_ARTIFACT_BY_PROVIDER = {
71
- 'grok-oauth': ['grok-oauth.json', 'grok-oauth-models.json'],
72
- 'anthropic-oauth': ['anthropic-oauth-credentials.json', 'anthropic-oauth-models.json'],
73
- 'openai-oauth': ['openai-oauth.json', 'openai-oauth-models.json'],
74
- };
75
-
76
- const INITIAL_MATH_JS = `export function mul(a, b) {
77
- return a * b;
78
- }
79
- `;
80
-
81
- function argValue(name, fallback = null) {
82
- const idx = process.argv.indexOf(name);
83
- if (idx >= 0 && idx + 1 < process.argv.length) return process.argv[idx + 1];
84
- const pref = `${name}=`;
85
- const hit = process.argv.find((a) => a.startsWith(pref));
86
- return hit ? hit.slice(pref.length) : fallback;
87
- }
88
- function hasFlag(name) { return process.argv.includes(name); }
89
-
90
- function resolveModelOpts(modelArg, providerArg) {
91
- const key = String(modelArg || '').trim().toLowerCase();
92
- if (MODEL_ALIASES[key] && !providerArg) return { ...MODEL_ALIASES[key] };
93
- return { provider: providerArg || null, model: modelArg || null };
94
- }
95
-
96
- function defaultUserDataDir() {
97
- return process.env.MIXDOG_DATA_DIR || join(process.env.MIXDOG_HOME || join(homedir(), '.mixdog'), 'data');
98
- }
99
-
100
- function readUnifiedConfig(dataDir) {
101
- try {
102
- const unified = JSON.parse(readFileSync(join(dataDir, 'mixdog-config.json'), 'utf8'));
103
- return unified && typeof unified === 'object' ? unified : {};
104
- } catch { return {}; }
105
- }
106
-
107
- function gitPathForRule(relFromSrc) {
108
- return `src/${String(relFromSrc).replace(/\\/g, '/')}`;
109
- }
110
-
111
- function readPriorRuleBlob(relFromSrc) {
112
- const gitPath = gitPathForRule(relFromSrc);
113
- try {
114
- return execFileSync('git', ['show', `HEAD:${gitPath}`], {
115
- cwd: REPO_ROOT,
116
- encoding: 'utf8',
117
- maxBuffer: 8 * 1024 * 1024,
118
- });
119
- } catch {
120
- return null;
121
- }
122
- }
123
-
124
- function readCurrentRule(relFromSrc) {
125
- return readFileSync(join(PLUGIN_ROOT, relFromSrc), 'utf8');
126
- }
127
-
128
- function ruleVariantBytes() {
129
- const rows = [];
130
- for (const rel of RULE_FILES) {
131
- const prior = readPriorRuleBlob(rel);
132
- const current = readCurrentRule(rel);
133
- const aText = prior != null ? prior : current;
134
- rows.push({
135
- file: rel,
136
- a_chars: aText.length,
137
- b_chars: current.length,
138
- prior_from_git: prior != null,
139
- });
140
- }
141
- return rows;
142
- }
143
-
144
- function authArtifactNamesForSandbox(realDataDir, provider) {
145
- const names = new Set();
146
- for (const file of AUTH_ARTIFACT_BY_PROVIDER[provider] || []) names.add(file);
147
- try {
148
- for (const entry of readdirSync(realDataDir, { withFileTypes: true })) {
149
- if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
150
- if (/oauth/i.test(entry.name) || /credentials/i.test(entry.name)) names.add(entry.name);
151
- }
152
- } catch { /* missing real data dir */ }
153
- return [...names];
154
- }
155
-
156
- function copyAuthArtifacts(realDataDir, sandboxDataDir, provider) {
157
- const copied = [];
158
- const skipped = [];
159
- for (const name of authArtifactNamesForSandbox(realDataDir, provider)) {
160
- const src = join(realDataDir, name);
161
- const dest = join(sandboxDataDir, name);
162
- if (!existsSync(src)) {
163
- skipped.push(name);
164
- continue;
165
- }
166
- try {
167
- copyFileSync(src, dest);
168
- copied.push(name);
169
- } catch {
170
- skipped.push(name);
171
- }
172
- }
173
- return { copied, skipped };
174
- }
175
-
176
- function materializePluginRoot(variant, sandboxRoot) {
177
- const pluginRoot = join(sandboxRoot, `plugin-${variant}`);
178
- cpSync(PLUGIN_ROOT, pluginRoot, { recursive: true });
179
- if (variant === 'A') {
180
- for (const rel of RULE_FILES) {
181
- const prior = readPriorRuleBlob(rel);
182
- if (prior != null) writeFileSync(join(pluginRoot, rel), prior, 'utf8');
183
- }
184
- }
185
- return pluginRoot;
186
- }
187
-
188
- function prepareDataDir(sandboxRoot, variant, realDataDir, userUnified, provider) {
189
- const dataDir = join(sandboxRoot, `data-${variant}`);
190
- mkdirSync(join(dataDir, 'history'), { recursive: true });
191
- writeFileSync(join(dataDir, 'mixdog-config.json'), JSON.stringify(userUnified, null, 2));
192
- copyAuthArtifacts(realDataDir, dataDir, provider);
193
- return dataDir;
194
- }
195
-
196
- function resetTaskCwd(taskCwd) {
197
- writeFileSync(join(taskCwd, 'math.js'), INITIAL_MATH_JS, 'utf8');
198
- }
199
-
200
- function prepareTaskCwd(parentDir) {
201
- const taskCwd = mkdtempSync(join(parentDir, 'task-'));
202
- resetTaskCwd(taskCwd);
203
- return taskCwd;
204
- }
205
-
206
- function extractSessionId(text) {
207
- const s = String(text || '');
208
- const m = s.match(/sessionId:\s*(sess_[A-Za-z0-9_]+)/) || s.match(/\b(sess_[A-Za-z0-9_]+)/);
209
- return m ? m[1] : null;
210
- }
211
-
212
- function runHeadlessWorker({ pluginRoot, dataDir, taskCwd, prompt, provider, model, effort, fast }) {
213
- const driver = [
214
- `import { runHeadlessRole } from ${JSON.stringify(HEADLESS)};`,
215
- `const out = [];`,
216
- `const code = await runHeadlessRole({`,
217
- ` agent: 'worker',`,
218
- ` message: ${JSON.stringify(prompt)},`,
219
- ` provider: ${JSON.stringify(provider || null)},`,
220
- ` model: ${JSON.stringify(model || null)},`,
221
- ` effort: ${JSON.stringify(effort || null)},`,
222
- ` fast: ${JSON.stringify(fast === true)},`,
223
- ` cwd: ${JSON.stringify(taskCwd)},`,
224
- ` write: (t) => out.push(t),`,
225
- ` writeErr: (t) => process.stderr.write(t),`,
226
- `});`,
227
- `process.stdout.write(out.join(''));`,
228
- `process.exit(code);`,
229
- ].join('\n');
230
- const started = Date.now();
231
- let raw = '';
232
- let ok = false;
233
- try {
234
- raw = execFileSync('node', ['--input-type=module', '-e', driver], {
235
- encoding: 'utf8',
236
- maxBuffer: 64 * 1024 * 1024,
237
- env: {
238
- ...process.env,
239
- MIXDOG_ROOT: pluginRoot,
240
- MIXDOG_DATA_DIR: dataDir,
241
- },
242
- });
243
- ok = true;
244
- } catch (e) {
245
- raw = String(e.stdout || '') + String(e.stderr || '');
246
- ok = false;
247
- }
248
- return { sessionId: extractSessionId(raw), ok, ms: Date.now() - started, raw };
249
- }
250
-
251
- function readRows(path) {
252
- if (!existsSync(path)) return [];
253
- const rows = [];
254
- for (const line of readFileSync(path, 'utf8').split(/\r?\n/)) {
255
- if (!line) continue;
256
- try {
257
- rows.push(JSON.parse(line));
258
- } catch { /* tail */ }
259
- }
260
- return rows;
261
- }
262
-
263
- function payload(row) {
264
- return row?.payload && typeof row.payload === 'object' ? row.payload : {};
265
- }
266
-
267
- function field(row, name) {
268
- if (row && row[name] != null) return row[name];
269
- const p = payload(row);
270
- return p[name] != null ? p[name] : null;
271
- }
272
-
273
- function num(row, name) {
274
- const n = Number(field(row, name));
275
- return Number.isFinite(n) ? n : null;
276
- }
277
-
278
- function sessionId(row) {
279
- return String(row?.session_id || row?.sessionId || field(row, 'session_id') || '');
280
- }
281
-
282
- function sum(values) {
283
- return values.reduce((s, v) => s + (Number.isFinite(Number(v)) ? Number(v) : 0), 0);
284
- }
285
-
286
- function groupBy(rows, keyFn) {
287
- const map = new Map();
288
- for (const row of rows) {
289
- const key = keyFn(row);
290
- if (!key) continue;
291
- if (!map.has(key)) map.set(key, []);
292
- map.get(key).push(row);
293
- }
294
- return map;
295
- }
296
-
297
- function inferSessionMeta(rows) {
298
- const sorted = [...rows].sort((a, b) => Number(a.ts || 0) - Number(b.ts || 0));
299
- const preset = sorted.find((r) => r.kind === 'preset_assign');
300
- const usage = [...sorted].reverse().find((r) => r.kind === 'usage_raw' || r.kind === 'usage');
301
- const tool = sorted.find((r) => r.kind === 'tool');
302
- const last = sorted[sorted.length - 1] || {};
303
- const tsValues = sorted.map((r) => Number(r.ts || 0)).filter((n) => n > 0);
304
- return {
305
- session_id: sessionId(last),
306
- parent_session_id: field(preset, 'parent_session_id') || field(preset, 'parentSessionId') || null,
307
- agent: field(preset, 'agent') || field(tool, 'agent') || field(usage, 'sourceName') || field(last, 'sourceName') || null,
308
- min_ts: tsValues.length ? Math.min(...tsValues) : null,
309
- max_ts: tsValues.length ? Math.max(...tsValues) : null,
310
- };
311
- }
312
-
313
- function selectSessionFamily(sessionMetas, query) {
314
- const selected = sessionMetas.find((m) => m.session_id === query)
315
- || sessionMetas.find((m) => m.session_id.startsWith(query));
316
- if (!selected) return [];
317
- const root = selected.parent_session_id
318
- ? sessionMetas.find((m) => m.session_id === selected.parent_session_id) || selected
319
- : selected;
320
- const ids = new Set([root.session_id, selected.session_id]);
321
- for (const meta of sessionMetas) {
322
- if (meta.parent_session_id === root.session_id) ids.add(meta.session_id);
323
- }
324
- return [...ids].filter(Boolean);
325
- }
326
-
327
- function sumUsageForSession(dataDir, rootSessionId) {
328
- const tracePath = join(dataDir, 'history', 'agent-trace.jsonl');
329
- const rows = readRows(tracePath);
330
- const bySid = groupBy(rows, sessionId);
331
- const sessionMetas = [...bySid.entries()].map(([, srows]) => inferSessionMeta(srows));
332
- const family = selectSessionFamily(sessionMetas, rootSessionId);
333
- const usageRows = rows.filter((r) => r.kind === 'usage_raw' && family.includes(sessionId(r)));
334
- return {
335
- tracePath,
336
- session_ids: family,
337
- prompt_tokens: sum(usageRows.map((r) => num(r, 'prompt_tokens'))),
338
- output_tokens: sum(usageRows.map((r) => num(r, 'output_tokens'))),
339
- cached_tokens: sum(usageRows.map((r) => num(r, 'cached_tokens'))),
340
- usage_rows: usageRows.length,
341
- };
342
- }
343
-
344
- // ---- lead mode: multi-agent role-split token attribution -------------------
345
-
346
- const ROLES = ['lead', 'worker', 'reviewer', 'other'];
347
-
348
- function roleOf(agent) {
349
- const a = String(agent || '').toLowerCase();
350
- if (!a) return 'other';
351
- if (a === 'lead' || a === 'main') return 'lead';
352
- if (a.includes('review')) return 'reviewer'; // reviewer before worker (heavy-worker matches 'worker')
353
- if (a.includes('worker')) return 'worker';
354
- return 'other';
355
- }
356
-
357
- function emptyRoleBucket() {
358
- return { prompt_tokens: 0, output_tokens: 0, cached_tokens: 0, usage_rows: 0, total_tokens: 0 };
359
- }
360
-
361
- // Transitive closure over parent_session_id from the Lead root: collects the
362
- // whole Lead+children session tree (worker/reviewer sessions link back via
363
- // parent_session_id recorded on their preset_assign rows).
364
- function collectSessionTree(sessionMetas, rootSessionId) {
365
- const byParent = new Map();
366
- for (const meta of sessionMetas) {
367
- const p = meta.parent_session_id || null;
368
- if (!byParent.has(p)) byParent.set(p, []);
369
- byParent.get(p).push(meta);
370
- }
371
- const ids = new Set();
372
- const queue = [rootSessionId];
373
- while (queue.length) {
374
- const id = queue.shift();
375
- if (!id || ids.has(id)) continue;
376
- ids.add(id);
377
- for (const child of byParent.get(id) || []) queue.push(child.session_id);
378
- }
379
- return ids;
380
- }
381
-
382
- function emptyRoleSplit(dataDir) {
383
- return {
384
- tracePath: join(dataDir, 'history', 'agent-trace.jsonl'),
385
- session_ids: [],
386
- byRole: { lead: emptyRoleBucket(), worker: emptyRoleBucket(), reviewer: emptyRoleBucket(), other: emptyRoleBucket() },
387
- total: { prompt_tokens: 0, output_tokens: 0, total_tokens: 0, usage_rows: 0 },
388
- };
389
- }
390
-
391
- function mathTaskCompleted(taskCwd) {
392
- let source = '';
393
- try {
394
- source = readFileSync(join(taskCwd, 'math.js'), 'utf8');
395
- } catch {
396
- return false;
397
- }
398
- return source !== INITIAL_MATH_JS
399
- && /export\s+function\s+add\s*\(\s*a\s*,\s*b\s*\)\s*\{\s*return\s+a\s*\+\s*b\s*;?\s*\}/.test(source)
400
- && /export\s+function\s+mul\s*\(\s*a\s*,\s*b\s*\)\s*\{\s*return\s+a\s*\*\s*b\s*;?\s*\}/.test(source);
401
- }
402
-
403
- function splitTokensByRole(dataDir, rootSessionId) {
404
- const tracePath = join(dataDir, 'history', 'agent-trace.jsonl');
405
- const rows = readRows(tracePath);
406
- const bySid = groupBy(rows, sessionId);
407
- const sessionMetas = [...bySid.entries()].map(([sid, srows]) => ({ ...inferSessionMeta(srows), session_id: sid }));
408
- const treeIds = collectSessionTree(sessionMetas, rootSessionId);
409
- const roleBySession = new Map();
410
- for (const meta of sessionMetas) {
411
- if (treeIds.has(meta.session_id)) roleBySession.set(meta.session_id, roleOf(meta.agent));
412
- }
413
- // The Lead root session is created via createSession() directly (no
414
- // session-builder), so it emits no preset_assign row and inferSessionMeta
415
- // falls back to sourceName ('internal-comms-bench-lead') which roleOf() maps
416
- // to 'other'. Pin the root to 'lead' explicitly. Worker/reviewer children go
417
- // through session-builder -> traceAgentPreset, so their agent is recorded.
418
- if (treeIds.has(rootSessionId)) roleBySession.set(rootSessionId, 'lead');
419
- const byRole = { lead: emptyRoleBucket(), worker: emptyRoleBucket(), reviewer: emptyRoleBucket(), other: emptyRoleBucket() };
420
- const usageRows = rows.filter((r) => r.kind === 'usage_raw' && treeIds.has(sessionId(r)));
421
- for (const r of usageRows) {
422
- const role = roleBySession.get(sessionId(r)) || 'other';
423
- const bucket = byRole[role] || byRole.other;
424
- bucket.prompt_tokens += num(r, 'prompt_tokens') || 0;
425
- bucket.output_tokens += num(r, 'output_tokens') || 0;
426
- bucket.cached_tokens += num(r, 'cached_tokens') || 0;
427
- bucket.usage_rows += 1;
428
- }
429
- const total = { prompt_tokens: 0, output_tokens: 0, total_tokens: 0, usage_rows: 0 };
430
- for (const role of ROLES) {
431
- byRole[role].total_tokens = byRole[role].prompt_tokens + byRole[role].output_tokens;
432
- total.prompt_tokens += byRole[role].prompt_tokens;
433
- total.output_tokens += byRole[role].output_tokens;
434
- total.total_tokens += byRole[role].total_tokens;
435
- total.usage_rows += byRole[role].usage_rows;
436
- }
437
- return { tracePath, session_ids: [...treeIds], byRole, total };
438
- }
439
-
440
- export function validateLeadRun({ taskCwd, run, split }) {
441
- const reasons = [];
442
- if (!run.ok) reasons.push('child did not return a successful benchmark result');
443
- if (!mathTaskCompleted(taskCwd)) reasons.push('math.js does not contain the approved add and preserved mul implementation');
444
- if ((split?.byRole?.worker?.usage_rows || 0) < 1) reasons.push('worker participation/usage is missing');
445
- if ((split?.byRole?.reviewer?.usage_rows || 0) < 1) reasons.push('reviewer participation/usage is missing');
446
- return { valid: reasons.length === 0, reasons };
447
- }
448
-
449
- export function leadModeExitCode(runsMeta, perVariant) {
450
- const allValid = ['A', 'B'].every((variant) => runsMeta[variant].length > 0 && runsMeta[variant].every((run) => run.valid));
451
- const anyUsage = ['A', 'B'].some((variant) => perVariant[variant].some((split) => split.total.usage_rows > 0));
452
- return allValid && anyUsage ? 0 : 1;
453
- }
454
-
455
- function median(values) {
456
- const arr = values.filter((v) => Number.isFinite(v)).sort((a, b) => a - b);
457
- if (!arr.length) return 0;
458
- const mid = Math.floor(arr.length / 2);
459
- return arr.length % 2 ? arr[mid] : (arr[mid - 1] + arr[mid]) / 2;
460
- }
461
-
462
- function mean(values) {
463
- const arr = values.filter((v) => Number.isFinite(v));
464
- return arr.length ? sum(arr) / arr.length : 0;
465
- }
466
-
467
- function aggregateVariant(splits) {
468
- const out = { byRole: {}, total: {} };
469
- for (const role of ROLES) {
470
- const totals = splits.map((s) => s.byRole[role].total_tokens);
471
- out.byRole[role] = { median: median(totals), mean: mean(totals), runs: totals };
472
- }
473
- const grand = splits.map((s) => s.total.total_tokens);
474
- out.total = { median: median(grand), mean: mean(grand), runs: grand };
475
- return out;
476
- }
477
-
478
- // Drives a REAL Lead session in the variant sandbox through the public session
479
- // runtime, including its deferred standalone tool surface.
480
- // The variant rule files and public runtime modules take effect through the
481
- // sandboxed MIXDOG_ROOT.
482
- export function buildLiveLeadDriver({
483
- runtimeUrl,
484
- traceUrl = pathToFileURL(join(PLUGIN_ROOT, 'runtime/agent/orchestrator/agent-trace-io.mjs')).href,
485
- taskCwd,
486
- prompt,
487
- approvalPrompt = DEFAULT_LEAD_APPROVAL_PROMPT,
488
- provider,
489
- model,
490
- effort,
491
- fast,
492
- }) {
493
- return [
494
- `import { createMixdogSessionRuntime } from ${JSON.stringify(runtimeUrl)};`,
495
- `import { drainAgentTrace } from ${JSON.stringify(traceUrl)};`,
496
- `const rt = await createMixdogSessionRuntime({ provider: ${JSON.stringify(provider)}, model: ${JSON.stringify(model)},`,
497
- ` cwd: ${JSON.stringify(taskCwd)}, toolMode: 'full' });`,
498
- effort ? `await rt.setEffort(${JSON.stringify(effort)});` : '',
499
- fast !== undefined ? `await rt.setFast(${JSON.stringify(fast)});` : '',
500
- `const prePromptTools = rt.toolsStatus?.()?.activeTools || [];`,
501
- `if (!prePromptTools.includes('agent')) throw new Error('Lead runtime agent tool is not active');`,
502
- `let busy = false; let kickDeferred = false; let wake = null;`,
503
- `rt.onNotification(() => { queueMicrotask(() => { kickDeferred = true; if (!busy && wake) wake(); }); return false; });`,
504
- `const askOnce = async (msg) => { busy = true; try { const { result } = await rt.ask(msg); return result; } finally { busy = false; } };`,
505
- `const agentsBusy = () => { const jobs = rt.agentStatus?.()?.agentJobs || []; return jobs.some((j) => /running|pending|spawn|queued/i.test(String(j?.status || j?.state || ''))); };`,
506
- `let result; let sessionId = '';`,
507
- `try {`,
508
- ` await askOnce(${JSON.stringify(prompt)});`,
509
- ` result = await askOnce(${JSON.stringify(approvalPrompt)});`,
510
- ` const deadline = Date.now() + 30 * 60_000;`,
511
- ` while (Date.now() < deadline) {`,
512
- ` if (!kickDeferred) {`,
513
- ` if (!agentsBusy()) break;`,
514
- ` const kicked = await new Promise((resolve) => { wake = () => resolve(true); setTimeout(() => resolve(false), 10_000); });`,
515
- ` wake = null;`,
516
- ` if (!kicked && !kickDeferred && !agentsBusy()) break;`,
517
- ` }`,
518
- ` if (!kickDeferred && !agentsBusy()) break;`,
519
- ` kickDeferred = false; result = (await askOnce('')) || result;`,
520
- ` }`,
521
- ` sessionId = rt.sessionId || rt.id || rt.session?.id || '';`,
522
- `}`,
523
- `finally { try { await rt.close('internal-comms-bench-lead'); } catch {} }`,
524
- `await drainAgentTrace();`,
525
- `const benchResult = JSON.stringify({ text: String(result?.text || result?.content || '').trim(), sessionId });`,
526
- `process.stdout.write(${JSON.stringify(CHILD_RESULT_START)} + benchResult + ${JSON.stringify(CHILD_RESULT_END)} + '\\n', () => process.exit(0));`,
527
- ].filter(Boolean).join('\n');
528
- }
529
-
530
- export function parseLiveLeadResult(stdout) {
531
- const source = String(stdout || '');
532
- const start = source.lastIndexOf(CHILD_RESULT_START);
533
- if (start < 0) return null;
534
- const jsonStart = start + CHILD_RESULT_START.length;
535
- const end = source.indexOf(CHILD_RESULT_END, jsonStart);
536
- if (end < 0) return null;
537
- try {
538
- const result = JSON.parse(source.slice(jsonStart, end));
539
- return typeof result?.sessionId === 'string' && result.sessionId ? result : null;
540
- } catch {
541
- return null;
542
- }
543
- }
544
-
545
- export function runLiveLeadDelegation({
546
- pluginRoot,
547
- dataDir,
548
- taskCwd,
549
- prompt,
550
- provider,
551
- model,
552
- effort,
553
- fast,
554
- runtimeUrls = null,
555
- }) {
556
- const runtimeUrl = runtimeUrls?.runtimeUrl || pathToFileURL(join(pluginRoot, 'mixdog-session-runtime.mjs')).href;
557
- const traceUrl = runtimeUrls?.traceUrl || pathToFileURL(join(pluginRoot, 'runtime/agent/orchestrator/agent-trace-io.mjs')).href;
558
- const driver = buildLiveLeadDriver({
559
- runtimeUrl,
560
- traceUrl,
561
- taskCwd,
562
- prompt,
563
- provider,
564
- model,
565
- effort,
566
- fast,
567
- });
568
- const started = Date.now();
569
- const child = spawnSync(process.execPath, ['--input-type=module', '-e', driver], {
570
- encoding: 'utf8',
571
- maxBuffer: 64 * 1024 * 1024,
572
- env: {
573
- ...process.env,
574
- MIXDOG_ROOT: pluginRoot,
575
- MIXDOG_DATA_DIR: dataDir,
576
- },
577
- });
578
- const stdout = String(child.stdout || '');
579
- const stderr = String(child.stderr || '');
580
- const result = parseLiveLeadResult(stdout);
581
- return {
582
- sessionId: result?.sessionId || null,
583
- ms: Date.now() - started,
584
- ok: child.status === 0 && !child.error && !!result,
585
- raw: stdout + stderr,
586
- stdout,
587
- stderr,
588
- exitCode: child.status,
589
- signal: child.signal || null,
590
- error: child.error ? String(child.error.message || child.error) : null,
591
- };
592
- }
593
-
594
- function fmtDeltaEntry(entry) {
595
- const sign = entry.delta >= 0 ? '+' : '';
596
- const pct = entry.pct == null ? '' : ` (${entry.pct >= 0 ? '+' : ''}${entry.pct.toFixed(1)}%)`;
597
- return `${sign}${Math.round(entry.delta)}${pct}`;
598
- }
599
-
600
- function runLeadMode({ route, effort, fast, repeat, jsonMode, leadPrompt }) {
601
- const realDataDir = defaultUserDataDir();
602
- const userUnified = readUnifiedConfig(realDataDir);
603
- const sandboxRoot = mkdtempSync(join(REPO_ROOT, '.tmp-internal-comms-bench-lead-'));
604
- const perVariant = { A: [], B: [] };
605
- const runsMeta = { A: [], B: [] };
606
- let invalidRun = null;
607
- try {
608
- const pluginRoots = {
609
- A: materializePluginRoot('A', sandboxRoot),
610
- B: materializePluginRoot('B', sandboxRoot),
611
- };
612
- runLoop: for (let i = 0; i < repeat; i += 1) {
613
- for (const variant of ['A', 'B']) {
614
- const taskCwd = prepareTaskCwd(sandboxRoot);
615
- const dataDir = prepareDataDir(sandboxRoot, `${variant}-r${i}`, realDataDir, userUnified, route.provider);
616
- process.stderr.write(`[internal-comms-bench] lead run ${i + 1}/${repeat} variant=${variant} ${route.provider}/${route.model}\n`);
617
- const run = runLiveLeadDelegation({
618
- pluginRoot: pluginRoots[variant],
619
- dataDir,
620
- taskCwd,
621
- prompt: leadPrompt,
622
- provider: route.provider,
623
- model: route.model,
624
- effort,
625
- fast,
626
- });
627
- const split = run.sessionId ? splitTokensByRole(dataDir, run.sessionId) : emptyRoleSplit(dataDir);
628
- const validation = validateLeadRun({ taskCwd, run, split });
629
- if (validation.valid) perVariant[variant].push(split);
630
- const meta = {
631
- ok: run.ok,
632
- valid: validation.valid,
633
- reasons: validation.reasons,
634
- ms: run.ms,
635
- sessionId: run.sessionId,
636
- total: split.total.total_tokens,
637
- diagnostics: {
638
- stdout: run.stdout,
639
- stderr: run.stderr,
640
- exitCode: run.exitCode,
641
- signal: run.signal,
642
- error: run.error,
643
- },
644
- };
645
- runsMeta[variant].push(meta);
646
- process.stderr.write(`[internal-comms-bench] -> ${validation.valid ? 'ok' : 'FAIL'} ${Math.round(run.ms / 1000)}s session=${run.sessionId || '(none)'} total=${split.total.total_tokens} lead=${split.byRole.lead.total_tokens} worker=${split.byRole.worker.total_tokens} reviewer=${split.byRole.reviewer.total_tokens} other=${split.byRole.other.total_tokens}${validation.valid ? '' : ` reasons=${validation.reasons.join('; ')}`}\n`);
647
- if (!validation.valid && (run.stdout || run.stderr || run.error)) {
648
- process.stderr.write(`[internal-comms-bench] child diagnostics variant=${variant} stdout=${JSON.stringify(run.stdout)} stderr=${JSON.stringify(run.stderr)} error=${JSON.stringify(run.error)}\n`);
649
- }
650
- if (!validation.valid) {
651
- invalidRun = { variant, index: i, reasons: validation.reasons };
652
- break runLoop;
653
- }
654
- }
655
- }
656
- } finally {
657
- rmSync(sandboxRoot, { recursive: true, force: true });
658
- }
659
-
660
- if (invalidRun) {
661
- process.stderr.write(`[internal-comms-bench] aborting before aggregation: invalid variant=${invalidRun.variant} run=${invalidRun.index + 1} reasons=${invalidRun.reasons.join('; ')}\n`);
662
- process.exit(1);
663
- return;
664
- }
665
-
666
- const aggA = aggregateVariant(perVariant.A);
667
- const aggB = aggregateVariant(perVariant.B);
668
- const deltaMedian = {};
669
- const deltaMean = {};
670
- for (const role of [...ROLES, 'total']) {
671
- const aM = role === 'total' ? aggA.total.median : aggA.byRole[role].median;
672
- const bM = role === 'total' ? aggB.total.median : aggB.byRole[role].median;
673
- const aAvg = role === 'total' ? aggA.total.mean : aggA.byRole[role].mean;
674
- const bAvg = role === 'total' ? aggB.total.mean : aggB.byRole[role].mean;
675
- deltaMedian[role] = { delta: bM - aM, pct: pctChange(bM, aM) };
676
- deltaMean[role] = { delta: bAvg - aAvg, pct: pctChange(bAvg, aAvg) };
677
- }
678
-
679
- if (jsonMode) {
680
- console.log(JSON.stringify({
681
- mode: 'lead',
682
- route,
683
- repeat,
684
- prompt: leadPrompt,
685
- runs: runsMeta,
686
- variants: { A: { label: 'prior_verbose@HEAD', ...aggA }, B: { label: 'optimized_on_disk', ...aggB } },
687
- delta_B_vs_A: { median: deltaMedian, mean: deltaMean },
688
- note: 'single runs are noise-dominated; median+mean over --repeat N reduce run-to-run noise.',
689
- }, null, 2));
690
- } else {
691
- console.log(`lead-mode multi-agent ${route.provider}/${route.model} repeat=${repeat}`);
692
- console.log('NOTE: single runs are noise-dominated; use --repeat N to stabilize (median+mean shown).');
693
- for (const [id, agg] of [['A', aggA], ['B', aggB]]) {
694
- console.log(`variant ${id} (${id === 'A' ? 'prior_verbose@HEAD' : 'optimized_on_disk'}) per-role tokens median/mean over ${repeat} run(s):`);
695
- for (const role of ROLES) {
696
- const r = agg.byRole[role];
697
- console.log(` ${role.padEnd(9)} med=${Math.round(r.median)} mean=${Math.round(r.mean)}`);
698
- }
699
- console.log(` ${'total'.padEnd(9)} med=${Math.round(agg.total.median)} mean=${Math.round(agg.total.mean)}`);
700
- }
701
- console.log('delta B-vs-A (median): ' + [...ROLES, 'total'].map((r) => `${r}=${fmtDeltaEntry(deltaMedian[r])}`).join(' '));
702
- console.log('delta B-vs-A (mean): ' + [...ROLES, 'total'].map((r) => `${r}=${fmtDeltaEntry(deltaMean[r])}`).join(' '));
703
- }
704
-
705
- process.exit(leadModeExitCode(runsMeta, perVariant));
706
- }
707
-
708
- function pctChange(b, a) {
709
- if (!Number.isFinite(a) || a === 0) return null;
710
- return ((b - a) / a) * 100;
711
- }
712
-
713
- function printUsage() {
714
- process.stdout.write(`internal-comms-bench — live A/B token effect (internal-comms rules).
715
-
716
- Variant A = prior verbose rules from git: git show HEAD:src/<rule> (fallback: current file).
717
- Variant B = optimized rules: current on-disk src/ copied to temp PLUGIN_ROOT.
718
-
719
- Modes:
720
- --mode worker (default) — single worker task via runHeadlessRole (bench-run child pattern).
721
- --mode lead — REAL internal-comms flow: a live Lead session is forced to delegate
722
- one small task to a worker and then a reviewer (via the agent tool).
723
- Tokens are split BY ROLE (lead/worker/reviewer/other) across the whole
724
- Lead+children session tree, parsed from the sandbox agent-trace.jsonl.
725
-
726
- Usage:
727
- node scripts/internal-comms-bench.mjs [--json]
728
- node scripts/internal-comms-bench.mjs --run [--model grok] [--provider P] [--effort E] [--fast] [--prompt "..."] [--json]
729
- node scripts/internal-comms-bench.mjs --run --mode lead [--repeat N] [--model grok] [--provider P] [--effort E] [--fast] [--prompt "..."] [--json]
730
-
731
- --run required for live model calls. Sandboxes temp PLUGIN_ROOT + MIXDOG_DATA_DIR; copies OAuth JSON read-only from your real data dir.
732
- --mode lead measures the optimization the worker mode cannot (Lead brief + agent handoff tokens).
733
- --repeat N (default 1) runs the A/B N times and reports per-role median AND mean; single runs are noise-dominated.
734
- `);
735
- }
736
-
737
- function main() {
738
- const jsonMode = hasFlag('--json');
739
- const doRun = hasFlag('--run');
740
- const mode = String(argValue('--mode', 'worker') || 'worker').trim().toLowerCase();
741
- const repeat = Math.max(1, Number.parseInt(argValue('--repeat', '1'), 10) || 1);
742
- const prompt = argValue('--prompt', mode === 'lead' ? DEFAULT_LEAD_PROMPT : DEFAULT_WORKER_PROMPT);
743
- const cli = resolveModelOpts(argValue('--model', doRun ? 'grok' : null), argValue('--provider', null));
744
- const effort = argValue('--effort', null);
745
- const fast = hasFlag('--fast');
746
-
747
- if (!doRun) {
748
- printUsage();
749
- const ruleStats = ruleVariantBytes();
750
- const aSum = sum(ruleStats.map((r) => r.a_chars));
751
- const bSum = sum(ruleStats.map((r) => r.b_chars));
752
- if (jsonMode) {
753
- console.log(JSON.stringify({
754
- mode: 'usage',
755
- run_mode: mode,
756
- repeat,
757
- rule_files: RULE_FILES,
758
- rule_stats: ruleStats,
759
- rule_chars: { A: aSum, B: bSum },
760
- liveCommand: 'node scripts/internal-comms-bench.mjs --run --model grok',
761
- liveLeadCommand: 'node scripts/internal-comms-bench.mjs --run --mode lead --repeat 3 --model grok',
762
- }, null, 2));
763
- } else {
764
- process.stdout.write(`[internal-comms-bench] rule chars A(prior@HEAD)=${aSum} B(on-disk)=${bSum} (${RULE_FILES.length} files); mode=${mode} repeat=${repeat}\n`);
765
- }
766
- process.exit(0);
767
- }
768
-
769
- const realDataDir = defaultUserDataDir();
770
- const userUnified = readUnifiedConfig(realDataDir);
771
- const route = {
772
- provider: cli.provider || MODEL_ALIASES.grok.provider,
773
- model: cli.model || MODEL_ALIASES.grok.model,
774
- };
775
-
776
- if (mode === 'lead') {
777
- runLeadMode({ route, effort, fast, repeat, jsonMode, leadPrompt: prompt });
778
- return;
779
- }
780
-
781
- const sandboxRoot = mkdtempSync(join(REPO_ROOT, '.tmp-internal-comms-bench-'));
782
- const results = {};
783
- try {
784
- const taskCwd = prepareTaskCwd(sandboxRoot);
785
- for (const variant of ['A', 'B']) {
786
- resetTaskCwd(taskCwd);
787
- const pluginRoot = materializePluginRoot(variant, sandboxRoot);
788
- const dataDir = prepareDataDir(sandboxRoot, variant, realDataDir, userUnified, route.provider);
789
- process.stderr.write(`[internal-comms-bench] variant=${variant} ${route.provider}/${route.model}\n`);
790
- const run = runHeadlessWorker({
791
- pluginRoot,
792
- dataDir,
793
- taskCwd,
794
- prompt,
795
- provider: route.provider,
796
- model: route.model,
797
- effort,
798
- fast,
799
- });
800
- const usage = run.sessionId
801
- ? sumUsageForSession(dataDir, run.sessionId)
802
- : {
803
- session_ids: [],
804
- prompt_tokens: 0,
805
- output_tokens: 0,
806
- cached_tokens: 0,
807
- usage_rows: 0,
808
- tracePath: join(dataDir, 'history', 'agent-trace.jsonl'),
809
- };
810
- usage.total_tokens = usage.prompt_tokens + usage.output_tokens;
811
- results[variant] = { ...run, usage };
812
- process.stderr.write(`[internal-comms-bench] -> ${run.ok ? 'ok' : 'FAIL'} ${Math.round(run.ms / 1000)}s session=${run.sessionId || '(none)'} tokens=${usage.total_tokens}\n`);
813
- }
814
- } finally {
815
- rmSync(sandboxRoot, { recursive: true, force: true });
816
- }
817
-
818
- const a = results.A?.usage || {};
819
- const b = results.B?.usage || {};
820
- const delta = {
821
- prompt_tokens: (b.prompt_tokens || 0) - (a.prompt_tokens || 0),
822
- output_tokens: (b.output_tokens || 0) - (a.output_tokens || 0),
823
- total_tokens: (b.total_tokens || 0) - (a.total_tokens || 0),
824
- pct_total_B_vs_A: pctChange(b.total_tokens || 0, a.total_tokens || 0),
825
- };
826
-
827
- if (jsonMode) {
828
- console.log(JSON.stringify({
829
- mode: 'live',
830
- route,
831
- prompt,
832
- variants: {
833
- A: { label: 'prior_verbose@HEAD', run: { ok: results.A.ok, ms: results.A.ms, sessionId: results.A.sessionId }, usage: a },
834
- B: { label: 'optimized_on_disk', run: { ok: results.B.ok, ms: results.B.ms, sessionId: results.B.sessionId }, usage: b },
835
- },
836
- delta_B_vs_A: delta,
837
- }, null, 2));
838
- } else {
839
- console.log(`live worker ${route.provider}/${route.model}`);
840
- for (const id of ['A', 'B']) {
841
- const u = results[id].usage;
842
- console.log(`variant ${id}: ${results[id].ok ? 'ok' : 'FAIL'} prompt=${u.prompt_tokens} output=${u.output_tokens} total=${u.total_tokens} sessions=${(u.session_ids || []).length}`);
843
- }
844
- const pct = delta.pct_total_B_vs_A;
845
- const pctStr = pct == null ? 'n/a' : `${pct >= 0 ? '+' : ''}${pct.toFixed(1)}%`;
846
- console.log(`delta B-vs-A: prompt=${delta.prompt_tokens >= 0 ? '+' : ''}${delta.prompt_tokens} output=${delta.output_tokens >= 0 ? '+' : ''}${delta.output_tokens} total=${delta.total_tokens >= 0 ? '+' : ''}${delta.total_tokens} (${pctStr})`);
847
- }
848
-
849
- const ok = results.A?.ok && results.B?.ok && (a.usage_rows > 0 || b.usage_rows > 0);
850
- process.exit(ok ? 0 : 1);
851
- }
852
-
853
- if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main();