mixdog 1.2.3 → 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 (465) hide show
  1. package/package.json +1 -1
  2. package/scripts/gate-local.mjs +6 -4
  3. package/scripts/lib/gate-scheduler.mjs +29 -11
  4. package/scripts/probe-provider-catalog.mjs +31 -0
  5. package/scripts/provider-pingpong-live.mjs +128 -38
  6. package/scripts/session-sweep.mjs +5 -25
  7. package/src/agents/maintainer/AGENT.md +1 -1
  8. package/src/agents/maintainer/agent.json +1 -1
  9. package/src/agents/reviewer/AGENT.md +2 -4
  10. package/src/agents/security/AGENT.md +1 -2
  11. package/src/agents/writer/AGENT.md +2 -3
  12. package/src/defaults/shipped-history.json +6 -1
  13. package/src/defaults/skills/image/SKILL.md +21 -23
  14. package/src/lib/keychain-cjs.cjs +13 -11
  15. package/src/rules/agent/AGENT.md +7 -5
  16. package/src/rules/lead/LEAD.md +7 -9
  17. package/src/rules/shared/45-destructive.md +4 -0
  18. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  19. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  20. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  21. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  22. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  23. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  24. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +1 -1
  25. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -3
  26. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  27. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  28. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +2 -5
  29. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +4 -0
  30. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  31. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  32. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +81 -10
  33. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +109 -5
  34. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +2 -1
  35. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +107 -37
  36. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +4 -1
  37. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +3 -1
  38. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  39. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  40. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  41. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  42. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  43. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +41 -11
  44. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +67 -5
  45. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +14 -4
  46. package/src/runtime/agent/orchestrator/providers/cursor.mjs +14 -1
  47. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +9 -6
  48. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +7 -2
  49. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +26 -4
  50. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +12 -6
  51. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +14 -6
  52. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +4 -4
  53. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  54. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  55. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +6 -1
  56. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +22 -10
  57. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -2
  58. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +33 -7
  59. package/src/runtime/agent/orchestrator/providers/gemini.mjs +11 -2
  60. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +9 -2
  62. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +9 -5
  63. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  64. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +4 -2
  65. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +16 -5
  66. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  67. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +60 -16
  68. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +11 -13
  69. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +30 -19
  70. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  71. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  72. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +42 -5
  73. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +13 -9
  74. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +1 -3
  75. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +18 -7
  76. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +36 -3
  77. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  78. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +11 -1
  79. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  80. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +3 -1
  81. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +2 -1
  82. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +7 -1
  83. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +1 -4
  84. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +0 -1
  85. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +7 -6
  86. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +13 -2
  87. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +4 -1
  88. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +1 -2
  89. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +5 -4
  90. package/src/runtime/agent/orchestrator/providers/registry.mjs +9 -1
  91. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +2 -1
  92. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +11 -4
  93. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +14 -4
  94. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +15 -3
  95. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +6 -2
  96. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  97. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +4 -1
  98. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  99. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  100. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  101. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +3 -1
  102. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  103. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +10 -10
  104. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +46 -8
  106. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  107. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  108. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  109. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  110. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  111. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +3 -11
  112. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  113. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +2 -0
  114. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  115. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +28 -0
  116. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  118. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  119. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +1 -1
  120. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  121. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  122. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -4
  123. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +3 -3
  124. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +0 -27
  125. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  126. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  127. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  128. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +4 -1
  129. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +4 -1
  130. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +1 -4
  131. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  132. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +5 -1
  133. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +8 -9
  134. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  135. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +15 -2
  136. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +1 -4
  137. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +3 -4
  138. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  139. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  140. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +21 -1
  141. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +38 -13
  142. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  143. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +5 -0
  144. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +19 -1
  145. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  146. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  147. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  148. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  149. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +29 -8
  150. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  151. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  152. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +32 -14
  153. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +17 -33
  155. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  156. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -3
  157. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  158. package/src/runtime/agent/orchestrator/session/manager.mjs +2 -9
  159. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  160. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +5 -2
  161. package/src/runtime/agent/orchestrator/session/side-question.mjs +12 -7
  162. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +5 -12
  163. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  164. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  165. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  166. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  167. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  169. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +5 -11
  170. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  171. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  172. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -32
  174. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  175. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  176. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  177. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  179. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  180. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +50 -116
  181. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  182. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  183. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +7 -8
  184. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  185. package/src/runtime/agent/orchestrator/session/store.mjs +3 -16
  186. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +11 -12
  187. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +37 -13
  188. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  189. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +4 -2
  190. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  191. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  192. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  193. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  194. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  195. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +204 -10
  196. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  197. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  198. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  199. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  200. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  201. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  202. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  203. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +200 -17
  204. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  205. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  206. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  207. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  208. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  209. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  210. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  211. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  212. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  213. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  214. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  215. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  216. package/src/runtime/attachments/store.d.mts +9 -0
  217. package/src/runtime/attachments/store.mjs +80 -9
  218. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  219. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  220. package/src/runtime/computer-bridge/action-schema.mjs +178 -178
  221. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  222. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  223. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  224. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  225. package/src/runtime/github/tool.mjs +118 -17
  226. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  227. package/src/runtime/media/catalog.mjs +4 -4
  228. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  229. package/src/runtime/media/defaults.mjs +37 -0
  230. package/src/runtime/media/jobs.mjs +12 -2
  231. package/src/runtime/media/lanes.mjs +12 -0
  232. package/src/runtime/media/tool-defs.mjs +15 -4
  233. package/src/runtime/media/tool.mjs +41 -12
  234. package/src/runtime/media/upstream-error.mjs +72 -6
  235. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  236. package/src/runtime/memory/lib/pg/process.mjs +5 -7
  237. package/src/runtime/memory/lib/pg/supervisor.mjs +4 -1
  238. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  239. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  240. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  241. package/src/runtime/office/authoring/pptx-html-measure.mjs +1 -1
  242. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  243. package/src/runtime/office/core/office-write-ledger.mjs +1 -5
  244. package/src/runtime/office/index.mjs +2 -3
  245. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  246. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  247. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  248. package/src/runtime/shared/atomic-file.d.mts +1 -1
  249. package/src/runtime/shared/background-tasks.mjs +6 -1
  250. package/src/runtime/shared/bounded-line-diff.mjs +11 -2
  251. package/src/runtime/shared/browser-launch.mjs +15 -0
  252. package/src/runtime/shared/err-text.mjs +42 -4
  253. package/src/runtime/shared/file-lock.mjs +6 -5
  254. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  255. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  256. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  257. package/src/runtime/shared/model-route-chain.mjs +48 -0
  258. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  259. package/src/runtime/shared/pid-liveness.mjs +12 -0
  260. package/src/runtime/shared/provider-api-key.mjs +6 -0
  261. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  262. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  263. package/src/runtime/shared/quiet-progress.mjs +101 -0
  264. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  265. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  266. package/src/runtime/shared/remote-intent.mjs +2 -42
  267. package/src/runtime/shared/slow-span.mjs +8 -1
  268. package/src/runtime/shared/statusline/statusline-segments.mjs +24 -2
  269. package/src/runtime/shared/tool-card-model/card-header.mjs +2 -1
  270. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  271. package/src/runtime/shared/tool-result-summary.mjs +16 -2
  272. package/src/runtime/shared/tool-status.mjs +3 -2
  273. package/src/runtime/shared/tool-surface.mjs +2 -3
  274. package/src/runtime/shared/tool-work-units.mjs +22 -15
  275. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  276. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  277. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  278. package/src/runtime/shared/transcript-writer.mjs +14 -4
  279. package/src/runtime/shared/turn-changes.mjs +2 -1
  280. package/src/runtime/shared/turn-snapshot.mjs +11 -3
  281. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  282. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  283. package/src/runtime/shared/worktrees/carry.mjs +6 -4
  284. package/src/runtime/shared/worktrees/contract.mjs +27 -1
  285. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  286. package/src/runtime/shared/worktrees/file-recovery.mjs +29 -13
  287. package/src/runtime/shared/worktrees/git-head.mjs +22 -13
  288. package/src/runtime/shared/worktrees/include.mjs +125 -7
  289. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  290. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  291. package/src/runtime/shared/worktrees/manager.mjs +378 -32
  292. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  293. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  294. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  295. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  296. package/src/runtime/terminal-bridge/client.mjs +14 -10
  297. package/src/session-runtime/boot/apis.mjs +7 -1
  298. package/src/session-runtime/boot/config.mjs +2 -0
  299. package/src/session-runtime/boot/facade.mjs +3 -0
  300. package/src/session-runtime/boot/session.mjs +3 -2
  301. package/src/session-runtime/boot/tools.mjs +3 -0
  302. package/src/session-runtime/conversation-import/service.mjs +1 -1
  303. package/src/session-runtime/goal-facade-api.mjs +2 -2
  304. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +44 -18
  305. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +4 -1
  306. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +22 -8
  307. package/src/session-runtime/internal-tool-executor.mjs +2 -0
  308. package/src/session-runtime/lifecycle/cold-heir.mjs +0 -1
  309. package/src/session-runtime/lifecycle/session-catalog.mjs +14 -16
  310. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +18 -53
  311. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  312. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  313. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  314. package/src/session-runtime/lifecycle/teardown.mjs +7 -16
  315. package/src/session-runtime/media-api.mjs +8 -0
  316. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  317. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  318. package/src/session-runtime/model-route/set-route.mjs +114 -34
  319. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  320. package/src/session-runtime/model-route-api.mjs +4 -2
  321. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  322. package/src/session-runtime/native-web-search.mjs +9 -8
  323. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  324. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  325. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  326. package/src/session-runtime/provider-models.mjs +1 -0
  327. package/src/session-runtime/provider-usage.mjs +4 -0
  328. package/src/session-runtime/route-resolution.mjs +3 -1
  329. package/src/session-runtime/runtime-core.mjs +4 -0
  330. package/src/session-runtime/runtime-facade.mjs +6 -0
  331. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  332. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  333. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  334. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  335. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  336. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  337. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  338. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  339. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  340. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  341. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  342. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  343. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +9 -6
  344. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  345. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  346. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  347. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  348. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  349. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  350. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  351. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  352. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  353. package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -9
  354. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  355. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  356. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  357. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  358. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  359. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  360. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  361. package/src/session-runtime/services/agent-tool/worker-index.mjs +28 -8
  362. package/src/session-runtime/services/agent-tool.mjs +4 -0
  363. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  364. package/src/session-runtime/services/provider-admin.mjs +77 -0
  365. package/src/session-runtime/session-create/session-options.mjs +7 -5
  366. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  367. package/src/session-runtime/session-transcript.mjs +4 -5
  368. package/src/session-runtime/session-turn-api.mjs +3 -9
  369. package/src/session-runtime/settings-builtin-tools-api.mjs +9 -6
  370. package/src/session-runtime/setup-tool/executor.mjs +23 -5
  371. package/src/session-runtime/setup-tool/extended-actions.mjs +6 -6
  372. package/src/session-runtime/setup-tool/settings-contract.mjs +7 -2
  373. package/src/session-runtime/setup-tool/tool-defs.mjs +13 -1
  374. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  375. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  376. package/src/session-runtime/turn/side-question-ops.mjs +1 -4
  377. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +2 -0
  378. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +4 -0
  379. package/src/session-runtime/turn/turn-run/turn-settle.mjs +8 -2
  380. package/src/session-runtime/turn/turn-run.mjs +1 -36
  381. package/src/session-runtime/usage-stats-api.mjs +4 -1
  382. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  383. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  384. package/src/session-runtime/workspace/project-branches.mjs +28 -36
  385. package/src/session-runtime/workspace/transition-steps.mjs +96 -95
  386. package/src/session-runtime/workspace/transitions.mjs +248 -68
  387. package/src/standalone/channel-transport.mjs +3 -4
  388. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  389. package/src/standalone/daemon-pg-stop.mjs +1 -3
  390. package/src/standalone/daemon-session-control.mjs +88 -0
  391. package/src/standalone/daemon-stored-session-views.mjs +23 -3
  392. package/src/standalone/daemon.mjs +2 -0
  393. package/src/standalone/local-session-runtime.mjs +11 -12
  394. package/src/standalone/session-protocol.mjs +7 -0
  395. package/src/standalone/session-runtime-inline-host.mjs +2 -0
  396. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  397. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  398. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  399. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  400. package/src/standalone/session-service/agent-tree.mjs +28 -2
  401. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  402. package/src/standalone/session-service/entries.mjs +1 -0
  403. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  404. package/src/standalone/session-service/quota-resume.mjs +28 -13
  405. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  406. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  407. package/src/standalone/session-tool-output.mjs +82 -0
  408. package/src/tui/app/app-view.jsx +2 -1
  409. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  410. package/src/tui/app/provider-setup-picker.mjs +15 -3
  411. package/src/tui/app/slash-commands.mjs +6 -0
  412. package/src/tui/app/slash-dispatch/session-commands.mjs +49 -0
  413. package/src/tui/components/Spinner.jsx +4 -0
  414. package/src/tui/components/SpinnerByline.jsx +21 -2
  415. package/src/tui/components/status-line/local-line.mjs +10 -2
  416. package/src/tui/dist/index.mjs +478 -251
  417. package/src/tui/session/active-tool-summary.mjs +1 -1
  418. package/src/tui/session/context-state.mjs +0 -3
  419. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  420. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  421. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  422. package/src/tui/session/quota-resume.mjs +140 -61
  423. package/src/tui/session/session-api/commands.mjs +4 -10
  424. package/src/tui/session/session-api/controls.mjs +12 -0
  425. package/src/tui/session/session-api/lifecycle/dispose.mjs +2 -9
  426. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  427. package/src/tui/session/session-api/lifecycle.mjs +13 -11
  428. package/src/tui/session/session-api/media.mjs +2 -0
  429. package/src/tui/session/session-api/routes.mjs +81 -57
  430. package/src/tui/session/session-api/settings.mjs +3 -3
  431. package/src/tui/session/session-api/worktree.mjs +3 -2
  432. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  433. package/src/tui/session/session-flow/drain.mjs +6 -4
  434. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  435. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  436. package/src/tui/session/session-flow/queue.mjs +1 -1
  437. package/src/tui/session/tool-approval.mjs +17 -8
  438. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  439. package/src/tui/session/tui-steering-persist.mjs +3 -5
  440. package/src/tui/session/turn-quiet.mjs +53 -0
  441. package/src/tui/session/turn-stream.mjs +5 -1
  442. package/src/tui/session/turn.mjs +38 -31
  443. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  444. package/src/tui/spinner-meta.mjs +10 -0
  445. package/src/tui/spinner-verbs.mjs +3 -0
  446. package/src/ui/statusline.mjs +13 -3
  447. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  448. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  449. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  450. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -302
  451. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  452. package/src/session-runtime/turn/share-ops.mjs +0 -77
  453. package/src/tui/session/cross-surface-share.mjs +0 -406
  454. package/src/tui/session/live-share/delta.mjs +0 -153
  455. package/src/tui/session/live-share/mirror.mjs +0 -106
  456. package/src/tui/session/live-share/owner.mjs +0 -254
  457. package/src/tui/session/live-share/retry.mjs +0 -54
  458. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  459. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  460. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  461. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  462. package/src/tui/session/live-share/viewer.mjs +0 -99
  463. package/src/tui/session/live-share/wire.mjs +0 -44
  464. package/src/tui/session/live-share.mjs +0 -154
  465. 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
