mixdog 1.4.1 → 1.4.3

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 (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mixdog",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Open-source coding agent that matches Codex on Terminal-Bench 2.1 with 63% fewer tokens.",
@@ -53,6 +53,7 @@
53
53
  "src/",
54
54
  "!src/tui/dev",
55
55
  "!src/**/*.test.mjs",
56
+ "!src/**/*.test-hook.mjs",
56
57
  "!src/**/*.test.jsx"
57
58
  ],
58
59
  "scripts": {
@@ -143,7 +144,7 @@
143
144
  "arm64"
144
145
  ],
145
146
  "dependencies": {
146
- "@anthropic-ai/sdk": "^0.135.0",
147
+ "@anthropic-ai/sdk": "^0.137.0",
147
148
  "@formulajs/formulajs": "^4.6.1",
148
149
  "@google/generative-ai": "^0.24.1",
149
150
  "@huggingface/transformers": "^4.3.1",
@@ -182,7 +183,7 @@
182
183
  "wrap-ansi": "^10.0.0",
183
184
  "ws": "^8.21.0",
184
185
  "yaml": "^2.9.0",
185
- "zod": "^3.25.76"
186
+ "zod": "^4.6.7"
186
187
  },
187
188
  "overrides": {
188
189
  "onnxruntime-node": {
@@ -13,7 +13,7 @@
13
13
  * node scripts/build-shipped-history.mjs --check (release workflow)
14
14
  * A shallow clone has no history: the committed file is left untouched.
15
15
  */
16
- import { execFileSync } from 'node:child_process';
16
+ import { execFileSync, spawn } from 'node:child_process';
17
17
  import { readFileSync, writeFileSync } from 'node:fs';
18
18
  import { dirname, join } from 'node:path';
19
19
  import { fileURLToPath } from 'node:url';
@@ -39,12 +39,89 @@ if (git('rev-parse', '--is-shallow-repository').toString().trim() === 'true') {
39
39
  process.exit(0);
40
40
  }
41
41
 
42
- const blobs = new Map();
43
- const blob = (sha) => {
44
- if (!blobs.has(sha)) blobs.set(sha, git('cat-file', 'blob', sha));
45
- return blobs.get(sha);
42
+ /**
43
+ * One long-lived `git cat-file --batch` answers every object read, so the whole
44
+ * history costs a single process. `read(spec)` resolves to {sha, type, body}
45
+ * or null when the object is missing.
46
+ */
47
+ const catFile = spawn('git', ['cat-file', '--batch'], { cwd: ROOT, stdio: ['pipe', 'pipe', 'inherit'] });
48
+ const waiting = [];
49
+ let pending = Buffer.alloc(0);
50
+ catFile.stdout.on('data', (chunk) => {
51
+ pending = Buffer.concat([pending, chunk]);
52
+ for (;;) {
53
+ const eol = pending.indexOf(10);
54
+ if (eol < 0) return;
55
+ const header = pending.toString('utf8', 0, eol);
56
+ if (header.endsWith(' missing')) {
57
+ pending = pending.subarray(eol + 1);
58
+ waiting.shift()(null);
59
+ continue;
60
+ }
61
+ const [sha, type, size] = header.split(' ');
62
+ const end = eol + 1 + Number(size);
63
+ if (pending.length < end + 1) return;
64
+ const body = pending.subarray(eol + 1, end);
65
+ pending = pending.subarray(end + 1);
66
+ waiting.shift()({ sha, type, body });
67
+ }
68
+ });
69
+ const read = (spec) =>
70
+ new Promise((resolve) => {
71
+ waiting.push(resolve);
72
+ catFile.stdin.write(`${spec}\n`);
73
+ });
74
+
75
+ /** Entries of a tree object body: [{ name, tree, sha }] in git (ls-tree) order. */
76
+ function parseTree(body) {
77
+ const entries = [];
78
+ for (let at = 0; at < body.length; ) {
79
+ const space = body.indexOf(32, at);
80
+ const nul = body.indexOf(0, space);
81
+ const mode = body.toString('latin1', at, space);
82
+ entries.push({
83
+ name: body.toString('utf8', space + 1, nul),
84
+ tree: mode === '40000',
85
+ sha: body.toString('hex', nul + 1, nul + 21),
86
+ });
87
+ at = nul + 21;
88
+ }
89
+ return entries;
90
+ }
91
+
92
+ const treeCache = new Map();
93
+ const blobCache = new Map();
94
+ const treeOf = async (sha) => {
95
+ if (!treeCache.has(sha))
96
+ treeCache.set(
97
+ sha,
98
+ read(sha).then(({ body }) => parseTree(body))
99
+ );
100
+ return treeCache.get(sha);
101
+ };
102
+ const blobOf = async (sha) => {
103
+ if (!blobCache.has(sha))
104
+ blobCache.set(
105
+ sha,
106
+ read(sha).then(({ body }) => body)
107
+ );
108
+ return blobCache.get(sha);
46
109
  };
47
110
 
111
+ /** Relative path -> blob sha for every file under a tree entry (a lone file keeps its own name). */
112
+ async function filesOf({ name, tree, sha }) {
113
+ if (!tree) return new Map([[name, sha]]);
114
+ const files = new Map();
115
+ const walk = async (treeSha, base) => {
116
+ for (const entry of await treeOf(treeSha)) {
117
+ if (entry.tree) await walk(entry.sha, `${base}${entry.name}/`);
118
+ else files.set(`${base}${entry.name}`, entry.sha);
119
+ }
120
+ };
121
+ await walk(sha, '');
122
+ return files;
123
+ }
124
+
48
125
  /** Names (path segment after `prefix`) that ever existed under prefix. */
49
126
  function everNames(prefix) {
50
127
  const names = new Set();
@@ -54,29 +131,39 @@ function everNames(prefix) {
54
131
  return [...names].sort();
55
132
  }
56
133
 
57
- /** Every version of `path`: Map of relative path -> blob sha, one per commit that touched it. */
58
- function versionsOf(path) {
59
- const versions = [];
60
- for (const commit of lines(git('log', '--format=%H', '--', path))) {
61
- const files = new Map();
62
- for (const row of lines(git('ls-tree', '-r', commit, '--', path))) {
63
- const [meta, file] = row.split('\t');
64
- files.set(file.slice(path.length + 1) || file.split('/').pop(), meta.split(' ')[2]);
134
+ /**
135
+ * Every distinct state `prefix/<name>` had in the commits the path-limited
136
+ * `git log -- path` lists (its history simplification decides which commits
137
+ * count). Only the object reads are batched through `cat-file`.
138
+ */
139
+ async function everVersions(prefix) {
140
+ const out = new Map();
141
+ for (const name of everNames(prefix)) {
142
+ const path = `${prefix}/${name}`;
143
+ const states = new Map();
144
+ for (const commit of lines(git('log', '--format=%H', '--', path))) {
145
+ const object = await read(`${commit}:${path}`);
146
+ if (object) states.set(object.sha, { name, tree: object.type === 'tree', sha: object.sha });
147
+ }
148
+ const versions = [];
149
+ for (const entry of states.values()) {
150
+ const files = await filesOf(entry);
151
+ if (files.size) versions.push(files);
65
152
  }
66
- if (files.size) versions.push(files);
153
+ out.set(name, versions);
67
154
  }
68
- return versions;
155
+ return out;
69
156
  }
70
-
71
157
  const unique = (hashes) => [...new Set(hashes)].sort();
72
158
 
73
- function packHistory(dir, entry) {
159
+ async function packHistory(dir, entry) {
74
160
  const out = {};
75
- for (const id of everNames(dir)) {
161
+ for (const [id, versions] of await everVersions(dir)) {
76
162
  const hashes = [];
77
- for (const files of versionsOf(`${dir}/${id}`)) {
78
- const read = (name) => (files.has(name) ? blob(files.get(name)).toString('utf8') : null);
79
- const definition = packDefinitionFrom(read, entry, id);
163
+ for (const files of versions) {
164
+ const texts = new Map();
165
+ for (const [file, sha] of files) texts.set(file, (await blobOf(sha)).toString('utf8'));
166
+ const definition = packDefinitionFrom((name) => texts.get(name) ?? null, entry, id);
80
167
  if (definition) hashes.push(hashDefinition(definition));
81
168
  }
82
169
  if (hashes.length) out[id] = unique(hashes);
@@ -84,32 +171,37 @@ function packHistory(dir, entry) {
84
171
  return out;
85
172
  }
86
173
 
87
- function outputStyleHistory() {
174
+ // Single-file definitions (output styles, orchestration modes): file name -> hashes.
175
+ async function fileHistory(prefix) {
88
176
  const out = {};
89
- for (const name of everNames('src/output-styles')) {
90
- const hashes = versionsOf(`src/output-styles/${name}`).map((files) => hashText(blob([...files.values()][0])));
177
+ for (const [name, versions] of await everVersions(prefix)) {
178
+ const hashes = [];
179
+ for (const files of versions) hashes.push(hashText(await blobOf([...files.values()][0])));
91
180
  if (hashes.length) out[name] = unique(hashes);
92
181
  }
93
182
  return out;
94
183
  }
95
184
 
96
- function skillHistory() {
185
+ async function skillHistory() {
97
186
  const out = {};
98
- for (const name of everNames('src/defaults/skills')) {
99
- const hashes = versionsOf(`src/defaults/skills/${name}`).map((files) =>
100
- hashTree([...files].map(([rel, sha]) => [rel, blob(sha)]))
101
- );
187
+ for (const [name, versions] of await everVersions('src/defaults/skills')) {
188
+ const hashes = [];
189
+ for (const files of versions) {
190
+ hashes.push(hashTree(await Promise.all([...files].map(async ([rel, sha]) => [rel, await blobOf(sha)]))));
191
+ }
102
192
  if (hashes.length) out[name] = unique(hashes);
103
193
  }
104
194
  return out;
105
195
  }
106
196
 
107
197
  const history = {
108
- agents: packHistory('src/agents', 'AGENT.md'),
109
- workflows: packHistory('src/workflows', 'WORKFLOW.md'),
110
- outputStyles: outputStyleHistory(),
111
- skills: skillHistory(),
198
+ agents: await packHistory('src/agents', 'AGENT.md'),
199
+ workflows: await packHistory('src/workflows', 'WORKFLOW.md'),
200
+ outputStyles: await fileHistory('src/output-styles'),
201
+ orchestration: await fileHistory('src/orchestration'),
202
+ skills: await skillHistory(),
112
203
  };
204
+ catFile.stdin.end();
113
205
  const text = `${JSON.stringify(history, null, 2)}\n`;
114
206
  if (CHECK) {
115
207
  let committed = '';
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  // Local pre-push check. Mirrors the test legs of .github/workflows/release-gate.yml
3
- // (jobs: runtime, runtime-slow, desktop, desktop-tests fast/slow). It MUST be
4
- // updated together with that workflow whenever those commands change.
5
- // Up front, before any build or leg, it runs two fast source checks and stops
6
- // if either fails: the gate's shipped-history job (build-shipped-history.mjs
7
- // --check; needs a full clone, a shallow one keeps the committed file), and the
8
- // released-section changelog check the desktop fast lane asserts
9
- // (changelog-locales.test.mjs; Deploy's plan adds the Unreleased section).
3
+ // (jobs: runtime, runtime-slow, desktop, desktop-tests fast/slow, shipped-history).
4
+ // It MUST be updated together with that workflow whenever those commands change.
5
+ // Up front it runs the released-section changelog check the desktop fast lane
6
+ // asserts (changelog-locales.test.mjs; Deploy's plan adds the Unreleased
7
+ // section) and stops if it fails. Everything else runs from one shared pool of
8
+ // workers (scripts/lib/gate-scheduler.mjs): every test lane is cut into shards
9
+ // of its own files (each run with the lane's own npm script command), and the
10
+ // desktop build + daemon end-to-end test, the patch smoke and the gate's
11
+ // shipped-history job (build-shipped-history.mjs --check; needs a full clone, a
12
+ // shallow one keeps the committed file) are units of the same pool. A failed
13
+ // shipped-history check stops new starts, so the gate still ends early on it.
14
+ // The whole run is at below-normal priority so the desktop stays responsive.
10
15
  // Not covered locally: runtime-macos, computer-backend (cargo + Linux X11),
11
16
  // desktop-tests `computer` lane (windows-latest, src/main/computer/ only),
12
17
  // relay (apps/relay tests), graph (cargo test), patch (cargo test of the
@@ -15,23 +20,34 @@
15
20
  // unittest). The gate's path
16
21
  // filtering is not applied: every check and leg always runs. Run `npm ci`
17
22
  // (root and apps/desktop) first.
23
+ // Usage: npm run gate:local [-- --test-concurrency=<workers>]
24
+ // (MIXDOG_TEST_CONCURRENCY also sets the pool size; default: half the cores, at most 8).
18
25
  import { spawn, spawnSync } from 'node:child_process';
19
26
  import fs from 'node:fs';
20
27
  import os from 'node:os';
21
28
  import path from 'node:path';
22
29
  import { fileURLToPath } from 'node:url';
23
- import { gateTestBudget, runGateLegs } from './lib/gate-scheduler.mjs';
30
+ import {
31
+ DEFAULT_ESTIMATE_MS,
32
+ gateTestBudget,
33
+ measuredFileTimes,
34
+ planShards,
35
+ readTimingHistory,
36
+ runPool,
37
+ saveTimingHistory,
38
+ } from './lib/gate-scheduler.mjs';
39
+ import { FULL_LOG_LABEL } from './lib/run-node-tests.mjs';
24
40
  import { pruneStaleTempDirs, removeTempDirSync } from './lib/stale-temp.mjs';
41
+ import { SUMMARY_TAG } from './lib/test-failure-summary.mjs';
25
42
 
26
43
  const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
27
44
  const started = Date.now();
45
+ const budget = gateTestBudget(process.argv.slice(2));
46
+ // Inherited by every process the gate starts (Windows and POSIX alike).
47
+ os.setPriority(os.constants.priority.PRIORITY_BELOW_NORMAL);
28
48
 
29
- const preChecks = ['node scripts/build-shipped-history.mjs --check', 'node scripts/check-changelog-locales.mjs'];
30
- const failedPreChecks = preChecks.filter(
31
- (cmd) => spawnSync(cmd, { cwd: root, stdio: 'inherit', shell: true }).status !== 0
32
- );
33
- if (failedPreChecks.length) {
34
- console.error(`[gate:local] pre-check failed: ${failedPreChecks.join('; ')}`);
49
+ if (spawnSync('node scripts/check-changelog-locales.mjs', { cwd: root, stdio: 'inherit', shell: true }).status !== 0) {
50
+ console.error('[gate:local] pre-check failed: node scripts/check-changelog-locales.mjs');
35
51
  process.exit(1);
36
52
  }
37
53
 
@@ -57,73 +73,214 @@ const RESOURCE_PREFIX = 'mixdog-gate-resources-';
57
73
  pruneStaleTempDirs([LOG_PREFIX, RESOURCE_PREFIX]);
58
74
  const logDir = fs.mkdtempSync(path.join(os.tmpdir(), LOG_PREFIX));
59
75
  const resourceDir = fs.mkdtempSync(path.join(os.tmpdir(), RESOURCE_PREFIX));
60
- const budget = gateTestBudget();
61
- // weight: relative worker share, roughly each leg's measured duration x its 3 workers
62
- // (runtime ~440s, runtime-slow ~545s, desktop fast ~390s, desktop slow ~280s).
63
- const legs = [
64
- { name: 'runtime', weight: 3, cmds: ['npm test', 'npm run smoke:patch'] },
65
- { name: 'desktop-tests-fast', weight: 3, cmds: ['npm test --prefix apps/desktop'] },
66
- { name: 'runtime-slow', weight: 4, cmds: ['npm run test:slow'] },
67
- { name: 'desktop-tests-slow', weight: 2, cmds: ['npm run test:slow --prefix apps/desktop'] },
68
- { name: 'desktop', cmds: ['npm run build --prefix apps/desktop', 'npm run test:daemon:e2e --prefix apps/desktop'] },
69
- ];
70
76
 
71
- function runCmd(cmd, logFd, concurrency) {
77
+ // Measured times live in the repository's common git dir, so every worktree
78
+ // and snapshot of the repo plans from the same history. Keys: a test file's
79
+ // repo-relative path, or `cmd:` + a command unit's commands. Timings only
80
+ // plan the run: without them (no git dir, unreadable or invalid history) the
81
+ // gate plans from default estimates.
82
+ const commonDir = spawnSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {
83
+ cwd: root,
84
+ encoding: 'utf8',
85
+ });
86
+ const historyPath = commonDir.status === 0 ? path.join(commonDir.stdout.trim(), 'mixdog-gate-timings.json') : null;
87
+ if (!historyPath) console.warn(`[gate:local] warning: no git common dir, timings not kept: ${commonDir.stderr}`);
88
+ const history = historyPath ? readTimingHistory(historyPath) : {};
89
+ const measured = {};
90
+
91
+ // Each test lane runs its package's own npm script command, given shard files
92
+ // as filters (scripts/test.mjs), without npm or a shell between: a shell's
93
+ // command line could not hold a shard's paths.
94
+ const testLanes = [
95
+ { name: 'runtime', pkg: '.', script: 'test', speed: 'fast' },
96
+ { name: 'runtime-slow', pkg: '.', script: 'test:slow', speed: 'slow' },
97
+ { name: 'desktop-tests-fast', pkg: 'apps/desktop', script: 'test', speed: 'fast' },
98
+ { name: 'desktop-tests-slow', pkg: 'apps/desktop', script: 'test:slow', speed: 'slow' },
99
+ ].map((lane) => {
100
+ const dir = path.join(root, lane.pkg);
101
+ const command = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8')).scripts[lane.script];
102
+ const [program, ...args] = command.split(/\s+/);
103
+ if (program !== 'node')
104
+ throw new Error(`${lane.pkg}/package.json "${lane.script}" must be a node command: ${command}`);
105
+ const list = spawnSync(process.execPath, [...args, '--list'], { cwd: dir, encoding: 'utf8' });
106
+ if (list.status !== 0) throw new Error(`${command} --list failed: ${list.stderr}`);
107
+ const files = list.stdout
108
+ .split(/\r?\n/)
109
+ .filter(Boolean)
110
+ .map((line) => line.replace(/^\S+\s+/, ''));
111
+ const key = (file) => path.posix.join(lane.pkg, file);
112
+ return {
113
+ ...lane,
114
+ dir,
115
+ args,
116
+ files,
117
+ key,
118
+ estimateOf: (file) => history[key(file)] ?? DEFAULT_ESTIMATE_MS[lane.speed],
119
+ };
120
+ });
121
+ const lanesByName = new Map(testLanes.map((lane) => [lane.name, lane]));
122
+ const commandUnits = [
123
+ { lane: 'shipped-history', cmds: ['node scripts/build-shipped-history.mjs --check'], stopOnFail: true },
124
+ { lane: 'runtime', cmds: ['npm run smoke:patch'] },
125
+ // Only the daemon end-to-end test reads the build (apps/desktop/out); no
126
+ // test lane does, so the build shares the pool with them.
127
+ { lane: 'desktop', cmds: ['npm run build --prefix apps/desktop', 'npm run test:daemon:e2e --prefix apps/desktop'] },
128
+ ].map((unit) => {
129
+ const key = `cmd:${unit.cmds.join(' && ')}`;
130
+ return { ...unit, key, estimate: history[key] ?? DEFAULT_ESTIMATE_MS.command };
131
+ });
132
+ const units = [...planShards(testLanes, budget), ...commandUnits];
133
+ const laneCounts = new Map();
134
+ for (const unit of units) {
135
+ laneCounts.set(unit.lane, (laneCounts.get(unit.lane) ?? 0) + 1);
136
+ unit.id = `${unit.lane}.${laneCounts.get(unit.lane)}`;
137
+ }
138
+ const laneNames = [...laneCounts.keys()];
139
+ const laneLog = (name) => path.join(logDir, `${name}.log`);
140
+
141
+ // Every unit is one worker: a shard runs its files one at a time.
142
+ const env = { ...process.env, MIXDOG_TEST_CONCURRENCY: '1', MIXDOG_TEST_OOXML_CACHE_DIR: resourceDir };
143
+ function run(command, args, options, fd) {
72
144
  return new Promise((resolve) => {
73
- fs.writeSync(logFd, `\n$ ${cmd}\n`);
74
- const child = spawn(cmd, {
75
- cwd: root,
76
- shell: true,
77
- windowsHide: true,
78
- stdio: ['ignore', logFd, logFd],
79
- env: {
80
- ...process.env,
81
- MIXDOG_TEST_CONCURRENCY: String(concurrency),
82
- MIXDOG_TEST_OOXML_CACHE_DIR: resourceDir,
83
- },
145
+ const child = spawn(command, args, { ...options, env, windowsHide: true, stdio: ['ignore', fd, fd] });
146
+ child.on('error', (error) => {
147
+ fs.writeSync(fd, `${error.stack}\n`);
148
+ resolve({ code: 1, signal: null });
84
149
  });
85
- child.on('error', () => resolve(1));
86
- child.on('close', (code) => resolve(code ?? 1));
150
+ child.on('close', (code, signal) => resolve({ code, signal }));
87
151
  });
88
152
  }
153
+ const passed = (exit) => exit.code === 0;
154
+ const ending = (exit) => (exit.signal ? `signal ${exit.signal}` : `exit code ${exit.code}`);
89
155
 
90
- async function runLeg(leg, concurrency) {
91
- const t0 = Date.now();
92
- leg.log = path.join(logDir, `${leg.name}.log`);
93
- const fd = fs.openSync(leg.log, 'w');
94
- leg.ok = true;
95
- for (const cmd of leg.cmds) {
96
- if ((await runCmd(cmd, fd, concurrency)) !== 0) {
97
- leg.ok = false;
98
- break;
156
+ // A shard's runner ends every run with its failure summary
157
+ // (scripts/lib/run-node-tests.mjs). One killed from outside (TerminateProcess,
158
+ // SIGKILL) or crashed prints nothing more, and Windows ends its node --test
159
+ // batch and test processes with it, so no reporter flushes either: name how it
160
+ // ended and what its full test log last recorded.
161
+ const DEAD_TAIL_LINES = 12;
162
+ function deadShardReport(unit, exit, output) {
163
+ if (passed(exit) || output.includes(SUMMARY_TAG)) return '';
164
+ const fullLog = output
165
+ .split(/\r?\n/)
166
+ .find((line) => line.startsWith(FULL_LOG_LABEL))
167
+ ?.slice(FULL_LOG_LABEL.length);
168
+ const tail =
169
+ fullLog && fs.existsSync(fullLog)
170
+ ? fs.readFileSync(fullLog, 'utf8').trimEnd().split(/\r?\n/).slice(-DEAD_TAIL_LINES)
171
+ : [];
172
+ return [
173
+ `${SUMMARY_TAG} RUN FAILED: ${unit.id} runner ended by ${ending(exit)} before its failure summary (killed from outside or crashed)`,
174
+ `${SUMMARY_TAG} last ${tail.length} line(s) of ${fullLog ?? 'its full test log (never named)'}:`,
175
+ ...tail.map((line) => ` ${line}`),
176
+ '',
177
+ ].join('\n');
178
+ }
179
+
180
+ const TIMING_REPORTER = new URL('./lib/gate-timing-reporter.mjs', import.meta.url).href;
181
+ async function runShard(unit, fd) {
182
+ const lane = lanesByName.get(unit.lane);
183
+ const timings = path.join(logDir, `${unit.id}.timings.jsonl`);
184
+ const args = [...lane.args, `--test-reporter=${TIMING_REPORTER}`, `--test-reporter-destination=${timings}`];
185
+ fs.writeSync(fd, `\n$ (${lane.pkg}) node ${[...args, ...unit.files].join(' ')}\n`);
186
+ const exit = await run(process.execPath, [...args, ...unit.files], { cwd: lane.dir }, fd);
187
+ const reported = Object.fromEntries(
188
+ (fs.existsSync(timings) ? fs.readFileSync(timings, 'utf8') : '')
189
+ .split('\n')
190
+ .filter(Boolean)
191
+ .map((line) => {
192
+ const { file, ms } = JSON.parse(line);
193
+ return [file, ms];
194
+ })
195
+ );
196
+ fs.rmSync(timings, { force: true });
197
+ for (const [file, ms] of Object.entries(measuredFileTimes(unit.files, reported, Date.now() - unit.start))) {
198
+ measured[lane.key(file)] = Math.round(ms);
199
+ }
200
+ return exit;
201
+ }
202
+
203
+ // The exit of the first command that failed, else of the last one.
204
+ async function runCommands(unit, fd) {
205
+ let exit = { code: 0, signal: null };
206
+ for (const cmd of unit.cmds) {
207
+ fs.writeSync(fd, `\n$ ${cmd}\n`);
208
+ exit = await run(cmd, [], { cwd: root, shell: true }, fd);
209
+ if (!passed(exit)) break;
210
+ }
211
+ measured[unit.key] = Date.now() - unit.start;
212
+ return exit;
213
+ }
214
+
215
+ let finished = 0;
216
+ async function runUnit(unit) {
217
+ const part = path.join(logDir, `${unit.id}.part.log`);
218
+ const fd = fs.openSync(part, 'w');
219
+ unit.start = Date.now();
220
+ let exit = { code: 1, signal: null };
221
+ let dead = '';
222
+ try {
223
+ exit = await (unit.files ? runShard(unit, fd) : runCommands(unit, fd));
224
+ if (unit.files) {
225
+ dead = deadShardReport(unit, exit, fs.readFileSync(part, 'utf8'));
226
+ if (dead) fs.writeSync(fd, `\n${dead}`);
99
227
  }
228
+ } finally {
229
+ fs.closeSync(fd);
230
+ unit.end = Date.now();
231
+ fs.appendFileSync(laneLog(unit.lane), fs.readFileSync(part));
232
+ fs.rmSync(part);
100
233
  }
101
- fs.closeSync(fd);
102
- leg.ms = Date.now() - t0;
234
+ const ok = passed(exit);
235
+ console.log(
236
+ `[gate:local] ${ok ? 'ok ' : 'FAIL'} ${unit.id} ${((unit.end - unit.start) / 1000).toFixed(1)}s (${++finished}/${units.length})${ok ? '' : ` ${ending(exit)}`}`
237
+ );
238
+ if (dead) process.stdout.write(dead);
239
+ return ok;
103
240
  }
104
241
 
105
- console.log(`[gate:local] build separately, then tests sharing ${budget} workers; logs: ${logDir}`);
242
+ console.log(
243
+ `[gate:local] ${units.length} units on ${budget} workers at below-normal priority; timings: ${historyPath}; logs: ${logDir}`
244
+ );
245
+ let notStarted = [];
106
246
  try {
107
- // TypeScript/bundling must not compete with four independent test runners.
108
- await runLeg(legs.at(-1), budget);
109
- await runGateLegs(legs.slice(0, -1), budget, runLeg);
247
+ notStarted = await runPool(units, budget, runUnit);
110
248
  } finally {
111
249
  removeTempDirSync(resourceDir);
250
+ // The next run plans from these; work this run did not reach keeps its old time.
251
+ const keys = [...testLanes.flatMap((lane) => lane.files.map(lane.key)), ...commandUnits.map((unit) => unit.key)];
252
+ const next = Object.fromEntries(
253
+ keys
254
+ .filter((key) => (measured[key] ?? history[key]) !== undefined)
255
+ .map((key) => [key, measured[key] ?? history[key]])
256
+ );
257
+ const saveError = historyPath && saveTimingHistory(historyPath, next);
258
+ if (saveError) console.warn(`[gate:local] warning: timings not saved (${saveError.message})`);
112
259
  }
113
260
 
114
261
  console.log('\n=== gate:local summary ===');
115
- for (const leg of legs) {
116
- console.log(`${leg.ok ? 'PASS' : 'FAIL'} ${leg.name} ${(leg.ms / 1000).toFixed(1)}s ${leg.log}`);
117
- if (!leg.ok) {
118
- const lines = fs
119
- .readFileSync(leg.log, 'utf8')
120
- .split(/\r?\n/)
121
- .filter((l) => l.includes('[failure-summary]'));
122
- for (const l of lines) console.log(` ${l}`);
123
- }
262
+ for (const name of laneNames) {
263
+ const laneUnits = units.filter((unit) => unit.lane === name);
264
+ const ran = laneUnits.filter((unit) => unit.end);
265
+ const status = ran.some((unit) => !unit.ok) ? 'FAIL' : ran.length < laneUnits.length ? 'NOT RUN' : 'PASS';
266
+ const span = ran.length ? Math.max(...ran.map((u) => u.end)) - Math.min(...ran.map((u) => u.start)) : 0;
267
+ const work = ran.reduce((sum, unit) => sum + unit.end - unit.start, 0);
268
+ console.log(
269
+ `${status} ${name} ${(span / 1000).toFixed(1)}s (${(work / 1000).toFixed(1)}s worker time, ${ran.length}/${laneUnits.length} units) ${laneLog(name)}`
270
+ );
271
+ if (status !== 'FAIL') continue;
272
+ const lines = fs
273
+ .readFileSync(laneLog(name), 'utf8')
274
+ .split(/\r?\n/)
275
+ .filter((l) => /\[failure-summary\] (?:RUN FAILED|HUNG|FAILED|FLAKY)/.test(l));
276
+ for (const l of lines) console.log(` ${l}`);
124
277
  }
278
+ if (notStarted.length)
279
+ console.log(
280
+ `Stopped after a failed ${units.find((u) => u.stopOnFail && u.ok === false).lane} check: ${notStarted.length} unit(s) not run`
281
+ );
125
282
  console.log(
126
283
  'Not covered locally: runtime-macos, computer-backend, desktop-tests computer lane (Windows-only), relay, graph, patch, browser-import, mobile-scripts'
127
284
  );
128
285
  console.log(`Total: ${((Date.now() - started) / 1000).toFixed(1)}s`);
129
- process.exit(legs.every((l) => l.ok) ? 0 : 1);
286
+ process.exit(units.every((unit) => unit.ok) ? 0 : 1);
@@ -6,6 +6,7 @@ import { readFileSync, writeFileSync } from 'node:fs';
6
6
  import { resolve } from 'node:path';
7
7
  import { performance } from 'node:perf_hooks';
8
8
  import { pathToFileURL } from 'node:url';
9
+ import { spawnTreeKill } from '../src/runtime/agent/orchestrator/mcp/child-tree.mjs';
9
10
  import { median, sortedFinite } from './lib/trace-stats.mjs';
10
11
 
11
12
  const USAGE = `usage: node scripts/graph-parity.mjs --old <binary> --new <binary> [--root <dir>] [--files <rel>...] [--json <out>] [--kind-map <path.json>] [--tokens] [--allow-new-languages <ids>] [--max-symbol-loss N] [--max-import-diff N] [--max-token-loss N] [--max-time-ratio 1.10] [--runs 3]
@@ -925,15 +926,19 @@ function reusedMetaLine(rec) {
925
926
  });
926
927
  }
927
928
 
929
+ // Windows: the shared, bounded creation-checked tree kill finds the
930
+ // descendants while the root still runs; the root, owned and alive, is then
931
+ // killed directly once that pass ends or runs out of time (spawnTreeKill).
928
932
  function killProcessTree(proc) {
933
+ if (process.platform === 'win32' && proc.pid && proc.exitCode === null && proc.signalCode === null) {
934
+ spawnTreeKill([proc.pid], { root: proc });
935
+ return;
936
+ }
929
937
  try {
930
938
  proc.kill();
931
939
  } catch {
932
940
  /* ignore */
933
941
  }
934
- if (process.platform === 'win32' && proc.pid) {
935
- spawn('taskkill', ['/pid', String(proc.pid), '/t', '/f'], { windowsHide: true, stdio: 'ignore' });
936
- }
937
942
  }
938
943
 
939
944
  export function runProcess(bin, args, { stdinText = null, timeoutMs = SPAWN_TIMEOUT_MS } = {}) {