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
@@ -3,44 +3,150 @@
3
3
  import { statSync } from 'node:fs';
4
4
  import { resolve } from 'node:path';
5
5
  import { listProjects } from '../../runtime/shared/projects.mjs';
6
+ import { applySessionSidebarChange } from '../../runtime/shared/session-sidebar-host.mjs';
6
7
  import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
7
8
 
9
+ const USER_TITLE_ERROR = 'session: the user already titled this session; the title was not changed';
10
+
8
11
  export function createWorkspaceToolHandlers({
9
12
  rt,
10
13
  goalRuntime,
11
14
  agentTool,
12
15
  notifyFnForSession,
13
- applyResolvedCwd,
14
16
  getWorkspaceApi = () => null,
17
+ getSessionManager = () => null,
18
+ getLifecycleApi = () => null,
19
+ executeSessionControl = null,
15
20
  }) {
16
21
  // The Lead's own worktree, on the user's request: the same authority the
17
22
  // branch chip menu drives, tolerating the calling turn but nothing else
18
23
  // running (workers, background shells).
19
- const worktreeAction = async (action, args, callerCtx) => {
20
- const workspace = getWorkspaceApi();
21
- if (!workspace) throw new Error(`cwd: ${action} is unavailable in this runtime`);
24
+ const assertLead = (action, callerCtx) => {
22
25
  const callerSessionId = callerCtx?.callerSessionId || rt.session?.id || null;
23
26
  if (!rt.session?.id || callerSessionId !== rt.session.id) {
24
- throw new Error(`cwd: ${action} belongs to the Lead session`);
27
+ throw new Error(`session: ${action} belongs to the Lead session`);
28
+ }
29
+ return rt.session.id;
30
+ };
31
+
32
+ const worktreeAction = async (action, args, callerCtx) => {
33
+ const workspace = getWorkspaceApi();
34
+ if (!workspace) throw new Error(`session: ${action} is unavailable in this runtime`);
35
+ assertLead(action, callerCtx);
36
+ let result;
37
+ if (action === 'merge-worktree') {
38
+ result = await workspace.mergeWorkspace({ confirmed: true }, { ownTurn: true });
39
+ } else if (action === 'remove-worktree') {
40
+ result = await workspace.removeWorktree({ force: args?.force === true }, { ownTurn: true });
41
+ } else if (action === 'list-worktrees') {
42
+ result = await workspace.listWorktrees();
43
+ } else {
44
+ result = await workspace.pruneWorktrees();
25
45
  }
26
- const result =
27
- action === 'merge-worktree'
28
- ? await workspace.mergeWorkspace({ confirmed: true }, { ownTurn: true })
29
- : action === 'remove-worktree'
30
- ? await workspace.removeWorktree({ force: args?.force === true }, { ownTurn: true })
31
- : action === 'list-worktrees'
32
- ? await workspace.listWorktrees()
33
- : await workspace.pruneWorktrees();
34
46
  return JSON.stringify({ action, cwd: rt.currentCwd, result }, null, 2);
35
47
  };
36
48
 
37
49
  const WORKTREE_ACTIONS = new Set(['merge-worktree', 'remove-worktree', 'list-worktrees', 'prune-worktrees']);
50
+ const SIDEBAR_ACTIONS = new Set(['favorite', 'archive']);
38
51
 
39
- const cwd = async (args, { callerCtx, callerCwd }) => {
40
- const action = clean(args?.action || (args?.path ? 'set' : 'get')).toLowerCase();
52
+ // Sidebar flags only (the desktop's favorite/archive metadata).
53
+ const sidebarAction = async (action, args, callerCtx) => {
54
+ const sessionId = assertLead(action, callerCtx);
55
+ if (typeof args?.value !== 'boolean') throw new Error(`session: value (boolean) is required for action=${action}`);
56
+ const change = action === 'favorite' ? { favorite: args.value } : { archived: args.value };
57
+ try {
58
+ await applySessionSidebarChange(sessionId, change);
59
+ } catch (error) {
60
+ throw new Error(`session: ${action} failed (${error?.message || error})`);
61
+ }
62
+ return JSON.stringify({ action, sessionId, ...change }, null, 2);
63
+ };
64
+
65
+ const session = async (args, { callerCtx, callerCwd }) => {
66
+ const action = clean(args?.action || (args?.path ? 'set-project' : 'status')).toLowerCase();
67
+ const target = clean(args?.session_id);
68
+ if (['list', 'read', 'send', 'cancel', 'delete'].includes(action) || (action === 'status' && target)) {
69
+ const callerSessionId = assertLead(action, callerCtx);
70
+ if (typeof executeSessionControl !== 'function') {
71
+ throw new Error('session: cross-session control is unavailable in this runtime');
72
+ }
73
+ return JSON.stringify(await executeSessionControl({ ...args, action }, { callerSessionId }));
74
+ }
75
+ if (target && target !== assertLead(action, callerCtx)) {
76
+ throw new Error(`session: action=${action} only applies to the current session`);
77
+ }
41
78
  if (WORKTREE_ACTIONS.has(action)) return worktreeAction(action, args, callerCtx);
79
+ if (SIDEBAR_ACTIONS.has(action)) return sidebarAction(action, args, callerCtx);
42
80
  let currentCwd = callerCwd;
43
- if (action === 'list') {
81
+ if (action === 'status' || action === 'list-projects' || action === 'set-project') assertLead(action, callerCtx);
82
+ if (action === 'rename') {
83
+ const sessionId = assertLead(action, callerCtx);
84
+ if (rt.config?.aiSessionTitles === false) throw new Error('session: AI session titles are disabled in settings');
85
+ const title = clean(args?.title);
86
+ if (!title) throw new Error('session: title is required for action=rename');
87
+ const result = await getSessionManager()?.updateSessionAiTitle(sessionId, title);
88
+ if (!result?.ok) {
89
+ throw new Error(
90
+ result?.reason === 'user-title'
91
+ ? USER_TITLE_ERROR
92
+ : `session: rename failed (${result?.reason || 'unavailable'})`
93
+ );
94
+ }
95
+ // Mirror the store's truth onto the live session, never the AI title
96
+ // itself: a manual rename that landed while the save was awaited wins.
97
+ const stored = getSessionManager()?.getSession?.(sessionId);
98
+ if (stored && rt.session?.id === sessionId && stored !== rt.session) {
99
+ rt.session.title = stored.title;
100
+ rt.session.titleLocked = stored.titleLocked;
101
+ rt.session.titleSource = stored.titleSource;
102
+ rt.session.titleUpdatedAt = stored.titleUpdatedAt;
103
+ }
104
+ if (stored && stored.titleSource === 'user') throw new Error(USER_TITLE_ERROR);
105
+ return JSON.stringify({ action, sessionId, title: result.title }, null, 2);
106
+ }
107
+ if (action === 'compact') {
108
+ const sessionId = assertLead(action, callerCtx);
109
+ rt.pendingCompactSessionIds ??= new Set();
110
+ rt.pendingCompactSessionIds.add(sessionId);
111
+ return JSON.stringify(
112
+ { action, sessionId, scheduled: true, note: 'Compaction runs right after the current turn finishes.' },
113
+ null,
114
+ 2
115
+ );
116
+ }
117
+ if (action === 'fork') {
118
+ const sessionId = assertLead(action, callerCtx);
119
+ const lifecycle = getLifecycleApi();
120
+ if (typeof lifecycle?.inheritToNewSession !== 'function') {
121
+ throw new Error('session: fork is unavailable in this runtime');
122
+ }
123
+ const result = await lifecycle.inheritToNewSession(sessionId, {
124
+ compact: args?.compact === true,
125
+ titleSuffix: ' (Fork)',
126
+ });
127
+ return JSON.stringify(
128
+ { action, sourceSessionId: sessionId, sessionId: result.sessionId, compacted: result.compacted === true },
129
+ null,
130
+ 2
131
+ );
132
+ }
133
+ if (action === 'status') {
134
+ const current = rt.session;
135
+ return JSON.stringify(
136
+ {
137
+ sessionId: callerCtx?.callerSessionId || current?.id || null,
138
+ title: current?.title || null,
139
+ titleSource: current?.titleSource || null,
140
+ cwd: currentCwd,
141
+ project: current?.workspace?.projectPath || current?.desktopSession?.projectPath || currentCwd,
142
+ provider: current?.provider || null,
143
+ model: current?.model || null,
144
+ },
145
+ null,
146
+ 2
147
+ );
148
+ }
149
+ if (action === 'list-projects') {
44
150
  return JSON.stringify(
45
151
  {
46
152
  cwd: currentCwd,
@@ -50,18 +156,23 @@ export function createWorkspaceToolHandlers({
50
156
  2
51
157
  );
52
158
  }
53
- if (action === 'set') {
159
+ if (action === 'set-project') {
54
160
  const rawPath = clean(args?.path);
55
- if (!rawPath) throw new Error('cwd: path is required for action=set');
161
+ if (!rawPath) throw new Error('session: path is required for action=set-project');
56
162
  const nextCwd = resolve(callerCwd || process.cwd(), rawPath);
57
163
  const stat = statSync(nextCwd);
58
- if (!stat.isDirectory()) throw new Error(`cwd: not a directory: ${nextCwd}`);
59
- currentCwd =
60
- typeof callerCtx?.setCallerCwd === 'function'
61
- ? clean(await callerCtx.setCallerCwd(nextCwd)) || nextCwd
62
- : applyResolvedCwd(nextCwd, { persistProjectSelection: true });
63
- } else if (action !== 'get') {
64
- throw new Error(`cwd: unknown action "${action}"`);
164
+ if (!stat.isDirectory()) throw new Error(`session: not a directory: ${nextCwd}`);
165
+ // The Lead's own call: the runtime's Project switch authority admits it
166
+ // during the calling turn and refuses inside a managed worktree.
167
+ if (typeof callerCtx?.setCallerCwd === 'function') {
168
+ currentCwd = clean(await callerCtx.setCallerCwd(nextCwd)) || nextCwd;
169
+ } else {
170
+ const workspace = getWorkspaceApi();
171
+ if (!workspace) throw new Error('session: set-project is unavailable in this runtime');
172
+ currentCwd = await workspace.switchProject(nextCwd, { ownTurn: true });
173
+ }
174
+ } else {
175
+ throw new Error(`session: unknown action "${action}"`);
65
176
  }
66
177
  return JSON.stringify(
67
178
  {
@@ -74,7 +185,7 @@ export function createWorkspaceToolHandlers({
74
185
  };
75
186
 
76
187
  return {
77
- cwd,
188
+ session,
78
189
  goal: async (args, { name, callerCtx }) =>
79
190
  await goalRuntime.executeTool(name, args || {}, {
80
191
  callerSessionId: callerCtx?.callerSessionId || rt.session?.id || rt.reservedSessionId || null,
@@ -6,6 +6,7 @@
6
6
  * to channel tools.
7
7
  */
8
8
  import { clean } from '../runtime/agent/orchestrator/runtime-core/session-text.mjs';
9
+ import { createAskUserToolHandlers } from './internal-tool-executor/ask-user-tool.mjs';
9
10
  import { createBridgeToolHandlers } from './internal-tool-executor/bridge-tools.mjs';
10
11
  import { createFeatureToolHandlers } from './internal-tool-executor/feature-tools.mjs';
11
12
  import { createKnowledgeToolHandlers } from './internal-tool-executor/knowledge-tools.mjs';
@@ -29,12 +30,15 @@ export function createInternalToolExecutor({
29
30
  runNativeWebSearch,
30
31
  activeToolSurface,
31
32
  mcpStatus,
32
- applyResolvedCwd,
33
33
  skillToolContent,
34
34
  getWorkspaceApi,
35
+ getSessionManager,
36
+ getLifecycleApi,
37
+ executeSessionControl,
35
38
  }) {
36
39
  const handlers = {
37
40
  ...createBridgeToolHandlers({ rt }),
41
+ ...createAskUserToolHandlers({ rt }),
38
42
  ...createFeatureToolHandlers({ rt, setupTool, officeToolsEnabled, mediaToolEnabled, tidyToolEnabled }),
39
43
  ...createKnowledgeToolHandlers({
40
44
  rt,
@@ -52,8 +56,10 @@ export function createInternalToolExecutor({
52
56
  goalRuntime,
53
57
  agentTool,
54
58
  notifyFnForSession,
55
- applyResolvedCwd,
56
59
  getWorkspaceApi,
60
+ getSessionManager,
61
+ getLifecycleApi,
62
+ executeSessionControl,
57
63
  }),
58
64
  };
59
65
 
@@ -0,0 +1,187 @@
1
+ /**
2
+ * src/session-runtime/lifecycle/cold-heir.mjs - the record of a heir that is
3
+ * NOT opened: a sibling of the source session on the same route, cwd and
4
+ * Project, persisted to the store and left cold for a later resume.
5
+ *
6
+ * The heir starts from the source's own record (same provider/model, tool
7
+ * surface, system layer, desktop classification) the way /clear's cold fork
8
+ * does, minus everything that belongs to the source alone: its conversation,
9
+ * in-flight turn, provider continuation, usage readings, title, worktree and
10
+ * ownership/lineage links — the heir is a root Lead of its own, linked to the
11
+ * source only through `inheritedFromSessionId`.
12
+ */
13
+ import {
14
+ ensureCodexWireSessionId,
15
+ mintSessionId,
16
+ } from '../../runtime/agent/orchestrator/session/manager/session-id.mjs';
17
+ import {
18
+ refreshSessionWorkspaceContext,
19
+ resetSessionBp3Environment,
20
+ } from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
21
+ import { buildWorkspacePromptContext } from '../../runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs';
22
+ import {
23
+ invalidateContextUsageSnapshot,
24
+ invalidateProviderContextBaseline,
25
+ } from '../../runtime/agent/orchestrator/session/loop/compact-policy.mjs';
26
+ import { deleteSession, evictLiveSession, saveSessionAsync } from '../../runtime/agent/orchestrator/session/store.mjs';
27
+ import { projectWorkspace } from '../../runtime/shared/worktrees/contract.mjs';
28
+ import { writeStderrBestEffort } from '../../runtime/shared/best-effort-stderr.mjs';
29
+ import { replacementSessionCwd } from '../workspace/workspace-state.mjs';
30
+
31
+ // Per-turn and per-process state of the source: the in-flight turn, its
32
+ // transient serializer-stripped aliases, and one-shot pending work.
33
+ const SOURCE_RUNTIME_FIELDS = [
34
+ 'liveTurnMessages',
35
+ 'toolApprovalHook',
36
+ '_providerPrefixGuardState',
37
+ 'activeTurnCheckpoint',
38
+ 'deferredInitialRefreshPending',
39
+ 'pendingGoalReminder',
40
+ 'goalReminderRevision',
41
+ 'pendingCacheBreakIntent',
42
+ 'contextPressureUnanchoredAfterRestart',
43
+ 'contextPressureUnanchoredReason',
44
+ // Store read-back projections of the SOURCE file.
45
+ 'storageMtimeMs',
46
+ 'storageSize',
47
+ ];
48
+
49
+ // Identity the source owns: its title (the carry decides the heir's), import
50
+ // provenance (a dedupe key), its own inheritance link (the carry sets the
51
+ // heir's), Codex wire identity, lifecycle provenance (a 'cli-resume' detach
52
+ // hides a row from Recent), and every ownership / lineage / visibility link —
53
+ // a self-link copied from a recovered root Lead would point at the source and
54
+ // classify the heir as an agent-only child.
55
+ const SOURCE_IDENTITY_FIELDS = [
56
+ 'title',
57
+ 'titleLocked',
58
+ 'titleSource',
59
+ 'titleUpdatedAt',
60
+ 'importOrigin',
61
+ 'inheritedFromSessionId',
62
+ 'codexWireSessionId',
63
+ 'detachedReason',
64
+ 'sessionVisibility',
65
+ 'task_id',
66
+ 'taskId',
67
+ ];
68
+
69
+ // The heir is an ordinary, user-visible root Lead owned by nobody but itself,
70
+ // whatever the source's ownership history (same identity a new Lead session
71
+ // or an imported conversation gets).
72
+ const ROOT_LEAD_IDENTITY = Object.freeze({
73
+ owner: 'cli',
74
+ agent: 'lead',
75
+ lane: 'cli',
76
+ sourceType: 'lead',
77
+ sourceName: 'main',
78
+ parentSessionId: null,
79
+ ownerSessionId: null,
80
+ visibility: null,
81
+ agentTag: null,
82
+ taskType: null,
83
+ permissionMode: null,
84
+ scopeKey: null,
85
+ });
86
+
87
+ /**
88
+ * The source as of its last committed turn. Mid-turn, `messages` already
89
+ * holds the in-flight user prompt (pre-committed before the provider call)
90
+ * while `liveTurnMessages` holds the turn's working transcript; the prompt is
91
+ * not part of the conversation yet, so it does not travel. Never mutates.
92
+ */
93
+ export function committedSource(source) {
94
+ const messages = Array.isArray(source?.messages) ? source.messages : [];
95
+ const live = source?.liveTurnMessages;
96
+ if (!Array.isArray(live) || live === messages || messages.at(-1)?.role !== 'user') return source;
97
+ return { ...source, messages: messages.slice(0, -1) };
98
+ }
99
+
100
+ /** A fresh, empty heir record of `source` — system layer only, nothing saved. */
101
+ export function buildColdHeir(source, now = Date.now()) {
102
+ const heir = {
103
+ ...source,
104
+ id: mintSessionId(),
105
+ // The heir runs on the very route that built these blocks; copies, so
106
+ // the heir never shares a message object with the source.
107
+ messages: structuredClone((source.messages || []).filter((message) => message?.role === 'system')),
108
+ closed: false,
109
+ status: 'idle',
110
+ generation: 0,
111
+ createdAt: now,
112
+ updatedAt: now,
113
+ lastUsedAt: now,
114
+ lastHeartbeatAt: null,
115
+ mcpPid: process.pid,
116
+ clientHostPid: null,
117
+ providerState: undefined,
118
+ totalInputTokens: 0,
119
+ totalOutputTokens: 0,
120
+ totalToolCalls: 0,
121
+ reasoningUsage: null,
122
+ totalCachedReadTokens: 0,
123
+ totalCacheWriteTokens: 0,
124
+ tokensCumulative: 0,
125
+ lastInputTokens: 0,
126
+ lastOutputTokens: 0,
127
+ lastCachedReadTokens: 0,
128
+ lastCacheWriteTokens: 0,
129
+ lastContextTokens: 0,
130
+ lastContextTokensUpdatedAt: now,
131
+ lastContextTokensStaleAfterCompact: false,
132
+ ...ROOT_LEAD_IDENTITY,
133
+ };
134
+ for (const key of [...SOURCE_RUNTIME_FIELDS, ...SOURCE_IDENTITY_FIELDS]) delete heir[key];
135
+ ensureCodexWireSessionId(heir);
136
+ // The compaction archive sidecar is keyed by the source id.
137
+ if (heir.compaction?.archive) {
138
+ heir.compaction = { ...heir.compaction };
139
+ delete heir.compaction.archive;
140
+ }
141
+ // A worktree belongs to the session that created it: like /new, the heir
142
+ // starts in the Project folder instead of sharing (and on delete, removing)
143
+ // the source's worktree.
144
+ const projectFolder = replacementSessionCwd(source);
145
+ if (projectFolder) {
146
+ heir.cwd = projectFolder;
147
+ heir.workspace = projectWorkspace({ projectPath: projectFolder });
148
+ }
149
+ // The source's staged working-folder change (its prompt still rooted at an
150
+ // earlier folder) is the source's own: the heir's prompt is built for the
151
+ // folder it actually starts in. Project memory follows the Project, which a
152
+ // worktree shares, so the source's current memory slice carries over.
153
+ const pending = source.workspaceReroot;
154
+ delete heir.workspaceReroot;
155
+ if ((projectFolder || pending) && heir.cwd) {
156
+ refreshSessionWorkspaceContext(heir, {
157
+ cwd: heir.cwd,
158
+ ...buildWorkspacePromptContext(heir, heir.cwd),
159
+ coreMemoryContext: pending?.target?.coreMemoryContext,
160
+ });
161
+ }
162
+ invalidateContextUsageSnapshot(heir);
163
+ invalidateProviderContextBaseline(heir);
164
+ // The `# Session` block names the session it was stamped for; the heir's
165
+ // first turn stamps its own.
166
+ resetSessionBp3Environment(heir);
167
+ return heir;
168
+ }
169
+
170
+ /**
171
+ * Persist the heir durably, then drop it from the same-process live cache:
172
+ * it is a cold session until someone resumes it. A failed save removes the
173
+ * half-made record and rejects.
174
+ */
175
+ export async function persistColdHeir(heir) {
176
+ try {
177
+ await saveSessionAsync(heir);
178
+ } catch (error) {
179
+ try {
180
+ deleteSession(heir.id);
181
+ } catch (cleanupError) {
182
+ writeStderrBestEffort(`[inherit] cleanup of ${heir.id} failed: ${cleanupError?.message || cleanupError}\n`);
183
+ }
184
+ throw error;
185
+ }
186
+ evictLiveSession(heir.id);
187
+ }
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * src/session-runtime/lifecycle/inheritance.mjs - session inheritance
3
3
  * (/inherit): fit preflight and the carry of another session's conversation
4
- * into the freshly created heir.
4
+ * into the freshly created heir — the live one (inheritFrom) or a cold sibling
5
+ * persisted without switching (inheritToNewSession), through one carry core.
5
6
  */
6
7
  import { hasUserConversationMessage } from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
7
8
  import { stripEffortConfiguration } from '../../runtime/agent/orchestrator/providers/effort-configuration.mjs';
@@ -14,6 +15,7 @@ import {
14
15
  inheritanceRouteTarget,
15
16
  } from '../inheritance-fit.mjs';
16
17
  import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
18
+ import { buildColdHeir, committedSource, persistColdHeir } from './cold-heir.mjs';
17
19
 
18
20
  export function createInheritance(deps, { compactConversation, saveSession }) {
19
21
  const { getSession, getRoute, mgr, createCurrentSession, invalidateContextStatusCache, getReservedSessionId } = deps;
@@ -143,6 +145,44 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
143
145
  };
144
146
  }
145
147
 
148
+ /**
149
+ * The ONE carry every inheritance path shares: measure the source's
150
+ * conversation on the heir's scale, compact it for the heir when asked to
151
+ * or when it cannot fit, and append it to the (empty) heir with its
152
+ * inheritance boundary. Refusals throw before the heir is touched; the
153
+ * source is never mutated.
154
+ */
155
+ async function carryConversation(source, target, { compact = false } = {}) {
156
+ // System blocks belong to the session that BUILT them: the target's own
157
+ // prompt was composed for the current model, tool surface, and workflow.
158
+ // Only the conversation itself travels.
159
+ let carried = inheritableMessages(source.messages);
160
+ if (!hasUserConversationMessage(carried)) {
161
+ throw new Error('inheritFrom: the source session has no conversation to carry');
162
+ }
163
+ // Decide BEFORE anything moves, on the heir's own scale. This is the
164
+ // same function inheritancePreflight() answers with, so the surface that
165
+ // offered the carry and the runtime that performs it cannot disagree —
166
+ // and a refusal no longer has to unwind a half-filled transcript.
167
+ const fit = inheritanceFit(carried, target);
168
+ let compacted = false;
169
+ // compact:true summarizes even a conversation that fits; otherwise only
170
+ // one that cannot fit is compacted.
171
+ if (compact || (fit.known && !fit.fits)) {
172
+ const next = await fitConversationForHeir(source, target, carried, fit, { required: compact });
173
+ compacted = next !== carried;
174
+ carried = next;
175
+ }
176
+ target.messages.push(
177
+ ...stripEffortConfiguration(inheritedCompatReplayMessages(structuredClone(carried), source.provider))
178
+ );
179
+ target.inheritedFromSessionId = source.id;
180
+ target.updatedAt = Date.now();
181
+ recordInheritanceBoundary(target, source);
182
+ if (!clean(target.title) && clean(source.title)) target.title = source.title;
183
+ return { messages: carried.length, compacted };
184
+ }
185
+
146
186
  /**
147
187
  * Session inheritance (/inherit): carry another session's conversation
148
188
  * into THIS freshly created session, so the transcript continues under a
@@ -174,41 +214,45 @@ export function createInheritance(deps, { compactConversation, saveSession }) {
174
214
  }
175
215
  const source = mgr.getSession(id);
176
216
  if (!source) throw new Error(`inheritFrom: session ${id} was not found`);
177
- // System blocks belong to the session that BUILT them: the target's own
178
- // prompt was composed for the current model, tool surface, and workflow.
179
- // Only the conversation itself travels.
180
- let carried = inheritableMessages(source.messages);
181
- if (!hasUserConversationMessage(carried)) {
182
- throw new Error('inheritFrom: the source session has no conversation to carry');
183
- }
184
- // Decide BEFORE anything moves, on the heir's own scale. This is the
185
- // same function inheritancePreflight() answers with, so the surface that
186
- // offered the carry and the runtime that performs it cannot disagree —
187
- // and a refusal no longer has to unwind a half-filled transcript.
188
- const fit = inheritanceFit(carried, target);
189
- // compact:true summarizes even a conversation that fits; otherwise only
190
- // one that cannot fit is compacted.
191
- if (compact || (fit.known && !fit.fits)) {
192
- carried = await fitConversationForHeir(source, target, carried, fit, { required: compact });
193
- }
194
- target.messages.push(
195
- ...stripEffortConfiguration(inheritedCompatReplayMessages(structuredClone(carried), source.provider))
196
- );
217
+ const { messages } = await carryConversation(source, target, { compact });
197
218
  invalidateContextStatusCache();
198
- target.inheritedFromSessionId = source.id;
199
- target.updatedAt = Date.now();
200
- recordInheritanceBoundary(target, source);
201
- if (!clean(target.title) && clean(source.title)) target.title = source.title;
202
219
  saveSession(target, { immediate: true });
203
220
  invalidateContextStatusCache();
204
221
  return {
205
222
  sessionId: target.id,
206
223
  sourceSessionId: source.id,
207
- messages: carried.length,
224
+ messages,
208
225
  provider: target.provider,
209
226
  model: target.model,
210
227
  };
211
228
  }
212
229
 
213
- return { inheritancePreflight, inheritFrom };
230
+ /**
231
+ * Inheritance WITHOUT switching: carry a session's conversation (normally
232
+ * the live one, possibly mid-turn) into a NEW session on the same route,
233
+ * cwd and Project, persisted cold for a later resume. The live session
234
+ * stays the current one and is never mutated; only its committed turns
235
+ * travel. Same carry, compaction and refusals as inheritFrom().
236
+ */
237
+ async function inheritToNewSession(sourceSessionId, { compact = false, titleSuffix = '' } = {}) {
238
+ const live = getSession();
239
+ const id = clean(sourceSessionId) || clean(live?.id);
240
+ if (!id) throw new TypeError('inheritToNewSession: source session id is required');
241
+ const stored = id === clean(live?.id) ? live : mgr.getSession(id);
242
+ if (!stored) throw new Error(`inheritFrom: session ${id} was not found`);
243
+ const source = committedSource(stored);
244
+ const heir = buildColdHeir(source);
245
+ const { messages, compacted } = await carryConversation(source, heir, { compact: compact === true });
246
+ // A suffixed title ("… (Fork)") tells the copy apart in session lists;
247
+ // locked as a model title so auto-titling keeps it, renames still win.
248
+ if (titleSuffix && clean(heir.title)) {
249
+ heir.title = `${clean(heir.title)}${titleSuffix}`;
250
+ heir.titleLocked = true;
251
+ heir.titleSource = 'ai';
252
+ }
253
+ await persistColdHeir(heir);
254
+ return { sessionId: heir.id, messages, compacted };
255
+ }
256
+
257
+ return { inheritancePreflight, inheritFrom, inheritToNewSession };
214
258
  }
@@ -7,7 +7,6 @@ import {
7
7
  isAgentOnlySession,
8
8
  isRootLeadSession,
9
9
  } from '../../runtime/agent/orchestrator/session/store-summary-visibility.mjs';
10
- import { listSessionHeartbeatMtimes } from '../../runtime/agent/orchestrator/session/store/paths-heartbeat.mjs';
11
10
  import {
12
11
  sessionMessageText,
13
12
  isSessionPreviewNoise,
@@ -15,6 +14,9 @@ import {
15
14
  clean,
16
15
  } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
17
16
 
17
+ import { isRealTurnMessage } from '../../runtime/agent/orchestrator/session/compact/user-message-kind.mjs';
18
+ import { realTurnCount as realTurnCountOf } from '../../runtime/agent/orchestrator/session/store-summary-fields.mjs';
19
+
18
20
  const VISIBLE_OWNERS = ['cli', 'user', 'mixdog'];
19
21
 
20
22
  function isLeadShaped(s, owner, sourceType) {
@@ -39,7 +41,9 @@ function previewOf(s) {
39
41
  const rawPreview = s.preview || '';
40
42
  let preview = isSessionPreviewNoise(rawPreview) ? '' : cleanSessionPreview(rawPreview);
41
43
  let messageCount = Math.max(0, Number(s.messageCount) || 0);
44
+ let realTurnCount = realTurnCountOf(s);
42
45
  if (!preview && Array.isArray(s.messages)) {
46
+ realTurnCount = s.messages.filter(isRealTurnMessage).length;
43
47
  const msgs = s.messages;
44
48
  const userPreviews = msgs
45
49
  .filter((m) => m && m.role === 'user')
@@ -50,26 +54,32 @@ function previewOf(s) {
50
54
  preview = userPreviews[0] || '';
51
55
  messageCount = msgs.filter((m) => m && (m.role === 'user' || m.role === 'assistant')).length;
52
56
  }
53
- return { preview, messageCount };
57
+ return { preview, messageCount, realTurnCount };
54
58
  }
55
59
 
56
- function leadSessionRow(s, heartbeatMtimes) {
57
- // Durable visibility is the catalog boundary. Apply it before the legacy
58
- // lead-shape heuristics so an explicitly agent-only child cannot leak just
59
- // because its owner field looks ordinary.
60
- if (isAgentOnlySession(s)) return null;
60
+ /** `working`: this session's turn is running in the daemon right now. */
61
+ export function leadSessionRow(s, working = false) {
62
+ const agentSession = isAgentOnlySession(s) || isAgentOwner(s);
61
63
  const owner = clean(s.owner || 'user').toLowerCase();
62
64
  // A root Lead can carry Agent ownership plus a self-link after recovery;
63
65
  // it remains an ordinary resumable session, not a child dispatch.
64
- if (!isRootLeadSession(s) && owner && !VISIBLE_OWNERS.includes(owner)) return null;
66
+ if (!agentSession && !isRootLeadSession(s) && owner && !VISIBLE_OWNERS.includes(owner)) return null;
65
67
  const sourceType = clean(s.sourceType || '').toLowerCase();
66
68
  // One-shot `mixdog exec` runs are never resumable conversations.
67
69
  if (sourceType === 'exec') return null;
68
- if (!isLeadShaped(s, owner, sourceType)) return null;
69
- const { preview, messageCount } = previewOf(s);
70
+ if (!agentSession && !isLeadShaped(s, owner, sourceType)) return null;
71
+ const { preview, messageCount, realTurnCount } = previewOf(s);
70
72
  if (!preview && messageCount === 0) return null;
71
73
  return {
72
74
  id: s.id,
75
+ agent: s.agent || null,
76
+ owner,
77
+ visibility: isAgentOnlySession(s) ? 'agent-only' : 'ordinary',
78
+ ownerSessionId: s.ownerSessionId || s.parentSessionId || null,
79
+ // Durable provenance the desktop uses to tell a real conversation from
80
+ // resume scratch or synthetic-only rows when no title source survives.
81
+ ...(realTurnCount === null ? {} : { realTurnCount }),
82
+ ...(s.detachedReason ? { detachedReason: s.detachedReason } : {}),
73
83
  updatedAt: s.updatedAt,
74
84
  // Conversation-activity timestamp for Recent ordering. Without this the
75
85
  // desktop falls back to updatedAt, which detach/resume bookkeeping
@@ -82,12 +92,10 @@ function leadSessionRow(s, heartbeatMtimes) {
82
92
  messageCount,
83
93
  title: cleanSessionPreview(s.title || '', 100),
84
94
  preview,
85
- // Working indicator: the .hb sidecar ALONE is the liveness signal. Its
86
- // deletion at turn end IS the completion signal, so the persisted
87
- // lastHeartbeatAt JSON field (refreshed by the final save) must not be
88
- // folded in — it pinned desktop spinners on for the full 2-minute TTL
89
- // after a turn had already finished.
90
- heartbeatAt: Number(heartbeatMtimes.get(s.id)) || 0,
95
+ // Working indicator: the in-memory runtime state ALONE is the liveness
96
+ // signal. The persisted lastHeartbeatAt JSON field (refreshed by the final
97
+ // save) must not be folded in — it outlives the turn it describes.
98
+ ...(working ? { working: true } : {}),
91
99
  desktopSession: s.desktopSession || null,
92
100
  // Automation origin: lets the desktop group schedule/webhook runner
93
101
  // sessions under the sidebar Automations section instead of Recent.
@@ -99,9 +107,8 @@ function leadSessionRow(s, heartbeatMtimes) {
99
107
  }
100
108
 
101
109
  export function listLeadSessions(mgr, options = {}) {
102
- const heartbeatMtimes = listSessionHeartbeatMtimes();
103
110
  return mgr
104
111
  .listSessions({ refreshFromStorage: options?.refreshFromStorage === true })
105
- .map((s) => leadSessionRow(s, heartbeatMtimes))
112
+ .map((s) => leadSessionRow(s, mgr.isSessionTurnInFlight?.(s.id) === true))
106
113
  .filter(Boolean);
107
114
  }