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
@@ -11,9 +11,17 @@ export const WORKTREE_NEW_TASK_DEFAULTS = Object.freeze(['branch', 'worktree']);
11
11
  /**
12
12
  * @typedef {object} WorktreeSettings
13
13
  * @property {'branch'|'worktree'} newTaskDefault
14
- * @property {string} branchPrefix Ref prefix for created branches; ends with "/".
14
+ * @property {string} branchPrefix Ref prefix for created branches, ending with "/";
15
+ * "" (default) names the branch after the task alone.
15
16
  * @property {number} sizeWarnBytes Repository size that asks for confirmation; 0 never asks.
16
17
  * @property {boolean} autoCleanup Remove clean, merged worktrees when their session ends.
18
+ * The four settings below apply only while it is on.
19
+ * @property {number} maxWorktrees Keep at most this many managed worktrees (oldest
20
+ * activity cleaned first); 0 keeps any number.
21
+ * @property {number} unusedDays Clean up worktrees unused this many days; 0 never.
22
+ * @property {boolean} cleanupArchived Archiving a session makes its worktrees disposable.
23
+ * @property {boolean} deleteBranch Cleanup deletes the worktree's branch too (its tip
24
+ * stays under the recovery ref); off keeps the branch.
17
25
  */
18
26
 
19
27
  /** @type {Readonly<WorktreeSettings>} */
@@ -22,8 +30,15 @@ export const WORKTREE_SETTINGS_DEFAULTS = Object.freeze({
22
30
  branchPrefix: DEFAULT_WORKTREE_BRANCH_PREFIX,
23
31
  sizeWarnBytes: 2 * 1024 ** 3,
24
32
  autoCleanup: true,
33
+ maxWorktrees: 15,
34
+ unusedDays: 30,
35
+ cleanupArchived: true,
36
+ deleteBranch: false,
25
37
  });
26
38
 
39
+ const WORKTREE_MAX_WORKTREES_LIMIT = 1000;
40
+ const WORKTREE_UNUSED_DAYS_LIMIT = 3650;
41
+
27
42
  const KEYS = Object.keys(WORKTREE_SETTINGS_DEFAULTS);
28
43
  const PREFIX_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*(\/[A-Za-z0-9][A-Za-z0-9._-]*)*\/$/;
29
44
 
