mixdog 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (692) hide show
  1. package/README.md +18 -0
  2. package/package.json +2 -1
  3. package/scripts/gate-local.mjs +6 -4
  4. package/scripts/lib/gate-scheduler.mjs +29 -11
  5. package/scripts/probe-provider-catalog.mjs +31 -0
  6. package/scripts/provider-pingpong-live.mjs +599 -0
  7. package/scripts/session-sweep.mjs +5 -25
  8. package/src/agents/advisor/AGENT.md +1 -1
  9. package/src/agents/advisor/agent.json +1 -1
  10. package/src/agents/maintainer/AGENT.md +1 -1
  11. package/src/agents/maintainer/agent.json +1 -1
  12. package/src/agents/reviewer/AGENT.md +2 -4
  13. package/src/agents/security/AGENT.md +1 -2
  14. package/src/agents/writer/AGENT.md +2 -3
  15. package/src/defaults/shipped-history.json +11 -1
  16. package/src/defaults/skills/image/SKILL.md +21 -23
  17. package/src/defaults/skills/setup/SKILL.md +6 -1
  18. package/src/defaults/skills/setup/references/actions.md +44 -22
  19. package/src/defaults/skills/setup/references/surfaces.md +10 -8
  20. package/src/headless-exec.mjs +15 -8
  21. package/src/lib/keychain-cjs.cjs +20 -15
  22. package/src/output-styles/common.md +11 -10
  23. package/src/rules/agent/AGENT.md +6 -4
  24. package/src/rules/lead/LEAD.md +7 -9
  25. package/src/rules/shared/45-destructive.md +4 -0
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -0
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +28 -7
  28. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -11
  29. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +92 -61
  30. package/src/runtime/agent/orchestrator/cache-mtime.mjs +10 -1
  31. package/src/runtime/agent/orchestrator/config-providers-merge.mjs +7 -0
  32. package/src/runtime/agent/orchestrator/config.mjs +5 -0
  33. package/src/runtime/agent/orchestrator/context/collect.mjs +1 -0
  34. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +26 -7
  35. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +112 -7
  36. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +101 -23
  37. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +2 -0
  38. package/src/runtime/agent/orchestrator/providers/anthropic-api-key-fetch.mjs +36 -0
  39. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +48 -20
  40. package/src/runtime/agent/orchestrator/providers/anthropic-error-contract.mjs +3 -1
  41. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +24 -17
  42. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +9 -9
  43. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +26 -44
  45. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +31 -15
  46. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-blocks.mjs +20 -1
  47. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-delta.mjs +15 -2
  48. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +11 -4
  49. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/message-events.mjs +3 -0
  50. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +12 -5
  51. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-outcome.mjs +1 -0
  52. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-state.mjs +14 -0
  53. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -0
  54. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +9 -0
  55. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +10 -0
  56. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +41 -12
  57. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +13 -1
  58. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +131 -9
  59. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +29 -10
  60. package/src/runtime/agent/orchestrator/providers/antigravity-retry-policy.mjs +125 -8
  61. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +12 -62
  62. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +117 -41
  63. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  64. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +117 -72
  65. package/src/runtime/agent/orchestrator/providers/compat-request-policy.mjs +78 -2
  66. package/src/runtime/agent/orchestrator/providers/cursor-auth.mjs +39 -5
  67. package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
  68. package/src/runtime/agent/orchestrator/providers/cursor-native-context.mjs +48 -0
  69. package/src/runtime/agent/orchestrator/providers/cursor-wire-exec.mjs +144 -34
  70. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +28 -4
  71. package/src/runtime/agent/orchestrator/providers/cursor-wire-request.mjs +8 -4
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-bridge.mjs +42 -11
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-stream-messages.mjs +109 -6
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +17 -4
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -2
  76. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +73 -7
  77. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +75 -6
  78. package/src/runtime/agent/orchestrator/providers/custom-reasoning.mjs +34 -7
  79. package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +32 -6
  80. package/src/runtime/agent/orchestrator/providers/deepseek.mjs +67 -0
  81. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +29 -5
  82. package/src/runtime/agent/orchestrator/providers/gemini-cache-policy.mjs +11 -4
  83. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +36 -13
  84. package/src/runtime/agent/orchestrator/providers/gemini-error-contract.mjs +101 -11
  85. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +41 -5
  86. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +1 -0
  87. package/src/runtime/agent/orchestrator/providers/gemini-rest-stream/watchdogs.mjs +16 -5
  88. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +19 -14
  89. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +371 -41
  90. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -2
  91. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +97 -49
  92. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +81 -10
  93. package/src/runtime/agent/orchestrator/providers/gemini.mjs +35 -8
  94. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -0
  96. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +60 -0
  97. package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +1 -0
  98. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +253 -42
  99. package/src/runtime/agent/orchestrator/providers/lib/anthropic-server-tool-usage.mjs +18 -0
  100. package/src/runtime/agent/orchestrator/providers/lib/anthropic-system-blocks.mjs +27 -6
  101. package/src/runtime/agent/orchestrator/providers/lib/claude-bridge-schema.mjs +392 -0
  102. package/src/runtime/agent/orchestrator/providers/lib/inclusive-usage.mjs +54 -0
  103. package/src/runtime/agent/orchestrator/providers/lib/origin-bound-fetch.mjs +16 -0
  104. package/src/runtime/agent/orchestrator/providers/lib/request-compression.mjs +86 -0
  105. package/src/runtime/agent/orchestrator/providers/lib/responses-terminal-fields.mjs +11 -0
  106. package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +8 -0
  107. package/src/runtime/agent/orchestrator/providers/lib/wire-pairing.mjs +50 -22
  108. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +133 -21
  109. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +13 -15
  110. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +7 -1
  111. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +1 -1
  112. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  113. package/src/runtime/agent/orchestrator/providers/model-proxy-provider.mjs +92 -16
  114. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -13
  115. package/src/runtime/agent/orchestrator/providers/openai-codex-metadata.mjs +2 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +133 -62
  117. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +35 -14
  118. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-result.mjs +5 -2
  119. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +39 -7
  120. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/tool-call-acc.mjs +2 -9
  121. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +5 -0
  122. package/src/runtime/agent/orchestrator/providers/openai-compat-error-contract.mjs +1 -1
  123. package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +84 -2
  124. package/src/runtime/agent/orchestrator/providers/openai-compat-options.mjs +47 -25
  125. package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +5 -1
  126. package/src/runtime/agent/orchestrator/providers/openai-compat-reasoning-field.mjs +155 -0
  127. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +40 -24
  128. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +63 -25
  129. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2901 -0
  130. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-parity.fixtures.mjs +183 -0
  131. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +87 -6
  132. package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +51 -3
  133. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +7 -1
  134. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +2 -0
  135. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +103 -26
  136. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +23 -4
  137. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +11 -6
  138. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +17 -2
  139. package/src/runtime/agent/orchestrator/providers/openai-direct-request.mjs +15 -23
  140. package/src/runtime/agent/orchestrator/providers/openai-http-sse-request.mjs +64 -52
  141. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +23 -10
  142. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/terminal-frames.mjs +28 -5
  143. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +10 -0
  144. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-items.mjs +18 -7
  145. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-outcome.mjs +4 -0
  146. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-state.mjs +5 -0
  147. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/text-relay.mjs +9 -1
  148. package/src/runtime/agent/orchestrator/providers/openai-model-capabilities.mjs +80 -0
  149. package/src/runtime/agent/orchestrator/providers/openai-oauth-dispatch.mjs +3 -1
  150. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +7 -0
  151. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +7 -1
  152. package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +72 -24
  153. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +323 -0
  154. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +50 -16
  155. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +7 -19
  156. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/refusals.mjs +60 -0
  157. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state/tool-calls.mjs +51 -36
  158. package/src/runtime/agent/orchestrator/providers/openai-ws-response-state.mjs +30 -0
  159. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +12 -0
  160. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/terminal-frames.mjs +25 -6
  161. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -9
  162. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +181 -0
  163. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +78 -70
  164. package/src/runtime/agent/orchestrator/providers/openrouter.mjs +74 -0
  165. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +150 -10
  166. package/src/runtime/agent/orchestrator/providers/registry.mjs +13 -2
  167. package/src/runtime/agent/orchestrator/providers/retry-classification.mjs +7 -1
  168. package/src/runtime/agent/orchestrator/providers/transport-scope.d.mts +6 -0
  169. package/src/runtime/agent/orchestrator/providers/transport-scope.mjs +28 -0
  170. package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +164 -0
  171. package/src/runtime/agent/orchestrator/providers/wire-route.mjs +522 -0
  172. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +1131 -0
  173. package/src/runtime/agent/orchestrator/providers/xai-tool-search.fixtures.mjs +195 -0
  174. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +104 -0
  175. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +8 -6
  176. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +24 -0
  177. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +15 -0
  178. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +30 -2
  179. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +3 -2
  180. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -3
  181. package/src/runtime/agent/orchestrator/runtime-core/provider-request-snapshot.mjs +7 -3
  182. package/src/runtime/agent/orchestrator/runtime-core/session-title.mjs +21 -1
  183. package/src/runtime/agent/orchestrator/runtime-core/skill-tool-loading.mjs +16 -3
  184. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge-contract.mjs +6 -0
  185. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +526 -0
  186. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  187. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-schema.mjs +10 -7
  188. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +178 -71
  189. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +102 -12
  190. package/src/runtime/agent/orchestrator/runtime-core/tool-exposure.mjs +96 -0
  191. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +10 -8
  192. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -2
  193. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +24 -0
  194. package/src/runtime/agent/orchestrator/session/cache/tool-result-reuse.mjs +10 -2
  195. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -3
  196. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +5 -11
  197. package/src/runtime/agent/orchestrator/session/catalog-db/worker.mjs +6 -22
  198. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +3 -2
  199. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +16 -93
  200. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +16 -2
  201. package/src/runtime/agent/orchestrator/session/compact/summary-anchor.mjs +5 -0
  202. package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +148 -0
  203. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +1 -1
  204. package/src/runtime/agent/orchestrator/session/context-tool-schema.mjs +17 -2
  205. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -4
  206. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +0 -6
  207. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +0 -6
  208. package/src/runtime/agent/orchestrator/session/eager-dispatch/admission.mjs +3 -2
  209. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +6 -1
  210. package/src/runtime/agent/orchestrator/session/historical-session-closure.mjs +10 -0
  211. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +2 -5
  212. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +89 -1
  213. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +1 -1
  214. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +56 -0
  215. package/src/runtime/agent/orchestrator/session/loop/deferred-call-through.mjs +18 -8
  216. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +1 -27
  217. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +1 -1
  218. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -10
  219. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +2 -9
  220. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +24 -10
  221. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +135 -0
  222. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +31 -4
  223. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +76 -0
  224. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +67 -20
  225. package/src/runtime/agent/orchestrator/session/loop/step-auto-effort.mjs +10 -10
  226. package/src/runtime/agent/orchestrator/session/loop/tool-call-resolution.mjs +95 -0
  227. package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +6 -0
  228. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +30 -3
  229. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +29 -5
  230. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +15 -1
  231. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +147 -0
  232. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +7 -5
  233. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +33 -3
  234. package/src/runtime/agent/orchestrator/session/manager/ask-support.mjs +0 -4
  235. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +23 -2
  236. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +34 -12
  237. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +54 -13
  238. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +33 -0
  239. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +57 -25
  240. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +11 -0
  241. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +22 -0
  242. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +57 -13
  243. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +8 -0
  244. package/src/runtime/agent/orchestrator/session/manager/failed-turn-rewind.mjs +16 -0
  245. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +6 -120
  246. package/src/runtime/agent/orchestrator/session/manager/pending-persist-queue.mjs +1 -1
  247. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +231 -16
  248. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +42 -49
  249. package/src/runtime/agent/orchestrator/session/manager/runtime-state.mjs +50 -0
  250. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +47 -17
  251. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +26 -4
  252. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +82 -0
  253. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +36 -35
  254. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +29 -13
  255. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +6 -3
  256. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +4 -1
  257. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +45 -0
  258. package/src/runtime/agent/orchestrator/session/manager.mjs +4 -10
  259. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +6 -0
  260. package/src/runtime/agent/orchestrator/session/send-instrumentation.mjs +2 -1
  261. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +17 -1
  262. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +96 -0
  263. package/src/runtime/agent/orchestrator/session/side-question.mjs +197 -0
  264. package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +22 -15
  265. package/src/runtime/agent/orchestrator/session/store/lifecycle-read.mjs +1 -1
  266. package/src/runtime/agent/orchestrator/session/store/listing.mjs +2 -6
  267. package/src/runtime/agent/orchestrator/session/store/live-cache-eviction.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +23 -0
  269. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +46 -37
  270. package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +1 -1
  271. package/src/runtime/agent/orchestrator/session/store/load-session.mjs +1 -1
  272. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +44 -37
  273. package/src/runtime/agent/orchestrator/session/store/session-observers.mjs +4 -2
  274. package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +59 -0
  275. package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +1 -1
  276. package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +1 -1
  277. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-finish.mjs +27 -21
  278. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +0 -8
  279. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +6 -18
  280. package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +33 -106
  281. package/src/runtime/agent/orchestrator/session/store/write-admission.mjs +4 -2
  282. package/src/runtime/agent/orchestrator/session/store-agent-worker-pool.mjs +5 -8
  283. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +136 -196
  284. package/src/runtime/agent/orchestrator/session/store-summary-archived-agent.mjs +34 -15
  285. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +53 -115
  286. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +8 -0
  287. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +10 -1
  288. package/src/runtime/agent/orchestrator/session/store-summary-locations.mjs +3 -29
  289. package/src/runtime/agent/orchestrator/session/store-summary-reader-catalog-fixture.mjs +1 -1
  290. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +17 -10
  291. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +9 -20
  292. package/src/runtime/agent/orchestrator/session/store.mjs +22 -19
  293. package/src/runtime/agent/orchestrator/session/tool-batch/execute-call.mjs +12 -12
  294. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +38 -14
  295. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +15 -4
  296. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +1 -1
  297. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +7 -1
  298. package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +4 -0
  299. package/src/runtime/agent/orchestrator/session/tool-schema-rejection.mjs +79 -0
  300. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +72 -15
  301. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +45 -0
  302. package/src/runtime/agent/orchestrator/stall-policy.mjs +50 -0
  303. package/src/runtime/agent/orchestrator/tools/bash-policy-scan.mjs +8 -2
  304. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +3 -3
  305. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +5 -1
  306. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +6 -2
  307. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +4 -1
  308. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +218 -20
  309. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +160 -39
  310. package/src/runtime/agent/orchestrator/tools/builtin/git-partial-stage.mjs +7 -5
  311. package/src/runtime/agent/orchestrator/tools/builtin/grep-formatting.mjs +14 -5
  312. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-context-expander.mjs +4 -3
  313. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-output.mjs +2 -1
  314. package/src/runtime/agent/orchestrator/tools/builtin/lib/grep-path-fanout.mjs +48 -44
  315. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +10 -3
  316. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +247 -49
  317. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +5 -4
  318. package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +6 -1
  319. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +23 -1
  320. package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +20 -0
  321. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +101 -2
  322. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/root-resolution.mjs +1 -1
  323. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1 -1
  324. package/src/runtime/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +1 -1
  325. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +67 -0
  326. package/src/runtime/agent/orchestrator/tools/lib/process-table-fixture.mjs +50 -0
  327. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +303 -63
  328. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -0
  329. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +108 -18
  330. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +77 -11
  331. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +81 -5
  332. package/src/runtime/agent/orchestrator/tools/patch/ui-diff.mjs +73 -39
  333. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +18 -1
  334. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -4
  335. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +88 -12
  336. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +2 -0
  337. package/src/runtime/attachments/store.d.mts +9 -0
  338. package/src/runtime/attachments/store.mjs +80 -9
  339. package/src/runtime/browser-bridge/browser-action-contract.d.mts +0 -1
  340. package/src/runtime/browser-bridge/browser-action-contract.mjs +0 -2
  341. package/src/runtime/computer-bridge/action-schema.mjs +219 -196
  342. package/src/runtime/computer-bridge/linux-readiness.d.mts +0 -2
  343. package/src/runtime/computer-bridge/linux-readiness.mjs +0 -16
  344. package/src/runtime/effort-judge/judge-client.mjs +21 -4
  345. package/src/runtime/effort-judge/judge-worker.mjs +4 -1
  346. package/src/runtime/github/tool.mjs +208 -17
  347. package/src/runtime/media/adapters/codex-image.mjs +140 -21
  348. package/src/runtime/media/catalog.mjs +4 -4
  349. package/src/runtime/media/chatgpt-usage.mjs +55 -0
  350. package/src/runtime/media/defaults.mjs +37 -0
  351. package/src/runtime/media/jobs.mjs +12 -2
  352. package/src/runtime/media/lanes.mjs +12 -0
  353. package/src/runtime/media/tool-defs.mjs +15 -4
  354. package/src/runtime/media/tool.mjs +41 -12
  355. package/src/runtime/media/upstream-error.mjs +72 -6
  356. package/src/runtime/memory/index.mjs +1 -0
  357. package/src/runtime/memory/lib/http-router/ingest-routes.mjs +22 -1
  358. package/src/runtime/memory/lib/ingest/transcript-offsets.mjs +2 -0
  359. package/src/runtime/memory/lib/ingest/transcript-rows.mjs +1 -0
  360. package/src/runtime/memory/lib/pg/adapter.mjs +98 -1
  361. package/src/runtime/memory/lib/pg/process.mjs +36 -33
  362. package/src/runtime/memory/lib/pg/run-child.mjs +49 -0
  363. package/src/runtime/memory/lib/pg/supervisor.mjs +112 -4
  364. package/src/runtime/memory/lib/runtime-fetcher.mjs +12 -13
  365. package/src/runtime/memory/lib/transcript-ingest.mjs +14 -0
  366. package/src/runtime/office/README.md +1 -1
  367. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  368. package/src/runtime/office/authoring/html-browser.mjs +18 -8
  369. package/src/runtime/office/authoring/html-document-author.mjs +2 -0
  370. package/src/runtime/office/authoring/pdf-html-runner.mjs +1 -1
  371. package/src/runtime/office/authoring/pptx-contact-sheet.mjs +2 -0
  372. package/src/runtime/office/authoring/pptx-html-measure.mjs +3 -1
  373. package/src/runtime/office/authoring/pptx-html-runner.mjs +2 -0
  374. package/src/runtime/office/authoring/xlsx-html-runner.mjs +3 -1
  375. package/src/runtime/office/core/office-actions-read.mjs +3 -0
  376. package/src/runtime/office/core/office-render-preview.mjs +2 -0
  377. package/src/runtime/office/core/office-session-dispatch.mjs +7 -0
  378. package/src/runtime/office/core/office-sessionless-actions.mjs +8 -0
  379. package/src/runtime/office/core/office-sessions.mjs +5 -0
  380. package/src/runtime/office/core/office-transactions.mjs +3 -0
  381. package/src/runtime/office/core/office-write-ledger.mjs +94 -0
  382. package/src/runtime/office/design/library/templates/mixdog-executive.mixdog-edit.pptx +0 -0
  383. package/src/runtime/office/index.mjs +29 -0
  384. package/src/runtime/office/pdf/pdf-analysis.mjs +0 -68
  385. package/src/runtime/office/pdf/pdf-edit-document.mjs +2 -0
  386. package/src/runtime/office/pdf/pdf-render.mjs +23 -7
  387. package/src/runtime/office/pdf/pdf-security.mjs +2 -0
  388. package/src/runtime/office/portable/portable-opc.mjs +4 -1
  389. package/src/runtime/office/quality/visual-diff.mjs +2 -0
  390. package/src/runtime/session-search/session-search-ingest.mjs +1 -1
  391. package/src/runtime/shared/agent-reap-state.mjs +13 -0
  392. package/src/runtime/shared/atomic-file.d.mts +1 -1
  393. package/src/runtime/shared/background-tasks.mjs +6 -1
  394. package/src/runtime/shared/bounded-file-read.mjs +13 -0
  395. package/src/runtime/shared/bounded-line-diff.mjs +191 -0
  396. package/src/runtime/shared/browser-launch.mjs +15 -0
  397. package/src/runtime/shared/buffered-appender.mjs +18 -0
  398. package/src/runtime/shared/config.mjs +78 -18
  399. package/src/runtime/shared/err-text.mjs +48 -4
  400. package/src/runtime/shared/file-lock.mjs +6 -5
  401. package/src/runtime/shared/file-permissions.d.mts +6 -1
  402. package/src/runtime/shared/file-permissions.mjs +54 -6
  403. package/src/runtime/shared/llm/anthropic-betas.mjs +1 -2
  404. package/src/runtime/shared/llm/anthropic-effort.mjs +6 -0
  405. package/src/runtime/shared/llm/provider-model-identities.mjs +1 -0
  406. package/src/runtime/shared/llm/usage-accounting.mjs +5 -2
  407. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +3 -0
  408. package/src/runtime/shared/loopback-listener.mjs +9 -0
  409. package/src/runtime/shared/model-route-chain.d.mts +8 -0
  410. package/src/runtime/shared/model-route-chain.mjs +48 -0
  411. package/src/runtime/shared/model-route-fallback.mjs +22 -0
  412. package/src/runtime/shared/pid-liveness.mjs +12 -0
  413. package/src/runtime/shared/provider-api-key.mjs +8 -0
  414. package/src/runtime/shared/provider-timeout-phase.mjs +17 -0
  415. package/src/runtime/shared/quiet-progress.d.mts +35 -0
  416. package/src/runtime/shared/quiet-progress.mjs +101 -0
  417. package/src/runtime/shared/quota-resume-store.mjs +32 -1
  418. package/src/runtime/shared/read-row-numbers.mjs +44 -0
  419. package/src/runtime/shared/remote-intent.mjs +2 -42
  420. package/src/runtime/shared/review-diff.mjs +52 -0
  421. package/src/runtime/shared/session-sidebar-host.d.mts +4 -0
  422. package/src/runtime/shared/session-sidebar-host.mjs +38 -0
  423. package/src/runtime/shared/slow-span.mjs +121 -0
  424. package/src/runtime/shared/statusline/statusline-segments.mjs +52 -6
  425. package/src/runtime/shared/tool-card-model/card-header.mjs +7 -1
  426. package/src/runtime/shared/tool-card-model/generic-detail.mjs +39 -5
  427. package/src/runtime/shared/tool-card-model.mjs +5 -2
  428. package/src/runtime/shared/tool-output-budget.mjs +2 -0
  429. package/src/runtime/shared/tool-output-limit.mjs +4 -0
  430. package/src/runtime/shared/tool-primitives.mjs +13 -0
  431. package/src/runtime/shared/tool-result-summary.mjs +22 -1
  432. package/src/runtime/shared/tool-status.mjs +3 -2
  433. package/src/runtime/shared/tool-surface.mjs +20 -6
  434. package/src/runtime/shared/tool-work-units.mjs +54 -11
  435. package/src/runtime/shared/transcript-metadata.mjs +49 -1
  436. package/src/runtime/shared/transcript-turn-keys.mjs +33 -0
  437. package/src/runtime/shared/transcript-writer/purge.mjs +74 -0
  438. package/src/runtime/shared/transcript-writer/transcript-file.mjs +10 -1
  439. package/src/runtime/shared/transcript-writer.mjs +24 -6
  440. package/src/runtime/shared/turn-changes.mjs +269 -100
  441. package/src/runtime/shared/turn-review-reply.mjs +8 -39
  442. package/src/runtime/shared/turn-snapshot-store.mjs +19 -108
  443. package/src/runtime/shared/turn-snapshot.mjs +865 -683
  444. package/src/runtime/shared/turn-worktree-snapshot.mjs +183 -255
  445. package/src/runtime/shared/user-data-guard.mjs +262 -49
  446. package/src/runtime/shared/worktrees/activity-gate.mjs +175 -0
  447. package/src/runtime/shared/worktrees/branch-management.mjs +179 -0
  448. package/src/runtime/shared/worktrees/carry.mjs +533 -0
  449. package/src/runtime/shared/worktrees/contract.mjs +60 -0
  450. package/src/runtime/shared/worktrees/dependencies.mjs +456 -0
  451. package/src/runtime/shared/worktrees/file-recovery.mjs +84 -0
  452. package/src/runtime/shared/worktrees/git-head.mjs +214 -0
  453. package/src/runtime/shared/worktrees/git.mjs +8 -3
  454. package/src/runtime/shared/worktrees/include.mjs +125 -7
  455. package/src/runtime/shared/worktrees/lock.mjs +1 -1
  456. package/src/runtime/shared/worktrees/maintenance.mjs +20 -2
  457. package/src/runtime/shared/worktrees/manager.mjs +525 -31
  458. package/src/runtime/shared/worktrees/merge.mjs +31 -21
  459. package/src/runtime/shared/worktrees/owner.mjs +2 -1
  460. package/src/runtime/shared/worktrees/paths.d.mts +6 -0
  461. package/src/runtime/shared/worktrees/preparation-report.mjs +79 -0
  462. package/src/runtime/shared/worktrees/setup-commands.mjs +232 -0
  463. package/src/runtime/shared/worktrees/workspace-visibility.mjs +17 -0
  464. package/src/runtime/terminal-bridge/client.mjs +57 -20
  465. package/src/runtime/terminal-bridge/tool-defs.mjs +13 -6
  466. package/src/runtime/tidy/apply.mjs +47 -2
  467. package/src/runtime/tidy/run-engines.mjs +11 -5
  468. package/src/session-runtime/agent-tool-routing.mjs +19 -13
  469. package/src/session-runtime/boot/apis.mjs +20 -6
  470. package/src/session-runtime/boot/config.mjs +2 -0
  471. package/src/session-runtime/boot/facade.mjs +4 -0
  472. package/src/session-runtime/boot/infrastructure.mjs +6 -1
  473. package/src/session-runtime/boot/session.mjs +3 -3
  474. package/src/session-runtime/boot/tools.mjs +7 -1
  475. package/src/session-runtime/conversation-import/service.mjs +1 -1
  476. package/src/session-runtime/cwd-plugins/cwd-apply.mjs +12 -5
  477. package/src/session-runtime/goal-facade-api.mjs +2 -2
  478. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +91 -0
  479. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -1
  480. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +15 -5
  481. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +137 -26
  482. package/src/session-runtime/internal-tool-executor.mjs +8 -2
  483. package/src/session-runtime/lifecycle/cold-heir.mjs +187 -0
  484. package/src/session-runtime/lifecycle/inheritance.mjs +71 -27
  485. package/src/session-runtime/lifecycle/session-catalog.mjs +25 -18
  486. package/src/session-runtime/lifecycle/session-switch/resume.mjs +6 -0
  487. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +36 -48
  488. package/src/session-runtime/lifecycle/session-switch.mjs +1 -1
  489. package/src/session-runtime/lifecycle/shared.mjs +5 -6
  490. package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -5
  491. package/src/session-runtime/lifecycle/teardown.mjs +70 -14
  492. package/src/session-runtime/lifecycle-api.mjs +1 -0
  493. package/src/session-runtime/mcp-glue/connect.mjs +17 -5
  494. package/src/session-runtime/media-api.mjs +8 -0
  495. package/src/session-runtime/model-route/route-ownership.mjs +60 -0
  496. package/src/session-runtime/model-route/route-persist.mjs +3 -2
  497. package/src/session-runtime/model-route/set-route.mjs +116 -36
  498. package/src/session-runtime/model-route/web-search-route.mjs +7 -2
  499. package/src/session-runtime/model-route-api.mjs +4 -2
  500. package/src/session-runtime/native-web-search/routes.mjs +37 -24
  501. package/src/session-runtime/native-web-search-usage.mjs +51 -0
  502. package/src/session-runtime/native-web-search.mjs +19 -9
  503. package/src/session-runtime/new-session-config.mjs +4 -2
  504. package/src/session-runtime/provider-auth/login.mjs +4 -0
  505. package/src/session-runtime/provider-auth/setup.mjs +4 -0
  506. package/src/session-runtime/provider-models/catalog-load.mjs +9 -0
  507. package/src/session-runtime/provider-models/web-search-catalog.mjs +23 -3
  508. package/src/session-runtime/provider-models.mjs +1 -0
  509. package/src/session-runtime/provider-usage.mjs +4 -0
  510. package/src/session-runtime/resource-scope-decorate.mjs +10 -3
  511. package/src/session-runtime/route-resolution.mjs +3 -1
  512. package/src/session-runtime/runtime-core.mjs +4 -0
  513. package/src/session-runtime/runtime-facade.mjs +6 -0
  514. package/src/session-runtime/runtime-review-api.mjs +8 -2
  515. package/src/session-runtime/services/agent-task-status.mjs +2 -0
  516. package/src/session-runtime/services/agent-tool/close-flow/close-all.mjs +0 -3
  517. package/src/session-runtime/services/agent-tool/close-flow.mjs +6 -7
  518. package/src/session-runtime/services/agent-tool/execute-send.mjs +2 -2
  519. package/src/session-runtime/services/agent-tool/execute-spawn.mjs +36 -3
  520. package/src/session-runtime/services/agent-tool/execute.mjs +9 -1
  521. package/src/session-runtime/services/agent-tool/helpers.mjs +30 -7
  522. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +81 -20
  523. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +7 -2
  524. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +6 -3
  525. package/src/session-runtime/services/agent-tool/lead-worker-index/forgotten-leads.mjs +29 -0
  526. package/src/session-runtime/services/agent-tool/lead-worker-index/index-file.mjs +1 -1
  527. package/src/session-runtime/services/agent-tool/lead-worker-index/lead-rows.mjs +3 -4
  528. package/src/session-runtime/services/agent-tool/lead-worker-index/reap-timers.mjs +9 -3
  529. package/src/session-runtime/services/agent-tool/lead-worker-index/row-settlement.mjs +7 -18
  530. package/src/session-runtime/services/agent-tool/lead-worker-index.mjs +82 -13
  531. package/src/session-runtime/services/agent-tool/model-select.mjs +82 -0
  532. package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -6
  533. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -1
  534. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +19 -5
  535. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -4
  536. package/src/session-runtime/services/agent-tool/spawn-flow.mjs +2 -1
  537. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +3 -0
  538. package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +1 -3
  539. package/src/session-runtime/services/agent-tool/tag-registry/tag-refresh.mjs +1 -3
  540. package/src/session-runtime/services/agent-tool/tag-registry.mjs +18 -10
  541. package/src/session-runtime/services/agent-tool/terminal-reaper/scan-admission.mjs +8 -41
  542. package/src/session-runtime/services/agent-tool/terminal-reaper/stale-rows.mjs +3 -3
  543. package/src/session-runtime/services/agent-tool/terminal-reaper.mjs +6 -23
  544. package/src/session-runtime/services/agent-tool/terminal-trace.mjs +0 -1
  545. package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -0
  546. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +32 -20
  547. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +5 -2
  548. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +10 -1
  549. package/src/session-runtime/services/agent-tool/worker-index.mjs +74 -15
  550. package/src/session-runtime/services/agent-tool.mjs +7 -0
  551. package/src/session-runtime/services/agent-watchdog-registry.mjs +2 -0
  552. package/src/session-runtime/services/channel-admin.mjs +19 -3
  553. package/src/session-runtime/services/memory-runtime-proxy/calls.mjs +4 -0
  554. package/src/session-runtime/services/memory-runtime-proxy.mjs +1 -0
  555. package/src/session-runtime/services/provider-admin.mjs +158 -15
  556. package/src/session-runtime/session-create/session-options.mjs +7 -5
  557. package/src/session-runtime/session-create/session-start-hook.mjs +2 -1
  558. package/src/session-runtime/session-transcript-purge.mjs +32 -0
  559. package/src/session-runtime/session-transcript.mjs +4 -5
  560. package/src/session-runtime/session-turn-api.mjs +17 -14
  561. package/src/session-runtime/settings-builtin-tools-api.mjs +18 -6
  562. package/src/session-runtime/setup-tool/executor.mjs +57 -9
  563. package/src/session-runtime/setup-tool/extended-actions.mjs +86 -6
  564. package/src/session-runtime/setup-tool/settings-contract.mjs +18 -3
  565. package/src/session-runtime/setup-tool/tool-defs.mjs +25 -4
  566. package/src/session-runtime/skills-api.mjs +3 -5
  567. package/src/session-runtime/tool-policy-refresh.mjs +83 -32
  568. package/src/session-runtime/tool-surface.mjs +5 -1
  569. package/src/session-runtime/turn/agent-ops.mjs +49 -2
  570. package/src/session-runtime/turn/compaction-gate.mjs +25 -0
  571. package/src/session-runtime/turn/session-ops.mjs +7 -5
  572. package/src/session-runtime/turn/side-question-ops.mjs +19 -0
  573. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +7 -1
  574. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +12 -3
  575. package/src/session-runtime/turn/turn-run/turn-settle.mjs +18 -2
  576. package/src/session-runtime/turn/turn-run/turn-timing.mjs +4 -3
  577. package/src/session-runtime/turn/turn-run.mjs +26 -45
  578. package/src/session-runtime/usage-stats-api.mjs +46 -11
  579. package/src/session-runtime/workflow-agents-api/agent-route.mjs +16 -1
  580. package/src/session-runtime/workspace/admission-gate.mjs +44 -15
  581. package/src/session-runtime/workspace/project-branches.mjs +35 -41
  582. package/src/session-runtime/workspace/transition-steps.mjs +215 -116
  583. package/src/session-runtime/workspace/transitions.mjs +428 -73
  584. package/src/standalone/channel-transport.mjs +3 -4
  585. package/src/standalone/daemon-agent-control.mjs +9 -1
  586. package/src/standalone/daemon-desktop-runtime.mjs +32 -1
  587. package/src/standalone/daemon-local-session-bridge.mjs +14 -1
  588. package/src/standalone/daemon-owner.mjs +17 -4
  589. package/src/standalone/daemon-pg-stop.mjs +49 -0
  590. package/src/standalone/daemon-session-control.mjs +88 -0
  591. package/src/standalone/daemon-stop-budget.d.mts +2 -0
  592. package/src/standalone/daemon-stop-budget.mjs +18 -0
  593. package/src/standalone/daemon-stored-session-views.mjs +25 -3
  594. package/src/standalone/daemon-telemetry.mjs +19 -0
  595. package/src/standalone/daemon.mjs +63 -1
  596. package/src/standalone/desktop-service-registry.mjs +5 -0
  597. package/src/standalone/local-session-runtime.mjs +80 -30
  598. package/src/standalone/session-client.mjs +42 -0
  599. package/src/standalone/session-protocol.mjs +14 -0
  600. package/src/standalone/session-proxy/projection.mjs +41 -4
  601. package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +15 -1
  602. package/src/standalone/session-runtime-inline-host.mjs +3 -0
  603. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +91 -49
  604. package/src/standalone/session-service/agent-tree/agent-child.mjs +19 -1
  605. package/src/standalone/session-service/agent-tree/agent-registry.mjs +25 -0
  606. package/src/standalone/session-service/agent-tree/agent-turns.mjs +9 -1
  607. package/src/standalone/session-service/agent-tree.mjs +28 -2
  608. package/src/standalone/session-service/entries/session-loads.mjs +16 -5
  609. package/src/standalone/session-service/entries.mjs +1 -0
  610. package/src/standalone/session-service/projection/transcript-window.mjs +39 -0
  611. package/src/standalone/session-service/quota-resume.mjs +28 -13
  612. package/src/standalone/session-service/session-calls/session-action.mjs +18 -3
  613. package/src/standalone/session-service/session-calls/session-turns.mjs +17 -6
  614. package/src/standalone/session-service/session-calls/session-views.mjs +6 -0
  615. package/src/standalone/session-service-api.mjs +6 -1
  616. package/src/standalone/session-state-patch.d.mts +2 -1
  617. package/src/standalone/session-state-patch.mjs +41 -1
  618. package/src/standalone/session-tool-output.mjs +82 -0
  619. package/src/tui/App.jsx +25 -0
  620. package/src/tui/app/app-view/floating-panel.jsx +26 -1
  621. package/src/tui/app/app-view.jsx +2 -1
  622. package/src/tui/app/btw-controller.mjs +118 -0
  623. package/src/tui/app/create-app-pickers.mjs +2 -0
  624. package/src/tui/app/provider-setup/provider-items.mjs +8 -0
  625. package/src/tui/app/provider-setup-picker.mjs +15 -3
  626. package/src/tui/app/shell-layout/row-budgets.mjs +11 -1
  627. package/src/tui/app/shell-layout/surfaces.mjs +3 -1
  628. package/src/tui/app/slash-commands.mjs +19 -3
  629. package/src/tui/app/slash-dispatch/session-commands.mjs +68 -6
  630. package/src/tui/app/use-global-key-input/approval-shortcut.mjs +12 -0
  631. package/src/tui/app/use-global-key-input.mjs +5 -12
  632. package/src/tui/app/use-prompt-handlers.mjs +11 -0
  633. package/src/tui/components/BtwPanel.jsx +53 -0
  634. package/src/tui/components/QuestionPanel.jsx +275 -0
  635. package/src/tui/components/Spinner.jsx +4 -0
  636. package/src/tui/components/SpinnerByline.jsx +21 -2
  637. package/src/tui/components/question-panel-model.mjs +156 -0
  638. package/src/tui/components/status-line/local-line.mjs +10 -2
  639. package/src/tui/dist/index.mjs +2897 -1722
  640. package/src/tui/session/active-tool-summary.mjs +1 -1
  641. package/src/tui/session/context-state.mjs +4 -5
  642. package/src/tui/session/goal-continuation/continuation-queue.mjs +2 -3
  643. package/src/tui/session/goal-continuation/deadline-delivery.mjs +4 -2
  644. package/src/tui/session/goal-continuation/session-boundary.mjs +21 -0
  645. package/src/tui/session/quota-resume.mjs +140 -61
  646. package/src/tui/session/session-api/commands.mjs +14 -10
  647. package/src/tui/session/session-api/controls.mjs +14 -2
  648. package/src/tui/session/session-api/integrations.mjs +9 -2
  649. package/src/tui/session/session-api/lifecycle/dispose.mjs +3 -9
  650. package/src/tui/session/session-api/lifecycle/resume.mjs +2 -7
  651. package/src/tui/session/session-api/lifecycle.mjs +14 -11
  652. package/src/tui/session/session-api/media.mjs +2 -0
  653. package/src/tui/session/session-api/routes.mjs +81 -57
  654. package/src/tui/session/session-api/settings.mjs +9 -3
  655. package/src/tui/session/session-api/worktree.mjs +3 -2
  656. package/src/tui/session/session-api.mjs +1 -0
  657. package/src/tui/session/session-flow/auto-clear.mjs +1 -3
  658. package/src/tui/session/session-flow/drain.mjs +6 -4
  659. package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -0
  660. package/src/tui/session/session-flow/queue/take-entries.mjs +2 -1
  661. package/src/tui/session/session-flow/queue.mjs +1 -1
  662. package/src/tui/session/tool-approval.mjs +20 -8
  663. package/src/tui/session/transcript-spill.mjs +14 -7
  664. package/src/tui/session/transcript-store/streaming-tail.mjs +1 -1
  665. package/src/tui/session/tui-steering-persist.mjs +3 -5
  666. package/src/tui/session/turn-quiet.mjs +53 -0
  667. package/src/tui/session/turn-stream.mjs +179 -32
  668. package/src/tui/session/turn.mjs +50 -36
  669. package/src/tui/session/worktree-setup-notice.mjs +38 -0
  670. package/src/tui/spinner-meta.mjs +10 -0
  671. package/src/tui/spinner-verbs.mjs +3 -0
  672. package/src/ui/statusline.mjs +13 -3
  673. package/src/workflows/default/WORKFLOW.md +3 -1
  674. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +0 -1
  675. package/src/runtime/agent/orchestrator/session/manager/foreign-pending-messages.mjs +0 -346
  676. package/src/runtime/agent/orchestrator/session/manager/session-owner-liveness.mjs +0 -117
  677. package/src/runtime/agent/orchestrator/session/store/paths-heartbeat.mjs +0 -246
  678. package/src/session-runtime/services/agent-tool/terminal-reaper/reap-timers.mjs +0 -142
  679. package/src/session-runtime/turn/share-ops.mjs +0 -77
  680. package/src/tui/session/cross-surface-share.mjs +0 -406
  681. package/src/tui/session/live-share/delta.mjs +0 -153
  682. package/src/tui/session/live-share/mirror.mjs +0 -106
  683. package/src/tui/session/live-share/owner.mjs +0 -254
  684. package/src/tui/session/live-share/retry.mjs +0 -54
  685. package/src/tui/session/live-share/viewer/frame-router.mjs +0 -32
  686. package/src/tui/session/live-share/viewer/pipe-client.mjs +0 -108
  687. package/src/tui/session/live-share/viewer/submit-acks.mjs +0 -65
  688. package/src/tui/session/live-share/viewer/sync-waiters.mjs +0 -53
  689. package/src/tui/session/live-share/viewer.mjs +0 -99
  690. package/src/tui/session/live-share/wire.mjs +0 -44
  691. package/src/tui/session/live-share.mjs +0 -154
  692. package/src/tui/session/shared-dir-watch.mjs +0 -69
