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,53 +1,62 @@
1
1
  /**
2
- * Runtime-liveness evidence for the destructive paths (close, detach,
3
- * delete): the freshness of a session's `.hb` sidecar, the veto rules derived
4
- * from it and the caller-supplied `isSessionLive` probe.
2
+ * Runtime-liveness veto for the destructive paths (close, delete): the
3
+ * caller-supplied `isSessionLive` probe over the daemon's in-memory runtime
4
+ * state, plus — for the sweep (`legacyOwnerVeto`) — the legacy `.hb` / `.own`
5
+ * markers an OLDER Mixdog process still running beside this one (mid-upgrade)
6
+ * keeps publishing. No current build writes those markers; they are only ever
7
+ * READ here, never refreshed.
5
8
  *
6
9
  * Separate from the write pipeline on purpose — a veto is a pure READ taken
7
10
  * before any commit lock is held, and markSessionClosed / deleteSession must
8
- * apply exactly the same rules.
11
+ * apply exactly the same rule.
9
12
  */
10
- import { existsSync, statSync } from 'node:fs';
11
13
  import { join } from 'node:path';
12
- import { getStoreDir, deleteHeartbeat } from './paths-heartbeat.mjs';
14
+ import { getStoreDir } from './session-paths.mjs';
15
+ import { probePath, readTextFile, PROBE_PRESENT } from './fs-probe.mjs';
13
16
 
