mixdog 1.2.5 → 1.2.6

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 (290) hide show
  1. package/package.json +1 -1
  2. package/scripts/lib/gate-scheduler.mjs +2 -2
  3. package/scripts/lib/run-node-tests.mjs +5 -14
  4. package/scripts/provider-pingpong-live.mjs +9 -9
  5. package/src/agents/advisor/AGENT.md +4 -4
  6. package/src/agents/advisor/agent.json +1 -1
  7. package/src/agents/reviewer/AGENT.md +2 -3
  8. package/src/agents/reviewer/agent.json +1 -1
  9. package/src/defaults/shipped-history.json +10 -0
  10. package/src/defaults/skills/browser-use/SKILL.md +2 -1
  11. package/src/defaults/skills/computer-use/SKILL.md +3 -1
  12. package/src/defaults/skills/visualize/SKILL.md +3 -2
  13. package/src/lib/rules-builder.cjs +1 -1
  14. package/src/output-styles/common.md +22 -6
  15. package/src/output-styles/detailed.md +7 -5
  16. package/src/output-styles/minimal.md +7 -3
  17. package/src/output-styles/simple.md +2 -3
  18. package/src/rules/agent/AGENT.md +3 -1
  19. package/src/rules/lead/LEAD.md +4 -3
  20. package/src/rules/shared/10-tool-workflow.md +2 -1
  21. package/src/rules/shared/60-verification.md +4 -5
  22. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
  23. package/src/runtime/agent/orchestrator/config.mjs +6 -0
  24. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
  25. package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
  26. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
  27. package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
  28. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
  29. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
  30. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
  31. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
  32. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
  34. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
  35. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
  36. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
  37. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
  38. package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
  39. package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
  40. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
  41. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
  42. package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
  43. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
  44. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
  45. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  46. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
  47. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
  51. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
  52. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  53. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
  56. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
  57. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
  58. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
  59. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
  60. package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
  61. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
  62. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
  63. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
  64. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
  65. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
  66. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
  67. package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
  68. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
  69. package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
  70. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
  71. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
  72. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
  73. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
  74. package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
  75. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
  76. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
  77. package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
  78. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
  79. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
  80. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
  81. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
  83. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
  84. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
  85. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
  86. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
  87. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
  88. package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
  89. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
  90. package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
  91. package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
  92. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
  93. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
  94. package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
  95. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
  96. package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
  97. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
  98. package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
  99. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
  100. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
  101. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
  102. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
  103. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
  104. package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
  105. package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
  106. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
  107. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
  108. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
  109. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
  112. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
  113. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
  114. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
  115. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
  116. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
  117. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
  118. package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
  119. package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
  120. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
  121. package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
  122. package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
  123. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
  124. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
  125. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
  126. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
  128. package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
  129. package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
  130. package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
  131. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
  132. package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
  133. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
  134. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
  135. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
  136. package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
  137. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
  138. package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
  139. package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
  140. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
  141. package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
  142. package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
  143. package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
  144. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
  145. package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
  146. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  147. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
  149. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
  150. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
  151. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
  152. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
  153. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
  155. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
  156. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
  157. package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
  158. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  159. package/src/runtime/attachments/office-extract.mjs +11 -9
  160. package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
  161. package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
  162. package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
  163. package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
  164. package/src/runtime/office/core/tabular.mjs +1 -1
  165. package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
  166. package/src/runtime/office/portable/docx-formatting.mjs +1 -1
  167. package/src/runtime/office/portable/docx-runs.mjs +1 -1
  168. package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
  169. package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
  170. package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
  171. package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
  172. package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
  173. package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
  174. package/src/runtime/office/portable/portable-opc.mjs +27 -13
  175. package/src/runtime/office/portable/portable-pivot.mjs +3 -3
  176. package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
  177. package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
  178. package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
  179. package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
  180. package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
  181. package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
  182. package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
  183. package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
  184. package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
  185. package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
  186. package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
  187. package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
  188. package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
  189. package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
  190. package/src/runtime/office/portable/portable-xml.mjs +1 -1
  191. package/src/runtime/shared/atomic-file.mjs +22 -13
  192. package/src/runtime/shared/background-tasks.mjs +60 -20
  193. package/src/runtime/shared/child-spawn-gate.mjs +26 -16
  194. package/src/runtime/shared/config.mjs +0 -10
  195. package/src/runtime/shared/file-lock.mjs +7 -1
  196. package/src/runtime/shared/file-permissions-worker.mjs +38 -0
  197. package/src/runtime/shared/file-permissions.d.mts +19 -4
  198. package/src/runtime/shared/file-permissions.mjs +310 -4
  199. package/src/runtime/shared/git-runner-worker.mjs +6 -78
  200. package/src/runtime/shared/llm/http-agent.mjs +7 -3
  201. package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
  202. package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
  203. package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
  204. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
  205. package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
  206. package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
  207. package/src/runtime/shared/memory-snapshot.mjs +5 -1
  208. package/src/runtime/shared/notify-trace.mjs +8 -1
  209. package/src/runtime/shared/pristine-execution-contract.json +5 -1
  210. package/src/runtime/shared/process-runner-worker.mjs +7 -0
  211. package/src/runtime/shared/process-runner.mjs +38 -0
  212. package/src/runtime/shared/provider-accounts.mjs +2 -1
  213. package/src/runtime/shared/provider-api-key.mjs +0 -1
  214. package/src/runtime/shared/read-row-numbers.mjs +1 -1
  215. package/src/runtime/shared/resource-admission.mjs +60 -18
  216. package/src/runtime/shared/run-child.mjs +84 -0
  217. package/src/runtime/shared/session-activity-signal.mjs +23 -0
  218. package/src/runtime/shared/shell-output-summary.mjs +23 -0
  219. package/src/runtime/shared/singleton-owner.mjs +126 -42
  220. package/src/runtime/shared/tool-output-limit.mjs +4 -2
  221. package/src/runtime/shared/tool-output-marker.mjs +58 -0
  222. package/src/runtime/shared/user-data-guard.mjs +28 -9
  223. package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
  224. package/src/runtime/shared/worktrees/git-head.mjs +20 -2
  225. package/src/runtime/shared/worktrees/lock.mjs +3 -2
  226. package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
  227. package/src/runtime/tidy/runners/biome.mjs +3 -1
  228. package/src/runtime/tidy/shadow.mjs +2 -1
  229. package/src/runtime/web-search/index.mjs +5 -7
  230. package/src/runtime/web-search/lib/formatter.mjs +42 -6
  231. package/src/runtime/web-search/tool-defs.mjs +6 -1
  232. package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
  233. package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
  234. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
  235. package/src/session-runtime/lifecycle/shared.mjs +19 -2
  236. package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
  237. package/src/session-runtime/lifecycle/teardown.mjs +5 -2
  238. package/src/session-runtime/lifecycle-api.mjs +3 -1
  239. package/src/session-runtime/provider-auth/login.mjs +10 -6
  240. package/src/session-runtime/provider-auth/setup.mjs +19 -2
  241. package/src/session-runtime/provider-catalog-cache.mjs +101 -25
  242. package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
  243. package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
  244. package/src/session-runtime/provider-models.mjs +76 -10
  245. package/src/session-runtime/provider-readiness.mjs +4 -0
  246. package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
  247. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
  248. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
  249. package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
  250. package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
  251. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
  252. package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
  253. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
  254. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
  255. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
  256. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
  257. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
  258. package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
  259. package/src/session-runtime/services/agent-tool.mjs +20 -0
  260. package/src/session-runtime/services/provider-admin.mjs +92 -20
  261. package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
  262. package/src/session-runtime/services/usage-dashboard.mjs +27 -69
  263. package/src/session-runtime/turn/session-ops.mjs +2 -2
  264. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  265. package/src/session-runtime/usage-stats-api.mjs +6 -1
  266. package/src/standalone/channel-transport/http-routes.mjs +10 -9
  267. package/src/standalone/daemon-desktop-runtime.mjs +20 -7
  268. package/src/standalone/daemon-owner.mjs +117 -25
  269. package/src/standalone/daemon.mjs +43 -13
  270. package/src/standalone/session-call-cache.mjs +6 -0
  271. package/src/standalone/session-protocol.mjs +1 -1
  272. package/src/standalone/session-service/retention/busy.mjs +7 -2
  273. package/src/standalone/session-transport/routes.mjs +7 -6
  274. package/src/tui/app/model-options.mjs +39 -2
  275. package/src/tui/app/model-picker.mjs +16 -2
  276. package/src/tui/app/provider-setup-picker.mjs +1 -2
  277. package/src/tui/dist/index.mjs +385 -104
  278. package/src/tui/session/notice-text.mjs +0 -1
  279. package/src/tui/session/session-api/intake/submission.mjs +7 -13
  280. package/src/tui/session/session-api/integrations.mjs +1 -5
  281. package/src/tui/session/session-flow/drain.mjs +8 -0
  282. package/src/tui/session/session-flow/steering.mjs +46 -0
  283. package/src/tui/session/session-flow.mjs +2 -0
  284. package/src/tui/session/turn-stream.mjs +33 -0
  285. package/src/tui/session/turn.mjs +30 -3
  286. package/src/ui/statusline.mjs +1 -6
  287. package/src/ui/streaming-markdown-heal.mjs +24 -7
  288. package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
  289. package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
  290. package/src/workflows/default/WORKFLOW.md +9 -13