@@ -35,16 +50,27 @@ function fieldError(key, value) {
35
50
  ? null
36
51
  : `must be one of ${WORKTREE_NEW_TASK_DEFAULTS.join(', ')}`;
37
52
  case 'branchPrefix':
38
- return typeof value === 'string' &&
39
- value.length <= 64 &&
40
- PREFIX_PATTERN.test(value) &&
41
- !value.includes('..') &&
42
- !/\.lock\//i.test(value)
53
+ return value === '' ||
54
+ (typeof value === 'string' &&
55
+ value.length <= 64 &&
56
+ PREFIX_PATTERN.test(value) &&
57
+ !value.includes('..') &&
58
+ !/\.lock\//i.test(value))
43
59
  ? null
44
- : 'must be a ref path ending with "/", e.g. "mixdog/"';
60
+ : 'must be empty or a ref path ending with "/", e.g. "mixdog/"';
45
61
  case 'sizeWarnBytes':
46
62
  return Number.isSafeInteger(value) && value >= 0 ? null : 'must be a non-negative integer';
63
+ case 'maxWorktrees':
64
+ return Number.isSafeInteger(value) && value >= 0 && value <= WORKTREE_MAX_WORKTREES_LIMIT
65
+ ? null
66
+ : `must be an integer from 0 to ${WORKTREE_MAX_WORKTREES_LIMIT}`;
67
+ case 'unusedDays':
68
+ return Number.isSafeInteger(value) && value >= 0 && value <= WORKTREE_UNUSED_DAYS_LIMIT
69
+ ? null
70
+ : `must be an integer from 0 to ${WORKTREE_UNUSED_DAYS_LIMIT}`;
47
71
  case 'autoCleanup':
72
+ case 'cleanupArchived':
73
+ case 'deleteBranch':
48
74
  return typeof value === 'boolean' ? null : 'must be a boolean';
49
75
  default:
50
76
  return 'is not a worktree setting';
@@ -106,7 +106,11 @@ export async function createTestWorktree(projectPath, extra = {}) {
106
106
  return { entry, ...id, ...extra };
107
107
  }
108
108
 
109
- /** The repository's branches under the default managed prefix. */
109
+ /** The branch prefix the suites configure (the default is none), so their
110
+ * managed branches are told apart from the repository's own. */
111
+ export const TEST_BRANCH_PREFIX = 'mixdog/';
112
+
113
+ /** The repository's branches under TEST_BRANCH_PREFIX. */
110
114
  export function prefixedBranches(repo) {
111
115
  return git(repo, 'for-each-ref', '--format=%(refname:short)', 'refs/heads/mixdog/').split('\n').filter(Boolean);
112
116
  }
@@ -0,0 +1,82 @@
1
+ // Read-only snapshot worktrees of delegated workers (`git worktree add
2
+ // --detach` through the git tool): the worker's session holds each one, and
3
+ // it is removed when that worker's turn settles (the session runtime's
4
+ // unload), like the Lead's turn snapshots. What a removal leaves (something
5
+ // still runs there, the process ends first) is the prune's and the startup
6
+ // reconcile's: a snapshot never outlives its holder.
7
+ //
8
+ // Dependency-free at load (the manager loads on first use) and shared through
9
+ // a global symbol, so every bundle copy of this module sees one ledger.
10
+ import { randomUUID } from 'node:crypto';
11
+ import { setTimeout as delay } from 'node:timers/promises';
12
+
13
+ const STATE_KEY = Symbol.for('mixdog.workerSnapshots.v1');
14
+ const RETRY_MS = 2_000;
15
+ const RETRY_LIMIT = 5;
16
+
17
+ const loadManager = () => import('./manager.mjs');
18
+
19
+ function state() {
20
+ globalThis[STATE_KEY] ??= { runtimeToken: `worker-snapshots-${randomUUID()}`, turns: new Map() };
21
+ return globalThis[STATE_KEY];
22
+ }
23
+
24
+ /**
25
+ * A snapshot of `commit` in the repository at `projectPath`, held by worker
26
+ * session `sessionId` until its turn settles (releaseWorkerSnapshots).
27
+ * @param {{ sessionId: string, projectPath: string, commit: string, txId?: string, confirmLarge?: boolean, manager?: object }} input
28
+ */
29
+ export async function createWorkerSnapshot({
30
+ sessionId,
31
+ projectPath,
32
+ commit,
33
+ txId = '',
34
+ confirmLarge = false,
35
+ manager = null,
36
+ }) {
37
+ const id = String(sessionId || '').trim();
38
+ if (!id) throw new Error('A worker snapshot needs the worker session.');
39
+ const tx = String(txId || '').trim() || `worker-snapshot-${randomUUID()}`;
40
+ const backend = manager || (await loadManager());
41
+ const entry = await backend.createSnapshotWorktree({
42
+ projectPath,
43
+ sessionId: id,
44
+ runtimeToken: state().runtimeToken,
45
+ commit,
46
+ txId: tx,
47
+ confirmLarge: confirmLarge === true,
48
+ });
49
+ const { turns } = state();
50
+ if (!turns.has(id)) turns.set(id, new Set());
51
+ turns.get(id).add(tx);
52
+ return entry;
53
+ }
54
+
55
+ /**
56
+ * The worker's turn settled: remove the snapshots it made. One a worker or
57
+ * background shell still runs in is retried with a doubling delay a few
58
+ * times; the rest stays for the prune / startup reconcile.
59
+ * @returns {Promise<{ removed: string[], kept: object[] }>}
60
+ */
61
+ export async function releaseWorkerSnapshots(
62
+ sessionId,
63
+ { manager = null, retryMs = RETRY_MS, retryLimit = RETRY_LIMIT } = {}
64
+ ) {
65
+ const id = String(sessionId || '');
66
+ const { turns } = state();
67
+ const made = turns.get(id);
68
+ const report = { removed: [], kept: [] };
69
+ if (!made?.size) return report;
70
+ turns.delete(id);
71
+ const backend = manager || (await loadManager());
72
+ let pending = [...made];
73
+ for (let attempt = 0; pending.length && attempt < retryLimit; attempt++) {
74
+ if (attempt > 0) await delay(retryMs * 2 ** (attempt - 1), undefined, { ref: false });
75
+ const result = await backend.removeSessionSnapshots(id, { txIds: pending });
76
+ report.removed.push(...result.removed);
77
+ const inUse = result.kept.filter((row) => row.reason === 'in-use');
78
+ report.kept = result.kept;
79
+ pending = inUse.map((row) => row.txId);
80
+ }
81
+ return report;
82
+ }
@@ -4,12 +4,22 @@
4
4
  // Policy gating happens BEFORE any network call: 'never' refuses, 'ask' returns
5
5
  // needsApproval unless the call carried approveDownloads:true, 'auto' proceeds.
6
6
  // Toolchain engines (rustfmt, gofmt, zig fmt, ...) are never downloadable.
7
- import { chmodSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSync } from 'node:fs';
7
+ import {
8
+ chmodSync,
9
+ existsSync,
10
+ mkdirSync,
11
+ readFileSync,
12
+ readdirSync,
13
+ renameSync,
14
+ rmSync,
15
+ statSync,
16
+ writeFileSync,
17
+ } from 'node:fs';
8
18
  import { fileURLToPath } from 'node:url';
9
19
  import { join } from 'node:path';
10
20
  import { MAX_NATIVE_BINARY_DOWNLOAD_BYTES, streamResponseToFile } from '../shared/bounded-download.mjs';
11
- import { platformEntryKey, platformKey, sha256File } from '../shared/native-asset.mjs';
12
- import { fileHasData } from '../shared/file-has-data.mjs';
21
+ import { platformEntryKey, platformKey, sha256File, validSha256 } from '../shared/native-asset.mjs';
22
+ import { fileHasDataAsync } from '../shared/file-has-data.mjs';
13
23
  import { readJsonSafe } from '../shared/json-file.mjs';
14
24
  import { ENGINE_CATALOG } from './engines.mjs';
15
25
  import { extractArchive } from './extract.mjs';
@@ -45,14 +55,73 @@ export function manifestAsset(manifest, id, pkey = platformEntryKey(manifest?.en
45
55
  return { entry, asset, version: String(entry.version || '0'), pkey: entry?.assets?.[pkey] ? pkey : 'any' };
46
56
  }
47
57
 
48
- /** An already-installed managed binary for `id`, or null. Sync, no network. */
49
- export function managedEngineBinary({ id, manifest, pluginData }) {
58
+ // The installer records the extracted binary's sha256 beside it; a reuse
59
+ // re-hashes the binary against that record. Like the other managed binaries
60
+ // (mixdog-spawn / patch / graph resolve their path once per process), the hash
61
+ // runs once per process per binary, again only when its size or mtime changes.
62
+ // An install from before the record existed has no digest file: its first use
63
+ // records the digest (trust on first use). An existing record that is invalid
64
+ // or does not match is never overwritten; that binary is tampered or corrupt.
65
+ export const ENGINE_DIGEST_FILE = '.engine.sha256';
66
+ const verifiedEngineBins = new Map();
67
+
68
+ function recordEngineDigest(digestFile, digest) {
69
+ const tmp = `${digestFile}.tmp-${process.pid}-${Date.now()}`;
70
+ try {
71
+ writeFileSync(tmp, digest);
72
+ renameSync(tmp, digestFile);
73
+ } catch {
74
+ /* unrecorded: this install is trusted for this process only */
75
+ } finally {
76
+ try {
77
+ rmSync(tmp, { force: true });
78
+ } catch {
79
+ /* a leftover temp file never matches the digest path */
80
+ }
81
+ }
82
+ }
83
+
84
+ // The recorded digest decides whether a binary is intact. Only an install from
85
+ // before the record existed has none; there alone the content probe keeps a
86
+ // crash-torn (empty or NUL-filled) binary from becoming the digest it is
87
+ // trusted by. A binary that cannot be statted, read or hashed cannot be
88
+ // verified, so it is not reused.
89
+ async function engineBinaryIntact(dir, full) {
90
+ try {
91
+ const stamp = statSync(full);
92
+ const key = `${stamp.size}:${stamp.mtimeMs}`;
93
+ if (verifiedEngineBins.get(full) === key) return true;
94
+ const digestFile = join(dir, ENGINE_DIGEST_FILE);
95
+ let recorded = null;
96
+ try {
97
+ recorded = readFileSync(digestFile, 'utf8').trim().toLowerCase();
98
+ } catch (error) {
99
+ if (error?.code !== 'ENOENT') return false;
100
+ }
101
+ if (recorded === null && !(await fileHasDataAsync(full))) return false;
102
+ const actual = await sha256File(full);
103
+ if (recorded === null) {
104
+ recordEngineDigest(digestFile, actual);
105
+ recorded = actual;
106
+ }
107
+ if (!validSha256(recorded) || actual !== recorded) return false;
108
+ verifiedEngineBins.set(full, key);
109
+ return true;
110
+ } catch {
111
+ return false;
112
+ }
113
+ }
114
+
115
+ /** An already-installed managed binary for `id`, or null. No network; the
116
+ * binary probe is async so a slow (scanned) open never stalls the event loop. */
117
+ export async function managedEngineBinary({ id, manifest, pluginData }) {
50
118
  const found = manifestAsset(manifest, id);
51
119
  if (!found || !pluginData) return null;
52
120
  const binPath = String(found.asset.binPath || '');
53
121
  if (!binPath) return null;
54
- const full = join(managedEngineDir(pluginData, id, found.version), binPath);
55
- return fileHasData(full) ? { path: full, version: found.version } : null;
122
+ const dir = managedEngineDir(pluginData, id, found.version);
123
+ const full = join(dir, binPath);
124
+ return (await engineBinaryIntact(dir, full)) ? { path: full, version: found.version } : null;
56
125
  }
57
126
 
58
127
  /** Throws unless `filePath` hashes to `expected`. */
@@ -72,7 +141,13 @@ export async function verifyDownloadDigest(filePath, expected, label = LABEL) {
72
141
  * Decide what an install call may do, without touching the network.
73
142
  * Returns { targets, present, needsApproval, errors }.
74
143
  */
75
- export function planInstall({ ids = [], manifest, pluginData = '', policy = 'auto', approveDownloads = false } = {}) {
144
+ export async function planInstall({
145
+ ids = [],
146
+ manifest,
147
+ pluginData = '',
148
+ policy = 'auto',
149
+ approveDownloads = false,
150
+ } = {}) {
76
151
  const targets = [];
77
152
  const present = [];
78
153
  const errors = [];
@@ -101,7 +176,7 @@ export function planInstall({ ids = [], manifest, pluginData = '', policy = 'aut
101
176
  });
102
177
  continue;
103
178
  }
104
- const installed = managedEngineBinary({ id, manifest, pluginData });
179
+ const installed = await managedEngineBinary({ id, manifest, pluginData });
105
180
  if (installed) {
106
181
  present.push({ id, version: installed.version, path: installed.path });
107
182
  continue;
@@ -242,8 +317,9 @@ export async function installEngine(
242
317
  const engineRoot = join(managedToolsDir(pluginData), target.id);
243
318
  const finalDir = managedEngineDir(pluginData, target.id, target.version);
244
319
  const binFull = join(finalDir, target.binPath);
245
- // An engine binary a crash left NUL-filled is not present: it is installed again.
246
- if (fileHasData(binFull)) {
320
+ // An engine binary a crash left NUL-filled, or that no longer matches its
321
+ // recorded digest, is not present: it is installed again.
322
+ if (await engineBinaryIntact(finalDir, binFull)) {
247
323
  return { id: target.id, version: target.version, path: binFull, bytes: 0, status: 'present' };
248
324
  }
249
325
  mkdirSync(engineRoot, { recursive: true });
@@ -272,12 +348,16 @@ export async function installEngine(
272
348
  /* best-effort */
273
349
  }
274
350
  }
351
+ writeFileSync(join(stageDir, ENGINE_DIGEST_FILE), await sha256File(stagedBin));
275
352
  try {
276
- if (existsSync(finalDir) && !fileHasData(binFull)) rmSync(finalDir, { recursive: true, force: true });
353
+ if (existsSync(finalDir) && !(await engineBinaryIntact(finalDir, binFull))) {
354
+ verifiedEngineBins.delete(binFull);
355
+ rmSync(finalDir, { recursive: true, force: true });
356
+ }
277
357
  renameSync(stageDir, finalDir);
278
358
  } catch (error) {
279
- // A concurrent install won the race; its verified copy is equivalent.
280
- if (!existsSync(binFull)) throw error;
359
+ // A concurrent install won the race only if the surviving copy verifies.
360
+ if (!(await engineBinaryIntact(finalDir, binFull))) throw error;
281
361
  }
282
362
  return { id: target.id, version: target.version, path: binFull, bytes, status: 'installed' };
283
363
  } finally {
@@ -305,7 +385,7 @@ export async function installEngines({
305
385
  stallTimeoutMs = undefined,
306
386
  } = {}) {
307
387
  const loaded = manifest || readEnginesManifest();
308
- const plan = planInstall({ ids, manifest: loaded, pluginData, policy, approveDownloads });
388
+ const plan = await planInstall({ ids, manifest: loaded, pluginData, policy, approveDownloads });
309
389
  const installed = [...plan.present];
310
390
  const errors = [...plan.errors];
311
391
  if (!pluginData && plan.targets.length > 0) {
@@ -6,6 +6,7 @@
6
6
  // on the id. AUX_LANGUAGE_EXTENSIONS adds the config/markup languages the graph
7
7
  // never parses but formatters do (PowerShell, JSON, TOML, ...).
8
8
  import { extname } from 'node:path';
9
+ import { startGit } from '../shared/git-launch.mjs';
9
10
  import { runProcess } from './process.mjs';
10
11
 
11
12
  export const CODE_LANGUAGE_EXTENSIONS = Object.freeze({
@@ -156,21 +157,22 @@ export function parseGraphLangs(stdout) {
156
157
 
157
158
  /** git-tracked files under `cwd`, filtered to the requested scope paths. */
158
159
  async function listScopedFiles({ cwd, paths = [], signal = null, timeoutMs = 20_000 } = {}) {
159
- const result = await runProcess(
160
- 'git',
161
- [
162
- '-c',
163
- 'core.quotepath=false',
164
- '--literal-pathspecs',
165
- 'ls-files',
166
- '--cached',
167
- '--others',
168
- '--exclude-standard',
169
- '-z',
170
- '--',
171
- ...paths,
172
- ],
173
- { cwd, signal, timeoutMs }
160
+ const args = [
161
+ '-c',
162
+ 'core.quotepath=false',
163
+ '--literal-pathspecs',
164
+ 'ls-files',
165
+ '--cached',
166
+ '--others',
167
+ '--exclude-standard',
168
+ '-z',
169
+ '--',
170
+ ...paths,
171
+ ];
172
+ const result = await startGit(
173
+ process.env,
174
+ (command, env) => runProcess(command, args, { cwd, signal, timeoutMs, env }),
175
+ (outcome) => ({ code: outcome.errorCode })
174
176
  );
175
177
  if (result.code !== 0) {
176
178
  return {
@@ -5,6 +5,7 @@
5
5
  // parser.
6
6
  import { spawn } from 'node:child_process';
7
7
  import { existsSync, readdirSync, statSync } from 'node:fs';
8
+ import { spawnTreeKill } from '../agent/orchestrator/mcp/child-tree.mjs';
8
9
  import { delimiter, extname, isAbsolute, join } from 'node:path';
9
10
 
10
11
  const DEFAULT_PROCESS_TIMEOUT_MS = 90_000;
@@ -108,8 +109,9 @@ function captureInto(state, key, chunk, cap) {
108
109
 
109
110
  /**
110
111
  * Spawn `bin` with `args` and collect its output.
111
- * Resolves `{code, signal, stdout, stderr, timedOut, error}` — a failed spawn is
112
- * reported, never thrown, so one broken engine cannot abort the multiplexer.
112
+ * Resolves `{code, signal, stdout, stderr, timedOut, error, errorCode}` — a
113
+ * failed spawn is reported (`errorCode`: its code, e.g. ENOENT), never thrown,
114
+ * so one broken engine cannot abort the multiplexer.
113
115
  */
114
116
  export function runProcess(
115
117
  bin,
@@ -151,6 +153,7 @@ export function runProcess(
151
153
  timedOut: false,
152
154
  truncated: false,
153
155
  error: error?.message || String(error),
156
+ errorCode: error?.code || '',
154
157
  });
155
158
  return;
156
159
  }
@@ -164,7 +167,7 @@ export function runProcess(
164
167
  if (child.exitCode != null || child.signalCode != null) return;
165
168
  try {
166
169
  if (process.platform === 'win32' && child.pid) {
167
- spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], { windowsHide: true, stdio: 'ignore' });
170
+ spawnTreeKill([child.pid], { root: child });
168
171
  } else {
169
172
  child.kill('SIGKILL');
170
173
  }
@@ -209,7 +212,7 @@ export function runProcess(
209
212
 
210
213
  // One exit path for both outcomes: whoever settles first reports the
211
214
  // captured output and clears the timers.
212
- const settle = (code, exitSignal, error) => {
215
+ const settle = (code, exitSignal, error, errorCode = '') => {
213
216
  if (settled) return;
214
217
  settled = true;
215
218
  clearTimers();
@@ -221,12 +224,13 @@ export function runProcess(
221
224
  timedOut,
222
225
  truncated: Boolean(state.stdoutTruncated || state.stderrTruncated),
223
226
  error,
227
+ errorCode,
224
228
  });
225
229
  };
226
230
 
227
231
  child.stdout?.on('data', (chunk) => captureInto(state, 'stdout', chunk, cap));
228
232
  child.stderr?.on('data', (chunk) => captureInto(state, 'stderr', chunk, cap));
229
- child.on('error', (error) => settle(-1, null, error?.message || String(error)));
233
+ child.on('error', (error) => settle(-1, null, error?.message || String(error), error?.code || ''));
230
234
  if (input != null && child.stdin) {
231
235
  child.stdin.on('error', () => {
232
236
  /* child may close stdin early */
@@ -135,7 +135,7 @@ function installableFlag(entry, manifest) {
135
135
  return entry.managed && manifestAsset(manifest, entry.id) ? { installable: true } : {};
136
136
  }
137
137
 
138
- function resolveOne({ cwd, entry, config, env, manifest, pluginData, pathIndex }) {
138
+ async function resolveOne({ cwd, entry, config, env, manifest, pluginData, pathIndex }) {
139
139
  const base = {
140
140
  id: entry.id,
141
141
  kind: entry.kind,
@@ -169,7 +169,8 @@ function resolveOne({ cwd, entry, config, env, manifest, pluginData, pathIndex }
169
169
  installHint: entry.hostInstallHint || entry.installHint,
170
170
  };
171
171
  }
172
- const managed = entry.managed && pluginData ? managedEngineBinary({ id: entry.id, manifest, pluginData }) : null;
172
+ const managed =
173
+ entry.managed && pluginData ? await managedEngineBinary({ id: entry.id, manifest, pluginData }) : null;
173
174
  if (managed) {
174
175
  return {
175
176
  ...base,
@@ -194,7 +195,7 @@ function resolveOne({ cwd, entry, config, env, manifest, pluginData, pathIndex }
194
195
  const onPath = pathBinary(entry, env, pathIndex);
195
196
  if (onPath) return { ...base, source: 'path', path: onPath.path, ...commandFor(entry, onPath.path) };
196
197
  if (entry.managed && pluginData) {
197
- const managed = managedEngineBinary({ id: entry.id, manifest, pluginData });
198
+ const managed = await managedEngineBinary({ id: entry.id, manifest, pluginData });
198
199
  if (managed) {
199
200
  return {
200
201
  ...base,
@@ -282,20 +283,22 @@ export async function resolveEngines({
282
283
  else if (languages.length > 0) requested = enginesForLanguages(languages);
283
284
  const unknown = engineIds.filter((id) => !ENGINE_IDS.includes(id));
284
285
 
285
- // One listing per PATH dir for the whole batch: this runs synchronously on
286
- // the host loop (the desktop's Code Tidy status read at startup).
286
+ // One listing per PATH dir for the whole batch (the desktop's Code Tidy
287
+ // status read at startup runs this on the host loop).
287
288
  const pathIndex = createPathIndex(env);
288
- const resolved = requested.map((id) => {
289
- const entry = ENGINE_CATALOG[id];
290
- const result = resolveOne({ cwd, entry, config, env, manifest: loadedManifest, pluginData, pathIndex });
291
- const configFile = projectConfigFileFor(cwd, entry);
292
- if (configFile) result.configFile = configFile;
293
- if (entry.requiresConfig && !configFile && result.source !== 'project-config') {
294
- result.skipped = 'no project config for this engine';
295
- }
296
- if (entry.toolchain) result.toolchain = true;
297
- return result;
298
- });
289
+ const resolved = await Promise.all(
290
+ requested.map(async (id) => {
291
+ const entry = ENGINE_CATALOG[id];
292
+ const result = await resolveOne({ cwd, entry, config, env, manifest: loadedManifest, pluginData, pathIndex });
293
+ const configFile = projectConfigFileFor(cwd, entry);
294
+ if (configFile) result.configFile = configFile;
295
+ if (entry.requiresConfig && !configFile && result.source !== 'project-config') {
296
+ result.skipped = 'no project config for this engine';
297
+ }
298
+ if (entry.toolchain) result.toolchain = true;
299
+ return result;
300
+ })
301
+ );
299
302
 
300
303
  // A project driving Prettier/ESLint from node_modules/.bin keeps them: Biome
301
304
  // stands down rather than reformatting against the project's own config.
@@ -1,5 +1,4 @@
1
1
  // Biome — JSON reporter for check, `--write` (1.x: `--apply`) for fix.
2
- import { availableParallelism } from 'node:os';
3
2
  import { mapLimit, runProcess } from '../process.mjs';
4
3
  import {
5
4
  FILES_PER_SPAWN,
@@ -19,8 +18,9 @@ export const BIOME_CHECK_ARGS = ['check', '--reporter=json', '--max-diagnostics=
19
18
  export const BIOME_TRUNCATED_NOTE =
20
19
  'biome JSON output was truncated; split the scope and re-run to get complete diagnostics';
21
20
  const EXPLAIN_TIMEOUT_MS = 8_000;
22
- // One short single-rule process each; scale the fan-out with the host.
23
- const EXPLAIN_CONCURRENCY = Math.max(4, Math.ceil(availableParallelism() / 2));
21
+ // One short single-rule process each, a few at a time: the host is the
22
+ // user's working machine, so the fan-out does not grow with its core count.
23
+ const EXPLAIN_CONCURRENCY = 4;
24
24
 
25
25
  function severityOf(value) {
26
26
  const level = String(value || '').toLowerCase();
@@ -214,7 +214,7 @@ async function satisfyMissingEngines({ resolution, cwd, engineFilter, approveDow
214
214
  if (policy === 'never') return { resolution, needsApproval: null, installed: null };
215
215
  const { installEngines, planInstall } = await import('./install.mjs');
216
216
  if (policy !== 'auto' && !approveDownloads) {
217
- const plan = planInstall({
217
+ const plan = await planInstall({
218
218
  ids: installable,
219
219
  manifest: resolution.manifest,
220
220
  pluginData: resolution.pluginData,
@@ -7,6 +7,7 @@
7
7
  // already non-conforming in HEAD had to be reverted by hand. Scope still comes
8
8
  // from `paths` and nothing here derives one from a diff: the split is a report
9
9
  // the caller reads before writing, so they can pass a precise file list.
10
+ import { startGit } from '../shared/git-launch.mjs';
10
11
  import { normalizeRel } from './languages.mjs';
11
12
  import { runProcess, which } from './process.mjs';
12
13
 
@@ -44,13 +45,16 @@ export async function listWorkingTreeChanges({
44
45
  env = process.env,
45
46
  } = {}) {
46
47
  if (!which('git', { env })) return { files: null, error: '', skipped: NO_GIT_REASON };
48
+ // The git the caller's own PATH names, as the lookup above found it.
49
+ const git = (args) =>
50
+ startGit(
51
+ env,
52
+ (command, childEnv) => runProcess(command, args, { cwd, signal, timeoutMs, env: childEnv }),
53
+ (result) => ({ code: result.errorCode })
54
+ );
47
55
  const [status, prefix] = await Promise.all([
48
- runProcess(
49
- 'git',
50
- ['-c', 'core.quotepath=false', '--literal-pathspecs', 'status', '--porcelain', '-z', '--untracked-files=all'],
51
- { cwd, signal, timeoutMs, env }
52
- ),
53
- runProcess('git', ['rev-parse', '--show-prefix'], { cwd, signal, timeoutMs, env }),
56
+ git(['-c', 'core.quotepath=false', '--literal-pathspecs', 'status', '--porcelain', '-z', '--untracked-files=all']),
57
+ git(['rev-parse', '--show-prefix']),
54
58
  ]);
55
59
  const failed = [status, prefix].find((result) => result.code !== 0);
56
60
  if (failed) {
@@ -43,6 +43,9 @@ export function validateVisualizeArgs(args) {
43
43
  return { ok: false, error: 'action must be open, close, annotate, capture, export, check, or inspect' };
44
44
  const input = args.input ?? {};
45
45
  if (typeof input !== 'object' || Array.isArray(input)) return { ok: false, error: 'input must be an object' };
46
+ if (args.action === 'open' && input.verify != null && typeof input.verify !== 'boolean') {
47
+ return { ok: false, error: 'open input.verify must be a boolean' };
48
+ }
46
49
  if (args.action === 'open' && input.content != null) {
47
50
  const content = input.content;
48
51
  if (input.targets != null)
@@ -114,7 +117,7 @@ export function validateVisualizeArgs(args) {
114
117
  if (args.action === 'export') {
115
118
  if (input.format !== 'png' && input.format !== 'pdf')
116
119
  return { ok: false, error: 'export requires input.format png or pdf' };
117
- if (typeof input.output !== 'string' || !new RegExp('\\.' + input.format + '$', 'i').test(input.output.trim())) {
120
+ if (typeof input.output !== 'string' || !new RegExp(`\\.${input.format}$`, 'i').test(input.output.trim())) {
118
121
  return { ok: false, error: `export requires input.output ending in .${input.format}` };
119
122
  }
120
123
  if (input.version != null && !(Number.isInteger(input.version) && input.version >= 1)) {
@@ -10,8 +10,8 @@ export const TOOL_DEFS = [
10
10
  name: 'visualize',
11
11
  title: 'Mixdog Visualize',
12
12
  description:
13
- 'Show the user any artifact you produced or changed (mockups, docs, decks, sheets, PDFs, images, video, local dev pages) in the desktop side panel beside the chat. Panel tabs auto-reload when a file changes, so re-opening after edits is unnecessary. ' +
14
- 'open: input.targets (1-3 file paths, relative to the working directory or absolute anywhere on this machine; 2-3 = side-by-side comparison; or a single http(s) URL alone, never mixed with files or other URLs), optional label, optional version (show that kept version of a file tab read-only; each open/reload that changes the files keeps a version). close: optional tab (omit = all). ' +
13
+ 'Show the user a finished deliverable you produced or changed (mockups, docs, decks, sheets, PDFs, images, video, local dev pages) in the desktop side panel beside the chat. A summary, plan or report of your own work is not one either: it stays in the chat. Your own check screenshots are not deliverables: look at them with read; open with verify: true only to run check/inspect/capture/export. Panel tabs auto-reload when a file changes, so re-opening after edits is unnecessary. ' +
14
+ 'open: input.targets (1-3 file paths, relative to the working directory or absolute anywhere on this machine; 2-3 = side-by-side comparison; or a single http(s) URL alone, never mixed with files or other URLs), optional label, optional version (show that kept version of a file tab read-only; each open/reload that changes the files keeps a version), optional verify (true = you open only to check your own work with check/inspect/capture/export: the user is not shown the tab and it closes when the turn ends; leave it off for anything the user should see). close: optional tab (omit = all). ' +
15
15
  'annotate: tab + add [{selector,label?}] | remove [selector] | clear; HTML pages only, never edits the file. capture: tab + output (.png path). ' +
16
16
  'export: tab + format (png|pdf) + output (project-relative path ending .png/.pdf) + optional version (a kept version of the tab) + optional overwrite (true replaces an existing file, only under design/; otherwise an existing file is refused). Writes a record of the approved page inside the project and returns its project-relative path, size/dimensions and the page problems seen while rendering. A single HTML page (file, or inline html/chart) is rendered whole in a hidden window, so the tab need not be on screen (PDF: HTML pages only; PNG has a pixel cap, over it export pdf or shorten the page); any other tab exports as capture does (the displayed tab, PNG only). Same project containment as capture: links and paths outside the working directory are refused. ' +
17
17
  'check: tab; HTML pages only; waits briefly for the page to settle and returns only its runtime problems (uncaught errors, unhandled rejections, CSP violations, console errors/warnings, missing local assets). ' +
@@ -61,6 +61,11 @@ export const TOOL_DEFS = [
61
61
  description:
62
62
  'open (file tabs): kept version number to show read-only instead of the live files. export: kept version number to render instead of the live page.',
63
63
  },
64
+ verify: {
65
+ type: 'boolean',
66
+ description:
67
+ 'open (files or content): true to check your own work only; the user is not shown the tab and it closes when the turn ends.',
68
+ },
64
69
  tab: { type: 'string', description: 'Tab id from open (close: omit for all).' },
65
70
  add: {
66
71
  type: 'array',