@@ -0,0 +1,94 @@
1
+ /**
2
+ * office-write-ledger.mjs — the workspace files one Office Use call wrote,
3
+ * with their exact before/after state, so the session's turn review counts
4
+ * them as its own changes and Undo can restore them.
5
+ *
6
+ * Ownership is never inferred from the folder: every route that writes a
7
+ * workspace file — the session's working copy, a created or converted
8
+ * document, a render's preview and page images, a split/extract/query output,
9
+ * an authored document and its sidecars, a secured PDF — hands the path to
10
+ * noteOfficeWrite BEFORE it writes, which captures the file's prior state.
11
+ * After the call, only noted files whose bytes changed are recorded. Scratch
12
+ * files outside the workspace (the system temp folder, the Office data
13
+ * folder) are never noted.
14
+ */
15
+ import { AsyncLocalStorage } from 'node:async_hooks';
16
+ import { statSync } from 'node:fs';
17
+ import { tmpdir } from 'node:os';
18
+ import { isAbsolute, relative, resolve } from 'node:path';
19
+ import { PATCH_EDIT_BUDGET_BYTES, createSnapshotBudget, reviewFileContent } from '../../shared/bounded-file-read.mjs';
20
+
21
+ const ledgers = new AsyncLocalStorage();
22
+
23
+ const pathKey = (path) => (process.platform === 'win32' ? path.toLowerCase() : path);
24
+
25
+ function inside(parent, child) {
26
+ if (!parent) return false;
27
+ const rel = relative(resolve(parent), child);
28
+ return !rel || (!rel.startsWith('..') && !isAbsolute(rel));
29
+ }
30
+
31
+ function fileStamp(path) {
32
+ try {
33
+ const info = statSync(path);
34
+ return info.isFile() ? { size: info.size, mtimeMs: info.mtimeMs } : null;
35
+ } catch {
36
+ return null;
37
+ }
38
+ }
39
+
40
+ /** Run one Office call with a ledger its write routes report into. */
41
+ export function runWithOfficeWriteLedger({ cwd, dataDir }, task) {
42
+ const ledger = {
43
+ cwd: resolve(cwd || process.cwd()),
44
+ dataDir: dataDir ? resolve(dataDir) : '',
45
+ budget: createSnapshotBudget(PATCH_EDIT_BUDGET_BYTES),
46
+ before: new Map(),
47
+ };
48
+ return { ledger, run: ledgers.run(ledger, task) };
49
+ }
50
+
51
+ /** A write receipt: the call is about to write `path`. The first receipt of a
52
+ * path captures its state before the write; a call without a ledger (no
53
+ * session to credit) and scratch paths are ignored. */
54
+ export function noteOfficeWrite(path) {
55
+ const ledger = ledgers.getStore();
56
+ const text = typeof path === 'string' ? path.trim() : '';
57
+ if (!ledger || !text) return;
58
+ const fullPath = resolve(ledger.cwd, text);
59
+ const key = pathKey(fullPath);
60
+ if (ledger.before.has(key)) return;
61
+ if (inside(ledger.dataDir, fullPath)) return;
62
+ if (inside(tmpdir(), fullPath) && !inside(ledger.cwd, fullPath)) return;
63
+ let content;
64
+ try {
65
+ content = reviewFileContent(fullPath, { budget: ledger.budget });
66
+ } catch {
67
+ return; // not a regular file: never recorded
68
+ }
69
+ ledger.before.set(key, { fullPath, content, stamp: fileStamp(fullPath) });
70
+ }
71
+
72
+ const sameBytes = (left, right) => Buffer.isBuffer(left) && Buffer.isBuffer(right) && left.equals(right);
73
+
74
+ /** Every noted file the call created, changed or removed, as
75
+ * `{ fullPath, before, after }` (null = absent). */
76
+ export function officeWriteChanges(ledger) {
77
+ const changes = [];
78
+ for (const { fullPath, content: before, stamp: priorStamp } of ledger.before.values()) {
79
+ const stamp = fileStamp(fullPath);
80
+ if (!priorStamp && !stamp) continue;
81
+ // Uncaptured bytes compare by their stamp; captured ones byte for byte.
82
+ const untouched = priorStamp && stamp && priorStamp.size === stamp.size && priorStamp.mtimeMs === stamp.mtimeMs;
83
+ if (untouched && !Buffer.isBuffer(before)) continue;
84
+ let after = null;
85
+ try {
86
+ after = stamp ? reviewFileContent(fullPath) : null;
87
+ } catch {
88
+ continue;
89
+ }
90
+ if (sameBytes(before, after)) continue;
91
+ changes.push({ fullPath, before, after });
92
+ }
93
+ return changes;
94
+ }
@@ -14,6 +14,7 @@ import {
14
14
  toolResult,
15
15
  } from './core/office-core.mjs';
