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
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * The ordinary session catalog engine: summary index (base + delta log),
3
- * session-file reconcile, `.hb` liveness and the background verification.
3
+ * session-file reconcile and the background verification. Turn liveness is
4
+ * not part of it: the daemon overlays its in-memory runtime state on the rows
5
+ * it serves.
4
6
  *
5
7
  * Leaf by design (no store.mjs, no config, no workers): the cold reader
6
8
  * (store-summary-reader.mjs) runs one instance on its own thread for the JSON
@@ -24,8 +26,10 @@ import {
24
26
  inheritedFromSessionId,
25
27
  isStoredSessionId,
26
28
  positiveNumber,
29
+ realTurnCount,
27
30
  workspaceSummary,
28
31
  } from './store-summary-fields.mjs';
32
+ import { isRealTurnMessage } from './compact/user-message-kind.mjs';
29
33
  import { byActivityThenId } from './catalog-db/schema.mjs';
30
34
  import {
31
35
  sessionStampOf,
@@ -85,18 +89,18 @@ export function stampedDerivation(kind, path, derive) {
85
89
 
86
90
  const SESSION_SUMMARY_INDEX_VERSION = 2;
87
91
 
88
- // Mirror of lifecycle-api.mjs listLeadSessions visibility: the cold catalog
89
- // must never surface worker/agent dispatches (memory ingest chunks, judges,
90
- // spawned agents) — the authoritative engine excludes them, so a click on
91
- // such a row dead-ends in "Session is not available." (user report).
92
+ // Catalog visibility: Agent sessions are listed like any other session (the
93
+ // desktop sidebar filters to Leads itself), while internal dispatches the
94
+ // engine cannot open (memory ingest chunks, judges, exec runs) stay out — a
95
+ // click on such a row dead-ends in "Session is not available." (user report).
92
96
  const LEAD_OWNERS = new Set(['cli', 'user', 'mixdog']);
93
97
 
94
98
  export function isLeadVisibleRow(row) {
95
99
  const owner = String(row.owner || 'user')
96
100
  .trim()
97
101
  .toLowerCase();
98
- if (isAgentOnlySession(row)) return false;
99
- if (!isRootLeadSession(row) && owner && !LEAD_OWNERS.has(owner)) return false;
102
+ const agentSession = isAgentOnlySession(row) || owner === 'agent';
103
+ if (!agentSession && !isRootLeadSession(row) && owner && !LEAD_OWNERS.has(owner)) return false;
100
104
  // Mirror listLeadSessions: a previewless zero-message row is an unusable
101
105
  // scratch (desktop boot leftovers, crashed first turns) — resuming it
102
106
  // shows an empty conversation, so the catalog hides it.
@@ -113,6 +117,7 @@ export function isLeadVisibleRow(row) {
113
117
  .trim()
114
118
  .toLowerCase();
115
119
  return (
120
+ agentSession ||
116
121
  agent === 'lead' ||
117
122
  sourceType === 'lead' ||
118
123
  sourceType === 'cli' ||
@@ -147,7 +152,7 @@ function messageText(content) {
147
152
  .join(' ');
148
153
  }
149
154
 
150
- export function normalizedRow(row, heartbeatAt = 0) {
155
+ export function normalizedRow(row) {
151
156
  if (!row || typeof row.id !== 'string' || !isStoredSessionId(row.id)) return null;
152
157
  return {
153
158
  id: row.id,
@@ -158,10 +163,6 @@ export function normalizedRow(row, heartbeatAt = 0) {
158
163
  lastUsedAt: positiveNumber(row.lastUsedAt, 0),
159
164
  createdAt: positiveNumber(row.createdAt, 0),
160
165
  lastHeartbeatAt: positiveNumber(row.lastHeartbeatAt, 0),
161
- // Liveness comes from the .hb sidecar mtime alone: stored row fields
162
- // (summary index / final session save) survive completion and must not
163
- // keep the desktop working indicator on after the sidecar is deleted.
164
- heartbeatAt: positiveNumber(heartbeatAt, 0),
165
166
  closed: row.closed === true,
166
167
  status: String(row.status || (row.closed === true ? 'closed' : 'idle')),
167
168
  owner: row.owner || 'user',
@@ -182,6 +183,7 @@ export function normalizedRow(row, heartbeatAt = 0) {
182
183
  permission: row.permission || null,
183
184
  toolPermission: row.toolPermission || null,
184
185
  messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
186
+ realTurnCount: realTurnCount(row),
185
187
  title: cleanText(row.title, 100),
186
188
  preview: cleanText(row.preview),
187
189
  generation: typeof row.generation === 'number' ? row.generation : 0,
@@ -193,35 +195,11 @@ export function normalizedRow(row, heartbeatAt = 0) {
193
195
  };
194
196
  }
195
197
 
196
- /** Newest heartbeat of each Lead's live agents, from rows carrying `heartbeatAt`. */
197
- export function agentHeartbeatsByOwner(rows) {
198
- const agentHeartbeatByOwner = new Map();
199
- for (const row of rows) {
200
- const heartbeatAt = positiveNumber(row?.heartbeatAt, 0);
201
- const ownerSessionId = String(row?.ownerSessionId || '').trim();
202
- const owner = String(row?.owner || '')
203
- .trim()
204
- .toLowerCase();
205
- const agent = String(row?.agent || '')
206
- .trim()
207
- .toLowerCase();
208
- if (!heartbeatAt || !ownerSessionId || (owner !== 'agent' && (!agent || agent === 'lead'))) continue;
209
- agentHeartbeatByOwner.set(ownerSessionId, Math.max(agentHeartbeatByOwner.get(ownerSessionId) || 0, heartbeatAt));
210
- }
211
- return agentHeartbeatByOwner;
212
- }
213
-
214
- function leadRowsWithAgentHeartbeat(rows) {
215
- const agentHeartbeatByOwner = agentHeartbeatsByOwner(rows);
216
- return rows
217
- .filter((row) => row && isLeadVisibleRow(row))
218
- .map((row) => {
219
- const agentHeartbeatAt = agentHeartbeatByOwner.get(row.id) || 0;
220
- return agentHeartbeatAt > 0 ? { ...row, agentHeartbeatAt } : row;
221
- });
198
+ function leadRows(rows) {
199
+ return rows.filter((row) => row && isLeadVisibleRow(row));
222
200
  }
223
201
 
224
- function rowFromSession(session, heartbeatAt = 0) {
202
+ function rowFromSession(session) {
225
203
  const messages = Array.isArray(session?.messages) ? session.messages : [];
226
204
  const preview =
227
205
  messages
@@ -236,14 +214,12 @@ function rowFromSession(session, heartbeatAt = 0) {
236
214
  )
237
215
  .map((message) => cleanText(messageText(message.content)))
238
216
  .find(Boolean) || '';
239
- return normalizedRow(
240
- {
241
- ...session,
242
- messageCount: messages.filter((message) => message?.role === 'user' || message?.role === 'assistant').length,
243
- preview,
244
- },
245
- heartbeatAt
246
- );
217
+ return normalizedRow({
218
+ ...session,
219
+ messageCount: messages.filter((message) => message?.role === 'user' || message?.role === 'assistant').length,
220
+ realTurnCount: messages.filter(isRealTurnMessage).length,
221
+ preview,
222
+ });
247
223
  }
248
224
 
249
225
  // ── Session file reconcile ──────────────────────────────────────────────────
@@ -289,7 +265,7 @@ function reconcileSessionFile(directory, storageId, retained, forceRead) {
289
265
  // record or a foreign identity is not this file's session.
290
266
  const record = readTopLevelLifecycleRecord(text);
291
267
  if (isLifecycleUnreadable(record) || record.id !== storageId) return null;
292
- return rowFromSession(record.doc, 0);
268
+ return rowFromSession(record.doc);
293
269
  });
294
270
  if (read.state === PROBE_ABSENT) return null;
295
271
  // Exists and could not be read (EACCES/EIO): retain the last known row
@@ -317,53 +293,46 @@ function deepFreeze(value) {
317
293
  return value;
318
294
  }
319
295
 
320
- /** The session ids (`<id>.json`) and live sidecar ids (`<id>.hb`) of
321
- * `directory`, or null when it cannot be enumerated. */
322
- function listSessionNames(directory) {
296
+ /** The session ids (`<id>.json`) of `directory`, or null when it cannot be
297
+ * enumerated. */
298
+ function listSessionIds(directory) {
323
299
  let names;
324
300
  try {
325
301
  names = readdirSync(directory);
326
302
  } catch {
327
303
  return null;
328
304
  }
329
- const sessionIds = [];
330
- const heartbeatIds = [];
331
- for (const filename of names) {
332
- if (filename.endsWith('.json')) sessionIds.push(filename.slice(0, -5));
333
- else if (filename.endsWith('.hb') && isStoredSessionId(filename.slice(0, -3))) {
334
- heartbeatIds.push(filename.slice(0, -3));
335
- }
336
- }
337
- return { sessionIds, heartbeatIds };
305
+ return names.filter((filename) => filename.endsWith('.json')).map((filename) => filename.slice(0, -5));
338
306
  }
339
307
 
340
- /** Every `.json` entry and `.hb` sidecar id of an enumerable `directory`, or
341
- * null when it cannot be enumerated. */
308
+ /** Every `.json` entry of an enumerable `directory`, or null when it cannot
309
+ * be enumerated. */
342
310
  function scanSessionEntries(directory, indexRowsById, forceRead) {
343
- const names = listSessionNames(directory);
344
- if (!names) return null;
311
+ const sessionIds = listSessionIds(directory);
312
+ if (!sessionIds) return null;
345
313
  const entries = new Map();
346
- for (const storageId of names.sessionIds) {
314
+ for (const storageId of sessionIds) {
347
315
  const entry = reconcileSessionFile(directory, storageId, indexRowsById.get(storageId), forceRead);
348
316
  if (entry) entries.set(storageId, entry);
349
317
  }
350
- return { entries, heartbeatIds: names.heartbeatIds };
318
+ return { entries };
351
319
  }
352
320
 
353
- /** The row an entry contributes (before liveness overlays), or null. */
321
+ /** The row an entry contributes, or null. */
354
322
  function entryRow(entry, id, indexRowsById) {
355
323
  if (!entry || entry.kind === 'none') return null;
356
324
  return (entry.kind === 'row' ? entry.row : indexRowsById.get(id)) || null;
357
325
  }
358
326
 
359
327
  /** Catalog rows of reconciled `entries`, in catalog order. */
360
- function assembleCatalog(entries, indexRowsById, heartbeatMtimes) {
328
+ function assembleCatalog(entries, indexRowsById) {
361
329
  const rows = [];
362
330
  for (const [id, entry] of entries) {
363
331
  const row = entryRow(entry, id, indexRowsById);
364
- if (row) rows.push({ ...row, heartbeatAt: positiveNumber(heartbeatMtimes.get(id), 0) });
332
+ // A copy: the cached entry rows are frozen and shared.
333
+ if (row) rows.push({ ...row });
365
334
  }
366
- return leadRowsWithAgentHeartbeat(rows).sort(byCatalogOrder);
335
+ return leadRows(rows).sort(byCatalogOrder);
367
336
  }
368
337
 
369
338
  /**
@@ -375,23 +344,18 @@ function assembleCatalog(entries, indexRowsById, heartbeatMtimes) {
375
344
  * durable summary and a single UNREADABLE file retains its last known row
376
345
  * instead of vanishing.
377
346
  */
378
- export function scanSessionFiles(heartbeatMtimes, indexRowsById, forceRead) {
347
+ export function scanSessionFiles(indexRowsById, forceRead) {
379
348
  const directory = join(dataDir(), 'sessions');
380
349
  const dirProbe = probePath(directory);
381
350
  if (dirProbe.state === PROBE_ABSENT) return [];
382
351
  if (dirProbe.state !== PROBE_PRESENT) return null;
383
352
  const scan = scanSessionEntries(directory, indexRowsById, forceRead);
384
- return scan && assembleCatalog(scan.entries, indexRowsById, heartbeatMtimes);
353
+ return scan && assembleCatalog(scan.entries, indexRowsById);
385
354
  }
386
355
 
387
356
  /** Listing from the index rows alone, or null without a valid index. */
388
- export function indexListing(index, heartbeatMtimes) {
389
- return (
390
- index.rows &&
391
- leadRowsWithAgentHeartbeat(
392
- index.rows.map((row) => ({ ...row, heartbeatAt: positiveNumber(heartbeatMtimes.get(row.id), 0) }))
393
- ).sort(byCatalogOrder)
394
- );
357
+ export function indexListing(index) {
358
+ return index.rows && leadRows(index.rows.map((row) => ({ ...row }))).sort(byCatalogOrder);
395
359
  }
396
360
 
397
361
  // ── Summary index ───────────────────────────────────────────────────────────
@@ -475,7 +439,7 @@ function readSummaryIndex(cached) {
475
439
  }
476
440
  // Same semantics as applySummaryLogText: last writer wins per id.
477
441
  if (op?.u && typeof op.u.id === 'string') {
478
- const row = normalizedRow(op.u, 0);
442
+ const row = normalizedRow(op.u);
479
443
  if (row) rowsById.set(row.id, deepFreeze(row));
480
444
  else rowsById.delete(op.u.id);
481
445
  touched.add(op.u.id);
@@ -509,7 +473,7 @@ function readSummaryIndex(cached) {
509
473
  }
510
474
  }
511
475
  const rows = applySummaryLogText({ rows: baseRows ?? [] }, index.logBytes.toString('utf8'))
512
- .rows.map((row) => normalizedRow(row, 0))
476
+ .rows.map((row) => normalizedRow(row))
513
477
  .filter(Boolean)
514
478
  .map(deepFreeze);
515
479
  for (const row of rows) index.signatures.set(row.id, JSON.stringify(row));
@@ -535,16 +499,10 @@ function changedIndexIds(previous, next) {
535
499
  return ids;
536
500
  }
537
501
 
538
- function sameMtimes(left, right) {
539
- if (!right || left.size !== right.size) return false;
540
- for (const [id, mtimeMs] of left) if (right.get(id) !== mtimeMs) return false;
541
- return true;
542
- }
543
-
544
502
  // ── Ordinary catalog ────────────────────────────────────────────────────────
545
503
  // The ordinary listing keeps its last reconcile and answers an unchanged call
546
- // from cheap stamps alone: the index pair (above), the sessions DIRECTORY and
547
- // the handful of live `.hb` sidecars — no per-session-file filesystem work.
504
+ // from cheap stamps alone: the index pair (above) and the sessions DIRECTORY —
505
+ // no per-session-file filesystem work.
548
506
  //
549
507
  // The directory stamp changes on every create, delete and rename in it
550
508
  // (including a temp-file + rename replace), and NOT on an in-place write
@@ -577,8 +535,6 @@ function newSessionCatalog(directory, dirStamp, index, scan) {
577
535
  dirSettled: isSettledSessionStamp(dirStamp),
578
536
  index,
579
537
  entries: scan.entries,
580
- heartbeatIds: scan.heartbeatIds,
581
- heartbeatMtimes: null,
582
538
  rows: null,
583
539
  dirty: new Set(),
584
540
  verifiedAt: Date.now(),
@@ -606,17 +562,16 @@ function reconcileKnownCatalog(catalog, directory, dirStamp, index, hinted) {
606
562
  changed = true;
607
563
  }
608
564
  if (!catalog.dirSettled || !sameSessionStamp(catalog.dirStamp, dirStamp)) {
609
- const names = listSessionNames(directory);
610
- if (!names) return null;
611
- const present = new Set(names.sessionIds);
565
+ const sessionIds = listSessionIds(directory);
566
+ if (!sessionIds) return null;
567
+ const present = new Set(sessionIds);
612
568
  for (const id of catalog.entries.keys()) {
613
569
  if (present.has(id)) continue;
614
570
  catalog.entries.delete(id);
615
571
  changedIds.add(id);
616
572
  changed = true;
617
573
  }
618
- for (const id of names.sessionIds) if (!catalog.entries.has(id)) ids.add(id);
619
- catalog.heartbeatIds = names.heartbeatIds;
574
+ for (const id of sessionIds) if (!catalog.entries.has(id)) ids.add(id);
620
575
  catalog.dirStamp = dirStamp;
621
576
  catalog.dirSettled = isSettledSessionStamp(dirStamp);
622
577
  }
@@ -630,20 +585,6 @@ function reconcileKnownCatalog(catalog, directory, dirStamp, index, hinted) {
630
585
  return { changed, changedIds };
631
586
  }
632
587
 
633
- /** Liveness: `.hb` sidecars are rewritten in place, so their mtimes are
634
- * probed every call (absent or unreadable contributes nothing). True when
635
- * they differ from the previous probe. */
636
- function refreshHeartbeatMtimes(catalog, directory) {
637
- const heartbeatMtimes = new Map();
638
- for (const id of catalog.heartbeatIds) {
639
- const probe = probePath(join(directory, `${id}.hb`));
640
- if (probe.state === PROBE_PRESENT && probe.mtimeMs > 0) heartbeatMtimes.set(id, probe.mtimeMs);
641
- }
642
- const differs = !sameMtimes(heartbeatMtimes, catalog.heartbeatMtimes);
643
- catalog.heartbeatMtimes = heartbeatMtimes;
644
- return differs;
645
- }
646
-
647
588
  /** Marks every entry of `snapshot` whose file no longer has the full stamp it
648
589
  * was judged at dirty (a replacement brings a new inode and change time even
649
590
  * when its size and mtime match). Stops early once `isCurrent()` is false. */
@@ -725,7 +666,6 @@ export function createOrdinaryCatalog() {
725
666
  }
726
667
  ({ changed, changedIds } = reconciled);
727
668
  }
728
- if (refreshHeartbeatMtimes(catalog, directory)) changed = true;
729
669
  if (changed) catalog.rows = null;
730
670
  if (assemble) rowsOf(catalog);
731
671
  armCatalogVerify(catalog);
@@ -735,9 +675,7 @@ export function createOrdinaryCatalog() {
735
675
 
736
676
  /** The (frozen) listing of a reconciled catalog, assembled on demand. */
737
677
  function rowsOf(catalog) {
738
- catalog.rows ||= assembleCatalog(catalog.entries, catalog.index.rowsById, catalog.heartbeatMtimes).map(
739
- Object.freeze
740
- );
678
+ catalog.rows ||= assembleCatalog(catalog.entries, catalog.index.rowsById).map(Object.freeze);
741
679
  return catalog.rows;
742
680
  }
743
681
 
@@ -791,7 +729,7 @@ export function createOrdinaryCatalog() {
791
729
  loadIndex,
792
730
  refresh,
793
731
  rowsOf,
794
- /** The row `id` contributes to the current catalog (before overlays). */
732
+ /** The row `id` contributes to the current catalog. */
795
733
  entryRow: (catalog, id) => entryRow(catalog.entries.get(id), id, catalog.index.rowsById),
796
734
  current: () => sessionCatalog,
797
735
  /** `listener()` runs when a background pass finds a session file that
@@ -55,6 +55,14 @@ export function inheritedFromSessionId(value) {
55
55
  return id || null;
56
56
  }
57
57
 
58
+ /** Count of real human turns a session persisted (actual user instructions
59
+ * plus compact summaries, which stand for earlier human turns); null for a
60
+ * row written before the field existed. */
61
+ export function realTurnCount(value) {
62
+ const count = value?.realTurnCount;
63
+ return typeof count === 'number' && Number.isFinite(count) && count >= 0 ? Math.floor(count) : null;
64
+ }
65
+
58
66
  export function importKey(value) {
59
67
  const key = typeof value?.importKey === 'string' ? value.importKey : value?.importOrigin?.key;
60
68
  return typeof key === 'string' && key.trim() ? key : null;
@@ -23,8 +23,10 @@ import {
23
23
  inheritedFromSessionId,
24
24
  isStoredSessionId,
25
25
  positiveNumber as _positiveNumber,
26
+ realTurnCount,
26
27
  workspaceSummary,
27
28
  } from './store-summary-fields.mjs';
29
+ import { isRealTurnMessage } from './compact/user-message-kind.mjs';
28
30
 
29
31
  export const SESSION_SUMMARY_INDEX_VERSION = 2;
30
32
 
@@ -92,6 +94,7 @@ function _sessionMessageProjection(session) {
92
94
  const cached = session && typeof session === 'object' ? sessionMessageProjectionMemo.get(session) : null;
93
95
  let start = 0;
94
96
  let count = 0;
97
+ let real = 0;
95
98
  let preview = '';
96
99
  let previewMessage = null;
97
100
  const canAppend =
@@ -101,6 +104,7 @@ function _sessionMessageProjection(session) {
101
104
  if (canAppend) {
102
105
  start = cached.length;
103
106
  count = cached.count;
107
+ real = cached.real;
104
108
  preview = cached.preview;
105
109
  previewMessage = cached.previewMessage;
106
110
  // The first real user message is stable in normal append-only session
@@ -112,6 +116,7 @@ function _sessionMessageProjection(session) {
112
116
  else {
113
117
  start = 0;
114
118
  count = 0;
119
+ real = 0;
115
120
  preview = '';
116
121
  previewMessage = null;
117
122
  }
@@ -120,6 +125,7 @@ function _sessionMessageProjection(session) {
120
125
  for (let index = start; index < messages.length; index += 1) {
121
126
  const message = messages[index];
122
127
  if (message && (message.role === 'user' || message.role === 'assistant')) count += 1;
128
+ if (isRealTurnMessage(message)) real += 1;
123
129
  if (!preview) {
124
130
  const candidate = _previewFromMessage(message);
125
131
  if (candidate) {
@@ -133,11 +139,12 @@ function _sessionMessageProjection(session) {
133
139
  length: messages.length,
134
140
  lastMessage: messages[messages.length - 1] || null,
135
141
  count,
142
+ real,
136
143
  preview,
137
144
  previewMessage,
138
145
  });
139
146
  }
140
- return { count, preview };
147
+ return { count, real, preview };
141
148
  }
142
149
 
143
150
  function _desktopSessionSummary(value, cwd = null) {
@@ -199,6 +206,7 @@ export function _sessionSummary(session) {
199
206
  : null,
200
207
  taskType: session.taskType || null,
201
208
  messageCount: messageProjection.count,
209
+ realTurnCount: messageProjection.real,
202
210
  title: _cleanPreview(session.title || '', 100),
203
211
  preview: messageProjection.preview,
204
212
  generation: typeof session.generation === 'number' ? session.generation : 0,
@@ -253,6 +261,7 @@ function _normalizeSummaryRow(row) {
253
261
  : null,
254
262
  taskType: row.taskType || null,
255
263
  messageCount: Math.max(0, Math.floor(Number(row.messageCount) || 0)),
264
+ realTurnCount: realTurnCount(row),
256
265
  title: _cleanPreview(row.title || '', 100),
257
266
  preview: _cleanPreview(row.preview || ''),
258
267
  generation: typeof row.generation === 'number' ? row.generation : 0,
@@ -1,14 +1,10 @@
1
1
  /**
2
- * Where the cold read-only catalog reads from, and the heartbeat-sidecar scan
3
- * that gives it liveness. Leaf module by design: no store.mjs, no config, no
4
- * workers — every consumer of the cold path resolves paths through here so
5
- * they cannot drift apart.
2
+ * Where the cold read-only catalog reads from. Leaf module by design: no
3
+ * store.mjs, no config, no workers — every consumer of the cold path resolves
4
+ * paths through here so they cannot drift apart.
6
5
  */
7
- import { readdirSync } from 'node:fs';
8
6
  import { homedir } from 'node:os';
9
7
  import { join } from 'node:path';
10
- import { probePath, PROBE_PRESENT } from './store/fs-probe.mjs';
11
- import { isStoredSessionId } from './store-summary-fields.mjs';
12
8
 
13
9
  export function dataDir() {
14
10
  if (process.env.MIXDOG_DATA_DIR) return process.env.MIXDOG_DATA_DIR;
@@ -23,25 +19,3 @@ export function storedAgentWorkerIndexPath() {
23
19
  export function storedLeadWorkerIndexPath() {
24
20
  return join(dataDir(), 'lead-workers.json');
25
21
  }
26
-
27
- export function sessionHeartbeatMtimes() {
28
- const directory = join(dataDir(), 'sessions');
29
- const result = new Map();
30
- if (probePath(directory).state !== PROBE_PRESENT) return result;
31
- let entries = [];
32
- try {
33
- entries = readdirSync(directory);
34
- } catch {
35
- return result;
36
- }
37
- for (const filename of entries) {
38
- if (!filename.endsWith('.hb')) continue;
39
- const id = filename.slice(0, -3);
40
- if (!isStoredSessionId(id)) continue;
41
- // Liveness is additive: a sidecar that is absent OR unreadable simply
42
- // contributes nothing, and can never remove a row.
43
- const probe = probePath(join(directory, filename));
44
- if (probe.state === PROBE_PRESENT && probe.mtimeMs > 0) result.set(id, probe.mtimeMs);
45
- }
46
- return result;
47
- }
@@ -28,7 +28,7 @@ test.after(() => {
28
28
  });
29
29
 
30
30
  /** Point the reader at a fresh data dir with an empty sessions directory. */
31
- export function useDataDir(prefix) {
31
+ export function isolateDataDir(prefix) {
32
32
  root = mkdtempSync(join(tmpdir(), prefix));
33
33
  roots.push(root);
34
34
  mkdirSync(join(root, 'sessions'));
@@ -29,7 +29,7 @@ import {
29
29
  storedTranscriptWorkerRunning,
30
30
  } from './store-transcript-worker.mjs';
31
31
  import { projectStoredTranscript } from './store-transcript-projection.mjs';
32
- import { dataDir, sessionHeartbeatMtimes } from './store-summary-locations.mjs';
32
+ import { dataDir } from './store-summary-locations.mjs';
33
33
  import { isStoredSessionId, workspaceSummary } from './store-summary-fields.mjs';
34
34
  import { readArchivedAgentResult } from './store-summary-archived-agent.mjs';
35
35
  import { compactionArchivePath, readCompactionArchivePage } from './compaction-archive.mjs';
@@ -42,9 +42,9 @@ import {
42
42
  sameSessionStamp,
43
43
  isSettledSessionStamp,
44
44
  } from './store/canonical-reader.mjs';
45
- // Worker-pool row projection (child + Lead indexes, heartbeat lease, cancel
46
- // ranking) lives in store-agent-worker-rows.mjs; re-exported so prior
47
- // importers of this module stay unchanged.
45
+ // Worker-pool row projection (child + Lead indexes, live-work evidence) lives
46
+ // in store-agent-worker-rows.mjs; re-exported so prior importers of this
47
+ // module stay unchanged.
48
48
  export { listStoredAgentWorkerLinks, listStoredAgentWorkers } from './store-agent-worker-rows.mjs';
49
49
  export { storedAgentWorkerIndexPath } from './store-summary-locations.mjs';
50
50
 
@@ -123,13 +123,12 @@ export function listStoredSessionSummaries(options = {}) {
123
123
  // nor empty: the scan still runs, and when IT cannot enumerate either, the
124
124
  // catalog reports nothing rather than inventing an empty truth.
125
125
  if (options.refreshFromStorage === true) {
126
- const heartbeatMtimes = sessionHeartbeatMtimes();
127
- return scanSessionFiles(heartbeatMtimes, index.rowsById, true) ?? indexListing(index, heartbeatMtimes) ?? [];
126
+ return scanSessionFiles(index.rowsById, true) ?? indexListing(index) ?? [];
128
127
  }
129
- if (options.rebuildIfMissing === false) return indexListing(index, sessionHeartbeatMtimes()) ?? [];
128
+ if (options.rebuildIfMissing === false) return indexListing(index) ?? [];
130
129
  // A missing/malformed index leaves every file to be parsed (once per
131
130
  // stamp); a present one lets unchanged files reuse their durable summary.
132
- return ordinaryCatalog.refresh(index).rows ?? indexListing(index, sessionHeartbeatMtimes()) ?? [];
131
+ return ordinaryCatalog.refresh(index).rows ?? indexListing(index) ?? [];
133
132
  }
134
133
 
135
134
  /** The catalog DB's answer to an ordinary listing (`{ rows, more }`), or
@@ -250,6 +249,14 @@ function storedSessionMetadata(sessionId, session) {
250
249
  };
251
250
  }
252
251
 
252
+ /** A record that is gone may be a reaped agent child: its parent is resolved
253
+ * from metadata only (worker link, summary-index row), never by a scan. */
254
+ function readVanishedSessionTranscript(sessionId) {
255
+ return readArchivedAgentResult(sessionId, {
256
+ catalogRow: (id) => ordinaryCatalog.loadIndex().rowsById.get(id) || null,
257
+ });
258
+ }
259
+
253
260
  /** The two files a stored transcript projection is built from. */
254
261
  function storedTranscriptInputPaths(sessionId) {
255
262
  return {
@@ -375,7 +382,7 @@ export async function readStoredSessionTranscript(id, options = {}) {
375
382
  // Phase durations of the parse this call ran (absent on a cache hit).
376
383
  const timing = {};
377
384
  const recordStat = probePath(recordPath);
378
- if (recordStat.state === PROBE_ABSENT) return readArchivedAgentResult(sessionId);
385
+ if (recordStat.state === PROBE_ABSENT) return readVanishedSessionTranscript(sessionId);
379
386
  if (recordStat.state !== PROBE_PRESENT) return null;
380
387
  const checkpoint = probePath(checkpointPath);
381
388
  const archive = probePath(archivePath);
@@ -441,7 +448,7 @@ export async function readStoredSessionTranscript(id, options = {}) {
441
448
  produce: (text) => produceStoredTranscript(text, readStamp, produceContext),
442
449
  });
443
450
  // The record vanished between stat and read: same answer as an absent probe.
444
- if (readState === PROBE_ABSENT) return readArchivedAgentResult(sessionId);
451
+ if (readState === PROBE_ABSENT) return readVanishedSessionTranscript(sessionId);
445
452
  if (typeof options.trace === 'function') {
446
453
  options.trace({
447
454
  sessionId,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The parse/recovery/projection body of one stored transcript read: durable
3
3
  * turn-checkpoint recovery for interrupted turns, the read-only checkpoint
4
- * projection for a live foreign owner, the cold context projection and the
4
+ * projection for a live turn, the cold context projection and the
5
5
  * pane-facing transcript shape.
6
6
  *
7
7
  * Kept apart from the cache/fingerprint policy in store-summary-reader.mjs
@@ -12,7 +12,7 @@
12
12
  import { sessionContextMeasurement, contextMeasurementStats } from '../../../shared/context-measurement.mjs';
13
13
  import { nextProjectionStamp } from './store-transcript-cache.mjs';
14
14
  import { join } from 'node:path';
15
- import { cleanValue, desktopSession, positiveNumber } from './store-summary-fields.mjs';
15
+ import { desktopSession, positiveNumber } from './store-summary-fields.mjs';
16
16
  import { compactionArchiveRange, readCompactionArchivePage } from './compaction-archive.mjs';
17
17
  import { dataDir } from './store-summary-locations.mjs';
18
18
 
@@ -20,27 +20,20 @@ import { dataDir } from './store-summary-locations.mjs';
20
20
  * per distinct content; its result is shared read-only through the cache. */
21
21
  export async function projectStoredTranscript(sessionId, doc, options) {
22
22
  let session = doc;
23
- const owner = cleanValue(session.owner).toLowerCase();
24
- const agent = cleanValue(session.agent).toLowerCase();
25
- const liveDetachedAgent =
26
- session.closed === true &&
27
- (owner === 'agent' || (agent && agent !== 'lead')) &&
28
- Boolean(cleanValue(session.ownerSessionId || session.parentSessionId));
29
23
  if (!options.checkpointAbsent) {
30
24
  const { projectTurnCheckpointMessages, readTurnCheckpoint } = await import('./manager/turn-checkpoint.mjs');
31
25
  const projectCheckpoint = () => {
32
26
  const checkpoint = readTurnCheckpoint(sessionId);
33
27
  if (checkpoint) session = { ...session, messages: projectTurnCheckpointMessages(session, checkpoint) };
34
28
  };
35
- if (liveDetachedAgent) {
36
- projectCheckpoint();
37
- } else {
38
- const { recoverSessionAfterProcessRestart } = await import('./manager.mjs');
29
+ const { isSessionTurnLive, recoverSessionAfterProcessRestart } = await import(
30
+ './manager/turn-checkpoint-recovery.mjs'
31
+ );
32
+ // A running turn is never recovered: project its checkpoint read-only.
33
+ if (isSessionTurnLive(sessionId)) projectCheckpoint();
34
+ else {
39
35
  session = recoverSessionAfterProcessRestart(sessionId) || session;
40
- // A live foreign owner is intentionally not recovered/mutated.
41
- // Project its durable working checkpoint read-only so the cold pane
42
- // never repaints the stale pre-compaction session.messages while it
43
- // waits for the owner's live-share frame.
36
+ // A closed session keeps its marker unrecovered.
44
37
  if (session?.activeTurnCheckpoint) projectCheckpoint();
45
38
  }
46
39
  }
@@ -134,9 +127,5 @@ export async function projectStoredTranscript(sessionId, doc, options) {
134
127
  displayContextWindow: displayContextWindow || null,
135
128
  autoCompactTokenLimit: autoCompactTokenLimit || null,
136
129
  }),
137
- // Desktop must not ask its unrelated active engine to recover/peek an
138
- // externally owned child: that runtime can only return the detached
139
- // Task row and masks this checkpoint projection.
140
- readOnlyDetachedAgent: liveDetachedAgent,
141
130
  };
142
131
  }