mixdog 1.4.2 → 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 (417) hide show
  1. package/package.json +2 -2
  2. package/scripts/build-shipped-history.mjs +15 -5
  3. package/scripts/gate-local.mjs +65 -19
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +2 -1
  6. package/scripts/lib/run-node-tests.mjs +17 -5
  7. package/scripts/lib/test-failure-summary.mjs +1 -8
  8. package/scripts/lib/test-spawn-ledger.mjs +33 -2
  9. package/scripts/post-release-check.mjs +26 -16
  10. package/scripts/provider-pingpong-live.mjs +1 -1
  11. package/scripts/prune-embedding-runtime.mjs +3 -1
  12. package/scripts/release-paths.mjs +7 -1
  13. package/src/defaults/shipped-history.json +20 -0
  14. package/src/defaults/skills/setup/SKILL.md +2 -2
  15. package/src/defaults/skills/setup/references/actions.md +16 -3
  16. package/src/defaults/skills/setup/references/surfaces.md +3 -0
  17. package/src/defaults/skills/setup-guide/SKILL.md +6 -1
  18. package/src/lib/instruction-text.cjs +36 -0
  19. package/src/lib/rules-builder.cjs +34 -20
  20. package/src/orchestration/balanced.md +23 -0
  21. package/src/orchestration/focused.md +22 -0
  22. package/src/orchestration/none.md +5 -0
  23. package/src/orchestration/swarm.md +24 -0
  24. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  25. package/src/rules/agent-mode/MIXY.md +2 -2
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +0 -1
  28. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -2
  29. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +0 -9
  30. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  31. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  32. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  33. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -4
  34. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -1
  35. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +199 -46
  36. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +3 -5
  37. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +9 -3
  38. package/src/runtime/agent/orchestrator/mcp/client.mjs +3 -5
  39. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  41. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  42. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  43. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  46. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  51. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  52. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +10 -1
  53. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  54. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +30 -0
  55. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  56. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  57. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  58. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  59. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  60. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  61. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  62. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  63. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  64. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  65. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  66. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  67. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  68. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  69. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  70. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -48
  71. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  72. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  73. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  74. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +9 -0
  75. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  79. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  80. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +2 -2
  82. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  83. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  86. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  87. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  88. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  92. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +1 -2
  94. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  97. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  99. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  100. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  101. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  102. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  104. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  106. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +6 -1
  107. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  108. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  109. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +57 -26
  111. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  112. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  113. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  114. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  115. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  116. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  117. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  118. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  119. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  120. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  121. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  122. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  123. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  125. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  126. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +19 -0
  127. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +19 -10
  128. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  130. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +31 -0
  131. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  132. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +42 -6
  133. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  134. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +11 -1
  135. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  137. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  138. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  139. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  140. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +1 -1
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  143. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  145. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  146. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  148. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  149. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  150. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  151. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  152. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  153. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +14 -5
  154. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +2 -2
  155. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  156. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  157. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  158. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  159. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  160. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  161. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  162. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  163. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  164. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  165. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  166. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  167. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +7 -3
  168. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +27 -9
  169. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  170. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  172. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  173. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1 -2
  174. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  175. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  176. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  177. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  179. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  180. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  181. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  182. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +2 -2
  183. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -4
  185. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  186. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  187. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  188. package/src/runtime/attachments/store.d.mts +1 -0
  189. package/src/runtime/attachments/store.mjs +2 -2
  190. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  191. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  192. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  193. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  194. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  195. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  196. package/src/runtime/channels/lib/whisper-server.mjs +12 -12
  197. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  198. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  199. package/src/runtime/connectors/connector-accounts-mcp.mjs +169 -33
  200. package/src/runtime/connectors/gmail-app-password.mjs +2 -2
  201. package/src/runtime/connectors/google-mcp.mjs +1 -1
  202. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  203. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  204. package/src/runtime/explore/explorer.mjs +0 -5
  205. package/src/runtime/explore/tool.mjs +3 -3
  206. package/src/runtime/local-provider/hardware.mjs +1 -1
  207. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  208. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  209. package/src/runtime/media/media-usage.mjs +1 -1
  210. package/src/runtime/media/store.mjs +1 -1
  211. package/src/runtime/memory/index.mjs +11 -1
  212. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  213. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  214. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  215. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  216. package/src/runtime/memory/lib/memory.mjs +17 -0
  217. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  218. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  219. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  220. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  221. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  222. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  223. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  224. package/src/runtime/office/capabilities.mjs +1 -1
  225. package/src/runtime/office/core/office-core.mjs +1 -1
  226. package/src/runtime/office/design/content-model.mjs +3 -3
  227. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  228. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  229. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  230. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  231. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  232. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  233. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  234. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  235. package/src/runtime/shared/atomic-file.d.mts +8 -0
  236. package/src/runtime/shared/background-tasks.mjs +22 -4
  237. package/src/runtime/shared/background-wait.mjs +66 -0
  238. package/src/runtime/shared/child-guardian.mjs +17 -7
  239. package/src/runtime/shared/config.mjs +313 -16
  240. package/src/runtime/shared/connector-catalog.d.mts +4 -5
  241. package/src/runtime/shared/connector-catalog.mjs +11 -1
  242. package/src/runtime/shared/file-lock.mjs +8 -3
  243. package/src/runtime/shared/git-runner.mjs +7 -2
  244. package/src/runtime/shared/idle-gc.mjs +30 -7
  245. package/src/runtime/shared/llm/http-agent.mjs +8 -5
  246. package/src/runtime/shared/llm/system-proxy.mjs +2 -1
  247. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  248. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  249. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  250. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  251. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  252. package/src/runtime/shared/process-runner.mjs +8 -4
  253. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  254. package/src/runtime/shared/routine-trigger.mjs +34 -0
  255. package/src/runtime/shared/run-child.d.mts +2 -1
  256. package/src/runtime/shared/run-child.mjs +70 -18
  257. package/src/runtime/shared/session-scratch.mjs +14 -2
  258. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  259. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  260. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  261. package/src/runtime/shared/tool-work-units.mjs +31 -6
  262. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  263. package/src/runtime/shared/turn-worktree-snapshot.mjs +6 -11
  264. package/src/runtime/shared/worker-requests.mjs +17 -3
  265. package/src/runtime/shared/worktrees/branch-management.mjs +1 -5
  266. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  267. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  268. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  269. package/src/runtime/shared/worktrees/git.mjs +44 -11
  270. package/src/runtime/shared/worktrees/include.mjs +6 -4
  271. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  272. package/src/runtime/shared/worktrees/manager.mjs +772 -75
  273. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  274. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  275. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  276. package/src/runtime/tidy/process.mjs +2 -1
  277. package/src/runtime/web-search/index.mjs +3 -22
  278. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  279. package/src/runtime/web-search/tool-defs.mjs +17 -26
  280. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  281. package/src/session-runtime/boot/apis.mjs +27 -4
  282. package/src/session-runtime/boot/begin.mjs +2 -0
  283. package/src/session-runtime/boot/config.mjs +10 -1
  284. package/src/session-runtime/boot/facade.mjs +1 -0
  285. package/src/session-runtime/boot/providers.mjs +70 -3
  286. package/src/session-runtime/boot/session.mjs +2 -0
  287. package/src/session-runtime/boot/tools.mjs +69 -25
  288. package/src/session-runtime/channel-config-api.mjs +1 -0
  289. package/src/session-runtime/config-change-effects.mjs +179 -0
  290. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  291. package/src/session-runtime/config-lifecycle.mjs +160 -24
  292. package/src/session-runtime/conversation-import/discovery.mjs +86 -7
  293. package/src/session-runtime/conversation-import/service.mjs +3 -2
  294. package/src/session-runtime/goal-facade-api.mjs +49 -3
  295. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  296. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  297. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +3 -11
  298. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +18 -4
  299. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  300. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  301. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  302. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  303. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  304. package/src/session-runtime/lifecycle/teardown/session-close.mjs +4 -4
  305. package/src/session-runtime/lifecycle-api.mjs +1 -0
  306. package/src/session-runtime/mcp-glue/server-catalog.mjs +14 -3
  307. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  308. package/src/session-runtime/model-route/set-route.mjs +40 -7
  309. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  310. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  311. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  312. package/src/session-runtime/provider-readiness.mjs +53 -4
  313. package/src/session-runtime/resource-api.mjs +1 -1
  314. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  315. package/src/session-runtime/resource-mcp-connector-accounts.mjs +5 -1
  316. package/src/session-runtime/resource-mcp-secrets.mjs +3 -3
  317. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  318. package/src/session-runtime/routine-executor.mjs +152 -0
  319. package/src/session-runtime/routine-home-turn.mjs +46 -5
  320. package/src/session-runtime/runtime-facade.mjs +5 -0
  321. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  322. package/src/session-runtime/schedule-session-run.mjs +1 -0
  323. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  324. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  325. package/src/session-runtime/services/agent-tool/send-flow.mjs +110 -6
  326. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  327. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  328. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +24 -6
  329. package/src/session-runtime/services/agent-tool.mjs +51 -1
  330. package/src/session-runtime/services/channel-admin.mjs +18 -0
  331. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  332. package/src/session-runtime/services/plugin-admin.mjs +4 -0
  333. package/src/session-runtime/services/seeds.mjs +7 -0
  334. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  335. package/src/session-runtime/session-create/materialize.mjs +4 -2
  336. package/src/session-runtime/session-create/session-options.mjs +2 -0
  337. package/src/session-runtime/settings-builtin-tools-api.mjs +1 -9
  338. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +1 -1
  339. package/src/session-runtime/setup-tool/executor.mjs +8 -1
  340. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  341. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  342. package/src/session-runtime/setup-tool/tool-defs.mjs +26 -1
  343. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  344. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  345. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  346. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  347. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  348. package/src/session-runtime/tool-surface.mjs +38 -1
  349. package/src/session-runtime/turn/agent-ops.mjs +10 -2
  350. package/src/session-runtime/turn/session-ops.mjs +2 -0
  351. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  352. package/src/session-runtime/turn/turn-run.mjs +1 -1
  353. package/src/session-runtime/webhook-session-run.mjs +2 -0
  354. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +1 -4
  355. package/src/session-runtime/workflow-agents-api/agent-route.mjs +3 -10
  356. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  357. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  358. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  359. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  360. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  361. package/src/session-runtime/workspace/session-view.mjs +1 -1
  362. package/src/session-runtime/workspace/transitions.mjs +20 -4
  363. package/src/session-runtime/workspace/worktree-maintenance.mjs +126 -6
  364. package/src/session-runtime/workspace/worktree-setup.mjs +13 -1
  365. package/src/session-runtime/workspace/worktree-tool.mjs +16 -0
  366. package/src/standalone/daemon-agent-control.mjs +25 -8
  367. package/src/standalone/daemon-desktop-runtime.mjs +6 -2
  368. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  369. package/src/standalone/daemon.mjs +54 -2
  370. package/src/standalone/local-session-runtime.mjs +16 -0
  371. package/src/standalone/session-client/daemon-unavailable.mjs +1 -1
  372. package/src/standalone/session-protocol.mjs +11 -0
  373. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  374. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  375. package/src/standalone/session-service/quota-resume.mjs +9 -0
  376. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  377. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  378. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  379. package/src/standalone/session-service/session-calls.mjs +2 -1
  380. package/src/tui/App.jsx +8 -0
  381. package/src/tui/app/clipboard.mjs +1 -1
  382. package/src/tui/app/create-app-pickers.mjs +2 -0
  383. package/src/tui/app/doctor.mjs +2 -2
  384. package/src/tui/app/panel-signature.mjs +1 -1
  385. package/src/tui/app/settings-picker.mjs +53 -8
  386. package/src/tui/app/shell-layout/row-budgets.mjs +2 -2
  387. package/src/tui/app/slash-commands.mjs +1 -1
  388. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  389. package/src/tui/app/slash-dispatch/session-commands.mjs +1 -1
  390. package/src/tui/app/use-prompt-queue-history.mjs +2 -2
  391. package/src/tui/app/use-transcript-activity.mjs +1 -1
  392. package/src/tui/app/use-transcript-window/geometry.mjs +1 -1
  393. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  394. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  395. package/src/tui/components/question-panel-model.mjs +4 -4
  396. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  397. package/src/tui/components/user-message-skills.mjs +1 -1
  398. package/src/tui/dist/index.mjs +309 -30
  399. package/src/tui/markdown/render-ansi.mjs +1 -1
  400. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  401. package/src/tui/session/agent-job-feed.mjs +2 -0
  402. package/src/tui/session/context-state.mjs +3 -0
  403. package/src/tui/session/quota-resume.mjs +1 -1
  404. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  405. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  406. package/src/tui/session/session-api/routes-agent-definitions.mjs +5 -0
  407. package/src/tui/session/session-api/worktree.mjs +13 -1
  408. package/src/tui/session/session-flow/drain.mjs +11 -14
  409. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  410. package/src/tui/session/turn-quiet.mjs +1 -1
  411. package/src/tui/session/turn.mjs +3 -0
  412. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  413. package/src/tui/spinner-meta.mjs +3 -3
  414. package/src/tui/spinner-verbs.mjs +2 -2
  415. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  416. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  417. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -7,34 +7,56 @@