16
16
  import { resolveSession } from './core/office-sessions.mjs';
17
+ import { officeWriteChanges, runWithOfficeWriteLedger } from './core/office-write-ledger.mjs';
17
18
 
18
19
  // Office work is minutes of real application time, and guessing which action carries it is how
19
20
  // tuning goes wrong. MIXDOG_OFFICE_TRACE writes one line per call so a slow run maps itself; it
@@ -27,6 +28,34 @@ const OFFICE_TRACE = process.env.MIXDOG_OFFICE_TRACE || '';
27
28
  const READ_ONLY_ACTIONS = new Set(['snapshot', 'get', 'query', 'issues', 'validate', 'describe', 'render', 'qa']);
28
29
 
29
30
  export async function executeOfficeTool(args = {}, context = {}) {
31
+ const sessionId = String(context.sessionId || '');
32
+ if (!sessionId) return await tracedOfficeTool(args, context);
33
+ const cwd = context.cwd || process.cwd();
34
+ const { ledger, run } = runWithOfficeWriteLedger({ cwd, dataDir: context.dataDir || defaultOfficeDataDir() }, () =>
35
+ tracedOfficeTool(args, context)
36
+ );
37
+ try {
38
+ return await run;
39
+ } finally {
40
+ await recordOfficeWrites(ledger, sessionId, cwd);
41
+ }
42
+ }
43
+
44
+ // The files this call's write routes reported join the session's turn review
45
+ // as its own changes (counted, and undoable where their bytes were captured).
46
+ // The recorder is loaded on first use; recording never affects the result.
47
+ async function recordOfficeWrites(ledger, sessionId, cwd) {
48
+ try {
49
+ const changes = officeWriteChanges(ledger);
50
+ if (changes.length === 0) return;
51
+ const { recordToolFileChanges } = await import('../agent/orchestrator/tools/patch/ui-diff.mjs');
52
+ recordToolFileChanges({ sessionId, basePath: cwd, changes });
53
+ } catch {
54
+ /* best-effort review channel */
55
+ }
56
+ }
57
+
58
+ async function tracedOfficeTool(args, context) {
30
59
  if (!OFFICE_TRACE) return await runOfficeTool(args, context);
31
60
  const startedAt = performance.now();
32
61
  try {
@@ -261,74 +261,6 @@ export async function extractPdfTextLayout(
261
261
  // so the adapter, the tool surface, and tests keep one import.
262
262
  export { findPdfText } from './pdf-search.mjs';
263
263
 
264
- // The text run at `index`, joined with the next run on the same line when only
265
- // the joined text names a category (a label the PDF drew as two runs).
266
- function categoryLabelAt(items, index, expected) {
267
- const item = items[index];
268
- const text = String(item?.text || '').trim();
269
- if (!text || expected.includes(text)) return text;
270
- let nextIndex = index + 1;
271
- while (nextIndex < items.length && !String(items[nextIndex]?.text || '').trim()) nextIndex += 1;
272
- const next = items[nextIndex];
273
- if (!next || Math.abs(Number(next.top) - Number(item.top)) > 1) return text;
274
- const joined = `${text}${String(next.text || '').trim()}`;
275
- return expected.includes(joined) ? joined : text;
276
- }
277
-
278
- // Every line that carries category labels, keyed by page and baseline.
279
- function categoryLabelRows(layout, expected) {
280
- const rows = [];
281
- for (const page of layout?.pages || []) {
282
- const items = Array.isArray(page.items) ? page.items : [];
283
- for (let index = 0; index < items.length; index += 1) {
284
- const item = items[index];
285
- const text = categoryLabelAt(items, index, expected);
286
- if (!text || !expected.includes(text)) continue;
287
- let row = rows.find((entry) => entry.page === page.page && Math.abs(entry.top - Number(item.top)) <= 1);
288
- if (!row) {
289
- row = { page: page.page, width: Number(page.width) || 0, top: Number(item.top), labels: [] };
290
- rows.push(row);
291
- }
292
- if (!row.labels.some((entry) => entry.text === text)) {
293
- row.labels.push({ text, x: Number(item.x) || 0 });
294
- }
295
- }
296
- }
297
- return rows;
298
- }
299
-
300
- function categoryRowSpacing(row, expected) {
301
- const labels = expected
302
- .map((text) => row.labels.find((entry) => entry.text === text))
303
- .sort((left, right) => left.x - right.x);
304
- const gaps = labels.slice(1).map((entry, index) => entry.x - labels[index].x);
305
- return {
306
- ...row,
307
- labels,
308
- span: labels.length > 1 ? labels.at(-1).x - labels[0].x : 0,
309
- minimumGap: gaps.length ? Math.min(...gaps) : 0,
310
- };
311
- }
312
-
313
- export function evaluatePowerPointCategorySpacing(layout, categories = []) {
314
- const expected = [...new Set(categories.map((entry) => String(entry || '').trim()).filter(Boolean))];
315
- const complete = categoryLabelRows(layout, expected)
316
- .filter((row) => expected.every((text) => row.labels.some((entry) => entry.text === text)))
317
- .map((row) => categoryRowSpacing(row, expected))
318
- .sort((left, right) => right.span - left.span);
319
- const best = complete[0] || null;
320
- const requiredGap = best ? best.width * 0.1 : 0;
321
- return {
322
- ok: expected.length <= 1 || Boolean(best && best.minimumGap >= requiredGap),
323
- categories: expected,
324
- page: best?.page || 0,
325
- labels: best?.labels || [],
326
- span: Number((best?.span || 0).toFixed(2)),
327
- minimumGap: Number((best?.minimumGap || 0).toFixed(2)),
328
- requiredGap: Number(requiredGap.toFixed(2)),
329
- };
330
- }
331
-
332
264
  // A PDF reports the runs it drew, not cells: a cell whose words were drawn as
333
265
  // separate runs would count as several columns and break its row against the
334
266
  // rows around it. Runs closer than half a line height are the same cell — the
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { mkdir, writeFile } from 'node:fs/promises';
7
7
  import { dirname, resolve } from 'node:path';
8
+ import { noteOfficeWrite } from '../core/office-write-ledger.mjs';
8
9
  import {
9
10
  PDFDocument,
10
11
  PDFArray,
@@ -130,6 +131,7 @@ export async function writeSibling(path, target, bytes) {
130
131
  if (output.toLowerCase() === resolve(path).toLowerCase())
131
132
  throw new Error('output must differ from the document being edited');
132
133
  await mkdir(dirname(output), { recursive: true });
134
+ noteOfficeWrite(output);
133
135
  await writeFile(output, bytes);
134
136
  return output;
135
137
  }
@@ -5,6 +5,7 @@ import { createCanvas, loadImage } from '@napi-rs/canvas';
5
5
  import { pdfjsStandardFontDataUrl, resolvedPdfJs } from '../../attachments/pdfjs-runtime.mjs';
6
6
  import { installPdfGlobals } from './pdf-document.mjs';
7
7
  import { workerExecArgv } from '../../shared/worker-exec-argv.mjs';
8
+ import { noteOfficeWrite } from '../core/office-write-ledger.mjs';
8
9
 
9
10
  const PAGE_NUMBER_PATTERN = /^\s*(?:(?:page\s*)?\d+\s*(?:of|\/)\s*\d+|페이지\s*\d+|\d+\s*페이지)\s*$/i;
10
11
 
@@ -144,8 +145,8 @@ async function runPdfRenderWorker(data, signal = null) {
144
145
  }
145
146
 
146
147
  // Many pages are reviewed as contact sheets: one labelled grid image per group
147
- // of pages, written next to the PDF.
148
- async function writeContactSheet(group, width, imagePath, renderPage) {
148
+ // of pages, for a file next to the PDF.
149
+ async function contactSheet(group, width, imagePath, renderPage) {
149
150
  const columns = group.length <= 2 ? 1 : Math.max(2, Math.ceil(Math.sqrt(group.length * 0.75)));
150
151
  const rows = Math.ceil(group.length / columns);
151
152
  const gap = 12;
@@ -182,7 +183,6 @@ async function writeContactSheet(group, width, imagePath, renderPage) {
182
183
  context.strokeRect(x, y + labelHeight, image.width, image.height);
183
184
  }
184
185
  const data = sheet.toBuffer('image/png');
185
- await writeFile(imagePath, data);
186
186
  return {
187
187
  page: group[0],
188
188
  pages: group,
@@ -204,7 +204,18 @@ async function writeContactSheet(group, width, imagePath, renderPage) {
204
204
  };
205
205
  }
206
206
 
207
- async function renderPdfPagesDirect(path, { pages = null, maxWidth = 1400, maximumScale = 2, signal = null } = {}) {
207
+ // The page images land beside the PDF, each reported as an Office write first.
208
+ async function writePageImages(images) {
209
+ for (const image of images) {
210
+ noteOfficeWrite(image.path);
211
+ await writeFile(image.path, Buffer.from(image.data, 'base64'));
212
+ }
213
+ }
214
+
215
+ async function renderPdfPagesDirect(
216
+ path,
217
+ { pages = null, maxWidth = 1400, maximumScale = 2, signal = null, writeImages = true } = {}
218
+ ) {
208
219
  if (signal?.aborted) throw new Error('PDF rendering was cancelled');
209
220
  installPdfGlobals();
210
221
  const { getDocument, VerbosityLevel } = await resolvedPdfJs();
@@ -248,7 +259,6 @@ async function renderPdfPagesDirect(path, { pages = null, maxWidth = 1400, maxim
248
259
  for (const pageNumber of selected) {
249
260
  const { canvas, data } = await renderPage(pageNumber, maxWidth);
250
261
  const imagePath = join(dirname(path), `${stem}-page-${pageNumber}.png`);
251
- await writeFile(imagePath, data);
252
262
  output.push({
253
263
  page: pageNumber,
254
264
  path: imagePath,
@@ -264,9 +274,10 @@ async function renderPdfPagesDirect(path, { pages = null, maxWidth = 1400, maxim
264
274
  for (let offset = 0; offset < selected.length; offset += pagesPerSheet) {
265
275
  const group = selected.slice(offset, offset + pagesPerSheet);
266
276
  const imagePath = join(dirname(path), `${stem}-pages-${group[0]}-${group.at(-1)}.png`);
267
- output.push(await writeContactSheet(group, width, imagePath, renderPage));
277
+ output.push(await contactSheet(group, width, imagePath, renderPage));
268
278
  }
269
279
  }
280
+ if (writeImages) await writePageImages(output);
270
281
  const reviewedPages = output.flatMap((image) => image.pages || [image.page]);
271
282
  const reviewedPageSet = new Set(reviewedPages);
272
283
  return {
@@ -293,7 +304,9 @@ export async function renderPdfPages(path, options = {}) {
293
304
  const signal = options.signal || null;
294
305
  if (signal?.aborted) throw new Error('PDF rendering was cancelled');
295
306
  if (!isMainThread) return await renderPdfPagesDirect(path, options);
296
- return await runPdfRenderWorker(
307
+ // The worker rasterizes; this thread writes the images, where the call's
308
+ // write ledger can see each one before it lands.
309
+ const rendered = await runPdfRenderWorker(
297
310
  {
298
311
  kind: PDF_RENDER_WORKER_KIND,
299
312
  path,
@@ -301,10 +314,13 @@ export async function renderPdfPages(path, options = {}) {
301
314
  pages: options.pages ?? null,
302
315
  maxWidth: options.maxWidth ?? 1400,
303
316
  maximumScale: options.maximumScale ?? 2,
317
+ writeImages: false,
304
318
  },
305
319
  },
306
320
  signal
307
321
  );
322
+ await writePageImages(rendered.images);
323
+ return rendered;
308
324
  }
309
325
 
310
326
  if (!isMainThread && [PDF_RENDER_WORKER_KIND, PDF_RENDER_PAGE_WORKER_KIND].includes(workerData?.kind)) {
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { writeFile, rm, rename } from 'node:fs/promises';
4
4
  import { dirname, join } from 'node:path';
5
+ import { noteOfficeWrite } from '../core/office-write-ledger.mjs';
5
6
 
6
7
  // qpdf on PATH, or wherever MIXDOG_QPDF_PATH points (the Windows installer
7
8
  // does not add itself to PATH).
@@ -89,6 +90,7 @@ export async function securePdf({ input, output, mode, password = '', ownerPassw
89
90
  ? ['--encrypt', password, ownerPassword || password, '256', '--', input, target]
90
91
  : [`--password=${password}`, '--decrypt', input, target];
91
92
  await writeFile(responsePath, `${args.join('\n')}\n`, { encoding: 'utf8', mode: 0o600 });
93
+ noteOfficeWrite(output);
92
94
  try {
93
95
  await run(QPDF, [`@${responsePath}`]);
94
96
  if (samePath) await rename(target, output);
@@ -1,6 +1,7 @@
1
1
  import { posix } from 'node:path';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { readFile, writeFile } from 'node:fs/promises';
4
+ import { noteOfficeWrite } from '../core/office-write-ledger.mjs';
4
5
  import { koreanParticleReplacements } from '../shared/korean-particles.mjs';
5
6
  import { presetLabels } from '../shared/labels.mjs';
6
7
  import {
@@ -137,7 +138,9 @@ export async function packageBuffer(zip) {
137
138
  }
138
139
 
139
140
  export async function savePackage(zip, path) {
140
- await writeFile(path, await packageBuffer(zip));
141
+ const bytes = await packageBuffer(zip);
142
+ noteOfficeWrite(path);
143
+ await writeFile(path, bytes);
141
144
  }
142
145
 
143
146
  export function relationshipMap(xml) {
@@ -1,6 +1,7 @@
1
1
  import { writeFile } from 'node:fs/promises';
2
2
  import { dirname, extname, basename, join } from 'node:path';
3
3
  import { createCanvas, loadImage } from '@napi-rs/canvas';
4
+ import { noteOfficeWrite } from '../core/office-write-ledger.mjs';
4
5
 
5
6
  function imageByPage(images) {
6
7
  return new Map((images || []).map((image) => [Number(image.page), image]));
@@ -61,6 +62,7 @@ export async function compareRenderedPages(beforeImages, afterImages, outputPdf)
61
62
  diffContext.putImageData(diff, 0, 0);
62
63
  const data = diffCanvas.toBuffer('image/png');
63
64
  const path = join(dirname(outputPdf), `${stem}-visual-diff-page-${page}.png`);
65
+ noteOfficeWrite(path);
64
66
  await writeFile(path, data);
65
67
  const total = width * height;
66
68
  metrics.push({
@@ -58,7 +58,7 @@ export async function forgetSessionSearch(sessionId) {
58
58
 
59
59
  async function loadStoreDeps() {
60
60
  const [{ getStoreDir }, { _storedSessionFromFile, STORED_SESSION_UNREADABLE }] = await Promise.all([
61
- import('../agent/orchestrator/session/store/paths-heartbeat.mjs'),
61
+ import('../agent/orchestrator/session/store/session-paths.mjs'),
62
62
  import('../agent/orchestrator/session/store/serialize.mjs'),
63
63
  ]);
64
64
  return {
@@ -3,6 +3,19 @@ import { positiveInt } from './numbers.mjs';
3
3
 
4
4
  export const TAG_TOMBSTONE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
5
5
 
6
+ // How long a finished agent (completed, failed or cancelled child, or a Lead
7
+ // row) stays listed in the Agents pane, measured from its finish stamp. This is
8
+ // pane visibility only: session reuse and cache reaping keep their own windows
9
+ // (resolveAgentTerminalReapMs).
10
+ export const AGENT_PANE_VISIBLE_MS = 60 * 60 * 1000;
11
+
12
+ /** Whether a row finished at `finishedAtMs` is still inside the pane window.
13
+ * Index rows are always stamped; a row with no usable stamp has no provable
14
+ * age and stays listed rather than vanishing on a guess. */
15
+ export function agentPaneVisible(finishedAtMs, now) {
16
+ return !(finishedAtMs > 0) || now - finishedAtMs < AGENT_PANE_VISIBLE_MS;
17
+ }
18
+
6
19
  export function stampMs(value) {
7
20
  if (typeof value === 'number') return Number.isFinite(value) && value > 0 ? value : 0;
8
21
  const text = clean(value);
@@ -23,5 +23,5 @@ export function writeJsonAtomicAsync(
23
23
  export function withFileLock<T>(
24
24
  lockPath: string,
25
25
  task: () => T | Promise<T>,
26
- options?: { timeoutMs?: number; staleMs?: number; secret?: boolean }
26
+ options?: { timeoutMs?: number; staleMs?: number; secret?: boolean; strictOwner?: boolean }
27
27
  ): Promise<T>;
@@ -330,13 +330,18 @@ export function settleCancelledBackgroundTask(taskId, { result } = {}) {
330
330
  export function cancelBackgroundTasks(options = {}) {
331
331
  const reason = clean(options.reason) || 'cancelled';
332
332
  const wanted = clean(options.surface);
333
+ const executionSessionId = clean(options.executionSessionId);
333
334
  let cancelled = 0;
334
335
  for (const task of [...tasks.values()]) {
335
336
  if (wanted && task.surface !== wanted) continue;
336
337
  // Scoped teardown must be exact. Legacy tasks without ownership stay
337
338
  // visible/recoverable, but may not be claimed by whichever session happens
338
339
  // to close first.
339
- if (!taskMatchesScope(task, options, { includeUnattributed: false })) continue;
340
+ if (executionSessionId) {
341
+ // Delegated work executes in its bound session; before binding it still
342
+ // belongs to the registering session. Notification ownership is separate.
343
+ if ((clean(task.meta?.sessionId) || task.ownerSessionId) !== executionSessionId) continue;
344
+ } else if (!taskMatchesScope(task, options, { includeUnattributed: false })) continue;
340
345
  if (TERMINAL_STATUSES.has(task.status)) {
341
346
  if (options.notify === false) silenceCancelledNotification(task);
342
347
  continue;
@@ -156,6 +156,19 @@ export function readBoundedFile(
156
156
  }
157
157
  }
158
158
 
159
+ /**
160
+ * A file's state for the turn review of a tool write: null when absent, its
161
+ * bytes (binary included) up to PATCH_EDIT_MAX_BYTES and within `budget`,
162
+ * otherwise an omitted marker — counted as changed, never diffed or restored.
163
+ * Throws ENOTREGULAR for anything but a regular file.
164
+ */
165
+ export function reviewFileContent(path, { budget = null } = {}) {
166
+ const read = readBoundedFile(path, { maxBytes: PATCH_EDIT_MAX_BYTES, budget, detectBinary: false });
167
+ if (read.state === 'absent') return null;
168
+ if (read.state === 'omitted') return { omitted: true, size: read.size, reason: read.reason };
169
+ return read.content;
170
+ }
171
+
159
172
  /** Human phrase for an omitted read: "binary (N bytes)", "larger than 8 MiB (N bytes)". */
160
173
  export function describeOmittedFile({ reason, size, limit } = {}) {
161
174
  const bytes = `${Number(size) || 0} bytes`;
@@ -0,0 +1,191 @@
1
+ // In-process line diffs for the turn-change paths, bounded the way codex
2
+ // bounds its own: every file gets a short timeout, every operation (one tool
3
+ // call, one review or seal pass) a total budget. A file over the size limits,
4
+ // past its timeout or past the spent budget gets one replacement hunk between
5
+ // its common line prefix and suffix instead — still an exact patch that
6
+ // applies, only not a minimal one. Results are cached by content, so the same
7
+ // pair is not diffed again across calls and reviews.
8
+ import { createHash } from 'node:crypto';
9
+ import { performance } from 'node:perf_hooks';
10
+ import { formatPatch, structuredPatch } from 'diff';
11
+
12
+ /** Longest a single file's Myers diff may run (codex's per-file value). */
13
+ export const LINE_DIFF_FILE_TIMEOUT_MS = 100;
14
+ /** Total Myers diff time one operation may spend across its files. */
15
+ // Kept well under the lag target: an operation also renders, hashes and
16
+ // bounds its patches outside the diff itself.
17
+ export const LINE_DIFF_OPERATION_BUDGET_MS = 150;
18
+ // A side over either limit is never Myers-diffed.
19
+ const LINE_DIFF_MAX_CHARS = 1024 * 1024;
20
+ const LINE_DIFF_MAX_LINES = 20_000;
21
+ const CONTEXT_LINES = 3;
22
+ const CACHE_MAX_ENTRIES = 512;
23
+ // Cached hunks reference their texts: bound the cache by their length.
24
+ const CACHE_MAX_CHARS = 32 * 1024 * 1024;
25
+
26
+ /** One operation's diff budget; pass it to every lineDiffHunks call of it. */
27
+ export function createLineDiffBudget(totalMs = LINE_DIFF_OPERATION_BUDGET_MS) {
28
+ return { remainingMs: totalMs };
29
+ }
30
+
31
+ const _cache = new Map();
32
+ let _cachedChars = 0;
33
+ const _hashByBytes = new WeakMap();
34
+
35
+ const sha1 = (value) => createHash('sha1').update(value).digest('hex');
36
+
37
+ /** Content hash of one side: a byte array is hashed once per object. A text
38
+ * hashes to the same id as its UTF-8 bytes; one that has no exact UTF-8 form
39
+ * (a lone surrogate) gets no id. */
40
+ function sideHash(source, text) {
41
+ if (source && typeof source === 'object') {
42
+ let hash = _hashByBytes.get(source);
43
+ if (!hash) {
44
+ hash = sha1(source);
45
+ _hashByBytes.set(source, hash);
46
+ }
47
+ return hash;
48
+ }
49
+ return text.isWellFormed() ? sha1(text) : null;
50
+ }
51
+
52
+ function cacheKey(sources, oldText, newText) {
53
+ const before = sideHash(sources[0], oldText);
54
+ const after = before && sideHash(sources[1], newText);
55
+ return after ? `${before}:${after}` : null;
56
+ }
57
+
58
+ function cacheGet(key) {
59
+ const entry = _cache.get(key);
60
+ if (!entry) return null;
61
+ _cache.delete(key);
62
+ _cache.set(key, entry);
63
+ return entry.result;
64
+ }
65
+
66
+ function cacheSet(key, result, chars) {
67
+ if (chars > CACHE_MAX_CHARS) return;
68
+ _cachedChars -= _cache.get(key)?.chars || 0;
69
+ _cache.delete(key);
70
+ _cache.set(key, { result, chars });
71
+ _cachedChars += chars;
72
+ while (_cache.size > CACHE_MAX_ENTRIES || _cachedChars > CACHE_MAX_CHARS) {
73
+ const [oldest, entry] = _cache.entries().next().value;
74
+ _cache.delete(oldest);
75
+ _cachedChars -= entry.chars;
76
+ }
77
+ }
78
+
79
+ function overLimits(text) {
80
+ if (text.length > LINE_DIFF_MAX_CHARS) return true;
81
+ let lines = 0;
82
+ for (let index = text.indexOf('\n'); index >= 0; index = text.indexOf('\n', index + 1)) {
83
+ lines += 1;
84
+ if (lines > LINE_DIFF_MAX_LINES) return true;
85
+ }
86
+ return false;
87
+ }
88
+
89
+ /** Lines with their `\n` (the last one may lack it), as jsdiff tokenizes. */
90
+ function lineTokens(text) {
91
+ if (!text) return [];
92
+ const lines = text.split('\n');
93
+ const tokens = lines.map((line, index) => (index < lines.length - 1 ? `${line}\n` : line));
94
+ if (tokens.at(-1) === '') tokens.pop();
95
+ return tokens;
96
+ }
97
+
98
+ /** The one hunk replacing everything between the texts' common line prefix
99
+ * and suffix, with up to three context lines each side, in jsdiff's hunk
100
+ * shape (`` included). */
101
+ function replacementHunks(oldText, newText) {
102
+ const before = lineTokens(oldText);
103
+ const after = lineTokens(newText);
104
+ const shortest = Math.min(before.length, after.length);
105
+ let start = 0;
106
+ while (start < shortest && before[start] === after[start]) start += 1;
107
+ let end = 0;
108
+ while (end < shortest - start && before[before.length - 1 - end] === after[after.length - 1 - end]) end += 1;
109
+ const lead = Math.min(CONTEXT_LINES, start);
110
+ const trail = Math.min(CONTEXT_LINES, end);
111
+ const lines = [];
112
+ const push = (mark, tokens) => {
113
+ for (const token of tokens) {
114
+ if (token.endsWith('\n')) lines.push(mark + token.slice(0, -1));
115
+ else lines.push(mark + token, '\');
116
+ }
117
+ };
118
+ push(' ', before.slice(start - lead, start));
119
+ push('-', before.slice(start, before.length - end));
120
+ push('+', after.slice(start, after.length - end));
121
+ push(' ', before.slice(before.length - end, before.length - end + trail));
122
+ const first = start - lead;
123
+ return [
124
+ {
125
+ oldStart: first + 1,
126
+ oldLines: before.length - end + trail - first,
127
+ newStart: first + 1,
128
+ newLines: after.length - end + trail - first,
129
+ lines,
130
+ },
131
+ ];
132
+ }
133
+
134
+ /**
135
+ * Hunks (context 3, jsdiff's structuredPatch shape) turning `oldText` into
136
+ * `newText`: jsdiff's own when its diff finishes within the file timeout and
137
+ * what is left of `budget` (`exact`), else the replacement hunk. `sources`
138
+ * are the raw sides the texts came from (bytes or the texts), used only as
139
+ * the cache key. The returned value is shared: never mutate it.
140
+ */
141
+ export function lineDiffHunks(oldText, newText, budget, sources = [oldText, newText]) {
142
+ if (oldText === newText) return { hunks: [], exact: true };
143
+ const key = cacheKey(sources, oldText, newText);
144
+ const cached = key ? cacheGet(key) || budget.fallbacks?.get(key) : null;
145
+ if (cached) return cached;
146
+ let result = null;
147
+ // A fallback forced by the operation's spent budget is not this pair's own
148
+ // outcome: it is not cached, so a later operation can still diff it.
149
+ let repeatable = true;
150
+ if (!overLimits(oldText) && !overLimits(newText)) {
151
+ if (budget.remainingMs > 0) {
152
+ const timeout = Math.min(LINE_DIFF_FILE_TIMEOUT_MS, budget.remainingMs);
153
+ const startedAt = performance.now();
154
+ const patch = structuredPatch('', '', oldText, newText, '', '', { context: CONTEXT_LINES, timeout });
155
+ budget.remainingMs -= performance.now() - startedAt;
156
+ if (patch) result = { hunks: patch.hunks, exact: true };
157
+ else repeatable = timeout >= LINE_DIFF_FILE_TIMEOUT_MS;
158
+ } else {
159
+ repeatable = false;
160
+ }
161
+ }
162
+ result ||= { hunks: replacementHunks(oldText, newText), exact: false };
163
+ if (key && repeatable) cacheSet(key, result, oldText.length + newText.length);
164
+ // Within its own operation it is final: the budget never grows back.
165
+ else if (key) {
166
+ budget.fallbacks ||= new Map();
167
+ budget.fallbacks.set(key, result);
168
+ }
169
+ return result;
170
+ }
171
+
172
+ /** The `--- `/`+++ ` headers and hunks of `hunks`, as jsdiff formats them,
173
+ * ending in exactly one newline. */
174
+ export function unifiedHunksBody(oldHeader, newHeader, hunks) {
175
+ const generated = formatPatch({
176
+ oldFileName: oldHeader,
177
+ newFileName: newHeader,
178
+ oldHeader: '',
179
+ newHeader: '',
180
+ hunks,
181
+ });
182
+ let end = generated.length;
183
+ // Linear trim: a /\n*$/ regex rescans from every position of a large patch.
184
+ while (end > 0 && generated.charCodeAt(end - 1) === 10) end -= 1;
185
+ return `${generated.slice(generated.search(/^--- /m), end)}\n`;
186
+ }
187
+
188
+ export function _resetLineDiffCacheForTest() {
189
+ _cache.clear();
190
+ _cachedChars = 0;
191
+ }
@@ -88,3 +88,18 @@ export function buildPuppeteerLaunchArgs(extra = []) {
88
88
  if (puppeteerNoSandboxEnabled()) args.push('--no-sandbox');
89
89
  return args;
90
90
  }
91
+
92
+ // A healthy headless launch answers in a few seconds; the observed CI failures
93
+ // are launches that never print the DevTools endpoint and hit puppeteer's 30 s
94
+ // TimeoutError (Windows runner, Linux runner). Puppeteer closes that child
95
+ // itself, so one fresh attempt is the remedy; a longer wait would only delay
96
+ // the same hang. Any other launch error (missing executable, bad args), or a
97
+ // timeout after `signal` aborted, is not retried.
98
+ export async function launchPuppeteerBrowser(puppeteer, options, { signal = null } = {}) {
99
+ try {
100
+ return await puppeteer.launch(options);
101
+ } catch (error) {
102
+ if (error?.name !== 'TimeoutError' || signal?.aborted) throw error;
103
+ return puppeteer.launch(options);
104
+ }
105
+ }