mixdog 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -8,8 +8,10 @@
8
8
  * loop each read stretched to seconds. This worker runs exactly that pipeline
9
9
  * (stat → read → stat, digest, readTopLevelLifecycleRecord →
10
10
  * projectStoredTranscript with no turn checkpoint) and hands back the
11
- * digest and the same projection value; only the finished window crosses
12
- * back.
11
+ * digest and one slice of the session's display history: the history itself
12
+ * is built once per content and kept here with its base, and only the window
13
+ * or page a request names (`slice`: `{ limit, skip }`) crosses back, with its
14
+ * serialized size measured here.
13
15
  *
14
16
  * Inside the worker, one projection base (recovery, prepared session and
15
17
  * whole-transcript context gauge) per session content is shared by every
@@ -60,8 +62,14 @@ function clientFor(sessionId) {
60
62
  * the full file stamp the bytes provably came from, or null. Rejects when the
61
63
  * worker cannot answer; callers then run the pipeline on their own thread.
62
64
  */
63
- export function projectStoredTranscriptOffThread({ sessionId, recordPath, itemLimit, known = null }) {
64
- return clientFor(sessionId)({ sessionId, recordPath, itemLimit, known });
65
+ export function projectStoredTranscriptOffThread({
66
+ sessionId,
67
+ recordPath,
68
+ known = null,
69
+ fingerprint = '',
70
+ slice = null,
71
+ }) {
72
+ return clientFor(sessionId)({ sessionId, recordPath, known, fingerprint, slice });
65
73
  }
66
74
 
67
75
  /** Whether the projection worker of `sessionId` is attached (a request now
@@ -321,15 +329,108 @@ async function buildBase(sessionId, text, previousMessages, timing) {
321
329
 
322
330
  const baseBuilds = createBaseBuilds({ build: buildBase });
323
331
 
324
- async function project({ sessionId, recordPath, itemLimit, known }) {
332
+ // Serialized bytes of the display histories this worker keeps for slicing:
333
+ // one larger than the per-session bound is rebuilt per request instead, and
334
+ // the oldest go once all of them exceed the worker's bound. The worker's idle
335
+ // exit releases every one.
336
+ // Measured: a history is about as large as its record (74 MB record: 75 MB
337
+ // history) and a page of a retained one costs ~0.2 s, a rebuilt one ~1 s. 96
338
+ // MB keeps the largest sessions seen (~78 MB records) smooth; 128 MB holds
339
+ // one of those beside a few ordinary ones.
340
+ const WORKER_HISTORY_SESSION_MAX_BYTES = 96 * 1024 * 1024;
341
+ const WORKER_HISTORY_MAX_BYTES = 128 * 1024 * 1024;
342
+
343
+ /**
344
+ * The display histories one worker retains (`{ value, rowBytes, bytes }`,
345
+ * keyed by session, Map order LRU) within `sessionMaxBytes` each and
346
+ * `maxBytes` together. A history of other content (`owner`, the record
347
+ * content it was built from, and its sidecar fingerprint) is never served.
348
+ */
349
+ export function createHistoryRetention({
350
+ sessionMaxBytes = WORKER_HISTORY_SESSION_MAX_BYTES,
351
+ maxBytes = WORKER_HISTORY_MAX_BYTES,
352
+ } = {}) {
353
+ const histories = new Map();
354
+ let retainedBytes = 0;
355
+ const drop = (sessionId) => {
356
+ const entry = histories.get(sessionId);
357
+ if (!entry) return;
358
+ histories.delete(sessionId);
359
+ retainedBytes -= entry.history.bytes;
360
+ };
361
+ return {
362
+ get(sessionId, owner, fingerprint) {
363
+ const entry = histories.get(sessionId);
364
+ if (!entry || entry.owner !== owner || entry.fingerprint !== fingerprint) return null;
365
+ histories.delete(sessionId);
366
+ histories.set(sessionId, entry);
367
+ return entry.history;
368
+ },
369
+ /** Keeps `history` when it fits; whether it was kept. */
370
+ retain(sessionId, owner, fingerprint, history) {
371
+ drop(sessionId);
372
+ if (history.bytes > sessionMaxBytes) return false;
373
+ histories.set(sessionId, { owner, fingerprint, history });
374
+ retainedBytes += history.bytes;
375
+ while (retainedBytes > maxBytes && histories.size > 1) drop(histories.keys().next().value);
376
+ return true;
377
+ },
378
+ forget: drop,
379
+ stats: () => ({ histories: histories.size, retainedBytes }),
380
+ };
381
+ }
382
+
383
+ const historyRetention = createHistoryRetention();
384
+ /** sessionId -> { owner, fingerprint, promise }: histories being built. */
385
+ const historyBuilds = new Map();
386
+
387
+ /** The display history of `built` (one base) under sidecar `fingerprint`,
388
+ * with each row's serialized bytes: retained, joined while another request
389
+ * builds it, or built now. */
390
+ async function displayHistory(sessionId, built, content, fingerprint, projection) {
391
+ const retained = historyRetention.get(sessionId, content, fingerprint);
392
+ if (retained) return { history: retained, historyBuilt: false };
393
+ const pending = historyBuilds.get(sessionId);
394
+ if (pending && pending.owner === content && pending.fingerprint === fingerprint) {
395
+ return { history: await pending.promise, historyBuilt: false };
396
+ }
397
+ const promise = (async () => {
398
+ const value = await projection.windowStoredTranscript(sessionId, built.base, {
399
+ history: true,
400
+ includeMessages: false,
401
+ });
402
+ const rowBytes = new Float64Array(value.items.length);
403
+ let bytes = 0;
404
+ for (let index = 0; index < value.items.length; index += 1) {
405
+ rowBytes[index] = Buffer.byteLength(JSON.stringify(value.items[index] ?? null));
406
+ bytes += rowBytes[index];
407
+ }
408
+ return { value, rowBytes, bytes };
409
+ })();
410
+ const record = { owner: content, fingerprint, promise };
411
+ historyBuilds.set(sessionId, record);
412
+ try {
413
+ const history = await promise;
414
+ if (historyBuilds.get(sessionId) === record) historyRetention.retain(sessionId, content, fingerprint, history);
415
+ return { history, historyBuilt: true };
416
+ } finally {
417
+ if (historyBuilds.get(sessionId) === record) historyBuilds.delete(sessionId);
418
+ }
419
+ }
420
+
421
+ async function project({ sessionId, recordPath, known, fingerprint = '', slice = null }) {
325
422
  const importStartedAt = performance.now();
326
- const [{ statSessionStamp, sameSessionStamp }, { readTextFile, PROBE_PRESENT }, { transcriptTextHash }, projection] =
327
- await Promise.all([
328
- import('./store/canonical-reader.mjs'),
329
- import('./store/fs-probe.mjs'),
330
- import('./store-transcript-cache.mjs'),
331
- import('./store-transcript-projection.mjs'),
332
- ]);
423
+ const [
424
+ { statSessionStamp, sameSessionStamp },
425
+ { readTextFile, PROBE_PRESENT },
426
+ { transcriptTextHash, historyStampOf },
427
+ projection,
428
+ ] = await Promise.all([
429
+ import('./store/canonical-reader.mjs'),
430
+ import('./store/fs-probe.mjs'),
431
+ import('./store-transcript-cache.mjs'),
432
+ import('./store-transcript-projection.mjs'),
433
+ ]);
333
434
  const timing = { importMs: performance.now() - importStartedAt };
334
435
  const observe = () => {
335
436
  try {
@@ -374,12 +475,32 @@ async function project({ sessionId, recordPath, itemLimit, known }) {
374
475
  const built = await pending;
375
476
  if (built === RESTART_READ) continue;
376
477
  if (built.unreadable) return { ...digest, unreadable: true };
377
- const value = await projection.windowStoredTranscript(sessionId, built.base, {
378
- itemLimit,
379
- includeMessages: false,
380
- });
478
+ // The whole display history stays here (within its budgets); only the
479
+ // requested slice crosses back.
480
+ const { history, historyBuilt } = await displayHistory(
481
+ sessionId,
482
+ built,
483
+ `${digest.textHash}:${digest.textChars}`,
484
+ fingerprint,
485
+ projection
486
+ );
487
+ const request = slice || {};
488
+ const historyStamp = historyStampOf(sessionId, digest.textHash, digest.textChars, fingerprint, request.epoch);
489
+ const proven = Boolean(request.held) && request.baseHistory === historyStamp;
490
+ const value = projection.storedHistorySlice(
491
+ history.value,
492
+ { ...request, proven },
493
+ {
494
+ digestOf: request.held && !proven ? await projection.heldRowsDigester() : null,
495
+ rowBytes: (index) => history.rowBytes[index],
496
+ }
497
+ );
498
+ const { windowStamp } = value;
499
+ delete value.windowStamp;
500
+ value.projectionStamp = `${historyStamp}/${windowStamp}`;
501
+ const bytes = Buffer.byteLength(JSON.stringify(value));
381
502
  timing.projectMs = performance.now() - projectStartedAt;
382
- return { ...digest, value, lifecycle: built.lifecycle };
503
+ return { ...digest, value, bytes, historyBuilt, lifecycle: built.lifecycle };
383
504
  } finally {
384
505
  if (!submitted) baseBuilds.release(ticket);
385
506
  }
@@ -388,6 +509,9 @@ async function project({ sessionId, recordPath, itemLimit, known }) {
388
509
 
389
510
  if (!isMainThread && workerData?.kind === WORKER_KIND) {
390
511
  serveWorkerRequests((payload) => {
391
- return payload?.forget ? baseBuilds.forget(payload.forget) : project(payload);
512
+ if (!payload?.forget) return project(payload);
513
+ historyRetention.forget(payload.forget);
514
+ historyBuilds.delete(payload.forget);
515
+ return baseBuilds.forget(payload.forget);
392
516
  });
393
517
  }
@@ -31,6 +31,7 @@ export {
31
31
  _removeSessionSummary,
32
32
  } from './store-summary-index.mjs';
33
33
  import { _sessionForDisk, _ensureLifecycleFields } from './store/serialize.mjs';
34
+ import { captureTranscriptSnapshot, recordLandedTranscript } from './store/transcript-durability.mjs';
34
35
  import {
35
36
  _cacheSessionSummary,
36
37
  _rollbackCachedSessionSummary,
@@ -337,6 +338,7 @@ function _doSaveSync(payload) {
337
338
  // rebuilt from them, never re-read from the later mutable live session.
338
339
  let attempted = null;
339
340
  try {
341
+ const transcript = captureTranscriptSnapshot(session);
340
342
  const disk = _sessionForDisk(session);
341
343
  attempted = JSON.stringify(disk);
342
344
  // The lifecycle these exact bytes carry, recorded with the commit stamp.
@@ -382,6 +384,7 @@ function _doSaveSync(payload) {
382
384
  _recordOwnSessionCommit(target, scratch, lifecycle);
383
385
  _publishLandedWriteEpoch(opts, epoch);
384
386
  _untrackSaveTmp(tmp);
387
+ recordLandedTranscript(session, transcript, epoch);
385
388
  if (mayMutate()) {
386
389
  if (publishSummary) _queueSessionSummaryUpsert(session, summaryVersion);
387
390
  _clearSaveStateIfCurrent(id, epoch);
@@ -627,6 +630,7 @@ async function _doSave(payload) {
627
630
  // payload, never the live session as it looks at settlement time.
628
631
  let attempted = null;
629
632
  try {
633
+ const transcript = captureTranscriptSnapshot(session);
630
634
  const disk = _sessionForDisk(session);
631
635
  attempted = JSON.stringify(disk);
632
636
  // Captured before the await: the lifecycle of exactly these bytes.
@@ -671,6 +675,7 @@ async function _doSave(payload) {
671
675
  _recordOwnSessionCommit(target, scratch, lifecycle);
672
676
  _publishLandedWriteEpoch(opts, epoch);
673
677
  _untrackSaveTmp(tmp);
678
+ recordLandedTranscript(session, transcript, epoch);
674
679
  if (mayMutate()) {
675
680
  _queueSessionSummaryUpsert(session, summaryVersion);
676
681
  _clearSaveStateIfCurrent(id, epoch);
@@ -45,6 +45,11 @@ const RUNTIME_CONTROL_SOURCES = new Set([
45
45
  'task-notification',
46
46
  ]);
47
47
  const ENVELOPE_OPEN_RE = new RegExp(`^\\s*<${SYNTHETIC_USER_ENVELOPE_TAG}\\b`, 'i');
48
+ // The stored crash marker reads like a user cancel ("Request interrupted ..."),
49
+ // and models answered it with "stopped as you asked" and dropped the work.
50
+ // On the wire it names the restart and asks to resume.
51
+ const PROCESS_RESTART_MARKER = '[Request interrupted by process restart]';
52
+ const PROCESS_RESTART_WIRE_TEXT = '[mixdog-runtime] The app restarted mid-turn. Continue from where you left off.';
48
53
 
49
54
  function messageText(message) {
50
55
  if (typeof message?.content === 'string') return message.content;
@@ -128,7 +133,8 @@ export function projectSyntheticUserEnvelopes(messages) {
128
133
  const projected = messages.map((message) => {
129
134
  const kind = classifySyntheticUserMessage(message);
130
135
  if (!kind) return message;
131
- const content = envelopeContent(message.content, kind);
136
+ const source = messageText(message).trim() === PROCESS_RESTART_MARKER ? PROCESS_RESTART_WIRE_TEXT : message.content;
137
+ const content = envelopeContent(source, kind);
132
138
  if (content === message.content) return message;
133
139
  changed = true;
134
140
  stats.wrapped += 1;
@@ -119,7 +119,15 @@ export function matchTailReminder(context, rules = TAIL_REMINDER_RULES) {
119
119
  }
120
120
 
121
121
  /** `messages` plus the tail reminder for this request (a copy; the input is untouched). */
122
- export function withTailReminder(messages, { session, provider, model }, language = _buildLeadLanguage()) {
122
+ // The session's own response language (as its prompt and settings notices
123
+ // carry it, session/manager/prompt-settings.mjs); a session without one (an
124
+ // agent, an older record) reads the config.
125
+ export function withTailReminder(
126
+ messages,
127
+ { session, provider, model },
128
+ // null is a recorded "no language", not a missing record.
129
+ language = session?.responseLanguage !== undefined ? session.responseLanguage : _buildLeadLanguage()
130
+ ) {
123
131
  const text = matchTailReminder({
124
132
  provider: session?.provider || provider?.name || '',
125
133
  model,
@@ -260,7 +260,7 @@ export function isStatusOnlyAgentCompletionNotification(text) {
260
260
  return !(hasAgentResponseResultText(result) || hasAgentResponseResultText(text));
261
261
  }
262
262
 
263
- export function hasAgentResponseResultText(text) {
263
+ function hasAgentResponseResultText(text) {
264
264
  const value = String(text || '').trim();
265
265
  if (!value) return false;
266
266
  const notification = parseTaskNotification(value);
@@ -685,7 +685,9 @@ export function restoreTranscriptItems(messages, { sessionId = 'session', itemLi
685
685
  export function sessionContextSnapshotProjection(session, contextStatus) {
686
686
  if (!contextStatus) return {};
687
687
  return {
688
- stats: contextMeasurementStats(contextStatus),
688
+ // The composer's usage readout reads the session totals from the same
689
+ // stats a live runtime publishes; a cold open has no runtime to add them.
690
+ stats: { ...contextMeasurementStats(contextStatus), usageReadout: contextStatus.usage?.usageReadout ?? null },
689
691
  contextWindow: Math.max(0, Number(session?.contextWindow || contextStatus.effectiveContextWindow || 0)),
690
692
  rawContextWindow: Math.max(0, Number(session?.rawContextWindow || contextStatus.rawContextWindow || 0)),
691
693
  effectiveContextWindowPercent: Number(
@@ -99,7 +99,7 @@ function feedbackDisplay(body) {
99
99
  return lines.join('\n');
100
100
  }
101
101
 
102
- export function withVisualizeFeedbackDisplay(text) {
102
+ function withVisualizeFeedbackDisplay(text) {
103
103
  const value = String(text ?? '');
104
104
  if (!value.includes(FEEDBACK_OPEN)) return value;
105
105
  return value.replace(FEEDBACK_BLOCK, (_block, body) => feedbackDisplay(body));
@@ -121,7 +121,7 @@ const PASTED_LINES = /· (\d+) lines?$/;
121
121
  const PASTED_TEXT_MAX_BYTES = 1024 * 1024;
122
122
  /** Blob bytes one transcript load may read to count the lines of pastes
123
123
  * whose stored name does not carry the count (pastes stored before it did). */
124
- export const PASTED_LINE_READ_BUDGET_BYTES = 4 * 1024 * 1024;
124
+ const PASTED_LINE_READ_BUDGET_BYTES = 4 * 1024 * 1024;
125
125
 
126
126
  /** A stored plain-text prompt part's text within the load's byte budget, else ''. */
127
127
  function offloadedPromptText(part, budget) {
@@ -137,11 +137,9 @@ export const PROVIDER_SSE_IDLE_TIMEOUT_MS = resolveTimeoutMs('MIXDOG_PROVIDER_SS
137
137
  // silent-window token rate a steady ~92 tok/s, i.e. live generation, not a
138
138
  // wedge). So a "semantic-silent" stream is NOT necessarily dead.
139
139
  //
140
- // 2026-08-03 v3 postmortem: this window used to be DERIVED from the agent
141
- // stall budget (warn − tick ≈ 285s). A harness that tightened STALL_TIMEOUT_S
142
- // to 300s silently collapsed it to 135s, which deterministically beheaded
143
- // live long-thinking turns (regex-chess / circuit-fibsqrt: ttft ~1.5s, then
144
- // killed at exactly 135s of silent thinking, 4 attempts ≈ 552s per turn).
140
+ // Deriving this window from the agent stall budget (warn − tick ≈ 285s) would
141
+ // let a harness that tightens STALL_TIMEOUT_S to 300s collapse it to 135s,
142
+ // which deterministically beheads live long-thinking turns.
145
143
  // Reference behavior: abort only after a 300s single-gap silence, and fall
146
144
  // back to non-streaming instead of killing the turn. The default is
147
145
  // therefore a FIXED 300s, decoupled from the warn math. The only remaining
@@ -1,4 +1,5 @@
1
1
  import { registerBackgroundTask, renderBackgroundTask } from '../../../../../shared/background-tasks.mjs';
2
+ import { stampShellJobCycle } from '../../../../../shared/background-wait.mjs';
2
3
  import { killShellJob, watchBackgroundShellJob } from '../shell-jobs.mjs';
3
4
  import { renderBackgroundPartialOutput } from '../shell-output.mjs';
4
5
  import { readShellTaskOutput } from '../lib/shell-task-output.mjs';
@@ -65,7 +66,9 @@ export function renderBackgroundedResult({
65
66
  }) {
66
67
  let task = null;
67
68
  if (result.jobId) {
68
- task = registerPromotedTask({ result, command, cwd, options, startedAtMs });
69
+ // The owner's user cycle at start decides whether it is waited on
70
+ // (background-wait.mjs), however the job reached the background.
71
+ task = stampShellJobCycle(registerPromotedTask({ result, command, cwd, options, startedAtMs }));
69
72
  try {
70
73
  watchBackgroundShellJob(result.jobId, {
71
74
  notifyFn: typeof options?.notifyFn === 'function' ? options.notifyFn : null,
@@ -25,6 +25,9 @@ import {
25
25
  * when the last observed survivor exits, `cancel` terminates them. */
26
26
  function trackSurvivingDescendants(handle, { command, cwd, options, startedAtMs } = {}) {
27
27
  if (!handle?.taskId) return null;
28
+ // Once cancelled, every observation pass terminates survivors that ignored
29
+ // the first kill, so a retry is not needed to finish the job.
30
+ let cancelled = false;
28
31
  try {
29
32
  const task = startBackgroundTask({
30
33
  taskId: handle.taskId,
@@ -36,10 +39,10 @@ function trackSurvivingDescendants(handle, { command, cwd, options, startedAtMs
36
39
  meta: { task_id: handle.taskId, stdout: null, stderr: null, cwd, timeoutMs: 0 },
37
40
  resultType: 'shell_task_result',
38
41
  run: async () => {
39
- await waitForShellDescendants(handle);
42
+ await waitForShellDescendants(handle, { sweep: () => cancelled });
40
43
  // The folder reservation the finished command handed to its
41
44
  // survivors ends with the last of them.
42
- releaseShellJobWorkspace(handle.taskId);
45
+ await releaseShellJobWorkspace(handle.taskId);
43
46
  return {
44
47
  task_id: handle.taskId,
45
48
  status: 'completed',
@@ -48,6 +51,7 @@ function trackSurvivingDescendants(handle, { command, cwd, options, startedAtMs
48
51
  },
49
52
  // The kill's own re-observation is what `task cancel` reports.
50
53
  cancel: () => {
54
+ cancelled = true;
51
55
  task.cancelOutcome = killShellDescendants(handle);
52
56
  },
53
57
  });
@@ -5,13 +5,16 @@
5
5
  // to background + task wait);
6
6
  // 2. a plain leading `cd <dir>` moves into the `cwd` argument;
7
7
  // 3. a shell file read (cat/Get-Content/grep/ls …) gets a pointer to the
8
- // read / grep / list tools — a note now, a rejection when the mode flips.
8
+ // read / grep / list tools — a note now, a rejection when the mode flips;
9
+ // 4. a command mentioning `git … worktree add` is rejected (worktrees go
10
+ // through the git tool; a textual check, so mentions as data are too).
9
11
  import { shellSplitPipelineSegments, shellSplitSegments, shellTokenize } from '../shell-analysis.mjs';
10
12
  import { resolveShellFor } from '../shell-runtime.mjs';
11
13
  import { formatShellToolFailure } from './result-format.mjs';
14
+ import { addsUnmanagedWorktree } from './worktree-add-guard.mjs';
12
15
 
13
16
  /** `warn` runs the read with a note; `reject` returns the block without running. */
14
- export const SHELL_FILE_READ_MODE = 'warn';
17
+ const SHELL_FILE_READ_MODE = 'warn';
15
18
  export const SHELL_FILE_READ_NOTE = 'Note: use the read / grep / list tools for files instead of the shell.';
16
19
  const SHELL_FILE_READ_BLOCK =
17
20
  'Blocked: use read / grep / list for files instead of the shell (read takes offset/limit for a window of a large file).';
@@ -194,6 +197,20 @@ function detectShellFileRead(command, shellType) {
194
197
  return operands.length >= minOperands ? { tool, command: name } : null;
195
198
  }
196
199
 
200
+ // ── 4. unmanaged worktrees ───────────────────────────────────────────────────
201
+
202
+ // A worktree added from the shell is invisible to the managed cleanup and
203
+ // outlives the session that made it, so `git … worktree add` never runs here.
204
+ // The check is textual (worktree-add-guard.mjs): a command that only mentions
205
+ // the phrase is refused too, so the message says how to go on either way.
206
+ const SHELL_WORKTREE_ADD_BLOCK =
207
+ 'Blocked: this shell command mentions `git … worktree add`, which does not run from the shell; ' +
208
+ 'Mixdog manages worktrees so they are cleaned up. To create one, use the git tool: command ' +
209
+ '"git worktree add --detach <path> [<commit>]" makes a read-only snapshot (removed when the turn ends; ' +
210
+ 'delegated workers too), and the Lead uses "git worktree add -b <branch> <path>" or action:"worktree" for a ' +
211
+ 'branch worktree. The check is textual: to search for that text use the grep tool, and keep the phrase out ' +
212
+ 'of shell commands (echo, commit messages, heredocs).';
213
+
197
214
  // ── the guard ────────────────────────────────────────────────────────────────
198
215
 
199
216
  /** The syntax family of the shell a call asks for (`args.shell`, as foreign adapters set it), else the default shell's. */
@@ -209,7 +226,7 @@ function recordFileRead(telemetry, entry) {
209
226
  }
210
227
 
211
228
  /**
212
- * Apply the three guards to a shell call.
229
+ * Apply the four guards to a shell call.
213
230
  * @returns {{ failure: string } | { args: object, notes: string[] }} the
214
231
  * rejection, or the call to run (a leading `cd` moved into `cwd`) with the
215
232
  * lines to add to its result.
@@ -230,6 +247,7 @@ export function guardShellCall(
230
247
  const sleepFailure = leadingSleepFailure(guarded.command, shellType);
231
248
  if (sleepFailure) return { failure: sleepFailure };
232
249
  }
250
+ if (addsUnmanagedWorktree(guarded.command)) return { failure: formatShellToolFailure(SHELL_WORKTREE_ADD_BLOCK) };
233
251
  const read = detectShellFileRead(guarded.command, shellType);
234
252
  if (read) {
235
253
  recordFileRead(telemetry, { mode: fileReadMode, tool: read.tool, command: read.command, agent, sessionId });
@@ -75,7 +75,7 @@ export function _finalizeShellResult(completedExit, text) {
75
75
 
76
76
  export function _shellFailureStatus(result, timeout) {
77
77
  // Prefer the signal reported by the process. `killed` is only a fallback
78
- // for platforms (notably taskkill on Windows) that close without one.
78
+ // for platforms (notably a Windows tree kill) that close without one.
79
79
  const signal = result.signal || (result.killed ? 'SIGKILL' : null);
80
80
  const exitCode = signal ? null : result.exitCode;
81
81
  const shellToolFailed = result.failurePhase === 'tool' || !!result.outputCaptureError;
@@ -0,0 +1,77 @@
1
+ // Whether a shell command mentions `git … worktree add`. A worktree added from
2
+ // the shell is invisible to the managed cleanup and outlives the session that
3
+ // made it, so the shell guard refuses it and points to the git tool.
4
+ //
5
+ // Deliberately textual, conservative and linear-time: no shell is parsed. The
6
+ // command is normalized once (escape and quote characters of every shell
7
+ // dropped, whitespace collapsed; a PowerShell -EncodedCommand decoded), then
8
+ // refused when `git` is followed anywhere later by `worktree … add`. Commands
9
+ // that only mention the phrase as data (echo, grep, a heredoc, a commit
10
+ // message) are refused too; the refusal says how to proceed.
11
+
12
+ const QUOTES = /['"\u2018\u2019\u201a\u201b\u201c\u201d\u201e]/g;
13
+ const GIT_WORD = /\bgit\b/i;
14
+ // `worktree` ending a token that is not an option: `worktree`, `$(worktree`, `alias.wa=worktree`.
15
+ const WORKTREE_TOKEN = /(?:^|[^\w-])worktree$/i;
16
+ const ADD_TOKEN = /^add\b/i;
17
+ // powershell/pwsh -EncodedCommand (any accepted prefix: -e, -ec, -enc, …) and its base64 argument.
18
+ const ENCODED_COMMAND = /(?:^|[\s'"])[-/]e(?:c|n[a-z]*)?\s+['"]?([A-Za-z0-9+/]{4,}={0,2})/gi;
19
+
20
+ /** The command with every shell's escapes and quotes dropped and whitespace collapsed.
21
+ * `joiner` replaces a line continuation: '' as POSIX joins `a\<newline>dd` into one
22
+ * word, ' ' where the continuation separates words. */
23
+ function normalize(text, joiner) {
24
+ return (
25
+ text
26
+ .replace(/[\\`]\r?\n/g, joiner)
27
+ // Hex escapes ($'\x61dd', "\x61dd").
28
+ .replace(/\\x([0-9a-fA-F]{2})/g, (_, hex) => String.fromCharCode(Number.parseInt(hex, 16)))
29
+ // The `$` of a POSIX $'…' / $"…" string.
30
+ .replace(/\$(?=['"])/g, '')
31
+ // PowerShell backtick and cmd caret escapes.
32
+ .replace(/[`^]/g, '')
33
+ .replace(QUOTES, '')
34
+ .replace(/\s+/g, ' ')
35
+ );
36
+ }
37
+
38
+ /** True when some `git` word comes before a `worktree … add` in `text`. One pass
39
+ * over the tokens: options (`-…`) between `worktree` and `add` are skipped and
40
+ * never start a match, so every token is visited once. */
41
+ function gitThenWorktreeAdd(text) {
42
+ const tokens = text.split(/[\s,]+/);
43
+ let gitSeen = false;
44
+ for (let i = 0; i < tokens.length; i += 1) {
45
+ const token = tokens[i];
46
+ if (!gitSeen) {
47
+ gitSeen = GIT_WORD.test(token);
48
+ continue;
49
+ }
50
+ if (token.startsWith('-') || !WORKTREE_TOKEN.test(token)) continue;
51
+ let next = i + 1;
52
+ while (next < tokens.length && tokens[next].startsWith('-')) next += 1;
53
+ if (next < tokens.length && ADD_TOKEN.test(tokens[next])) return true;
54
+ i = next - 1;
55
+ }
56
+ return false;
57
+ }
58
+
59
+ /** True when `command` would (or might) run `git … worktree add`. */
60
+ export function addsUnmanagedWorktree(command) {
61
+ const raw = String(command ?? '');
62
+ const texts = [raw];
63
+ for (const [, encoded] of raw.matchAll(ENCODED_COMMAND)) {
64
+ texts.push(Buffer.from(encoded, 'base64').toString('utf16le'));
65
+ }
66
+ return texts.some((text) =>
67
+ ['', ' '].some((joiner) => {
68
+ const normalized = normalize(text, joiner);
69
+ // A backslash is a POSIX escape (`a\dd` is `add`) or a Windows path separator
70
+ // (`C:\Git\cmd\git.exe`): both readings are checked.
71
+ return (
72
+ gitThenWorktreeAdd(normalized.replace(/\\(?=[A-Za-z])/g, '')) ||
73
+ gitThenWorktreeAdd(normalized.replaceAll('\\', '/'))
74
+ );
75
+ })
76
+ );
77
+ }
@@ -32,7 +32,6 @@ export {
32
32
  SURVIVING_DESCENDANTS_WARNING,
33
33
  SURVIVING_DESCENDANTS_UNREACHABLE_WARNING,
34
34
  _backgroundResultLines,
35
- getDedupedDestructiveWarnings,
36
35
  _placeDestructiveWarningsAfterStatus,
37
36
  formatShellToolFailure,
38
37
  _shellFailureStatus,