mixdog 1.2.2 → 1.2.4

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 (692) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +6 -4
  4. package/scripts/lib/gate-scheduler.mjs +29 -11
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +599 -0
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/advisor/AGENT.md +1 -1
  9. package/src/agents/advisor/agent.json +1 -1
  10. package/src/agents/maintainer/AGENT.md +1 -1
  11. package/src/agents/maintainer/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +2 -4
  13. package/src/agents/security/AGENT.md +1 -2
  14. package/src/agents/writer/AGENT.md +2 -3
  15. package/src/defaults/shipped-history.json +11 -1
  16. package/src/defaults/skills/image/SKILL.md +21 -23
  17. package/src/defaults/skills/setup/SKILL.md +6 -1
  18. package/src/defaults/skills/setup/references/actions.md +44 -22
  19. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  20. package/src/headless-exec.mjs +15 -8
  21. package/src/lib/keychain-cjs.cjs +20 -15
  22. package/src/output-styles/common.md +11 -10
  23. package/src/rules/agent/AGENT.md +6 -4
  24. package/src/rules/lead/LEAD.md +7 -9
  25. package/src/rules/shared/45-destructive.md +4 -0
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  29. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  30. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  31. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  32. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  36. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  42. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
  46. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  51. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  52. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  53. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  58. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
  59. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  60. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
  61. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
  63. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  65. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
  76. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
  77. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
  78. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  79. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  80. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  81. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
  82. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  83. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
  84. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
  85. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  86. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  88. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
  89. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
  90. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
  92. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
  93. package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
  94. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  96. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  97. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  98. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
  99. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  100. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  101. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
  102. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  103. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  105. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  106. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  107. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
  108. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
  109. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  110. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  112. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  113. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
  114. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
  115. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
  117. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  118. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
  128. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  129. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  138. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  140. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  141. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  142. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
  143. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  144. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  145. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  147. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  148. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  150. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  151. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
  153. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  154. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
  155. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
  156. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  157. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
  158. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  159. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  160. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  161. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
  162. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
  163. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
  164. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
  165. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
  166. package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
  167. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
  168. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  169. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  170. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
  171. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
  172. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  173. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
  174. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
  175. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  176. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
  177. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  178. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  179. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  180. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  181. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  182. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  183. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
  184. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  186. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  187. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  188. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
  189. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
  190. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  191. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  192. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  193. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  194. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  195. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  196. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
  197. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  198. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  199. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
  200. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  201. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  202. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
  203. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  204. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  205. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  206. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  207. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  208. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
  209. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  210. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  211. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  212. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
  213. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  215. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  216. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
  217. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  219. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  220. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
  221. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
  222. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
  223. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  224. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  225. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
  226. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  227. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  228. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  229. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
  230. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  231. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
  232. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
  233. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  234. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  235. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
  236. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  237. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
  238. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  239. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  240. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
  241. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
  242. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  243. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  244. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  245. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  246. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  247. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
  248. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  249. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  250. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
  251. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
  252. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  253. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
  254. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  255. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
  256. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  257. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  258. package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
  259. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  260. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  261. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
  262. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  263. package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
  264. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
  265. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  266. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  267. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  269. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  270. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  271. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  272. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
  273. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  274. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  275. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  276. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  277. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
  278. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  279. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  280. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  281. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
  282. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  283. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  284. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  285. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
  286. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  287. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  288. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  289. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  290. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
  291. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  292. package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
  293. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
  294. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
  295. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  296. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  297. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  298. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  299. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
  300. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  301. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  302. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  303. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  304. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  305. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  306. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  307. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  308. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
  309. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  310. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  311. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  312. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  313. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  314. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  315. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  316. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
  317. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  318. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  319. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  320. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  321. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  322. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  323. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  324. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  325. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  326. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  327. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  328. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  329. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  330. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  331. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  332. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  333. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  334. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  335. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  336. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  337. package/src/runtime/attachments/store.d.mts +9 -0
  338. package/src/runtime/attachments/store.mjs +80 -9
  339. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  340. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  341. package/src/runtime/computer-bridge/action-schema.mjs +219 -196
  342. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  343. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  344. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  345. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  346. package/src/runtime/github/tool.mjs +208 -17
  347. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  348. package/src/runtime/media/catalog.mjs +4 -4
  349. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  350. package/src/runtime/media/defaults.mjs +37 -0
  351. package/src/runtime/media/jobs.mjs +12 -2
  352. package/src/runtime/media/lanes.mjs +12 -0
  353. package/src/runtime/media/tool-defs.mjs +15 -4
  354. package/src/runtime/media/tool.mjs +41 -12
  355. package/src/runtime/media/upstream-error.mjs +72 -6
  356. package/src/runtime/memory/index.mjs +1 -0
  357. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  358. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  359. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  360. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  361. package/src/runtime/memory/lib/pg/process.mjs +36 -33
  362. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  363. package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
  364. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  365. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  366. package/src/runtime/office/README.md +1 -1
  367. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  368. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  369. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  370. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  371. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  372. package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
  373. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  374. package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
  375. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  376. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  377. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  378. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  379. package/src/runtime/office/core/office-sessions.mjs +5 -0
  380. package/src/runtime/office/core/office-transactions.mjs +3 -0
  381. package/src/runtime/office/core/office-write-ledger.mjs +94 -0
  382. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  383. package/src/runtime/office/index.mjs +29 -0
  384. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  385. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  386. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  387. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  388. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  389. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  390. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  391. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  392. package/src/runtime/shared/atomic-file.d.mts +1 -1
  393. package/src/runtime/shared/background-tasks.mjs +6 -1
  394. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  395. package/src/runtime/shared/bounded-line-diff.mjs +191 -0
  396. package/src/runtime/shared/browser-launch.mjs +15 -0
  397. package/src/runtime/shared/buffered-appender.mjs +18 -0
  398. package/src/runtime/shared/config.mjs +78 -18
  399. package/src/runtime/shared/err-text.mjs +48 -4
  400. package/src/runtime/shared/file-lock.mjs +6 -5
  401. package/src/runtime/shared/file-permissions.d.mts +6 -1
  402. package/src/runtime/shared/file-permissions.mjs +54 -6
  403. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  404. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  405. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  406. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  407. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  408. package/src/runtime/shared/loopback-listener.mjs +9 -0
  409. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  410. package/src/runtime/shared/model-route-chain.mjs +48 -0
  411. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  412. package/src/runtime/shared/pid-liveness.mjs +12 -0
  413. package/src/runtime/shared/provider-api-key.mjs +8 -0
  414. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  415. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  416. package/src/runtime/shared/quiet-progress.mjs +101 -0
  417. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  418. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  419. package/src/runtime/shared/remote-intent.mjs +2 -42
  420. package/src/runtime/shared/review-diff.mjs +52 -0
  421. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  422. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  423. package/src/runtime/shared/slow-span.mjs +121 -0
  424. package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
  425. package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
  426. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  427. package/src/runtime/shared/tool-card-model.mjs +5 -2
  428. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  429. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  430. package/src/runtime/shared/tool-primitives.mjs +13 -0
  431. package/src/runtime/shared/tool-result-summary.mjs +22 -1
  432. package/src/runtime/shared/tool-status.mjs +3 -2
  433. package/src/runtime/shared/tool-surface.mjs +20 -6
  434. package/src/runtime/shared/tool-work-units.mjs +54 -11
  435. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  436. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  437. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  438. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  439. package/src/runtime/shared/transcript-writer.mjs +24 -6
  440. package/src/runtime/shared/turn-changes.mjs +269 -100
  441. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  442. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  443. package/src/runtime/shared/turn-snapshot.mjs +865 -683
  444. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  445. package/src/runtime/shared/user-data-guard.mjs +262 -49
  446. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  447. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  448. package/src/runtime/shared/worktrees/carry.mjs +533 -0
  449. package/src/runtime/shared/worktrees/contract.mjs +60 -0
  450. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  451. package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
  452. package/src/runtime/shared/worktrees/git-head.mjs +214 -0
  453. package/src/runtime/shared/worktrees/git.mjs +8 -3
  454. package/src/runtime/shared/worktrees/include.mjs +125 -7
  455. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  456. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  457. package/src/runtime/shared/worktrees/manager.mjs +525 -31
  458. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  459. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  460. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  461. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  462. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  463. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  464. package/src/runtime/terminal-bridge/client.mjs +57 -20
  465. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  466. package/src/runtime/tidy/apply.mjs +47 -2
  467. package/src/runtime/tidy/run-engines.mjs +11 -5
  468. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  469. package/src/session-runtime/boot/apis.mjs +20 -6
  470. package/src/session-runtime/boot/config.mjs +2 -0
  471. package/src/session-runtime/boot/facade.mjs +4 -0
  472. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  473. package/src/session-runtime/boot/session.mjs +3 -3
  474. package/src/session-runtime/boot/tools.mjs +7 -1
  475. package/src/session-runtime/conversation-import/service.mjs +1 -1
  476. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  477. package/src/session-runtime/goal-facade-api.mjs +2 -2
  478. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
  479. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  480. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
  481. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
  482. package/src/session-runtime/internal-tool-executor.mjs +8 -2
  483. package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
  484. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  485. package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
  486. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  487. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
  488. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  489. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  490. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  491. package/src/session-runtime/lifecycle/teardown.mjs +70 -14
  492. package/src/session-runtime/lifecycle-api.mjs +1 -0
  493. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  494. package/src/session-runtime/media-api.mjs +8 -0
  495. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  496. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  497. package/src/session-runtime/model-route/set-route.mjs +116 -36
  498. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  499. package/src/session-runtime/model-route-api.mjs +4 -2
  500. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  501. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  502. package/src/session-runtime/native-web-search.mjs +19 -9
  503. package/src/session-runtime/new-session-config.mjs +4 -2
  504. package/src/session-runtime/provider-auth/login.mjs +4 -0
  505. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  506. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  507. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  508. package/src/session-runtime/provider-models.mjs +1 -0
  509. package/src/session-runtime/provider-usage.mjs +4 -0
  510. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  511. package/src/session-runtime/route-resolution.mjs +3 -1
  512. package/src/session-runtime/runtime-core.mjs +4 -0
  513. package/src/session-runtime/runtime-facade.mjs +6 -0
  514. package/src/session-runtime/runtime-review-api.mjs +8 -2
  515. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  516. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  517. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  518. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  519. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  520. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  521. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  522. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  523. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  524. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  525. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  526. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  527. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  528. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  529. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  530. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
  531. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  532. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  533. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  534. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  535. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  536. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  537. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  538. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  539. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  540. package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
  541. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  542. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  543. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  544. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  545. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  546. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  547. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  548. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  549. package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
  550. package/src/session-runtime/services/agent-tool.mjs +7 -0
  551. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  552. package/src/session-runtime/services/channel-admin.mjs +19 -3
  553. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  554. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  555. package/src/session-runtime/services/provider-admin.mjs +158 -15
  556. package/src/session-runtime/session-create/session-options.mjs +7 -5
  557. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  558. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  559. package/src/session-runtime/session-transcript.mjs +4 -5
  560. package/src/session-runtime/session-turn-api.mjs +17 -14
  561. package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
  562. package/src/session-runtime/setup-tool/executor.mjs +57 -9
  563. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  564. package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
  565. package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
  566. package/src/session-runtime/skills-api.mjs +3 -5
  567. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  568. package/src/session-runtime/tool-surface.mjs +5 -1
  569. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  570. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  571. package/src/session-runtime/turn/session-ops.mjs +7 -5
  572. package/src/session-runtime/turn/side-question-ops.mjs +19 -0
  573. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
  574. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
  575. package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
  576. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  577. package/src/session-runtime/turn/turn-run.mjs +26 -45
  578. package/src/session-runtime/usage-stats-api.mjs +46 -11
  579. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  580. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  581. package/src/session-runtime/workspace/project-branches.mjs +35 -41
  582. package/src/session-runtime/workspace/transition-steps.mjs +215 -116
  583. package/src/session-runtime/workspace/transitions.mjs +428 -73
  584. package/src/standalone/channel-transport.mjs +3 -4
  585. package/src/standalone/daemon-agent-control.mjs +9 -1
  586. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  587. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  588. package/src/standalone/daemon-owner.mjs +17 -4
  589. package/src/standalone/daemon-pg-stop.mjs +49 -0
  590. package/src/standalone/daemon-session-control.mjs +88 -0
  591. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  592. package/src/standalone/daemon-stop-budget.mjs +18 -0
  593. package/src/standalone/daemon-stored-session-views.mjs +25 -3
  594. package/src/standalone/daemon-telemetry.mjs +19 -0
  595. package/src/standalone/daemon.mjs +63 -1
  596. package/src/standalone/desktop-service-registry.mjs +5 -0
  597. package/src/standalone/local-session-runtime.mjs +80 -30
  598. package/src/standalone/session-client.mjs +42 -0
  599. package/src/standalone/session-protocol.mjs +14 -0
  600. package/src/standalone/session-proxy/projection.mjs +41 -4
  601. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  602. package/src/standalone/session-runtime-inline-host.mjs +3 -0
  603. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  604. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  605. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  606. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  607. package/src/standalone/session-service/agent-tree.mjs +28 -2
  608. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  609. package/src/standalone/session-service/entries.mjs +1 -0
  610. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  611. package/src/standalone/session-service/quota-resume.mjs +28 -13
  612. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  613. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  614. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  615. package/src/standalone/session-service-api.mjs +6 -1
  616. package/src/standalone/session-state-patch.d.mts +2 -1
  617. package/src/standalone/session-state-patch.mjs +41 -1
  618. package/src/standalone/session-tool-output.mjs +82 -0
  619. package/src/tui/App.jsx +25 -0
  620. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  621. package/src/tui/app/app-view.jsx +2 -1
  622. package/src/tui/app/btw-controller.mjs +118 -0
  623. package/src/tui/app/create-app-pickers.mjs +2 -0
  624. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  625. package/src/tui/app/provider-setup-picker.mjs +15 -3
  626. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  627. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  628. package/src/tui/app/slash-commands.mjs +19 -3
  629. package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
  630. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  631. package/src/tui/app/use-global-key-input.mjs +5 -12
  632. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  633. package/src/tui/components/BtwPanel.jsx +53 -0
  634. package/src/tui/components/QuestionPanel.jsx +275 -0
  635. package/src/tui/components/Spinner.jsx +4 -0
  636. package/src/tui/components/SpinnerByline.jsx +21 -2
  637. package/src/tui/components/question-panel-model.mjs +156 -0
  638. package/src/tui/components/status-line/local-line.mjs +10 -2
  639. package/src/tui/dist/index.mjs +2897 -1722
  640. package/src/tui/session/active-tool-summary.mjs +1 -1
  641. package/src/tui/session/context-state.mjs +4 -5
  642. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  643. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  644. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  645. package/src/tui/session/quota-resume.mjs +140 -61
  646. package/src/tui/session/session-api/commands.mjs +14 -10
  647. package/src/tui/session/session-api/controls.mjs +14 -2
  648. package/src/tui/session/session-api/integrations.mjs +9 -2
  649. package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
  650. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  651. package/src/tui/session/session-api/lifecycle.mjs +14 -11
  652. package/src/tui/session/session-api/media.mjs +2 -0
  653. package/src/tui/session/session-api/routes.mjs +81 -57
  654. package/src/tui/session/session-api/settings.mjs +9 -3
  655. package/src/tui/session/session-api/worktree.mjs +3 -2
  656. package/src/tui/session/session-api.mjs +1 -0
  657. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  658. package/src/tui/session/session-flow/drain.mjs +6 -4
  659. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  660. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  661. package/src/tui/session/session-flow/queue.mjs +1 -1
  662. package/src/tui/session/tool-approval.mjs +20 -8
  663. package/src/tui/session/transcript-spill.mjs +14 -7
  664. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  665. package/src/tui/session/tui-steering-persist.mjs +3 -5
  666. package/src/tui/session/turn-quiet.mjs +53 -0
  667. package/src/tui/session/turn-stream.mjs +179 -32
  668. package/src/tui/session/turn.mjs +50 -36
  669. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  670. package/src/tui/spinner-meta.mjs +10 -0
  671. package/src/tui/spinner-verbs.mjs +3 -0
  672. package/src/ui/statusline.mjs +13 -3
  673. package/src/workflows/default/WORKFLOW.md +3 -1
  674. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  675. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  676. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  677. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
  678. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  679. package/src/session-runtime/turn/share-ops.mjs +0 -77
  680. package/src/tui/session/cross-surface-share.mjs +0 -406
  681. package/src/tui/session/live-share/delta.mjs +0 -153
  682. package/src/tui/session/live-share/mirror.mjs +0 -106
  683. package/src/tui/session/live-share/owner.mjs +0 -254
  684. package/src/tui/session/live-share/retry.mjs +0 -54
  685. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  686. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  687. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  688. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  689. package/src/tui/session/live-share/viewer.mjs +0 -99
  690. package/src/tui/session/live-share/wire.mjs +0 -44
  691. package/src/tui/session/live-share.mjs +0 -154
  692. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -2,7 +2,12 @@