7
7
  // timeoutMs (the child is killed), EMAXBUFFER once stdout+stderr exceed
8
8
  // maxBytes, or the spawn error itself.
9
9
  import { spawn } from 'node:child_process';
10
+ import { spawnTreeKill } from '../agent/orchestrator/mcp/child-tree.mjs';
10
11
 
11
12
  /** Kills `child` with everything it started. On Windows a plain kill ends only
12
13
  * the child itself: `git` there is a launcher whose git.exe (and the alias,
13
- * hook or filter it runs) would live on, still holding the output pipes. */
14
+ * hook or filter it runs) would live on, still holding the output pipes.
15
+ * Settles once the kill was attempted (on Windows: once the tree kill finished). */
14
16
  export function killChildTree(child) {
15
17
  if (process.platform === 'win32' && child.pid && child.exitCode === null) {
16
- const taskkill = `${process.env.SystemRoot || 'C:\\Windows'}\\System32\\taskkill.exe`;
17
- const fallback = () => {
18
- try {
19
- child.kill();
20
- } catch {}
21
- };
22
- spawn(taskkill, ['/PID', String(child.pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true })
23
- .once('error', fallback)
24
- .once('exit', (code) => {
25
- if (code !== 0) fallback();
26
- });
27
- return;
18
+ // The shared pass kills `child` itself once it ends or runs out of time.
19
+ const pass = spawnTreeKill([child.pid], { root: child });
20
+ if (!pass) return Promise.resolve();
21
+ return new Promise((resolve) => {
22
+ pass.once('error', resolve).once('exit', resolve);
23
+ });
28
24
  }
29
25
  try {
30
26
  child.kill();
31
27
  } catch {}
28
+ return Promise.resolve();
32
29
  }
33
30
 
34
- export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes, stdoutEncoding = 'utf8' }) {
31
+ /** The child has exited (an exit code or the signal that ended it). */
32
+ const childEnded = (child) => child.exitCode !== null || child.signalCode !== null;
33
+
34
+ /**
35
+ * `waitForExitMs` (> 0): a timeout rejects only once the killed child has
36
+ * exited, or after that many more ms; the error then carries `pid` and
37
+ * `childExited` (false: it outlived the wait). 0 (default): the timeout
38
+ * rejects as soon as the kill was sent.
39
+ * `killTree` (default true): a timeout kills the child's whole tree. false:
40
+ * only the child, directly — for the process-table and tree-kill helpers,
41
+ * whose own tree kill would be one more pass on the same stuck table read.
42
+ */
43
+ export function runChild({
44
+ command,
45
+ args,
46
+ cwd,
47
+ input,
48
+ env,
49
+ timeoutMs,
50
+ maxBytes,
51
+ stdoutEncoding = 'utf8',
52
+ waitForExitMs = 0,
53
+ killTree = true,
54
+ // Tests only: a stand-in for child_process.spawn (in-process callers; not serializable).
55
+ spawnChild = spawn,
56
+ }) {
35
57
  return new Promise((resolvePromise, rejectPromise) => {
36
58
  const hasInput = (typeof input === 'string' || ArrayBuffer.isView(input)) && input.length > 0;
37
- const child = spawn(command, args, {
59
+ const child = spawnChild(command, args, {
38
60
  cwd,
39
61
  ...(env ? { env } : {}),
40
62
  windowsHide: true,
@@ -45,6 +67,7 @@ export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes,
45
67
  let outputBytes = 0;
46
68
  let stdinError = null;
47
69
  let settled = false;
70
+ let timedOut = false;
48
71
  const finish = (error, result) => {
49
72
  if (settled) return;
50
73
  settled = true;
@@ -52,17 +75,41 @@ export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes,
52
75
  if (error) rejectPromise(error);
53
76
  else resolvePromise(result);
54
77
  };
78
+ const exited = new Promise((resolve) => child.once('exit', resolve));
55
79
  // timeoutMs 0: no deadline (the caller's own work bounds the child).
56
80
  const timer =
57
81
  timeoutMs > 0
58
82
  ? setTimeout(() => {
59
83
  const error = new Error(`${command} ${args.join(' ')} timed out after ${timeoutMs}ms`);
60
84
  error.code = 'ETIMEDOUT';
61
- killChildTree(child);
62
- finish(error);
85
+ timedOut = true;
86
+ let killed = Promise.resolve();
87
+ if (killTree) killed = killChildTree(child);
88
+ else {
89
+ try {
90
+ child.kill();
91
+ } catch {}
92
+ }
93
+ if (!(waitForExitMs > 0)) {
94
+ finish(error);
95
+ return;
96
+ }
97
+ let bound;
98
+ const wait = new Promise((resolve) => {
99
+ bound = setTimeout(resolve, waitForExitMs);
100
+ });
101
+ void Promise.race([Promise.all([exited, killed]), wait]).then(() => {
102
+ clearTimeout(bound);
103
+ error.pid = child.pid ?? null;
104
+ error.childExited = childEnded(child);
105
+ finish(error);
106
+ });
63
107
  }, timeoutMs)
64
108
  : null;
65
109
  const collect = (chunks, chunk) => {
110
+ // Once a timeout terminates the child, it alone settles: later output
111
+ // (or an overflow) neither settles early nor grows the buffers.
112
+ if (timedOut) return;
66
113
  const next = Buffer.from(chunk);
67
114
  outputBytes += next.length;
68
115
  if (outputBytes > maxBytes) {
@@ -78,8 +125,13 @@ export function runChild({ command, args, cwd, input, env, timeoutMs, maxBytes,
78
125
  };
79
126
  child.stdout.on('data', (chunk) => collect(stdout, chunk));
80
127
  child.stderr.on('data', (chunk) => collect(stderr, chunk));
81
- child.once('error', (error) => finish(error));
128
+ child.on('error', (error) => {
129
+ // An error while a timeout terminates the child (a failed kill) is the timeout's.
130
+ if (!timedOut) finish(error);
131
+ });
82
132
  child.once('close', (code) => {
133
+ // A timed-out child's close is the timeout's to report.
134
+ if (timedOut) return;
83
135
  const result = {
84
136
  code: Number(code ?? 1),
85
137
  // 'base64' keeps non-UTF-8 bytes (a replayable patch) intact across the thread hop.
@@ -1,16 +1,25 @@
1
1
  // Per-session scratch directory under Mixdog's data directory. Processes the
2
2
  // `shell` tool starts see it as TEMP/TMP/TMPDIR, so scratch files never land in
3
3
  // the project, and it is removed with its session (session-delete.mjs).
4
+ import { createHash } from 'node:crypto';
4
5
  import { mkdirSync, rmSync } from 'node:fs';
5
6
  import { join } from 'node:path';
6
7
  import { resolvePluginData } from './plugin-paths.mjs';
7
8
 
8
9
  const SESSION_ID = /^[A-Za-z0-9_-]+$/;
9
10
 
11
+ // The folder is named by a short digest of the id, not the id itself: a desktop
12
+ // session id is 77 characters, and a TEMP that long leaves too little of
13
+ // Windows' 260-character path limit for what runs under it (Git refuses a
14
+ // $GIT_DIR over 220 characters, LibreOffice crashes on a profile past ~150).
15
+ // The "." is a character no session id has, so no id's legacy folder (named
16
+ // after the id itself) can ever be another session's digest folder.
17
+ const scratchName = (id) => `s.${createHash('sha256').update(id).digest('hex').slice(0, 16)}`;
18
+
10
19
  /** The session's scratch path (not created), or '' for an unusable id. */
11
20
  export function sessionScratchDir(sessionId) {
12
21
  const id = typeof sessionId === 'string' ? sessionId : '';
13
- return SESSION_ID.test(id) ? join(resolvePluginData(), 'scratch', id) : '';
22
+ return SESSION_ID.test(id) ? join(resolvePluginData(), 'scratch', scratchName(id)) : '';
14
23
  }
15
24
 
16
25
  /** Create the session's scratch directory if absent; returns its path ('' without a session id). */
@@ -22,7 +31,10 @@ export function ensureSessionScratchDir(sessionId) {
22
31
 
23
32
  export function removeSessionScratchDir(sessionId) {
24
33
  const dir = sessionScratchDir(sessionId);
25
- if (dir) rmSync(dir, { recursive: true, force: true });
34
+ if (!dir) return;
35
+ rmSync(dir, { recursive: true, force: true });
36
+ // Earlier versions named the folder after the full id.
37
+ rmSync(join(resolvePluginData(), 'scratch', sessionId), { recursive: true, force: true });
26
38
  }
27
39
 
28
40
  /** Point an env's temp variables at the session's scratch directory. */
@@ -9,7 +9,13 @@ import { dirname, join, relative } from 'node:path';
9
9
  import { readMarkdownDocument } from './markdown-frontmatter.mjs';
10
10
 
11
11
  export const SHIPPED_HISTORY_FILE = ['defaults', 'shipped-history.json'];
12
- export const EMPTY_HISTORY = Object.freeze({ agents: {}, workflows: {}, outputStyles: {}, skills: {} });
12
+ export const EMPTY_HISTORY = Object.freeze({
13
+ agents: {},
14
+ workflows: {},
15
+ outputStyles: {},
16
+ orchestration: {},
17
+ skills: {},
18
+ });
13
19
 
14
20
  // Leftovers from hand edits or editors that never belong to a definition.
15
21
  const IGNORABLE_STRAY = /(\.(bak|orig|tmp)|~)$/i;
@@ -513,10 +513,7 @@
513
513
  "normalizedName": "load_tool",
514
514
  "label": "Load Tools",
515
515
  "parsedArgs": {
516
- "names": [
517
- "office",
518
- "media"
519
- ]
516
+ "names": ["office", "media"]
520
517
  },
521
518
  "isShellSurface": false,
522
519
  "isSkillSurface": false,
@@ -752,10 +749,7 @@
752
749
  "normalizedName": "",
753
750
  "label": "",
754
751
  "parsedArgs": {
755
- "categoryOrder": [
756
- "read",
757
- "search"
758
- ]
752
+ "categoryOrder": ["read", "search"]
759
753
  },
760
754
  "isShellSurface": false,
761
755
  "isSkillSurface": false,
@@ -825,10 +819,7 @@
825
819
  "normalizedName": "",
826
820
  "label": "",
827
821
  "parsedArgs": {
828
- "loadingTargets": [
829
- "office",
830
- "media"
831
- ]
822
+ "loadingTargets": ["office", "media"]
832
823
  },
833
824
  "isShellSurface": false,
834
825
  "isSkillSurface": false,
@@ -193,6 +193,8 @@ const TRANSCRIPT_HIDDEN_CONTROL_TOOL_NAMES = new Set([
193
193
  'get_goal',
194
194
  'set_goal_tasks',
195
195
  'update_goal',
196
+ // The step list shows in its own composer panel, not as transcript cards.
197
+ 'todo',
196
198
  'load_tool',
197
199
  'tool_search',
198
200
  // A bot's reaction shows as its emoji under the user's message, not as a card.
@@ -420,13 +420,8 @@ function goalUnit(a) {
420
420
  const verbs = {
421
421
  status: ['Checking', 'Checked'],
422
422
  create: ['Creating', 'Created'],
423
- pause: ['Pausing', 'Paused'],
424
- resume: ['Resuming', 'Resumed'],
425
- set_tasks: ['Planning', 'Planned'],
426
- update_tasks: ['Updating', 'Updated'],
427
423
  complete: ['Completing', 'Completed'],
428
424
  block: ['Blocking', 'Blocked'],
429
- abandon: ['Abandoning', 'Abandoned'],
430
425
  }[action] || ['Updating', 'Updated'];
431
426
  return unitDescriptor('Setup', {
432
427
  count: 1,
@@ -526,6 +521,14 @@ function agentUnit(a) {
526
521
  if (/^(?:status|read|list)$/.test(type)) {
527
522
  return unitDescriptor('Agent', { count, active: 'Checking', done: 'Checked', noun: 'agent' });
528
523
  }
524
+ // Stopping an agent is not calling it, and ending a finished agent's
525
+ // session (close) is not cancelling its work.
526
+ if (type === 'cancel') {
527
+ return unitDescriptor('Agent', { count, active: 'Cancelling', done: 'Cancelled', noun: 'agent', effect: true });
528
+ }
529
+ if (type === 'close') {
530
+ return unitDescriptor('Agent', { count, active: 'Ending', done: 'Ended', noun: 'agent', effect: true });
531
+ }
529
532
  return unitDescriptor('Agent', { count, noun: 'agent' });
530
533
  }
531
534
 
@@ -628,6 +631,28 @@ function cwdUnit(a) {
628
631
  });
629
632
  }
630
633
 
634
+ /** The `session` tool: its session actions are about sessions, not the legacy
635
+ * `cwd` tool's working directory (which cwdUnit's fallback names). */
636
+ function sessionUnit(a) {
637
+ const action = String(a.action || a.type || '').toLowerCase();
638
+ if (action === 'create') {
639
+ return unitDescriptor('Setup', { active: 'Creating', done: 'Created', noun: 'session', effect: true });
640
+ }
641
+ if (action === 'send') {
642
+ return unitDescriptor('Setup', { active: 'Sending to', done: 'Sent to', noun: 'session', effect: true });
643
+ }
644
+ if (action === 'cancel') {
645
+ return unitDescriptor('Setup', { active: 'Cancelling', done: 'Cancelled', noun: 'session', effect: true });
646
+ }
647
+ if (action === 'delete') {
648
+ return unitDescriptor('Setup', { active: 'Deleting', done: 'Deleted', noun: 'session', effect: true });
649
+ }
650
+ if (/^(?:list|bots|read|suggest)$/.test(action)) {
651
+ return unitDescriptor('Setup', { active: 'Checking', done: 'Checked', noun: 'session' });
652
+ }
653
+ return cwdUnit(a);
654
+ }
655
+
631
656
  const TOOL_UNITS = new Map([
632
657
  [
633
658
  'read',
@@ -747,7 +772,7 @@ const TOOL_UNITS = new Map([
747
772
  () => unitDescriptor('Setup', { active: 'Listing', done: 'Listed', noun: 'MCP resource template' }),
748
773
  ],
749
774
  ['cwd', cwdUnit], // legacy: old transcripts
750
- ['session', cwdUnit],
775
+ ['session', sessionUnit],
751
776
  ]);
752
777
 
753
778
  function mcpUnit(name, a) {
@@ -98,6 +98,9 @@ let _writeSeq = 0;
98
98
  // `${sessionId}\0${checkpointId}` → seals in flight. A sealing turn's change
99
99
  // record is `pending` and its session refuses Undo/Reapply until it lands.
100
100
  const _pendingFreezes = new Map();
101
+ // `${sessionId}\0${checkpointId}` → getTurnChanges reads in flight. A seal of
102
+ // that checkpoint landing marks them: each may hold the record from before it.
103
+ const _changeReads = new Map();
101
104
  // Per-session Undo/Reapply chain.
102
105
  const _changeMutations = new Map();
103
106
  // `${sessionId}\0${checkpointId}` → path keys whose worktree state is unknown
@@ -1241,6 +1244,7 @@ function sealTurn(ownerSessionId, tracker) {
1241
1244
  const count = (_pendingFreezes.get(key) || 1) - 1;
1242
1245
  if (count > 0) _pendingFreezes.set(key, count);
1243
1246
  else _pendingFreezes.delete(key);
1247
+ for (const read of _changeReads.get(key) || []) read.sealLanded = true;
1244
1248
  });
1245
1249
  tracker.freezing = run;
1246
1250
  return run;
@@ -1788,9 +1792,26 @@ function requiredCheckpointId(value) {
1788
1792
  export async function getTurnChanges(sessionId, options = {}) {
1789
1793
  const ownerSessionId = clean(sessionId);
1790
1794
  const checkpointId = requiredCheckpointId(options?.checkpointId);
1791
- let record = ownerSessionId
1792
- ? withUnknownChangeStates(ownerSessionId, await loadTurnChangeRecord(ownerSessionId, checkpointId))
1793
- : null;
1795
+ // Settled only when no seal of this checkpoint was in flight at any point of
1796
+ // the record read: one in flight before or after it (a completion wake
1797
+ // reopened the turn meanwhile), or one that landed during it, answers
1798
+ // pending instead of the record from before that seal.
1799
+ const inFlight = () => Boolean(ownerSessionId) && turnChangesPending(ownerSessionId, checkpointId);
1800
+ const key = pendingFreezeKey(ownerSessionId, checkpointId);
1801
+ const read = { sealLanded: false };
1802
+ const reads = _changeReads.get(key) || new Set();
1803
+ _changeReads.set(key, reads.add(read));
1804
+ let pending = inFlight();
1805
+ let record;
1806
+ try {
1807
+ record = ownerSessionId
1808
+ ? withUnknownChangeStates(ownerSessionId, await loadTurnChangeRecord(ownerSessionId, checkpointId))
1809
+ : null;
1810
+ } finally {
1811
+ reads.delete(read);
1812
+ if (reads.size === 0 && _changeReads.get(key) === reads) _changeReads.delete(key);
1813
+ }
1814
+ pending ||= read.sealLanded || inFlight();
1794
1815
  // An old record's outside-root file kept no counts: measure it so the card
1795
1816
  // agrees with the session review and the island.
1796
1817
  if (record?.files?.length) {
@@ -1801,7 +1822,7 @@ export async function getTurnChanges(sessionId, options = {}) {
1801
1822
  };
1802
1823
  }
1803
1824
  let status = 'missing';
1804
- if (ownerSessionId && turnChangesPending(ownerSessionId, checkpointId)) status = 'pending';
1825
+ if (pending) status = 'pending';
1805
1826
  else if (record) status = record.files?.length || record.outside?.length ? 'ready' : 'none';
1806
1827
  const reply = turnChangesReply({
1807
1828
  status,
@@ -2083,6 +2104,7 @@ export function _resetTurnSnapshotForTest() {
2083
2104
  _turnsBySession.clear();
2084
2105
  _diffTrackersBySession.clear();
2085
2106
  _pendingFreezes.clear();
2107
+ _changeReads.clear();
2086
2108
  _changeMutations.clear();
2087
2109
  _unknownChangeStates.clear();
2088
2110
  _parkedWorkerReviews.clear();
@@ -268,15 +268,7 @@ async function sourceGitPath(root, suffix) {
268
268
  async function sourceGitPaths(state) {
269
269
  if (state.sourcePaths) return state.sourcePaths;
270
270
  const result = await runGit(
271
- [
272
- 'rev-parse',
273
- '--path-format=absolute',
274
- '--git-path',
275
- 'info/exclude',
276
- '--git-path',
277
- 'index',
278
- '--git-common-dir',
279
- ],
271
+ ['rev-parse', '--path-format=absolute', '--git-path', 'info/exclude', '--git-path', 'index', '--git-common-dir'],
280
272
  { cwd: state.root, allowFailure: true }
281
273
  );
282
274
  const lines = String(result.stdout || '')
@@ -695,7 +687,8 @@ async function hashBlobs(state, items, env) {
695
687
  // git ignores a symbolic-link .gitattributes, so only a regular file is carried over.
696
688
  ...[...directories].map(async (dir) => {
697
689
  const source = join(state.root, dir, '.gitattributes');
698
- if ((await lstat(source).catch(() => null))?.isFile()) await copyFile(source, join(scratch, dir, '.gitattributes'));
690
+ if ((await lstat(source).catch(() => null))?.isFile())
691
+ await copyFile(source, join(scratch, dir, '.gitattributes'));
699
692
  }),
700
693
  ]);
701
694
  const options = { cwd: scratch, env };
@@ -720,7 +713,9 @@ async function hashBlobs(state, items, env) {
720
713
  });
721
714
  const oids = hashed.stdout.split('\n').filter(Boolean);
722
715
  if (oids.length !== plain.length) throw new Error('hash-object answered a different number of blobs');
723
- plain.forEach((item, index) => ids.set(item, oids[index].trim()));
716
+ plain.forEach((item, index) => {
717
+ ids.set(item, oids[index].trim());
718
+ });
724
719
  }
725
720
  } finally {
726
721
  await rm(scratch, { recursive: true, force: true }).catch(() => {});
@@ -67,8 +67,15 @@ export function createWorkerRequestClient(url, { idleExitMs = 0, onEvent = null,
67
67
  created.unref();
68
68
  if (worker === created) armIdleTimer(created);
69
69
  }
70
- if (error) entry.reject(Object.assign(new Error(error.message), { code: error.code }));
71
- else entry.resolve(result);
70
+ if (error) {
71
+ entry.reject(
72
+ Object.assign(
73
+ new Error(error.message),
74
+ { code: error.code },
75
+ typeof error.childExited === 'boolean' ? { childExited: error.childExited, pid: error.pid } : {}
76
+ )
77
+ );
78
+ } else entry.resolve(result);
72
79
  });
73
80
  created.on('error', (error) => {
74
81
  if (worker === created) {
@@ -132,7 +139,14 @@ export function serveWorkerRequests(handler) {
132
139
  (error) =>
133
140
  parentPort.postMessage({
134
141
  id,
135
- error: { message: String(error?.message || error), code: error?.code ?? null },
142
+ error: {
143
+ message: String(error?.message || error),
144
+ code: error?.code ?? null,
145
+ // A timed-out child's fate (run-child.mjs waitForExitMs).
146
+ ...(typeof error?.childExited === 'boolean'
147
+ ? { childExited: error.childExited, pid: error.pid ?? null }
148
+ : {}),
149
+ },
136
150
  })
137
151
  );
138
152
  });
@@ -48,11 +48,7 @@ async function inspect(projectPath, branch) {
48
48
  branch,
49
49
  commit,
50
50
  target: repo.currentBranch,
51
- targetCommit: pair
52
- ? pair[1]
53
- : repo.currentBranch
54
- ? await branchCommit(repo.projectPath, repo.currentBranch)
55
- : null,
51
+ targetCommit: pair ? pair[1] : repo.currentBranch ? await branchCommit(repo.projectPath, repo.currentBranch) : null,
56
52
  path: holder?.path ?? null,
57
53
  worktreeId: entry?.id ?? null,
58
54
  kind: holder ? (samePath(holder.path, repo.topLevel) ? 'project' : entry ? 'managed' : 'external') : 'free',
@@ -14,8 +14,10 @@ import { resolvePluginData } from '../plugin-paths.mjs';
14
14
 
15
15
  /** Versioned directory under the data dir that holds every managed worktree. */
16
16
  export const WORKTREE_STORE_DIR = 'worktrees-v1';
17
- /** Default ref prefix for branches created for managed worktrees. */
18
- export const DEFAULT_WORKTREE_BRANCH_PREFIX = 'mixdog/';
17
+ /** Default ref prefix for branches created for managed worktrees: none, the
18
+ * branch is the task's name. Which branches Mixdog owns is the registry's
19
+ * record, never this prefix. */
20
+ export const DEFAULT_WORKTREE_BRANCH_PREFIX = '';
19
21
 
20
22
  export const WORKSPACE_TRANSITION_STATES = Object.freeze(['idle', 'provisioning', 'switching', 'removing', 'recovery']);
21
23
  const WORKTREE_ENTRY_STATES = Object.freeze(['creating', 'ready', 'deleting', 'recovery']);
@@ -347,13 +349,21 @@ export function normalizeWorktreeOwner(input) {
347
349
  * The branch menu's rows (the desktop DesktopGitBranch shape) for the local
348
350
  * branch names the manager lists: `current` marks the branch checked out in
349
351
  * the project folder; managed lists hold local branches only.
352
+ * `committedAt` (branch → ISO time of its tip) becomes `lastCommitAt`.
350
353
  * @param {string[]} names
351
354
  * @param {BranchOccupancy[]} occupancy
352
- * @returns {Array<{ name: string, current: boolean, remote: false, upstream: string }>}
355
+ * @param {Record<string, string>} [committedAt]
356
+ * @returns {Array<{ name: string, current: boolean, remote: false, upstream: string, lastCommitAt?: string }>}
353
357
  */
354
- export function branchMenuEntries(names, occupancy) {
358
+ export function branchMenuEntries(names, occupancy, committedAt = {}) {
355
359
  const current = new Set(occupancy.filter((row) => row.kind === 'current').map((row) => row.branch));
356
- return names.map((name) => ({ name, current: current.has(name), remote: false, upstream: '' }));
360
+ return names.map((name) => ({
361
+ name,
362
+ current: current.has(name),
363
+ remote: false,
364
+ upstream: '',
365
+ ...(committedAt[name] ? { lastCommitAt: committedAt[name] } : {}),
366
+ }));
357
367
  }
358
368
 
359
369
  // ---------------------------------------------------------------------------
@@ -416,7 +426,7 @@ export function managedWorktreePath(repoCommonDir, slug, options) {
416
426
  /**
417
427
  * @param {string} slug
418
428
  * @param {string} [prefix]
419
- * @returns {string} e.g. "mixdog/fix-login"
429
+ * @returns {string} e.g. "fix-login", or "mixdog/fix-login" with prefix "mixdog/"
420
430
  */
421
431
  export function worktreeBranchName(slug, prefix = DEFAULT_WORKTREE_BRANCH_PREFIX) {
422
432
  const error = worktreeNameError(slug);