14
- function _heartbeatMtime(id) {
17
+ export const LEGACY_MARKER_SUFFIXES = ['.hb', '.own'];
18
+ // An older live owner rewrote `.hb` every ≤5s mid-turn and `.own` every ~20s
19
+ // while holding the session open; one untouched this long holds nothing.
20
+ export const LEGACY_MARKER_FRESH_MS = 2 * 60 * 1000;
21
+
22
+ function processAlive(pid) {
15
23
  try {
16
- const path = join(getStoreDir(), `${id}.hb`);
17
- return existsSync(path) ? statSync(path).mtimeMs || 0 : 0;
18
- } catch {
19
- return 0;
24
+ process.kill(pid, 0);
25
+ return true;
26
+ } catch (error) {
27
+ // ESRCH: no such process. EPERM means the pid exists.
28
+ return error?.code === 'EPERM';
20
29
  }
21
30
  }
22
31
 
23
- /**
24
- * Freshness of a session's `.hb` heartbeat sidecar (0 when absent). Used by
25
- * the fork-on-resume guard: a fresh heartbeat published by another process
26
- * means the session is actively being driven there RIGHT NOW.
27
- */
28
- export function readSessionHeartbeatMtime(id) {
29
- if (!id) return 0;
30
- return _heartbeatMtime(id);
31
- }
32
-
33
- export function _runtimeLivenessVeto(id, options = {}) {
34
- return typeof options.isSessionLive === 'function' && options.isSessionLive(id);
32
+ /** A legacy marker's evidence, or null when it is not there to judge. The
33
+ * marker holds `<msTimestamp>\n<pid>\n`; a pid-less (pre-pid) marker names
34
+ * no owner, so it is neither live nor dead. */
35
+ export function readLegacyMarker(path, now = Date.now()) {
36
+ const probe = probePath(path);
37
+ if (probe.state !== PROBE_PRESENT) return null;
38
+ const read = readTextFile(path);
39
+ const pid = read.state === PROBE_PRESENT ? Number(read.text.split('\n')[1]) || 0 : 0;
40
+ const alive = pid > 0 && processAlive(pid);
41
+ return {
42
+ fresh: now - (probe.mtimeMs || 0) <= LEGACY_MARKER_FRESH_MS,
43
+ ownerAlive: alive,
44
+ ownerDead: pid > 0 && !alive,
45
+ };
35
46
  }
36
47
 
37
- export function _heartbeatLivenessVeto(id, options = {}) {
38
- const heartbeatMtime = _heartbeatMtime(id);
39
- if (!(heartbeatMtime > 0)) return false;
40
- const hasHeartbeatSnapshot = Object.hasOwn(options, 'heartbeatSnapshotMtime');
41
- const snapshotMtime = Number(options.heartbeatSnapshotMtime) || 0;
42
- if (hasHeartbeatSnapshot && heartbeatMtime > snapshotMtime) return true;
43
- const freshMs = Number(options.heartbeatFreshMs);
44
- return Number.isFinite(freshMs) && freshMs > 0 && Date.now() - heartbeatMtime <= freshMs;
48
+ /** Whether a legacy marker of the session names a live owner pid with a
49
+ * fresh heartbeat: that session is driven by another live process. */
50
+ export function _legacyOwnerLivenessVeto(id, now = Date.now()) {
51
+ if (typeof id !== 'string' || !/^[A-Za-z0-9_-]+$/.test(id)) return false;
52
+ const dir = getStoreDir();
53
+ return LEGACY_MARKER_SUFFIXES.some((suffix) => {
54
+ const marker = readLegacyMarker(join(dir, `${id}${suffix}`), now);
55
+ return Boolean(marker?.fresh && marker.ownerAlive);
56
+ });
45
57
  }
46
58
 
47
- export function _deleteHeartbeatUnlessNewer(id, options = {}) {
48
- const hasHeartbeatSnapshot = Object.hasOwn(options, 'heartbeatSnapshotMtime');
49
- const snapshotMtime = Number(options.heartbeatSnapshotMtime) || 0;
50
- if (!hasHeartbeatSnapshot || _heartbeatMtime(id) <= snapshotMtime) {
51
- deleteHeartbeat(id);
52
- }
59
+ export function _runtimeLivenessVeto(id, options = {}) {
60
+ if (typeof options.isSessionLive === 'function' && options.isSessionLive(id)) return true;
61
+ return options.legacyOwnerVeto === true && _legacyOwnerLivenessVeto(id);
53
62
  }
@@ -8,7 +8,7 @@ import {
8
8
  readCanonicalSessionRecord,
9
9
  acceptStrictSessionRecords,
10
10
  } from './canonical-reader.mjs';
11
- import { sessionPath } from './paths-heartbeat.mjs';
11
+ import { sessionPath } from './session-paths.mjs';
12
12
  import { noteMemoryRelease } from '../../../../shared/idle-gc.mjs';
13
13
 
14
14
  // Recent full-session reads are much hotter than writes while a user hops
@@ -4,7 +4,7 @@
4
4
  * snapshot, or the evidence-backed failed-save snapshot. Nothing here writes;
5
5
  * the precedence rules are the whole responsibility.
6
6
  */
7
- import { sessionPath } from './paths-heartbeat.mjs';
7
+ import { sessionPath } from './session-paths.mjs';
8
8
  import { _savePending } from './pending-saves.mjs';
9
9
  import { _liveSessions, _droppedSaveIds, getFailedSaveSnapshot } from './live-state.mjs';
10
10
  import { _readStoredSessionCached } from './load-cache.mjs';
@@ -9,7 +9,7 @@ import { isAgentOwner } from '../../agent-owner.mjs';
9
9
  import { listStoredAgentWorkerLinks } from '../store-agent-worker-rows.mjs';
10
10
  import { listStoredSessionSummaries } from './listing.mjs';
11
11
  import { STORED_SESSION_UNREADABLE, _storedSessionFromFile } from './serialize.mjs';
12
- import { getStoreDir, sessionPath, deleteSessionPresence } from './paths-heartbeat.mjs';
12
+ import { getStoreDir, sessionPath } from './session-paths.mjs';
13
13
  import {
14
14
  readCanonicalSessionRecord as _readCanonicalRecord,
15
15
  CANONICAL_RECORD_UNREADABLE as LIFECYCLE_AMBIGUOUS,
@@ -32,7 +32,7 @@ import {
32
32
  import { purgeSessionSaveBookkeeping as _purgeSessionSaveBookkeeping } from './save-worker.mjs';
33
33
  import { _uncacheSessionSummary, _queueSessionSummaryRemoval, _cachedSummaryRows } from './summary-cache.mjs';
34
34
  import { _savePending, _clearDebounce, _releasePendingSlot } from './pending-saves.mjs';
35
- import { _runtimeLivenessVeto, _heartbeatLivenessVeto, _deleteHeartbeatUnlessNewer } from './liveness-veto.mjs';
35
+ import { _runtimeLivenessVeto } from './liveness-veto.mjs';
36
36
  import { _runSessionPurgeHooks } from './session-observers.mjs';
37
37
  import { deleteCompactionArchive } from '../compaction-archive.mjs';
38
38
 
@@ -40,8 +40,8 @@ import { deleteCompactionArchive } from '../compaction-archive.mjs';
40
40
  * metadata only (the summary rows and the agent-worker links — no folder
41
41
  * scan); each candidate's own file is then read strictly and must still be an
42
42
  * agent-owned record linked to this parent, so a stale/foreign metadata row
43
- * can never name a deletion target. Used only by explicit parent deletion;
44
- * ordinary close/context switches keep the relationship intact. */
43
+ * can never name a deletion target. Parent deletion no longer removes these
44
+ * children; they outlive the parent as independent sessions. */
45
45
  export function listOwnedAgentSessionIds(ownerSessionId) {
46
46
  const ownerId = String(ownerSessionId || '').trim();
47
47
  if (!/^[A-Za-z0-9_-]+$/.test(ownerId)) return [];
@@ -78,14 +78,11 @@ function knownSessionCwds(id) {
78
78
  export function deleteSession(id, options = {}) {
79
79
  // Keep caller probes and all vetoes ahead of the non-reentrant lock and
80
80
  // ahead of pending-save disruption, matching markSessionClosed().
81
- if (_runtimeLivenessVeto(id, options) || _heartbeatLivenessVeto(id, options)) return false;
81
+ if (_runtimeLivenessVeto(id, options)) return false;
82
82
  const deleteGuard = _guardedSaveOptions(id);
83
83
  const commitControl = _acquireWriteCommit(deleteGuard);
84
84
  if (commitControl === false) return false;
85
85
  try {
86
- // Cross-process revival after full-TTL silence remains best-effort; the
87
- // tombstone resurrection guard is authoritative. Only re-stat .hb here.
88
- if (_heartbeatLivenessVeto(id, options)) return false;
89
86
  // ── 1. unlink FIRST, still holding the commit lock ─────────────────────
90
87
  // A failed unlink is NOT a delete: the canonical bytes are still there, so
91
88
  // nothing may be purged, cancelled or closed — every pending write, parked
@@ -141,9 +138,6 @@ export function deleteSession(id, options = {}) {
141
138
  _savePending.delete(id);
142
139
  _purgeSessionSaveBookkeeping(id);
143
140
  _runSessionPurgeHooks(id, { cwds: knownSessionCwds(id) });
144
- // Preserve a sidecar published strictly after the sweep's scan snapshot.
145
- _deleteHeartbeatUnlessNewer(id, options);
146
- deleteSessionPresence(id);
147
141
  // The display-only compaction archive has no meaning without its session.
148
142
  deleteCompactionArchive(getStoreDir(), id);
149
143
  _clearLiveSession(id);
@@ -0,0 +1,59 @@
1
+ import { existsSync, mkdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getPluginData } from '../../config.mjs';
4
+
5
+ // Session file paths are rebuilt on every load/save/sidecar probe. Memoize the
6
+ // joined strings per data dir: a changed data dir (MIXDOG_DATA_DIR switch)
7
+ // drops the whole memo, and the per-extension maps are bounded.
8
+ const SESSION_PATH_MEMO_LIMIT = 4096;
9
+ let _memoDataDir = null;
10
+ let _memoStoreDir = null;
11
+ const _memoFilePaths = new Map(); // extension → Map<id, path>
12
+
13
+ function _storeDirPath() {
14
+ const dataDir = getPluginData();
15
+ if (dataDir !== _memoDataDir) {
16
+ _memoDataDir = dataDir;
17
+ _memoStoreDir = join(dataDir, 'sessions');
18
+ _memoFilePaths.clear();
19
+ }
20
+ return _memoStoreDir;
21
+ }
22
+
23
+ function _memoFilePath(dir, id, extension) {
24
+ let byId = _memoFilePaths.get(extension);
25
+ if (!byId) {
26
+ byId = new Map();
27
+ _memoFilePaths.set(extension, byId);
28
+ }
29
+ let path = byId.get(id);
30
+ if (path === undefined) {
31
+ path = join(dir, _sessionFileName(id, extension));
32
+ if (byId.size >= SESSION_PATH_MEMO_LIMIT) byId.clear();
33
+ byId.set(id, path);
34
+ }
35
+ return path;
36
+ }
37
+ export function getStoreDir() {
38
+ const dir = _storeDirPath();
39
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
40
+ return dir;
41
+ }
42
+ function _sessionFileName(id, extension) {
43
+ return `${id}${extension}`;
44
+ }
45
+ // Enforce minted session-id shape before using it in a path to prevent
46
+ // `../` traversal. session IDs are generated by createSession as
47
+ // `sess_<timestamp>_<hex>` — reject anything that doesn't match.
48
+ function _assertSessionId(id) {
49
+ if (!id || typeof id !== 'string' || !/^[A-Za-z0-9_-]+$/.test(id)) {
50
+ throw new Error(`[session-store] invalid session id: ${JSON.stringify(id)}`);
51
+ }
52
+ }
53
+ function _sessionFilePath(id, extension) {
54
+ _assertSessionId(id);
55
+ return _memoFilePath(getStoreDir(), id, extension);
56
+ }
57
+ export function sessionPath(id) {
58
+ return _sessionFilePath(id, '.json');
59
+ }
@@ -1,7 +1,7 @@
1
1
  import { readdirSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { getPluginData } from '../../config.mjs';
4
- import { getStoreDir } from './paths-heartbeat.mjs';
4
+ import { getStoreDir } from './session-paths.mjs';
5
5
  import { probePath, PROBE_PRESENT, PROBE_ABSENT } from './fs-probe.mjs';
6
6
  import { STORED_SESSION_UNREADABLE, _storedSessionFromFile } from './serialize.mjs';
7
7
  import {
@@ -4,7 +4,7 @@
4
4
  // sidecars. The generator yields between records so cooperative hosts never
5
5
  // hold the event loop for a whole directory scan; the synchronous wrapper
6
6
  // drains it in one go.
7
- import { getStoreDir } from '../paths-heartbeat.mjs';
7
+ import { getStoreDir } from '../session-paths.mjs';
8
8
  import { probePath, PROBE_PRESENT } from '../fs-probe.mjs';
9
9
  import { persistSweepRecordCache, pruneSweepRecordCache } from './sweep-record.mjs';
10
10
  import { collectSweepRows, createSweepTally, resolveSweepPlan } from './sweep-plan.mjs';
@@ -1,17 +1,13 @@
1
1
  // sweep/sweep-finish.mjs
2
2
  // What runs after every row has its verdict: the resumable-open retention
3
- // cap, the orphan sidecar reap, and the one batched summary-index prune.
3
+ // cap, the legacy/orphan sidecar reap, and the one batched summary-index prune.
4
4
  import { readdirSync, unlinkSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
6
  import { probePath, PROBE_PRESENT, PROBE_ABSENT } from '../fs-probe.mjs';
7
7
  import { _queueSummaryIndexPrune } from '../summary-cache.mjs';
8
8
  import { deleteSession } from '../session-delete.mjs';
9
9
  import { COMPACTION_ARCHIVE_SUFFIX } from '../../compaction-archive.mjs';
10
- import { isSidecarOwnerDead } from '../paths-heartbeat.mjs';
11
-
12
- // A live presence owner rewrites `.own` every ~20s; one untouched for the
13
- // attach guard's whole freshness window holds nothing open.
14
- const PRESENCE_ORPHAN_AGE_MS = 2 * 60 * 1000;
10
+ import { LEGACY_MARKER_SUFFIXES, readLegacyMarker } from '../liveness-veto.mjs';
15
11
 
16
12
  /** Retention cap: prune resumable open (non-tombstone) sessions newest-first
17
13
  * — keep the most recent openMaxCount, prune anything older than openMaxAgeMs
@@ -37,8 +33,7 @@ export function pruneOpenCandidates({ plan, now, tally }) {
37
33
  deleteSession(c.id, {
38
34
  deferSummaryUpdate: true,
39
35
  isSessionLive: plan.isSessionLive,
40
- heartbeatSnapshotMtime: c.heartbeatSnapshotMtime,
41
- heartbeatFreshMs: c.heartbeatFreshMs,
36
+ legacyOwnerVeto: true,
42
37
  })
43
38
  ) {
44
39
  tally.openPruned++;
@@ -53,40 +48,40 @@ export function pruneOpenCandidates({ plan, now, tally }) {
53
48
  }
54
49
  }
55
50
 
56
- /** Orphan .hb/.own/compaction-archive reap: a sidecar whose .json no longer
51
+ /** Legacy `.hb` heartbeat and `.own` presence sidecars are written by no
52
+ * current build, but an older Mixdog process still running mid-upgrade keeps
53
+ * publishing them. One is reaped only once it holds nothing: its recorded
54
+ * owner pid is dead or it went stale; a fresh marker of a live (or
55
+ * unrecorded) owner is kept. Orphan compaction-archive reap: an archive whose .json no longer
57
56
  * exists is dead weight once it is also stale (older than maxAge) — the
58
- * session JSON was swept/closed but the sidecar lingered (crashed owner or
59
- * pre-fix orphan). The staleness gate avoids nuking the sidecar of a session
60
- * mid-create whose .json write has not landed yet. Yields between sidecars
61
- * like the row loop. */
57
+ * session JSON was swept/closed but the archive lingered. The staleness gate
58
+ * avoids nuking the archive of a session mid-create whose .json write has not
59
+ * landed yet. Yields between sidecars like the row loop. */
62
60
  export function* reapOrphanSidecars({ plan, dir, now, tally }) {
63
- const recordOf = (sidecar) =>
64
- sidecar.endsWith(COMPACTION_ARCHIVE_SUFFIX)
65
- ? `${sidecar.slice(0, -COMPACTION_ARCHIVE_SUFFIX.length)}.json`
66
- : sidecar.replace(/\.(hb|own)$/, '.json');
61
+ const recordOf = (sidecar) => `${sidecar.slice(0, -COMPACTION_ARCHIVE_SUFFIX.length)}.json`;
62
+ const unlinkSidecar = (h) => {
63
+ try {
64
+ unlinkSync(join(dir, h));
65
+ tally.cleaned++;
66
+ } catch {
67
+ /* ignore */
68
+ }
69
+ };
67
70
  try {
68
71
  for (const h of readdirSync(dir).filter(
69
72
  (f) => f.endsWith('.hb') || f.endsWith('.own') || f.endsWith(COMPACTION_ARCHIVE_SUFFIX)
70
73
  )) {
71
74
  yield undefined;
72
- // Only a PROVEN-absent session file makes its sidecar an orphan.
75
+ if (LEGACY_MARKER_SUFFIXES.some((suffix) => h.endsWith(suffix))) {
76
+ const marker = readLegacyMarker(join(dir, h), now);
77
+ if (marker && (marker.ownerDead || !marker.fresh)) unlinkSidecar(h);
78
+ continue;
79
+ }
80
+ // Only a PROVEN-absent session file makes its archive an orphan.
73
81
  if (probePath(join(dir, recordOf(h))).state !== PROBE_ABSENT) continue;
74
82
  const sidecarProbe = probePath(join(dir, h));
75
83
  if (sidecarProbe.state !== PROBE_PRESENT) continue;
76
- // A presence sidecar is only ever published while its record exists,
77
- // so one without a record whose recorded owner is dead (or which no
78
- // live owner refreshed within the presence window) is a leftover of a
79
- // deleted session, not a session mid-create.
80
- const orphanPresence =
81
- h.endsWith('.own') && (now - sidecarProbe.mtimeMs > PRESENCE_ORPHAN_AGE_MS || isSidecarOwnerDead(join(dir, h)));
82
- if (orphanPresence || now - sidecarProbe.mtimeMs > plan.maxAge) {
83
- try {
84
- unlinkSync(join(dir, h));
85
- tally.cleaned++;
86
- } catch {
87
- /* ignore */
88
- }
89
- }
84
+ if (now - sidecarProbe.mtimeMs > plan.maxAge) unlinkSidecar(h);
90
85
  }
91
86
  } catch {
92
87
  /* dir scan failure — non-fatal */
@@ -2,7 +2,6 @@
2
2
  // One sweep's resolved options (what to sweep and with which bounds), the
3
3
  // candidate rows it visits, and the tally it fills in.
4
4
  import { readdirSync } from 'node:fs';
5
- import { loadConfig } from '../../../config.mjs';
6
5
  import { listStoredSessionSummaries } from '../listing.mjs';
7
6
  import { DEFAULT_SESSION_TTL_MS, RESUMABLE_OPEN_MAX_AGE_MS, RESUMABLE_OPEN_MAX_COUNT } from './sweep-record.mjs';
8
7
 
@@ -11,12 +10,6 @@ export function resolveSweepPlan(ttlMs, options = {}) {
11
10
  options = ttlMs;
12
11
  ttlMs = options.ttlMs;
13
12
  }
14
- let terminalReapConfig = null;
15
- try {
16
- terminalReapConfig = loadConfig({ secrets: false });
17
- } catch {
18
- /* built-ins remain available */
19
- }
20
13
  const sweepIdle = options.sweepIdle !== false;
21
14
  const tombstoneMaxAgeMs = Number(options.tombstoneMaxAgeMs);
22
15
  const optAge = Number(options.openMaxAgeMs);
@@ -24,7 +17,6 @@ export function resolveSweepPlan(ttlMs, options = {}) {
24
17
  return {
25
18
  maxAge: ttlMs || DEFAULT_SESSION_TTL_MS,
26
19
  sweepIdle,
27
- terminalReapConfig,
28
20
  tombstoneMaxAgeMs,
29
21
  sweepTombstones: Number.isFinite(tombstoneMaxAgeMs) && tombstoneMaxAgeMs > 0,
30
22
  // Retention cap for resumable open sessions runs only on the idle sweep
@@ -1,18 +1,14 @@
1
1
  // sweep/sweep-record.mjs
2
2
  // What the stale-session sweep reads per record and the bounds it decides
3
- // with: the fingerprint-cached lifecycle record, the linked-agent retention
4
- // rule, and the idle / retention / blank-scratch thresholds.
3
+ // with: the fingerprint-cached lifecycle record and the
4
+ // idle / retention / blank-scratch thresholds.
5
5
  import { readFileSync } from 'node:fs';
6
6
  import { join } from 'node:path';
7
7
  import { writeJsonAtomicSync } from '../../../../../shared/atomic-file.mjs';
8
8
  import { getPluginData } from '../../../config.mjs';
9
- import { isAgentOwner } from '../../../agent-owner.mjs';
10
9
  import { readTopLevelLifecycleRecord, isLifecycleUnreadable } from '../../lifecycle-scan.mjs';
11
- import { sessionPath } from '../paths-heartbeat.mjs';
12
- import { probePath, PROBE_ABSENT } from '../fs-probe.mjs';
13
10
 
14
11
  export const DEFAULT_SESSION_TTL_MS = 5 * 60 * 1000; // 5 minutes idle — aligned with Anthropic 5m messages tier and OpenAI in-memory cache window
15
- export const AGENT_TERMINAL_STATUSES = new Set(['idle', 'done', 'error']);
16
12
  // Hard wall-clock ceiling for sessions stuck in status='running'. The
17
13
  // stream-watchdog should abort stalled streams within ~120s, but if it misses
18
14
  // one (process crash, watchdog not started, provider never returned), this
@@ -52,7 +48,7 @@ export const BLANK_SCRATCH_MAX_AGE_MS = 60 * 60 * 1000; // 1h
52
48
  // running is still parsed again.
53
49
  const sweepRecordCache = new Map();
54
50
  const SWEEP_RECORD_CACHE_FILE = 'session-sweep-records.json';
55
- const SWEEP_RECORD_CACHE_VERSION = 1;
51
+ const SWEEP_RECORD_CACHE_VERSION = 2;
56
52
  let sweepRecordCacheDataDir = null;
57
53
  let sweepRecordCacheDirty = false;
58
54
  let sweepRecordParses = 0;
@@ -86,11 +82,13 @@ function syncSweepRecordCache() {
86
82
  }
87
83
 
88
84
  // The only document fields sweep-row reads (effectiveFields, the closed
89
- // check and retainedLinkedAgent). Caching the whole top-level document kept
85
+ // check). Caching the whole top-level document kept
90
86
  // every session's tool catalogs, schemas and provider state alive — one
91
87
  // entry per session file, measured at ~290MB of a 470MB daemon heap.
92
88
  const SWEEP_DOC_FIELDS = [
93
89
  'id',
90
+ 'closed',
91
+ 'closedReason',
94
92
  'owner',
95
93
  'status',
96
94
  'provider',
@@ -172,13 +170,3 @@ export function sweepRecordCacheStats() {
172
170
  syncSweepRecordCache();
173
171
  return { entries: sweepRecordCache.size, parses: sweepRecordParses };
174
172
  }
175
-
176
- /** Child-agent transcripts share their visible parent's retention boundary.
177
- * Presence (including a tombstone or unreadable file) preserves the child;
178
- * only proven parent absence releases it to ordinary cleanup. */
179
- export function retainedLinkedAgent(session) {
180
- if (!session || !isAgentOwner(session)) return false;
181
- const parentId = String(session.ownerSessionId || session.parentSessionId || '').trim();
182
- if (!/^[A-Za-z0-9_-]+$/.test(parentId) || parentId === session.id) return false;
183
- return probePath(sessionPath(parentId)).state !== PROBE_ABSENT;
184
- }