2
2
  // standby fast path, the spawn-burst gate around process creation, and the
3
3
  // delayed live foreground record once the command has reached a shell.
4
4
  import { acquire as acquireChildSpawnSlot } from '../../../../shared/child-spawn-gate.mjs';
5
- import { publishForegroundShellRecord, trackForegroundShellJob } from '../builtin/shell-jobs.mjs';
5
+ import {
6
+ killShellJob,
7
+ publishForegroundShellRecord,
8
+ trackForegroundShellJob,
9
+ waitForShellJob,
10
+ } from '../builtin/shell-jobs.mjs';
6
11
  import {
7
12
  nativeSpawnFileCaptureReady,
8
13
  nativeSpawnSupportsStdinPipe,
@@ -13,6 +18,11 @@ import { _maybeEncodePowerShellCommand } from '../shell-powershell.mjs';
13
18
  import { spawnShellWithRetry as _spawnShellWithRetry } from './shell-spawn-retry.mjs';
14
19
  import { STANDBY_ARGS, takeWarmShellStandby } from './shell-warm-standby.mjs';
15
20
  import { SHELL_OUTPUT_DISK_CAP } from '../shell-exec-output.mjs';
21
+ import { admitWorkspaceActivity, tryAdmitWorkspaceActivity } from '../../../../shared/worktrees/activity-gate.mjs';
22
+ import { worktreeError } from '../../../../shared/worktrees/contract.mjs';
23
+ import { capturePreKill, registerForegroundOwnedTree, treeKillForceSettle } from './shell-run-state.mjs';
24
+ import { releaseAdmissionOnConfirmedTermination } from './shell-run-settle.mjs';
25
+ import { killAfterSnapshot } from './shell-descendants.mjs';
16
26
 
17
27
  // Foreground visibility threshold. Every shell readout (CLI statusline,
18
28
  // desktop island) scans the on-disk job records, so a foreground command is
@@ -148,7 +158,7 @@ async function gatedSpawn({
148
158
  * the moment the command reached it. Throws on spawn failure; the caller
149
159
  * turns that into the spawn-failed result.
150
160
  */
151
- export async function spawnShellChild({
161
+ async function spawnAdmittedShellChild({
152
162
  run,
153
163
  shell,
154
164
  shellArg,
@@ -163,6 +173,9 @@ export async function spawnShellChild({
163
173
  clientHostPid,
164
174
  }) {
165
175
  const { useDirectArgv, spawnCommand, argv } = shapeArgv({ directArgv, shellArg, shellArgs, command, execScript });
176
+ // Set before any child exists: a startup that fails after the child is
177
+ // created still publishes a visible record and an owned termination hold.
178
+ run.foregroundRecordInput = { command, cwd, ownerSessionId, clientHostPid };
166
179
  const onChildError = (err) => {
167
180
  run.spawnError = run.spawnError || err;
168
181
  run.failurePhase = 'tool';
@@ -209,10 +222,22 @@ export async function spawnShellChild({
209
222
  clientHostPid,
210
223
  }));
211
224
  run.child = spawned.child;
225
+ registerForegroundOwnedTree(run, ownerSessionId);
226
+ const parentAdmission = run.workspaceAdmission;
227
+ const childAdmission = tryAdmitWorkspaceActivity(ownerSessionId || run.foregroundRecordId, cwd || process.cwd(), {
228
+ pid: Number(run.child.pid) || process.pid,
229
+ kind: 'command',
230
+ });
231
+ if (!childAdmission) throw worktreeError('WORKTREE_BUSY_JOBS', 'The command workspace changed during spawn.');
232
+ run.workspaceAdmission = () => {
233
+ childAdmission();
234
+ parentAdmission();
235
+ };
212
236
  spawned.attachErrorHandler(onChildError);
213
237
  // Feed the script only after the error handler is attached; server
214
238
  // messages cannot be processed before this synchronous block yields.
215
239
  // Single atomic write+EOF, as for the standby.
240
+ abortSignal?.throwIfAborted();
216
241
  if (standby) standby.feed(spawnCommand, cwd);
217
242
  else if (stdinScript !== null) spawned.child.writeStdin(stdinScript, { close: true });
218
243
  // The command has now reached a shell. This is the start moment every
@@ -224,15 +249,56 @@ export async function spawnShellChild({
224
249
  run.foregroundRecordTimer = null;
225
250
  if (run.settled || run.autoBackgrounded || !run.child?.pid) return;
226
251
  run.foregroundRecordPublished = true;
227
- publishForegroundShellRecord({
228
- jobId: run.foregroundRecordId,
229
- command,
230
- cwd,
231
- pid: run.child.pid,
232
- startedAtMs: run.commandStartedAtMs,
233
- ownerSessionId,
234
- clientHostPid,
235
- });
252
+ try {
253
+ publishForegroundShellRecord({
254
+ ...run.foregroundRecordInput,
255
+ jobId: run.foregroundRecordId,
256
+ pid: run.child.pid,
257
+ startedAtMs: run.commandStartedAtMs,
258
+ });
259
+ } catch (error) {
260
+ run.spawnError = error;
261
+ run.failureReason = 'workspace publication failed';
262
+ treeKillForceSettle(run, 'workspace-publication-failed');
263
+ }
236
264
  }, FOREGROUND_RECORD_DELAY_MS);
237
265
  run.foregroundRecordTimer.unref?.();
238
266
  }
267
+
268
+ /** Admission precedes both native process creation and feeding a warm shell. */
269
+ export async function spawnShellChild(input) {
270
+ input.run.workspaceAdmission = await admitWorkspaceActivity(
271
+ input.ownerSessionId || input.run.foregroundRecordId,
272
+ input.cwd || process.cwd(),
273
+ input.abortSignal,
274
+ { kind: 'command' }
275
+ );
276
+ try {
277
+ input.abortSignal?.throwIfAborted();
278
+ return await spawnAdmittedShellChild(input);
279
+ } catch (error) {
280
+ if (!input.run.child) {
281
+ input.run.workspaceAdmission();
282
+ input.run.workspaceAdmission = null;
283
+ } else {
284
+ try {
285
+ // Identities first: the kill may break the parent chain.
286
+ // Bounded: the kill is sent even if the snapshot hangs or fails.
287
+ await killAfterSnapshot(capturePreKill(input.run), () => killShellJob(input.run.foregroundRecordId));
288
+ const detail = await waitForShellJob(input.run.foregroundRecordId);
289
+ if (!detail || !['completed', 'failed', 'cancelled'].includes(detail.nativeStatus)) {
290
+ throw new Error('The child termination could not be confirmed; workspace admission is retained.');
291
+ }
292
+ input.run.workspaceAdmission?.();
293
+ input.run.workspaceAdmission = null;
294
+ } catch (cleanupError) {
295
+ input.run.killUnconfirmed = true;
296
+ // No settle will ever run for this run; the reservation is released
297
+ // only once the child has exited and its descendants are gone.
298
+ releaseAdmissionOnConfirmedTermination(input.run);
299
+ throw new AggregateError([error, cleanupError], 'Shell startup failed and workspace cleanup remains blocked.');
300
+ }
301
+ }
302
+ throw error;
303
+ }
304
+ }
@@ -4,8 +4,37 @@
4
4
  // tree-kill. The spawn, settle and auto-background phases live in their own
5
5
  // modules and read/write this one record.
6
6
  import { randomUUID } from 'node:crypto';
7
- import { retireForegroundShellRecord } from '../builtin/shell-jobs.mjs';
7
+ import { publishForegroundShellRecord, retireForegroundShellRecord } from '../builtin/shell-jobs.mjs';
8
8
  import { ShellTextDecoder, TaskOutput, treeKill } from '../shell-exec-output.mjs';
9
+ import { createProcessTreeTracker, killAfterSnapshot } from './shell-descendants.mjs';
10
+ import { registerOwnedShellTree } from './owned-shell-trees.mjs';
11
+
12
+ /** One pre-kill identity read of the run's tree (every kill path shares it):
13
+ * resolves true once the capture is complete, false when it failed. */
14
+ export function capturePreKill(run) {
15
+ run.terminationTracker = run.terminationTracker || createProcessTreeTracker({ pid: run.child.pid });
16
+ const rootExited = run.child.exitCode != null || run.child.signalCode != null;
17
+ return run.terminationTracker.capture({ rootExited }).catch(() => false);
18
+ }
19
+
20
+ /** Session close cancels every tree its session owns. For a foreground run
21
+ * that cancel must snapshot the identities first, exactly like the run's own
22
+ * kill, and mark the run owner-cancelled so its settle completes on confirmed
23
+ * termination instead of on the root's exit. */
24
+ export function registerForegroundOwnedTree(run, ownerSessionId) {
25
+ if (!ownerSessionId) return;
26
+ run.ownedTree = {
27
+ ownerSessionId,
28
+ prepareKill: () => {
29
+ if (run.settled || run.autoBackgrounded || !run.child?.pid) return true;
30
+ run.killed = true;
31
+ run.ownerCancelled = true;
32
+ run.killCause = run.killCause || 'session-close';
33
+ return run.terminationTracker?.complete === true || capturePreKill(run);
34
+ },
35
+ };
36
+ registerOwnedShellTree(run.foregroundRecordId, run.ownedTree);
37
+ }
9
38
 
10
39
  // Treekill + exit confirmation. treeKill alone leaves settle() pending on
11
40
  // 'close'/'exit'; on Windows a taskkill miss or a grandchild holding stdio
@@ -85,6 +114,12 @@ export function createShellRun({ abortSignal, resolve, jobId = null }) {
85
114
  foregroundRecordId: jobId || `job_${Date.now()}_${randomUUID().slice(0, 6)}`,
86
115
  foregroundRecordTimer: null,
87
116
  foregroundRecordPublished: false,
117
+ // Command/cwd/owner the live record is published with.
118
+ foregroundRecordInput: null,
119
+ // Process identities captured before a kill, and the stop() of the
120
+ // observation loop that holds the workspace until they are gone.
121
+ terminationTracker: null,
122
+ stopTerminationWatch: null,
88
123
  };
89
124
  }
90
125
 
@@ -149,6 +184,49 @@ export function clearForegroundRecord(run) {
149
184
  // Runtime of the COMMAND (see startMs).
150
185
  export const elapsedSinceStart = (run) => Math.max(0, Date.now() - (run.commandStartedAtMs || run.startMs));
151
186
 
187
+ /** The command's result is reported, but its processes are not confirmed
188
+ * gone: the live record stays — now marked unconfirmed — until the
189
+ * termination watch retires it. */
190
+ export function keepTerminationUnconfirmedRecord(run) {
191
+ if (run.foregroundRecordTimer) {
192
+ clearTimeout(run.foregroundRecordTimer);
193
+ run.foregroundRecordTimer = null;
194
+ }
195
+ if (!run.foregroundRecordInput || !run.child?.pid) return;
196
+ try {
197
+ publishForegroundShellRecord({
198
+ ...run.foregroundRecordInput,
199
+ jobId: run.foregroundRecordId,
200
+ pid: run.child.pid,
201
+ startedAtMs: run.commandStartedAtMs,
202
+ terminationUnconfirmed: true,
203
+ });
204
+ run.foregroundRecordPublished = true;
205
+ } catch {
206
+ /* the record is presentation; the workspace admission stays held */
207
+ }
208
+ }
209
+
210
+ // Record the tree's identities while the root is still alive, THEN kill: once
211
+ // an intermediate dies its children's parent links dangle and a snapshot taken
212
+ // afterwards can no longer find them.
213
+ // The kill waits for the snapshot at most PROCESS_TABLE_READ_BOUND_MS and is
214
+ // sent whether the snapshot succeeded, failed or is still pending (a late
215
+ // snapshot is still absorbed; a missing one leaves the outcome unknown, so the
216
+ // workspace stays held under the observation loop). The confirmation deadline
217
+ // starts once the kill is actually issued.
218
+ function snapshotThenKill(run, afterKill) {
219
+ if (!run.child?.pid) {
220
+ treeKill(run.child);
221
+ afterKill();
222
+ return;
223
+ }
224
+ void killAfterSnapshot(capturePreKill(run), () => {
225
+ treeKill(run.child);
226
+ afterKill();
227
+ });
228
+ }
229
+
152
230
  export function treeKillForceSettle(run, cause) {
153
231
  run.killed = true;
154
232
  run.killCause = run.killCause || cause || 'runtime-guard';
@@ -161,8 +239,7 @@ export function treeKillForceSettle(run, cause) {
161
239
  if (run.child?.exitCode != null || run.child?.signalCode != null) return;
162
240
  attempts += 1;
163
241
  if (attempts < KILL_CONFIRM_ATTEMPTS) {
164
- treeKill(run.child);
165
- armConfirmation();
242
+ snapshotThenKill(run, armConfirmation);
166
243
  return;
167
244
  }
168
245
  run.partialOutput = true;
@@ -172,6 +249,5 @@ export function treeKillForceSettle(run, cause) {
172
249
  }, KILL_CONFIRM_INTERVAL_MS);
173
250
  if (deadline.unref) deadline.unref();
174
251
  };
175
- treeKill(run.child);
176
- armConfirmation();
252
+ snapshotThenKill(run, armConfirmation);
177
253
  }
@@ -1,8 +1,9 @@
1
1
  // UI-diff side channel: a committed apply_patch (or edit-tool write) records
2
2
  // a turn-review change entry and a per-call diff the desktop/TUI tool cards
3
3
  // pick up. Display only — never affects edit semantics.
4
- import { createTwoFilesPatch } from 'diff';
4
+ import { createLineDiffBudget, lineDiffHunks, unifiedHunksBody } from '../../../../shared/bounded-line-diff.mjs';
5
5
  import { boundReviewPatch } from '../../../../shared/review-diff.mjs';
6
+ import { decodeText } from '../../../../shared/turn-changes.mjs';
6
7
  import { recordTurnDiffChanges } from '../../../../shared/turn-snapshot.mjs';
7
8
  import { pathKey, resolveV4AEntryPath } from './paths.mjs';
8
9
  import { patchHeaderPathForResolved } from './read-redirects.mjs';
@@ -38,31 +39,21 @@ function headerPath(value) {
38
39
  .replace(/\\/g, '/');
39
40
  }
40
41
 
41
- const DIFF_TIMEOUT_MS = 100;
42
-
43
- const utf8 = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
44
-
45
42
  function isOmitted(value) {
46
43
  return Boolean(value) && typeof value === 'object' && !(value instanceof Uint8Array) && value.omitted === true;
47
44
  }
48
45
 
49
- // Text of one side: '' for an absent file, null when it is not UTF-8 text.
46
+ // Text of one side: '' for an absent file, null when it is binary (not UTF-8
47
+ // or holding a NUL byte) — the same rule as the turn review's tracker diffs.
50
48
  function sideText(value) {
51
- if (value == null) return '';
52
- if (typeof value === 'string') return value;
53
- if (value instanceof Uint8Array) {
54
- try {
55
- return utf8.decode(value);
56
- } catch {
57
- return null;
58
- }
59
- }
49
+ if (value == null || typeof value === 'string' || value instanceof Uint8Array) return decodeText(value);
60
50
  return null;
61
51
  }
62
52
 
63
53
  // One file's change, from the call's own before and after states: absent
64
54
  // (null), bytes or text, or an omitted marker when the bytes were not kept.
65
- function renderCallChange({ displayPath, newDisplayPath, before, after }) {
55
+ // `budget` is the call's line-diff budget.
56
+ function renderCallChange({ displayPath, newDisplayPath, before, after }, budget) {
66
57
  const oldName = headerPath(displayPath) || 'unknown file';
67
58
  const newName = headerPath(newDisplayPath) || oldName;
68
59
  const oldHeader = before == null ? '/dev/null' : `a/${oldName}`;
@@ -82,23 +73,46 @@ function renderCallChange({ displayPath, newDisplayPath, before, after }) {
82
73
  return oldName === newName ? '' : `${head}similarity index 100%\nrename from ${oldName}\nrename to ${newName}\n`;
83
74
  }
84
75
  const rename = oldName === newName ? '' : `rename from ${oldName}\nrename to ${newName}\n`;
85
- try {
86
- const generated = createTwoFilesPatch(oldHeader, newHeader, oldText, newText, '', '', {
87
- context: 3,
88
- timeout: DIFF_TIMEOUT_MS,
89
- });
90
- const start = generated.search(/^--- /m);
91
- if (start >= 0) return `${head}${rename}${generated.slice(start).replace(/\n*$/, '\n')}`;
92
- } catch {
93
- // A pathological diff timing out must not stall tool completion.
76
+ const { hunks } = lineDiffHunks(oldText, newText, budget, [before ?? null, after ?? null]);
77
+ return `${head}${rename}${unifiedHunksBody(oldHeader, newHeader, hunks)}`;
78
+ }
79
+
80
+ // Added/deleted lines of one rendered change, counted in its hunks only.
81
+ function hunkLineCounts(patch) {
82
+ let additions = 0;
83
+ let deletions = 0;
84
+ let inHunk = false;
85
+ for (const line of patch.split('\n')) {
86
+ if (line.startsWith('@@')) inHunk = true;
87
+ else if (inHunk && line.startsWith('+')) additions += 1;
88
+ else if (inHunk && line.startsWith('-')) deletions += 1;
94
89
  }
95
- return `${head}${rename}Binary files ${oldHeader} and ${newHeader} differ\n`;
90
+ return { additions, deletions };
91
+ }
92
+
93
+ // Each change with the line counts of its own unbounded diff (the turn review
94
+ // sums them per file), plus the call's whole diff, within the call's budget.
95
+ export function measureCallChanges(changes, budget = createLineDiffBudget()) {
96
+ const patches = (changes || []).map((change) => renderCallChange(change, budget));
97
+ return {
98
+ diff: patches.join(''),
99
+ changes: (changes || []).map((change, index) => ({ ...change, ...hunkLineCounts(patches[index]) })),
100
+ };
96
101
  }
97
102
 
98
103
  // A call's card shows the change that call made — its own before against its
99
104
  // own after — never the turn's running total for the same files.
100
105
  export function callUiDiff(changes) {
101
- return (changes || []).map(renderCallChange).join('');
106
+ return measureCallChanges(changes).diff;
107
+ }
108
+
109
+ // Fold the call's measured changes into the turn review and publish its card
110
+ // diff. Both share one line-diff budget: the call is one operation.
111
+ function recordCallChanges(callId, sessionId, changes) {
112
+ const budget = createLineDiffBudget();
113
+ const measured = measureCallChanges(changes, budget);
114
+ recordTurnDiffChanges(sessionId, measured.changes, budget);
115
+ registerApplyPatchUiDiff(callId, measured.diff);
102
116
  }
103
117
 
104
118
  // Edit-tool UI diff: a successful single-file str-replace edit records the
@@ -108,21 +122,42 @@ export function callUiDiff(changes) {
108
122
  export function registerEditToolUiDiff({ callId, sessionId, basePath, fullPath, before, after }) {
109
123
  if (!callId || !sessionId || typeof fullPath !== 'string') return;
110
124
  try {
111
- const changes = [
112
- {
113
- path: fullPath,
114
- displayPath: patchHeaderPathForResolved(basePath || '', fullPath),
115
- before: before ?? null,
116
- after: after ?? null,
117
- },
118
- ];
119
- recordTurnDiffChanges(sessionId, changes);
120
- registerApplyPatchUiDiff(callId, callUiDiff(changes));
125
+ recordCallChanges(callId, sessionId, [toolFileChange(basePath, { fullPath, before, after })]);
121
126
  } catch {
122
127
  // best-effort display channel
123
128
  }
124
129
  }
125
130
 
131
+ function toolFileChange(basePath, { fullPath, before, after }) {
132
+ return {
133
+ path: fullPath,
134
+ displayPath: patchHeaderPathForResolved(basePath || '', fullPath),
135
+ before: before ?? null,
136
+ after: after ?? null,
137
+ };
138
+ }
139
+
140
+ // Writes of a tool without a per-call card (tidy, office): each change
141
+ // `{ fullPath, before, after }` (null = absent, bytes, or an omitted marker)
142
+ // joins the turn review with its own line counts, like an edit-tool write.
143
+ // Side channel only — never affects the tool result.
144
+ export function recordToolFileChanges({ sessionId, basePath, changes }) {
145
+ if (!sessionId || !changes?.length) return;
146
+ try {
147
+ const budget = createLineDiffBudget();
148
+ recordTurnDiffChanges(
149
+ sessionId,
150
+ measureCallChanges(
151
+ changes.map((change) => toolFileChange(basePath, change)),
152
+ budget
153
+ ).changes,
154
+ budget
155
+ );
156
+ } catch {
157
+ // best-effort review channel
158
+ }
159
+ }
160
+
126
161
  // Review content of one snapshot: null when absent, the bytes when captured,
127
162
  // and an explicit omitted marker (never empty bytes) when they were not.
128
163
  function snapshotContent(snapshot) {
@@ -184,8 +219,7 @@ export function registerCommittedPatchUiDiff({
184
219
  after: snapshotContent(after),
185
220
  });
186
221
  }
187
- recordTurnDiffChanges(sessionId, changes);
188
- registerApplyPatchUiDiff(callId, callUiDiff(changes));
222
+ recordCallChanges(callId, sessionId, changes);
189
223
  } catch {
190
224
  // Review collection is a side channel and must never affect committed
191
225
  // apply_patch success/failure semantics.
@@ -105,8 +105,25 @@ export function formatToolStartProgress(name, args = {}) {
105
105
  // ── host_input / cwd ─────────────────────────────────────────────
106
106
  case 'inject_input':
107
107
  return 'injecting input';
108
- case 'cwd':
108
+ case 'cwd': // legacy: old transcripts
109
109
  return a.action === 'set' ? 'setting cwd' : 'resolving cwd';
110
+ case 'session':
111
+ switch (a.action) {
112
+ case 'set-project':
113
+ return 'setting project';
114
+ case 'rename':
115
+ return 'renaming session';
116
+ case 'compact':
117
+ return 'scheduling compaction';
118
+ case 'fork':
119
+ return 'forking into a new session';
120
+ case 'favorite':
121
+ return a.value === false ? 'unfavoriting session' : 'favoriting session';
122
+ case 'archive':
123
+ return a.value === false ? 'unarchiving session' : 'archiving session';
124
+ default:
125
+ return 'checking session';
126
+ }
110
127
 
111
128
  default:
112
129
  return `running ${name}`;
@@ -27,9 +27,9 @@ export {
27
27
  } from './shell-powershell.mjs';
28
28
  export { stripAnsi, ExecResult } from './shell-exec-output.mjs';
29
29
 
30
- async function _execPolicyBlockMessage(command) {
30
+ async function _execPolicyBlockMessage(command, elevationApproved = false) {
31
31
  const { checkExecPolicyMessage } = await import('./bash-policy-scan.mjs');
32
- return checkExecPolicyMessage(command);
32
+ return checkExecPolicyMessage(command, { elevationApproved });
33
33
  }
34
34
 
35
35
  // Admission-wait ceiling. Without it a saturated shell lane (all leases held
@@ -233,7 +233,7 @@ const failedResult = (run, stderr, failureReason) =>
233
233
  // Admission lease, policy preflight, then the spawn. Resolves the run with a
234
234
  // tool-phase failure and returns false when the command never reaches a shell.
235
235
  async function admitAndSpawn(run, params, { admissionWaitMs, onSaturated }) {
236
- const { admission, command, ownerSessionId, abortSignal } = params;
236
+ const { admission, command, ownerSessionId, abortSignal, elevationApproved } = params;
237
237
  try {
238
238
  run.resourceLease = await acquireShellLeaseBounded(admission, {
239
239
  abortSignal,
@@ -241,7 +241,7 @@ async function admitAndSpawn(run, params, { admissionWaitMs, onSaturated }) {
241
241
  label: `[task_id: ${run.foregroundRecordId}] ${String(command || '').slice(0, 120)}`,
242
242
  ownerKey: ownerSessionId,
243
243
  });
244
- const policyErr = await _execPolicyBlockMessage(command);
244
+ const policyErr = await _execPolicyBlockMessage(command, elevationApproved === true);
245
245
  if (policyErr) {
246
246
  await releaseResourceLease(run);
247
247
  run.resolveResult(failedResult(run, policyErr, 'preflight failed'));
@@ -544,6 +544,8 @@ export function execShellCommand(options) {
544
544
  // hands the script to the shell out-of-band — see the POSIX env+eval path in
545
545
  // bash-tool.mjs, which keeps the command body out of the child's argv.
546
546
  execScript = null,
547
+ // The user approved this call's elevation 'ask' decision (runtime-set).
548
+ elevationApproved = false,
547
549
  } = options;
548
550
  return new Promise(async (resolve) => {
549
551
  const run = createShellRun({ abortSignal, resolve, jobId });
@@ -565,6 +567,7 @@ export function execShellCommand(options) {
565
567
  abortSignal,
566
568
  directArgv,
567
569
  execScript,
570
+ elevationApproved,
568
571
  ownerSessionId,
569
572
  clientHostPid,
570
573
  },
@@ -2,7 +2,7 @@ import { extractHeredocBodies, extractShellCInner, stripQuotedAndHeredoc } from
2
2
  import { extractPowerShellCommandInner } from './shell-powershell.mjs';
3
3
  import { decodePowerShellEncodedCommand, isBlockedCommand, WRAPPER_NAMES } from './shell-policy.mjs';
4
4
 
5
- /** @typedef {'allow'|'deny'} ExecPolicyDecision */
5
+ /** @typedef {'allow'|'ask'|'deny'} ExecPolicyDecision */
6
6
 
7
7
  const EXEC_POLICY_DENY_PATTERNS = [
8
8
  /\b(curl|wget|fetch|Invoke-WebRequest|iwr)\b[^\n|&;]*\|[^\n|&;]*\b(sh|bash|zsh|dash|pwsh|powershell)(?:\.exe)?\b/i,
@@ -16,9 +16,28 @@ const EXEC_POLICY_DENY_PATTERNS = [
16
16
  // lookahead instead of the previous bare `iex\s+`.
17
17
  /\|\s*iex\b/i,
18
18
  /\biex\s+[$("'@]/i,
19
- /\bStart-Process\b[^\n]*\s-Verb\s+RunAs\b/i,
20
19
  ];
21
20
 
21
+ // Elevated launch: `Start-Process` (or its aliases `saps` / `start`) with
22
+ // `-Verb RunAs`. Not a hard deny — the user is asked (parity with Claude Code's
23
+ // "Command requests elevated privileges"). `-Verb` may be abbreviated to any
24
+ // prefix (`-v`, `-ve`, `-ver`) and take its value after a space or a colon.
25
+ // `Start-Process` matches anywhere (as the former deny rule did); the short
26
+ // aliases only at a command position so `npm start -v RunAs` stays allowed.
27
+ const ELEVATION_ASK_PATTERN =
28
+ /(?:\bStart-Process\b|(?:^|[;&|({=\n])\s*(?:&\s*)?(?:saps|start)(?![\w-]))[^\n]*?\s-v(?:e(?:rb?)?)?(?:\s*:\s*|\s+)RunAs\b/i;
29
+ const ELEVATION_ASK_REASON = 'Command requests elevated privileges';
30
+
31
+ // PowerShell spellings of the same token that the quote-stripping pass would
32
+ // otherwise hide or split: backtick line continuation, backtick-escaped
33
+ // letters (`-V`erb`), and a quoted `-Verb` value (`-Verb:'RunAs'`).
34
+ function _normalizeElevationSyntax(text) {
35
+ return String(text || '')
36
+ .replace(/`\r?\n/g, ' ')
37
+ .replace(/`([A-Za-z])/g, '$1')
38
+ .replace(/(\s-v\w*(?:\s*:\s*|\s+))(['"])\s*RunAs\s*\2/gi, '$1RunAs');
39
+ }
40
+
22
41
  // Verbs with no non-destructive invocation. `dd` is deliberately ABSENT: the
23
42
  // disk-destroying form (`of=/dev/<disk>`) is hard-blocked at every command
24
43
  // position by shell-policy, while `dd if=/dev/zero of=file` is the ordinary
@@ -39,12 +58,44 @@ const EXEC_POLICY_DENY_COMMANDS = new Set([
39
58
  'parted',
40
59
  ]);
41
60
 
42
- const _POLICY_RANK = { allow: 0, deny: 1 };
61
+ const _POLICY_RANK = { allow: 0, ask: 1, deny: 2 };
43
62
 
44
63
  // EVERY command position, not just the first: a deny-listed verb after `&&`,
45
64
  // `;`, `|` or a newline is still an execution request, and reading only
46
65
  // segment 0 let `true && shutdown /s` through. Callers pass quote-stripped
47
66
  // text, so prose inside a string ("graceful shutdown") never reaches here.
67
+ const _ELEVATION_WRAPPERS = new Set(['sudo', 'doas', 'pkexec', 'gsudo']);
68
+ const _bareName = (token) =>
69
+ token
70
+ .replace(/^.*[\\/]/, '')
71
+ .toLowerCase()
72
+ .replace(/\.(exe|cmd|bat|com)$/i, '');
73
+
74
+ // Returns the first privilege-escalation wrapper (sudo, doas, pkexec, gsudo,
75
+ // with or without path/extension) found at any command position, else null.
76
+ function _elevationWrapperAtPositions(command) {
77
+ for (const seg of String(command || '').split(/[;&|\n]+/)) {
78
+ const tokens = seg.trim().split(/\s+/).filter(Boolean);
79
+ let i = 0;
80
+ while (i < tokens.length) {
81
+ const t = tokens[i];
82
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
83
+ i++;
84
+ continue;
85
+ }
86
+ const base = _bareName(t);
87
+ if (_ELEVATION_WRAPPERS.has(base)) return base;
88
+ if (WRAPPER_NAMES.has(base)) {
89
+ i++;
90
+ while (i < tokens.length && (/^[-+]/.test(tokens[i]) || /^\d+[smhd]?$/.test(tokens[i]))) i++;
91
+ continue;
92
+ }
93
+ break;
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+
48
99
  function _commandNamesAtPositions(command) {
49
100
  const names = [];
50
101
  for (const seg of String(command || '').split(/[;&|\n]+/)) {
@@ -56,7 +107,7 @@ function _commandNamesAtPositions(command) {
56
107
  i++;
57
108
  continue;
58
109
  }
59
- if (WRAPPER_NAMES.has(t.toLowerCase())) {
110
+ if (WRAPPER_NAMES.has(_bareName(t))) {
60
111
  i++;
61
112
  while (i < tokens.length && (/^[-+]/.test(tokens[i]) || /^\d+[smhd]?$/.test(tokens[i]))) i++;
62
113
  continue;
@@ -74,14 +125,15 @@ function classifyExecPolicy(command) {
74
125
  if (!text.trim()) return { decision: 'allow', reason: '' };
75
126
  // Scan executable syntax, not quoted log/search text. Recursively preserve
76
127
  // actual shell, PowerShell, heredoc, and encoded-command payload coverage.
77
- const executableTargets = [
78
- stripQuotedAndHeredoc(text),
79
- ...extractShellCInner(text).map(stripQuotedAndHeredoc),
80
- ...extractPowerShellCommandInner(text).map(stripQuotedAndHeredoc),
81
- ...extractHeredocBodies(text).map(stripQuotedAndHeredoc),
128
+ const rawTargets = [
129
+ text,
130
+ ...extractShellCInner(text),
131
+ ...extractPowerShellCommandInner(text),
132
+ ...extractHeredocBodies(text),
82
133
  ];
83
134
  const decodedPowerShell = decodePowerShellEncodedCommand(text);
84
- if (decodedPowerShell) executableTargets.push(stripQuotedAndHeredoc(decodedPowerShell));
135
+ if (decodedPowerShell) rawTargets.push(decodedPowerShell);
136
+ const executableTargets = rawTargets.map(stripQuotedAndHeredoc);
85
137
  if (executableTargets.some((target) => isBlockedCommand(target))) {
86
138
  return {
87
139
  decision: 'deny',
@@ -115,6 +167,24 @@ function classifyExecPolicy(command) {
115
167
  };
116
168
  }
117
169
  }
170
+ // Elevation asks only after every deny rule above has had its say.
171
+ for (const target of rawTargets) {
172
+ const hit = ELEVATION_ASK_PATTERN.exec(stripQuotedAndHeredoc(_normalizeElevationSyntax(target)));
173
+ if (hit) {
174
+ return {
175
+ decision: 'ask',
176
+ reason: ELEVATION_ASK_REASON,
177
+ rule: 'elevation',
178
+ match: hit[0].trim().slice(0, 80),
179
+ };
180
+ }
181
+ }
182
+ for (const target of executableTargets) {
183
+ const wrapper = _elevationWrapperAtPositions(target);
184
+ if (wrapper) {
185
+ return { decision: 'ask', reason: ELEVATION_ASK_REASON, rule: 'elevation', match: wrapper };
186
+ }
187
+ }
118
188
  // Destructive-but-legitimate commands are NOT judged here. The caller
119
189
  // computes that non-blocking warning once (getDedupedDestructiveWarnings)
120
190
  // and prepends it to the result; deriving it again per scan target only
@@ -140,9 +210,15 @@ export function evaluateExecPolicyFromTargets(targets) {
140
210
  return worst;
141
211
  }
142
212
 
143
- /** Pre-spawn block message — deny is the only decision this scan produces. */
144
- export function formatExecPolicyBlockMessage(policyResult) {
213
+ /** Pre-spawn block message. An 'ask' decision blocks unless the runtime
214
+ * already obtained the user's approval for this call (`elevationApproved`). */
215
+ export function formatExecPolicyBlockMessage(policyResult, { elevationApproved = false } = {}) {
145
216
  const r = policyResult || { decision: 'allow' };
217
+ if (r.decision === 'ask') {
218
+ if (elevationApproved === true) return null;
219
+ const rule = r.rule ? ` [rule ${r.rule}${r.match ? `: "${r.match}"` : ''}]` : '';
220
+ return `Error: command requires user approval for elevation — ${r.reason || ELEVATION_ASK_REASON}${rule}; no approval was granted for this call`;
221
+ }
146
222
  if (r.decision === 'deny') {
147
223
  const rule = r.rule ? ` [rule ${r.rule}${r.match ? `: "${r.match}"` : ''}]` : '';
148
224
  const alt = r.alternative ? `; instead: ${r.alternative}` : '';
@@ -17,6 +17,8 @@ export const WRAPPER_NAMES = new Set([
17
17
  'env',
18
18
  'sudo',
19
19
  'doas',
20
+ 'pkexec',
21
+ 'gsudo',
20
22
  'nice',
21
23
  'stdbuf',
22
24
  'chronic',