@@ -7,6 +7,7 @@ import {
7
7
  } from './tool-execution-contract.mjs';
8
8
  import { presentErrorText } from './err-text.mjs';
9
9
  import { clean } from './clean.mjs';
10
+ import { emitSessionActivityChange } from './session-activity-signal.mjs';
10
11
  import {
11
12
  parseTaskNotification,
12
13
  renderTaskCompletionEnvelope,
@@ -104,12 +105,17 @@ function hasScopeCriteria(scope) {
104
105
  return Boolean(scope?.callerSessionId || scope?.routingSessionId || scope?.clientHostPid);
105
106
  }
106
107
 
107
- function taskMatchesScope(task, options = {}, { includeUnattributed = true } = {}) {
108
+ function taskSessionIdOf(task) {
109
+ return task.ownerSessionId || task.notifyContext?.callerSessionId || task.notifyContext?.routingSessionId || null;
110
+ }
111
+
112
+ // `scope` is normalizeTaskScope(options), normalized once per scan by the
113
+ // caller: a scan is O(tasks), and the daemon runs one per session per
114
+ // busy-count, so per-task normalization multiplied into seconds under load.
115
+ function taskMatchesScope(task, scope, { includeUnattributed = true } = {}) {
108
116
  if (!task) return false;
109
- const scope = normalizeTaskScope(options);
110
117
  if (!hasScopeCriteria(scope)) return true;
111
- const taskSessionId =
112
- task.ownerSessionId || task.notifyContext?.callerSessionId || task.notifyContext?.routingSessionId || null;
118
+ const taskSessionId = taskSessionIdOf(task);
113
119
  const taskClientHostPid = task.clientHostPid || task.notifyContext?.clientHostPid || null;
114
120
  // Legacy/unattributed tasks remain visible so old async jobs are still recoverable.
115
121
  if (!taskSessionId && !taskClientHostPid) return includeUnattributed;
@@ -127,11 +133,13 @@ function pruneTasks(options = {}) {
127
133
  const { force = false, surface } = options;
128
134
  const now = Date.now();
129
135
  const wanted = clean(surface);
130
- for (const [taskId, task] of [...tasks.entries()]) {
136
+ const scope = normalizeTaskScope(options);
137
+ // Deleting the entry being visited is safe during Map iteration.
138
+ for (const [taskId, task] of tasks) {
131
139
  if (wanted && task.surface !== wanted) continue;
132
- if (!taskMatchesScope(task, options)) continue;
133
140
  const finishedAt = task.finishedAtMs || 0;
134
- if (force || (finishedAt > 0 && now - finishedAt > TASK_TTL_MS)) tasks.delete(taskId);
141
+ if (!force && !(finishedAt > 0 && now - finishedAt > TASK_TTL_MS)) continue;
142
+ if (taskMatchesScope(task, scope)) tasks.delete(taskId);
135
143
  }
136
144
  if (tasks.size <= MAX_TASKS) return;
137
145
  const removable = [...tasks.values()]
@@ -197,6 +205,7 @@ export function registerBackgroundTask({
197
205
  notifyOnCancel: notifyOnCancel === true,
198
206
  };
199
207
  tasks.set(id, task);
208
+ emitSessionActivityChange(task.ownerSessionId || '');
200
209
  return task;
201
210
  }
202
211
 
@@ -230,38 +239,64 @@ export function getBackgroundTask(taskId, options = {}) {
230
239
  if (!task) return null;
231
240
  const wanted = clean(options.surface);
232
241
  if (wanted && task.surface !== wanted) return null;
233
- if (!taskMatchesScope(task, options)) return null;
242
+ if (!taskMatchesScope(task, normalizeTaskScope(options))) return null;
234
243
  return task;
235
244
  }
236
245
 
246
+ function countsAsActive(task, wanted, awaitedOnly) {
247
+ return task.status === 'running' && !(awaitedOnly && task.detached === true) && (!wanted || task.surface === wanted);
248
+ }
249
+
237
250
  /** Lifetime signal: a session-owned background task remains live
238
- * work even while the interactive turn is idle and every view is detached. */
251
+ * work even while the interactive turn is idle and every view is detached.
252
+ * `awaitedOnly` leaves out `detached` tasks: processes a finished command
253
+ * deliberately left running (an app or server it launched), which nothing is
254
+ * waiting on and which may outlive the session's work by days.
255
+ * A read: pruning only ever drops finished tasks, which never count here. */
239
256
  export function hasActiveBackgroundTasks(options = {}) {
240
- pruneTasks(options);
241
257
  const wanted = clean(options.surface);
242
- return [...tasks.values()].some(
243
- (task) =>
244
- task.status === 'running' &&
245
- (!wanted || task.surface === wanted) &&
246
- taskMatchesScope(task, options, { includeUnattributed: false })
247
- );
258
+ const awaitedOnly = options.awaitedOnly === true;
259
+ const scope = normalizeTaskScope(options);
260
+ for (const task of tasks.values()) {
261
+ if (countsAsActive(task, wanted, awaitedOnly) && taskMatchesScope(task, scope, { includeUnattributed: false })) {
262
+ return true;
263
+ }
264
+ }
265
+ return false;
266
+ }
267
+
268
+ /** Every owner session `hasActiveBackgroundTasks({ callerSessionId, surface,
269
+ * awaitedOnly })` answers true for, from ONE pass over the tasks: a caller
270
+ * asking for every session (busy counts, pool rows) scans once instead of
271
+ * once per session. */
272
+ export function activeBackgroundTaskSessionIds(options = {}) {
273
+ const wanted = clean(options.surface);
274
+ const awaitedOnly = options.awaitedOnly === true;
275
+ const ids = new Set();
276
+ for (const task of tasks.values()) {
277
+ if (!countsAsActive(task, wanted, awaitedOnly)) continue;
278
+ const sessionId = taskSessionIdOf(task);
279
+ if (sessionId) ids.add(sessionId);
280
+ }
281
+ return ids;
248
282
  }
249
283
 
250
284
  export function listBackgroundTasks(options = {}) {
251
285
  const { surface } = options;
252
286
  pruneTasks(options);
253
287
  const wanted = clean(surface);
288
+ const scope = normalizeTaskScope(options);
254
289
  return [...tasks.values()]
255
290
  .filter((task) => !wanted || task.surface === wanted)
256
- .filter((task) => taskMatchesScope(task, options))
291
+ .filter((task) => taskMatchesScope(task, scope))
257
292
  .map((task) => taskSummary(task));
258
293
  }
259
294
 
260
295
  export function cleanupBackgroundTasks(options = {}) {
261
296
  const wanted = clean(options.surface);
297
+ const scope = normalizeTaskScope(options);
262
298
  const countForSurface = () =>
263
- [...tasks.values()].filter((task) => (!wanted || task.surface === wanted) && taskMatchesScope(task, options))
264
- .length;
299
+ [...tasks.values()].filter((task) => (!wanted || task.surface === wanted) && taskMatchesScope(task, scope)).length;
265
300
  const before = countForSurface();
266
301
  pruneTasks(options);
267
302
  const after = countForSurface();
@@ -331,6 +366,7 @@ export function cancelBackgroundTasks(options = {}) {
331
366
  const reason = clean(options.reason) || 'cancelled';
332
367
  const wanted = clean(options.surface);
333
368
  const executionSessionId = clean(options.executionSessionId);
369
+ const scope = normalizeTaskScope(options);
334
370
  let cancelled = 0;
335
371
  for (const task of [...tasks.values()]) {
336
372
  if (wanted && task.surface !== wanted) continue;
@@ -341,7 +377,7 @@ export function cancelBackgroundTasks(options = {}) {
341
377
  // Delegated work executes in its bound session; before binding it still
342
378
  // belongs to the registering session. Notification ownership is separate.
343
379
  if ((clean(task.meta?.sessionId) || task.ownerSessionId) !== executionSessionId) continue;
344
- } else if (!taskMatchesScope(task, options, { includeUnattributed: false })) continue;
380
+ } else if (!taskMatchesScope(task, scope, { includeUnattributed: false })) continue;
345
381
  if (TERMINAL_STATUSES.has(task.status)) {
346
382
  if (options.notify === false) silenceCancelledNotification(task);
347
383
  continue;
@@ -413,6 +449,7 @@ export function completeBackgroundTask(
413
449
  if (error != null) task.error = presentErrorText(error, { surface: task.surface });
414
450
  if (resultType) task.resultType = resultType;
415
451
  if (instruction) task.notificationInstruction = compactText(instruction, 1_000);
452
+ emitSessionActivityChange(task.ownerSessionId || '');
416
453
  if (notify) {
417
454
  task.meta = sanitizeTaskMeta(task.meta);
418
455
  notifyTaskCompletion(task, instruction);
@@ -522,6 +559,9 @@ export function renderBackgroundTaskNotification(task) {
522
559
  : resultTextForTask(task);
523
560
  if (task.surface === 'shell') {
524
561
  const parsed = parseTaskNotification(result);
562
+ // The completion envelope already carries the result (exit code,
563
+ // duration, output or its summary): deliver it as is.
564
+ if (parsed?.result) return result;
525
565
  return renderShellCompletionNotice({
526
566
  jobId: task.taskId,
527
567
  status: task.status,
@@ -1,4 +1,4 @@
1
- import { availableParallelism } from 'node:os';
1
+ import { availableParallelism, totalmem } from 'node:os';
2
2
  import { createOwnerFairGate } from './owner-fair-gate.mjs';
3
3
  import { currentToolExecutionOwner } from './tool-execution-owner.mjs';
4
4
  import { positiveInt } from './numbers.mjs';
@@ -9,8 +9,9 @@ import { positiveInt } from './numbers.mjs';
9
9
  // singleton semaphore CAN bound the number of concurrent child processes (rg,
10
10
  // mixdog-graph, …) across ALL agents/workers in this daemon.
11
11
  //
12
- // Default: Windows search scales conservatively from 1..4 with CPU count;
13
- // code-graph remains 1. Other platforms are unbounded. Windows measurements
12
+ // Default: Windows search and code-graph-query scale 2..8 with CPU count;
13
+ // code-graph builds 1..4 with cores and memory. Other platforms bound search
14
+ // only. Windows measurements
14
15
  // showed both extremes are poor: cap 1 creates multi-session queue latency,
15
16
  // while unbounded multithreaded rg amplifies Defender/process-scan and disk
16
17
  // contention. Separate lanes isolate short search from long graph builds.
@@ -28,7 +29,8 @@ function resolveDefaultChildSpawnLaneMaxInflight(
28
29
  laneName,
29
30
  env = process.env,
30
31
  platform = process.platform,
31
- parallelism = availableParallelism()
32
+ parallelism = availableParallelism(),
33
+ memoryBytes = totalmem()
32
34
  ) {
33
35
  const lane = _laneName(laneName);
34
36
  const laneOverride = positiveInt(env[`MIXDOG_CHILD_SPAWN_${_laneEnvKey(lane)}_MAX_INFLIGHT`]);
@@ -45,13 +47,19 @@ function resolveDefaultChildSpawnLaneMaxInflight(
45
47
  // Slots are held only across the spawn itself, so a small cap smooths the
46
48
  // AV convoy without limiting how many commands run concurrently.
47
49
  if (lane === 'process-spawn') return Math.max(2, Math.min(4, Math.floor(cpus / 6) || 2));
48
- // One cold graph build saturates memory/disk; allow a second only on big hosts.
49
- if (lane === 'code-graph') return cpus >= 12 ? 2 : 1;
50
- if (lane !== 'search') return 1;
51
- // Multiple rg processes beat one under multi-session load, but each process
52
- // is itself threaded and Defender amplifies excess fan-out. Burst stress
53
- // measured cap-4 starvation (find p50 15s at 8 concurrent sessions), so
54
- // scale with cores and cap at eight: 4→2, 8→3, 12→4, 18→6, 24+→8.
50
+ // Graph builds (Worker thread + native walk/parse) hold a slot for seconds
51
+ // and are memory-heavy: one per 4 cores and per 4 GiB, 1..4. Builds of one
52
+ // repo are already single-flight (build.mjs); distinct repos are independent.
53
+ if (lane === 'code-graph') {
54
+ const memGb = Math.floor((Number(memoryBytes) || 0) / 1024 ** 3);
55
+ return Math.max(1, Math.min(4, Math.floor(cpus / 4), Math.floor(memGb / 4)));
56
+ }
57
+ if (lane !== 'search' && lane !== 'code-graph-query') return 1;
58
+ // Short read-only walks: rg, and the graph binary's `--manifest` that
59
+ // validates a cached graph. Multiple processes beat one under multi-session
60
+ // load, but each is itself threaded and Defender amplifies excess fan-out.
61
+ // Burst stress measured cap-4 starvation (find p50 15s at 8 concurrent
62
+ // sessions), so scale with cores and cap at eight: 4→2, 8→3, 12→4, 18→6, 24+→8.
55
63
  return Math.max(2, Math.min(8, Math.ceil(cpus / 3)));
56
64
  }
57
65
 
@@ -87,11 +95,13 @@ function _laneSetting(name, suffix, fallback) {
87
95
  // ── Lanes ────────────────────────────────────────────────────────────────
88
96
  // Independent optional limits and queues:
89
97
  // 'search' — short-lived rg processes.
90
- // 'code-graph' — long-lived graph workers / native graph binaries. A cold
91
- // graph build can hold its slot for seconds-to-minutes; a
92
- // single shared lane would let one build
93
- // stall every rg spawn behind it. Separate lanes remove that
94
- // starvation class while keeping each spawn family bounded.
98
+ // 'code-graph' — long-lived graph build workers. A cold build can hold its
99
+ // slot for seconds-to-minutes; a single shared lane would let
100
+ // one build stall every rg spawn behind it. Separate lanes
101
+ // remove that starvation class while keeping each spawn
102
+ // family bounded.
103
+ // 'code-graph-query' — the short read-only manifest walk that validates
104
+ // a cached graph, so queries never wait behind builds.
95
105
  function _makeLane(name) {
96
106
  const limit = resolveDefaultChildSpawnLaneMaxInflight(name);
97
107
  const queueMax = _laneSetting(name, 'MAX_QUEUE', 1024);
@@ -608,7 +608,6 @@ export function updateSectionAsync(section, updater) {
608
608
  export const SECRET_ACCOUNTS = Object.freeze({
609
609
  agentApiKey: (provider) => `agent.${provider}.apiKey`,
610
610
  openaiUsageSessionKey: 'agent.openai.usageSessionKey',
611
- opencodeGoConsoleKey: 'agent.opencode-go.consoleKey',
612
611
  });
613
612
 
614
613
  // ── Secret-aware getters ─────────────────────────────────────────────────────
@@ -639,15 +638,6 @@ export function getOpenAIUsageSessionKey() {
639
638
  );
640
639
  }
641
640
 
642
- export function getOpenCodeGoConsoleKey() {
643
- return (
644
- process.env.OPENCODE_CONSOLE_API_KEY ||
645
- process.env.OPENCODE_GO_CONSOLE_API_KEY ||
646
- process.env.MIXDOG_OPENCODE_CONSOLE_API_KEY ||
647
- _readSecret(SECRET_ACCOUNTS.opencodeGoConsoleKey)
648
- );
649
- }
650
-
651
641
  /**
652
642
  * Persist a secret to the OS keychain. Throws on failure.
653
643
  * Never writes to mixdog-config.json.
@@ -24,7 +24,13 @@ import { createKeyedSerialQueue } from './keyed-serial-queue.mjs';
24
24
  import { sleep, sleepSync } from './sleep.mjs';
25
25
 
26
26
  const LOCK_WAIT_CODES = new Set(['EEXIST', 'EPERM', 'EACCES', 'EBUSY']);
27
- export const DEFAULT_BACKOFFS_MS = Object.freeze([25, 50, 100, 200, 400, 800, 1200, 1600]);
27
+ // Cross-process waits must poll (in-process waiters already queue on
28
+ // lockQueue and wake on release). Each sleep is capped at 200 ms: longer
29
+ // sleeps overshoot a release by up to their full length, and the synchronous
30
+ // paths block the event loop for each sleep. The schedule keeps the earlier
31
+ // ~4.2 s total window for rename retries (Windows AV/indexer file holds).
32
+ const RETRY_MAX_MS = 200;
33
+ export const DEFAULT_BACKOFFS_MS = Object.freeze([25, 50, 100, ...Array(20).fill(RETRY_MAX_MS)]);
28
34
  const configuredLockTimeoutMs = Number(process.env.MIXDOG_LOCK_TIMEOUT_MS);
29
35
  const DEFAULT_LOCK_TIMEOUT_MS =
30
36
  Number.isFinite(configuredLockTimeoutMs) && configuredLockTimeoutMs >= 0 ? configuredLockTimeoutMs : 2000;
@@ -0,0 +1,38 @@
1
+ // Worker side of file-permissions.mjs's sync bridge: owner-only enforcement
2
+ // for synchronous callers, through this thread's own long-lived ACL helper.
3
+ // Every request is answered on the port, then the shared counter (slot 0) is
4
+ // bumped and notified so the blocked caller wakes; slot 1 marks this thread
5
+ // gone, slot 2 marks it ready.
6
+ import { workerData } from 'node:worker_threads';
7
+ import { enforceOwnerOnlyAclWin32Async, prewarmOwnerOnlyAclWin32 } from './file-permissions.mjs';
8
+
9
+ const { port, signal } = workerData;
10
+
11
+ function wake() {
12
+ Atomics.add(signal, 0, 1);
13
+ Atomics.notify(signal, 0);
14
+ }
15
+
16
+ process.on('exit', () => {
17
+ Atomics.store(signal, 1, 1);
18
+ wake();
19
+ });
20
+
21
+ port.on('message', async (request) => {
22
+ if (request?.warm === true) {
23
+ await prewarmOwnerOnlyAclWin32({ bridge: false });
24
+ return;
25
+ }
26
+ let reply;
27
+ try {
28
+ await enforceOwnerOnlyAclWin32Async(request.path, { fresh: true });
29
+ reply = { id: request.id, ok: true };
30
+ } catch (error) {
31
+ reply = { id: request.id, ok: false, message: String(error?.message || error), code: error?.code ?? null };
32
+ }
33
+ port.postMessage(reply);
34
+ wake();
35
+ });
36
+
37
+ Atomics.store(signal, 2, 1);
38
+ wake();
@@ -1,8 +1,23 @@
1
1
  export function enforceOwnerOnlyAclWin32(targetPath: string, options?: { fresh?: boolean }): void;
2
2
 
3
- export function enforceOwnerOnlyAclWin32Async(
4
- targetPath: string,
5
- options?: { fresh?: boolean }
6
- ): Promise<void>;
3
+ /** Test hook: the live per-process ACL helper, or null. */
4
+ export function ownerOnlyAclHelperForTests(): import('node:child_process').ChildProcess | null;
5
+
6
+ /** Test/diagnostic hook: helper attachment, pending requests, starts in the restart window. */
7
+ export function ownerOnlyAclHelperStats(): {
8
+ alive: boolean;
9
+ pid: number | null;
10
+ pending: number;
11
+ recentStarts: number;
12
+ };
13
+
14
+ /** Non-fresh calls verify (and tighten) the real DACL on every call through a shared helper. */
15
+ export function enforceOwnerOnlyAclWin32Async(targetPath: string, options?: { fresh?: boolean }): Promise<void>;
7
16
 
8
17
  export function enforceOwnerOnlyDirectoryWin32Async(targetPath: string): Promise<void>;
18
+
19
+ /** Test hook: synchronous calls skip the sync bridge and use the one-shot update. */
20
+ export function disableOwnerOnlyAclSyncBridgeForTests(): void;
21
+
22
+ /** Starts this thread's ACL helper and the sync bridge off any write path. Never rejects. */
23
+ export function prewarmOwnerOnlyAclWin32(options?: { bridge?: boolean }): Promise<void>;