@@ -87,18 +89,18 @@ export function stampedDerivation(kind, path, derive) {
87
89
 
88
90
  const SESSION_SUMMARY_INDEX_VERSION = 2;
89
91
 
90
- // Mirror of lifecycle-api.mjs listLeadSessions visibility: the cold catalog
91
- // must never surface worker/agent dispatches (memory ingest chunks, judges,
92
- // spawned agents) — the authoritative engine excludes them, so a click on
93
- // 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).
94
96
  const LEAD_OWNERS = new Set(['cli', 'user', 'mixdog']);
95
97
 
96
98
  export function isLeadVisibleRow(row) {
97
99
  const owner = String(row.owner || 'user')
98
100
  .trim()
99
101
  .toLowerCase();
100
- if (isAgentOnlySession(row)) return false;
101
- 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;
102
104
  // Mirror listLeadSessions: a previewless zero-message row is an unusable
103
105
  // scratch (desktop boot leftovers, crashed first turns) — resuming it
104
106
  // shows an empty conversation, so the catalog hides it.
@@ -115,6 +117,7 @@ export function isLeadVisibleRow(row) {
115
117
  .trim()
116
118
  .toLowerCase();
117
119
  return (
120
+ agentSession ||
118
121
  agent === 'lead' ||
119
122
  sourceType === 'lead' ||
120
123
  sourceType === 'cli' ||
@@ -149,7 +152,7 @@ function messageText(content) {
149
152
  .join(' ');
150
153
  }
151
154
 
152
- export function normalizedRow(row, heartbeatAt = 0) {
155
+ export function normalizedRow(row) {
153
156
  if (!row || typeof row.id !== 'string' || !isStoredSessionId(row.id)) return null;
154
157
  return {
155
158
  id: row.id,
@@ -160,10 +163,6 @@ export function normalizedRow(row, heartbeatAt = 0) {
160
163
  lastUsedAt: positiveNumber(row.lastUsedAt, 0),
161
164
  createdAt: positiveNumber(row.createdAt, 0),
162
165
  lastHeartbeatAt: positiveNumber(row.lastHeartbeatAt, 0),
163
- // Liveness comes from the .hb sidecar mtime alone: stored row fields
164
- // (summary index / final session save) survive completion and must not
165
- // keep the desktop working indicator on after the sidecar is deleted.
166
- heartbeatAt: positiveNumber(heartbeatAt, 0),
167
166
  closed: row.closed === true,
168
167
  status: String(row.status || (row.closed === true ? 'closed' : 'idle')),
169
168
  owner: row.owner || 'user',
@@ -196,35 +195,11 @@ export function normalizedRow(row, heartbeatAt = 0) {
196
195
  };
197
196
  }
198
197
 
199
- /** Newest heartbeat of each Lead's live agents, from rows carrying `heartbeatAt`. */
200
- export function agentHeartbeatsByOwner(rows) {
201
- const agentHeartbeatByOwner = new Map();
202
- for (const row of rows) {
203
- const heartbeatAt = positiveNumber(row?.heartbeatAt, 0);
204
- const ownerSessionId = String(row?.ownerSessionId || '').trim();
205
- const owner = String(row?.owner || '')
206
- .trim()
207
- .toLowerCase();
208
- const agent = String(row?.agent || '')
209
- .trim()
210
- .toLowerCase();
211
- if (!heartbeatAt || !ownerSessionId || (owner !== 'agent' && (!agent || agent === 'lead'))) continue;
212
- agentHeartbeatByOwner.set(ownerSessionId, Math.max(agentHeartbeatByOwner.get(ownerSessionId) || 0, heartbeatAt));
213
- }
214
- return agentHeartbeatByOwner;
215
- }
216
-
217
- function leadRowsWithAgentHeartbeat(rows) {
218
- const agentHeartbeatByOwner = agentHeartbeatsByOwner(rows);
219
- return rows
220
- .filter((row) => row && isLeadVisibleRow(row))
221
- .map((row) => {
222
- const agentHeartbeatAt = agentHeartbeatByOwner.get(row.id) || 0;
223
- return agentHeartbeatAt > 0 ? { ...row, agentHeartbeatAt } : row;
224
- });
198
+ function leadRows(rows) {
199
+ return rows.filter((row) => row && isLeadVisibleRow(row));
225
200
  }
226
201
 
227
- function rowFromSession(session, heartbeatAt = 0) {
202
+ function rowFromSession(session) {
228
203
  const messages = Array.isArray(session?.messages) ? session.messages : [];
229
204
  const preview =
230
205
  messages
@@ -239,15 +214,12 @@ function rowFromSession(session, heartbeatAt = 0) {
239
214
  )
240
215
  .map((message) => cleanText(messageText(message.content)))
241
216
  .find(Boolean) || '';
242
- return normalizedRow(
243
- {
244
- ...session,
245
- messageCount: messages.filter((message) => message?.role === 'user' || message?.role === 'assistant').length,
246
- realTurnCount: messages.filter(isRealTurnMessage).length,
247
- preview,
248
- },
249
- heartbeatAt
250
- );
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
+ });
251
223
  }
252
224
 
253
225
  // ── Session file reconcile ──────────────────────────────────────────────────
@@ -293,7 +265,7 @@ function reconcileSessionFile(directory, storageId, retained, forceRead) {
293
265
  // record or a foreign identity is not this file's session.
294
266
  const record = readTopLevelLifecycleRecord(text);
295
267
  if (isLifecycleUnreadable(record) || record.id !== storageId) return null;
296
- return rowFromSession(record.doc, 0);
268
+ return rowFromSession(record.doc);
297
269
  });
298
270
  if (read.state === PROBE_ABSENT) return null;
299
271
  // Exists and could not be read (EACCES/EIO): retain the last known row
@@ -321,53 +293,46 @@ function deepFreeze(value) {
321
293
  return value;
322
294
  }
323
295
 
324
- /** The session ids (`<id>.json`) and live sidecar ids (`<id>.hb`) of
325
- * `directory`, or null when it cannot be enumerated. */
326
- function listSessionNames(directory) {
296
+ /** The session ids (`<id>.json`) of `directory`, or null when it cannot be
297
+ * enumerated. */
298
+ function listSessionIds(directory) {
327
299
  let names;
328
300
  try {
329
301
  names = readdirSync(directory);
330
302
  } catch {
331
303
  return null;
332
304
  }
333
- const sessionIds = [];
334
- const heartbeatIds = [];
335
- for (const filename of names) {
336
- if (filename.endsWith('.json')) sessionIds.push(filename.slice(0, -5));
337
- else if (filename.endsWith('.hb') && isStoredSessionId(filename.slice(0, -3))) {
338
- heartbeatIds.push(filename.slice(0, -3));
339
- }
340
- }
341
- return { sessionIds, heartbeatIds };
305
+ return names.filter((filename) => filename.endsWith('.json')).map((filename) => filename.slice(0, -5));
342
306
  }
343
307
 
344
- /** Every `.json` entry and `.hb` sidecar id of an enumerable `directory`, or
345
- * null when it cannot be enumerated. */
308
+ /** Every `.json` entry of an enumerable `directory`, or null when it cannot
309
+ * be enumerated. */
346
310
  function scanSessionEntries(directory, indexRowsById, forceRead) {
347
- const names = listSessionNames(directory);
348
- if (!names) return null;
311
+ const sessionIds = listSessionIds(directory);
312
+ if (!sessionIds) return null;
349
313
  const entries = new Map();
350
- for (const storageId of names.sessionIds) {
314
+ for (const storageId of sessionIds) {
351
315
  const entry = reconcileSessionFile(directory, storageId, indexRowsById.get(storageId), forceRead);
352
316
  if (entry) entries.set(storageId, entry);
353
317
  }
354
- return { entries, heartbeatIds: names.heartbeatIds };
318
+ return { entries };
355
319
  }
356
320
 
357
- /** The row an entry contributes (before liveness overlays), or null. */
321
+ /** The row an entry contributes, or null. */
358
322
  function entryRow(entry, id, indexRowsById) {
359
323
  if (!entry || entry.kind === 'none') return null;
360
324
  return (entry.kind === 'row' ? entry.row : indexRowsById.get(id)) || null;
361
325
  }
362
326
 
363
327
  /** Catalog rows of reconciled `entries`, in catalog order. */
364
- function assembleCatalog(entries, indexRowsById, heartbeatMtimes) {
328
+ function assembleCatalog(entries, indexRowsById) {
365
329
  const rows = [];
366
330
  for (const [id, entry] of entries) {
367
331
  const row = entryRow(entry, id, indexRowsById);
368
- 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 });
369
334
  }
370
- return leadRowsWithAgentHeartbeat(rows).sort(byCatalogOrder);
335
+ return leadRows(rows).sort(byCatalogOrder);
371
336
  }
372
337
 
373
338
  /**
@@ -379,23 +344,18 @@ function assembleCatalog(entries, indexRowsById, heartbeatMtimes) {
379
344
  * durable summary and a single UNREADABLE file retains its last known row
380
345
  * instead of vanishing.
381
346
  */
382
- export function scanSessionFiles(heartbeatMtimes, indexRowsById, forceRead) {
347
+ export function scanSessionFiles(indexRowsById, forceRead) {
383
348
  const directory = join(dataDir(), 'sessions');
384
349
  const dirProbe = probePath(directory);
385
350
  if (dirProbe.state === PROBE_ABSENT) return [];
386
351
  if (dirProbe.state !== PROBE_PRESENT) return null;
387
352
  const scan = scanSessionEntries(directory, indexRowsById, forceRead);
388
- return scan && assembleCatalog(scan.entries, indexRowsById, heartbeatMtimes);
353
+ return scan && assembleCatalog(scan.entries, indexRowsById);
389
354
  }
390
355
 
391
356
  /** Listing from the index rows alone, or null without a valid index. */
392
- export function indexListing(index, heartbeatMtimes) {
393
- return (
394
- index.rows &&
395
- leadRowsWithAgentHeartbeat(
396
- index.rows.map((row) => ({ ...row, heartbeatAt: positiveNumber(heartbeatMtimes.get(row.id), 0) }))
397
- ).sort(byCatalogOrder)
398
- );
357
+ export function indexListing(index) {
358
+ return index.rows && leadRows(index.rows.map((row) => ({ ...row }))).sort(byCatalogOrder);
399
359
  }
400
360
 
401
361
  // ── Summary index ───────────────────────────────────────────────────────────
@@ -479,7 +439,7 @@ function readSummaryIndex(cached) {
479
439
  }
480
440
  // Same semantics as applySummaryLogText: last writer wins per id.
481
441
  if (op?.u && typeof op.u.id === 'string') {
482
- const row = normalizedRow(op.u, 0);
442
+ const row = normalizedRow(op.u);
483
443
  if (row) rowsById.set(row.id, deepFreeze(row));
484
444
  else rowsById.delete(op.u.id);
485
445
  touched.add(op.u.id);
@@ -513,7 +473,7 @@ function readSummaryIndex(cached) {
513
473
  }
514
474
  }
515
475
  const rows = applySummaryLogText({ rows: baseRows ?? [] }, index.logBytes.toString('utf8'))
516
- .rows.map((row) => normalizedRow(row, 0))
476
+ .rows.map((row) => normalizedRow(row))
517
477
  .filter(Boolean)
518
478
  .map(deepFreeze);
519
479
  for (const row of rows) index.signatures.set(row.id, JSON.stringify(row));
@@ -539,16 +499,10 @@ function changedIndexIds(previous, next) {
539
499
  return ids;
540
500
  }
541
501
 
542
- function sameMtimes(left, right) {
543
- if (!right || left.size !== right.size) return false;
544
- for (const [id, mtimeMs] of left) if (right.get(id) !== mtimeMs) return false;
545
- return true;
546
- }
547
-
548
502
  // ── Ordinary catalog ────────────────────────────────────────────────────────
549
503
  // The ordinary listing keeps its last reconcile and answers an unchanged call
550
- // from cheap stamps alone: the index pair (above), the sessions DIRECTORY and
551
- // 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.
552
506
  //
553
507
  // The directory stamp changes on every create, delete and rename in it
554
508
  // (including a temp-file + rename replace), and NOT on an in-place write
@@ -581,8 +535,6 @@ function newSessionCatalog(directory, dirStamp, index, scan) {
581
535
  dirSettled: isSettledSessionStamp(dirStamp),
582
536
  index,
583
537
  entries: scan.entries,
584
- heartbeatIds: scan.heartbeatIds,
585
- heartbeatMtimes: null,
586
538
  rows: null,
587
539
  dirty: new Set(),
588
540
  verifiedAt: Date.now(),
@@ -610,17 +562,16 @@ function reconcileKnownCatalog(catalog, directory, dirStamp, index, hinted) {
610
562
  changed = true;
611
563
  }
612
564
  if (!catalog.dirSettled || !sameSessionStamp(catalog.dirStamp, dirStamp)) {
613
- const names = listSessionNames(directory);
614
- if (!names) return null;
615
- const present = new Set(names.sessionIds);
565
+ const sessionIds = listSessionIds(directory);
566
+ if (!sessionIds) return null;
567
+ const present = new Set(sessionIds);
616
568
  for (const id of catalog.entries.keys()) {
617
569
  if (present.has(id)) continue;
618
570
  catalog.entries.delete(id);
619
571
  changedIds.add(id);
620
572
  changed = true;
621
573
  }
622
- for (const id of names.sessionIds) if (!catalog.entries.has(id)) ids.add(id);
623
- catalog.heartbeatIds = names.heartbeatIds;
574
+ for (const id of sessionIds) if (!catalog.entries.has(id)) ids.add(id);
624
575
  catalog.dirStamp = dirStamp;
625
576
  catalog.dirSettled = isSettledSessionStamp(dirStamp);
626
577
  }
@@ -634,20 +585,6 @@ function reconcileKnownCatalog(catalog, directory, dirStamp, index, hinted) {
634
585
  return { changed, changedIds };
635
586
  }
636
587
 
637
- /** Liveness: `.hb` sidecars are rewritten in place, so their mtimes are
638
- * probed every call (absent or unreadable contributes nothing). True when
639
- * they differ from the previous probe. */
640
- function refreshHeartbeatMtimes(catalog, directory) {
641
- const heartbeatMtimes = new Map();
642
- for (const id of catalog.heartbeatIds) {
643
- const probe = probePath(join(directory, `${id}.hb`));
644
- if (probe.state === PROBE_PRESENT && probe.mtimeMs > 0) heartbeatMtimes.set(id, probe.mtimeMs);
645
- }
646
- const differs = !sameMtimes(heartbeatMtimes, catalog.heartbeatMtimes);
647
- catalog.heartbeatMtimes = heartbeatMtimes;
648
- return differs;
649
- }
650
-
651
588
  /** Marks every entry of `snapshot` whose file no longer has the full stamp it
652
589
  * was judged at dirty (a replacement brings a new inode and change time even
653
590
  * when its size and mtime match). Stops early once `isCurrent()` is false. */
@@ -729,7 +666,6 @@ export function createOrdinaryCatalog() {
729
666
  }
730
667
  ({ changed, changedIds } = reconciled);
731
668
  }
732
- if (refreshHeartbeatMtimes(catalog, directory)) changed = true;
733
669
  if (changed) catalog.rows = null;
734
670
  if (assemble) rowsOf(catalog);
735
671
  armCatalogVerify(catalog);
@@ -739,9 +675,7 @@ export function createOrdinaryCatalog() {
739
675
 
740
676
  /** The (frozen) listing of a reconciled catalog, assembled on demand. */
741
677
  function rowsOf(catalog) {
742
- catalog.rows ||= assembleCatalog(catalog.entries, catalog.index.rowsById, catalog.heartbeatMtimes).map(
743
- Object.freeze
744
- );
678
+ catalog.rows ||= assembleCatalog(catalog.entries, catalog.index.rowsById).map(Object.freeze);
745
679
  return catalog.rows;
746
680
  }
747
681
 
@@ -795,7 +729,7 @@ export function createOrdinaryCatalog() {
795
729
  loadIndex,
796
730
  refresh,
797
731
  rowsOf,
798
- /** The row `id` contributes to the current catalog (before overlays). */
732
+ /** The row `id` contributes to the current catalog. */
799
733
  entryRow: (catalog, id) => entryRow(catalog.entries.get(id), id, catalog.index.rowsById),
800
734
  current: () => sessionCatalog,
801
735
  /** `listener()` runs when a background pass finds a session file that
@@ -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
@@ -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
  }
@@ -6,7 +6,7 @@
6
6
  import { closeSync, fsyncSync, openSync, writeFileSync } from 'node:fs';
7
7
  import * as fsp from 'node:fs/promises';
8
8
  import { randomBytes } from 'node:crypto';
9
- import { sessionPath } from './store/paths-heartbeat.mjs';
9
+ import { sessionPath } from './store/session-paths.mjs';
10
10
  import {
11
11
  guardedSaveOptions as _guardedSaveOptions,
12
12
  cancelSessionWrites as _cancelSessionWrites,
@@ -30,17 +30,6 @@ export {
30
30
  _upsertSessionSummary,
31
31
  _removeSessionSummary,
32
32
  } from './store-summary-index.mjs';
33
- export {
34
- publishHeartbeat,
35
- deleteHeartbeat,
36
- publishSessionPresence,
37
- deleteSessionPresence,
38
- readSessionPresenceMtime,
39
- isSessionPresenceOwnerDead,
40
- readSessionHeartbeatOwnerPid,
41
- isSessionHeartbeatOwnerDead,
42
- isProcessAlive,
43
- } from './store/paths-heartbeat.mjs';
44
33
  import { _sessionForDisk, _ensureLifecycleFields } from './store/serialize.mjs';
45
34
  import {
46
35
  _cacheSessionSummary,
@@ -55,11 +44,9 @@ import {
55
44
  withdrawPendingOwnCommit as _withdrawPendingOwnCommit,
56
45
  recordOwnSessionCommit as _recordOwnSessionCommit,
57
46
  } from './store/canonical-reader.mjs';
58
- // Durable lifecycle reads, heartbeat freshness and live-cache reclamation are
59
- // owned by dedicated modules; re-exported so prior importers of store.mjs
60
- // stay unchanged.
47
+ // Durable lifecycle reads and live-cache reclamation are owned by dedicated
48
+ // modules; re-exported so prior importers of store.mjs stay unchanged.
61
49
  export { readSessionLifecycleFromDisk, readSessionLifecycleStateFromDisk } from './store/lifecycle-read.mjs';
62
- export { readSessionHeartbeatMtime } from './store/liveness-veto.mjs';
63
50
  export { evictLiveSession, evictIdleLiveSessions } from './store/live-cache-eviction.mjs';
64
51
  import {
65
52
  setLiveSession,
@@ -78,7 +78,12 @@ export async function executeBatchCall(batch, call, callIndex) {
78
78
  // Read entries are stat-validated; scoped entries retain dependency
79
79
  // invalidation and their bounded TTL. A miss proceeds to execution.
80
80
  function lookupCaches(batch, call, exec) {
81
- const cached = lookupToolResultReuse({ sessionId: batch.sessionId, call, cwd: batch.cwd });
81
+ const cached = lookupToolResultReuse({
82
+ sessionId: batch.sessionId,
83
+ call,
84
+ cwd: batch.cwd,
85
+ sessionRef: batch.sessionRef,
86
+ });
82
87
  if (cached?.kind === 'read') exec.readCacheHit = cached.entry;
83
88
  else if (cached?.kind === 'scoped') exec.scopedCacheHit = cached.entry;
84
89
  }
@@ -115,9 +120,7 @@ async function executeLive(batch, call, callIndex, exec) {
115
120
  // this session never received the discarded body.
116
121
  let discardedRead = false;
117
122
  if (eager !== undefined && eager.mutationEpoch < epoch.mutation && isEagerDispatchable(call.name, tools)) {
118
- const stale = _isReadTool(call.name)
119
- ? mutationAffectsRead(epoch, eager.mutationEpoch, call, batch.cwd)
120
- : true;
123
+ const stale = _isReadTool(call.name) ? mutationAffectsRead(epoch, eager.mutationEpoch, call, batch.cwd) : true;
121
124
  if (stale) {
122
125
  discardedRead = _isReadTool(call.name);
123
126
  pending.delete(call.id);
@@ -176,14 +179,10 @@ async function executeSerially(batch, call, exec, suppressReadUnchangedStub = fa
176
179
  exec.executionStartedAt = Date.now();
177
180
  exec.serialExecutionStartedAt = exec.executionStartedAt;
178
181
  exec.localSearchTelemetry = {};
179
- exec.result = await executeToolFn(
180
- call.name,
181
- call.arguments,
182
- cwd,
183
- sessionId,
184
- sessionRef,
185
- { ...invocationOptions(batch, call, exec), ...(suppressReadUnchangedStub ? { suppressReadUnchangedStub: true } : {}) }
186
- );
182
+ exec.result = await executeToolFn(call.name, call.arguments, cwd, sessionId, sessionRef, {
183
+ ...invocationOptions(batch, call, exec),
184
+ ...(suppressReadUnchangedStub ? { suppressReadUnchangedStub: true } : {}),
185
+ });
187
186
  exec.toolEndedAt = Date.now();
188
187
  classifyExecuted(call, exec);
189
188
  }