mixdog 1.3.5 → 1.4.1

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 (515) hide show
  1. package/NOTICE.md +2 -2
  2. package/README.md +2 -2
  3. package/package.json +2 -11
  4. package/scripts/check-voice-runtime-inputs.mjs +25 -0
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/gate-local.mjs +16 -5
  7. package/scripts/latest-guard.mjs +21 -9
  8. package/scripts/lib/isolated-test-env.mjs +10 -5
  9. package/scripts/lib/run-node-tests.mjs +37 -37
  10. package/scripts/lib/scoped-temp.d.mts +16 -0
  11. package/scripts/lib/scoped-temp.mjs +123 -0
  12. package/scripts/lib/stale-temp.mjs +44 -0
  13. package/scripts/native-release-status.mjs +2 -2
  14. package/scripts/post-release-check.mjs +1 -6
  15. package/scripts/pptx-kit-index.mjs +17 -4
  16. package/scripts/recall-history-cases.json +1 -1
  17. package/scripts/suite-health.mjs +20 -2
  18. package/scripts/test-data-dir.mjs +10 -7
  19. package/scripts/test.mjs +7 -11
  20. package/src/agents/reviewer/AGENT.md +7 -11
  21. package/src/agents/reviewer/agent.json +1 -1
  22. package/src/app.mjs +4 -0
  23. package/src/defaults/shipped-history.json +22 -1
  24. package/src/defaults/skills/browser-use/SKILL.md +62 -12
  25. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  26. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  27. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  28. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  29. package/src/defaults/skills/computer-use/SKILL.md +35 -9
  30. package/src/defaults/skills/setup/SKILL.md +22 -0
  31. package/src/defaults/skills/setup/references/actions.md +39 -5
  32. package/src/defaults/skills/setup/references/surfaces.md +11 -2
  33. package/src/defaults/skills/visualize/SKILL.md +2 -1
  34. package/src/lib/rules-builder.cjs +39 -20
  35. package/src/output-styles/common.md +2 -2
  36. package/src/output-styles/simple.md +1 -1
  37. package/src/rules/agent/AGENT.md +11 -10
  38. package/src/rules/lead/LEAD.md +23 -20
  39. package/src/rules/shared/05-tool-calls.md +5 -6
  40. package/src/rules/shared/10-tool-workflow.md +4 -0
  41. package/src/rules/shared/45-destructive.md +0 -2
  42. package/src/rules/shared/50-execution.md +2 -0
  43. package/src/rules/shared/60-verification.md +7 -5
  44. package/src/rules/shared/70-delivery.md +7 -9
  45. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +29 -6
  46. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  47. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  48. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  49. package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
  50. package/src/runtime/agent/orchestrator/config.mjs +17 -1
  51. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  52. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +73 -68
  53. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +57 -2
  54. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  55. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +176 -72
  56. package/src/runtime/agent/orchestrator/mcp/client.mjs +19 -0
  57. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +5 -2
  58. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +192 -133
  59. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +42 -6
  60. package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
  61. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +7 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
  63. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  64. package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
  65. package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  67. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  69. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
  70. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +159 -69
  71. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  72. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +70 -33
  73. package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
  74. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  75. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +123 -102
  76. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  77. package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
  78. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  79. package/src/runtime/agent/orchestrator/providers/cursor.mjs +25 -13
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
  82. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +210 -20
  83. package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
  84. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
  85. package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
  86. package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
  87. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  88. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  89. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
  90. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  91. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  92. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  93. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +2 -1
  94. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
  95. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +9 -2
  96. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
  97. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
  98. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
  99. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
  100. package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
  101. package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
  102. package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
  103. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
  104. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
  106. package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
  107. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +136 -5
  109. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  113. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +20 -12
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +48 -22
  117. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  118. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  119. package/src/runtime/agent/orchestrator/providers/registry.mjs +38 -0
  120. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  121. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  122. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +49 -16
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +7 -6
  127. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +9 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +3 -1
  131. package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
  132. package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
  133. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +798 -0
  134. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
  136. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
  137. package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
  138. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +280 -45
  139. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  140. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  141. package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
  142. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +163 -22
  143. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +132 -17
  144. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
  145. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
  146. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +90 -22
  147. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -1
  148. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +11 -5
  149. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +0 -2
  150. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  151. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +1 -1
  152. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +51 -25
  153. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +37 -3
  154. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +3 -1
  155. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +1 -1
  156. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
  158. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +31 -3
  159. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +20 -3
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +5 -4
  162. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  163. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  164. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +49 -21
  165. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  166. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +12 -3
  167. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  168. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
  172. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  173. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  174. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +24 -14
  175. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  176. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  177. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +130 -0
  178. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +27 -9
  179. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +81 -8
  180. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  181. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -8
  182. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +12 -5
  183. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +9 -4
  185. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
  186. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  187. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +21 -5
  188. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +9 -0
  189. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +24 -9
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  191. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +150 -0
  192. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
  193. package/src/runtime/agent/orchestrator/session/routine-result.mjs +36 -9
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
  203. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +8 -6
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
  207. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +81 -22
  208. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +92 -3
  209. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +79 -3
  214. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  216. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  217. package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
  218. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  219. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
  225. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +31 -6
  226. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +110 -26
  227. package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
  228. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +31 -5
  229. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +22 -8
  230. package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
  231. package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
  232. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
  233. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
  234. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
  235. package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
  236. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
  237. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  238. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
  239. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
  240. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  241. package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
  242. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +26 -4
  243. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  244. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  245. package/src/runtime/browser-bridge/client.mjs +73 -8
  246. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  247. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  248. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  249. package/src/runtime/channels/lib/config.mjs +6 -61
  250. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  251. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  252. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  253. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  254. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  255. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  256. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  257. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  258. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  259. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  260. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  261. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  262. package/src/runtime/channels/lib/scheduler.mjs +33 -147
  263. package/src/runtime/channels/lib/schedules-db.mjs +34 -11
  264. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  265. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -2
  266. package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
  267. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  268. package/src/runtime/channels/lib/whisper-port.mjs +10 -1
  269. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  270. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  271. package/src/runtime/channels/lib/worker-main.mjs +10 -34
  272. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  273. package/src/runtime/computer-bridge/actions.mjs +9 -1
  274. package/src/runtime/computer-bridge/client.mjs +180 -8
  275. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  276. package/src/runtime/computer-bridge/error-recovery.mjs +28 -2
  277. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
  278. package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
  279. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  280. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  281. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  282. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  283. package/src/runtime/connectors/google-mcp.mjs +10 -12
  284. package/src/runtime/local-provider/server-process.mjs +2 -1
  285. package/src/runtime/media/adapters/gemini-video.mjs +4 -1
  286. package/src/runtime/media/adapters/xai-media.mjs +2 -1
  287. package/src/runtime/memory/lib/embedding-worker.mjs +6 -3
  288. package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
  289. package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
  290. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  291. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  292. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  293. package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
  294. package/src/runtime/office/design/design-art-direction.mjs +29 -27
  295. package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
  296. package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
  297. package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
  298. package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
  299. package/src/runtime/office/quality/assurance-structure-docx.mjs +3 -1
  300. package/src/runtime/office/quality/design-review.mjs +1 -5
  301. package/src/runtime/office/quality/document-brief.mjs +1 -5
  302. package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
  303. package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
  304. package/src/runtime/session-search/session-search-db.mjs +73 -9
  305. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  306. package/src/runtime/shared/abort-race.mjs +89 -0
  307. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  308. package/src/runtime/shared/agent-kind.mjs +4 -3
  309. package/src/runtime/shared/bot-owned-work.mjs +56 -0
  310. package/src/runtime/shared/bounded-download.mjs +8 -3
  311. package/src/runtime/shared/config.mjs +2 -13
  312. package/src/runtime/shared/connector-accounts.mjs +20 -10
  313. package/src/runtime/shared/connector-catalog.d.mts +29 -0
  314. package/src/runtime/shared/connector-catalog.mjs +150 -0
  315. package/src/runtime/shared/connector-triggers.mjs +22 -19
  316. package/src/runtime/shared/defaults-separation.mjs +2 -17
  317. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  318. package/src/runtime/shared/err-text.mjs +24 -15
  319. package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
  320. package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
  321. package/src/runtime/shared/file-permissions.d.mts +0 -8
  322. package/src/runtime/shared/file-permissions.mjs +0 -11
  323. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  324. package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
  325. package/src/runtime/shared/handoff-artifacts.mjs +18 -8
  326. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  327. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  328. package/src/runtime/shared/idle-auto-clear-gate.mjs +126 -0
  329. package/src/runtime/shared/llm/cost.mjs +5 -1
  330. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  331. package/src/runtime/shared/loopback-listener.mjs +25 -2
  332. package/src/runtime/shared/mixy-presence.mjs +22 -0
  333. package/src/runtime/shared/model-route-chain.d.mts +7 -2
  334. package/src/runtime/shared/model-route-chain.mjs +22 -4
  335. package/src/runtime/shared/open-url.mjs +10 -0
  336. package/src/runtime/shared/orchestration.d.mts +2 -0
  337. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  338. package/src/runtime/shared/profile-config.cjs +1 -1
  339. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  340. package/src/runtime/shared/prompt-origin.mjs +21 -0
  341. package/src/runtime/shared/provider-accounts.mjs +7 -1
  342. package/src/runtime/shared/provider-display-name.mjs +29 -0
  343. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  344. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  345. package/src/runtime/shared/routine-trigger.mjs +10 -0
  346. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  347. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  348. package/src/runtime/shared/session-activity-signal.mjs +48 -1
  349. package/src/runtime/shared/session-scratch.mjs +37 -0
  350. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  351. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  352. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  353. package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
  354. package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
  355. package/src/runtime/shared/tool-result-summary.mjs +2 -15
  356. package/src/runtime/shared/tool-surface.mjs +3 -0
  357. package/src/runtime/shared/tool-work-units.mjs +2 -0
  358. package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
  359. package/src/runtime/shared/worktrees/contract.mjs +4 -1
  360. package/src/runtime/shared/worktrees/git.mjs +15 -0
  361. package/src/runtime/shared/worktrees/manager.mjs +87 -38
  362. package/src/runtime/shared/worktrees/test-support.mjs +14 -13
  363. package/src/runtime/terminal-bridge/client.mjs +10 -1
  364. package/src/runtime/visualize-bridge/client.mjs +29 -8
  365. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  366. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  367. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  368. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  369. package/src/session-runtime/agent-home-delivery.mjs +489 -185
  370. package/src/session-runtime/agent-task-sessions.mjs +467 -229
  371. package/src/session-runtime/agent-tool-routing.mjs +8 -41
  372. package/src/session-runtime/boot/apis.mjs +9 -0
  373. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  374. package/src/session-runtime/boot/providers.mjs +3 -0
  375. package/src/session-runtime/boot/tools.mjs +11 -2
  376. package/src/session-runtime/bot-status.mjs +12 -6
  377. package/src/session-runtime/bot-target.mjs +38 -0
  378. package/src/session-runtime/channel-config-api.mjs +6 -1
  379. package/src/session-runtime/config-lifecycle.mjs +6 -0
  380. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  381. package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
  382. package/src/session-runtime/conversation-import/discovery.mjs +271 -25
  383. package/src/session-runtime/conversation-import/service.mjs +26 -5
  384. package/src/session-runtime/handoff-attachments.mjs +82 -31
  385. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +144 -41
  386. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -0
  387. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
  388. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +8 -2
  389. package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
  390. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  391. package/src/session-runtime/lifecycle/session-catalog.mjs +12 -2
  392. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  393. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  394. package/src/session-runtime/mcp-glue/server-catalog.mjs +55 -3
  395. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  396. package/src/session-runtime/mixy-heartbeat.mjs +153 -33
  397. package/src/session-runtime/model-route/set-route.mjs +11 -2
  398. package/src/session-runtime/notification-bus.mjs +31 -117
  399. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  400. package/src/session-runtime/notification-listeners.mjs +76 -0
  401. package/src/session-runtime/owned-automation-run.mjs +2 -1
  402. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  403. package/src/session-runtime/provider-catalog-cache.mjs +82 -36
  404. package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
  405. package/src/session-runtime/provider-models.mjs +4 -2
  406. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  407. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  408. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  409. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  410. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  411. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  412. package/src/session-runtime/resource-recall-api.mjs +6 -1
  413. package/src/session-runtime/routine-owner.mjs +40 -9
  414. package/src/session-runtime/runtime-feature-gates.mjs +5 -1
  415. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  416. package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
  417. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
  418. package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
  419. package/src/session-runtime/services/agent-tool/render.mjs +71 -17
  420. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +13 -4
  421. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  422. package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
  423. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  424. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  425. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  426. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  427. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  428. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  429. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  430. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  431. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  432. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  433. package/src/session-runtime/services/channel-admin.mjs +7 -13
  434. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  435. package/src/session-runtime/services/provider-admin.mjs +2 -1
  436. package/src/session-runtime/services/seeds.mjs +0 -28
  437. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  438. package/src/session-runtime/session-create/session-options.mjs +1 -0
  439. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  440. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  441. package/src/session-runtime/settings-system-api.mjs +13 -1
  442. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  443. package/src/session-runtime/setup-tool/executor.mjs +145 -22
  444. package/src/session-runtime/setup-tool/extended-actions.mjs +8 -3
  445. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  446. package/src/session-runtime/setup-tool/settings-contract.mjs +4 -3
  447. package/src/session-runtime/setup-tool/tool-defs.mjs +64 -5
  448. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  449. package/src/session-runtime/tool-policy/policy-stage.mjs +17 -2
  450. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  451. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
  452. package/src/session-runtime/workflow-agents-api/agent-route.mjs +15 -4
  453. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
  454. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  455. package/src/session-runtime/workspace/transitions.mjs +25 -0
  456. package/src/session-runtime/workspace/worktree-tool.mjs +26 -9
  457. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  458. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  459. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  460. package/src/standalone/channel-transport.mjs +1 -1
  461. package/src/standalone/daemon-channels-loader.mjs +10 -8
  462. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  463. package/src/standalone/daemon-session-control/request.mjs +51 -0
  464. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  465. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  466. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  467. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  468. package/src/standalone/daemon-session-control.mjs +142 -190
  469. package/src/standalone/daemon.mjs +26 -3
  470. package/src/standalone/session-client.mjs +7 -3
  471. package/src/standalone/session-protocol.mjs +5 -0
  472. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  473. package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
  474. package/src/standalone/session-service/quota-resume.mjs +3 -0
  475. package/src/standalone/session-service/retention/busy.mjs +65 -1
  476. package/src/standalone/session-service/session-calls/session-action.mjs +30 -2
  477. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  478. package/src/standalone/session-tool-output.mjs +15 -7
  479. package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
  480. package/src/tui/app/app-view/floating-panel.jsx +7 -4
  481. package/src/tui/app/model-options.mjs +3 -28
  482. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
  483. package/src/tui/app/model-picker/route-selection.mjs +5 -6
  484. package/src/tui/app/provider-setup/oauth-actions.mjs +38 -20
  485. package/src/tui/app/provider-setup/provider-items.mjs +8 -2
  486. package/src/tui/app/provider-setup-picker.mjs +9 -5
  487. package/src/tui/components/QuestionPanel.jsx +13 -4
  488. package/src/tui/dist/index.mjs +133 -92
  489. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  490. package/src/tui/session/initial-state.mjs +3 -0
  491. package/src/tui/session/notice-surface.mjs +7 -1
  492. package/src/tui/session/queue-helpers.mjs +3 -42
  493. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  494. package/src/tui/session/session-api/routes-write.mjs +5 -1
  495. package/src/tui/session/session-api/routes.mjs +1 -0
  496. package/src/tui/session/session-api/settings.mjs +17 -1
  497. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  498. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  499. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  500. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  501. package/src/tui/session/session-flow/drain.mjs +118 -149
  502. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  503. package/src/tui/session/session-flow/queue/take-entries.mjs +16 -2
  504. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  505. package/src/tui/session/tool-approval-request.mjs +39 -0
  506. package/src/tui/session/tool-approval-settle.mjs +62 -0
  507. package/src/tui/session/tool-approval.mjs +69 -115
  508. package/src/tui/session/tui-steering-persist.mjs +8 -1
  509. package/src/tui/session/turn-stream.mjs +19 -2
  510. package/src/tui/session/turn.mjs +1 -0
  511. package/src/ui/statusline-agents.mjs +1 -3
  512. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  513. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  514. package/scripts/code-graph-description-contract.mjs +0 -188
  515. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -30,6 +30,7 @@ import {
30
30
  import { withFileLockSync } from '../../../shared/atomic-file.mjs';
31
31
  import { isPidAlive } from '../../../shared/pid-liveness.mjs';
32
32
  import { envFlag } from '../../../shared/env.mjs';
33
+ import { createSharedAbortable } from '../../../shared/abort-race.mjs';
33
34
  import { ensurePrivateRuntimeRoot, resolveRuntimeRoot } from '../../../shared/runtime-root.mjs';
34
35
 
35
36
  let _pgProc = null;
@@ -51,7 +52,7 @@ async function _getPgProc() {
51
52
  /** @type {{ port: number, pgdata: string, runtimeDir: string, proc: unknown } | null} */
52
53
  let _live = null;
53
54
  /** Dedup: one ensure coroutine at a time. */
54
- let _ensureInFlight = null;
55
+ let _ensureShared = null;
55
56
  /** Per-process flag — postgresql.conf reconcile attempted once per supervisor. */
56
57
  let _v2ReconcileTried = false;
57
58
  /** Set by stopOwnedPgForShutdown: this process is exiting, no further ensure. */
@@ -542,7 +543,7 @@ async function tryReusePgInstance({ pgdata, runtimeDir, healthcheckPg, source =
542
543
  return null;
543
544
  }
544
545
 
545
- // ── Internal: full ensure logic (runs exclusively via _ensureInFlight) ────────
546
+ // ── Internal: full ensure logic (runs exclusively via _ensureShared) ──────────
546
547
 
547
548
  function _pgdataDir(dataDir) {
548
549
  return join(dataDir, 'pgdata');
@@ -555,13 +556,15 @@ export function pgClusterExists(dataDir) {
555
556
  return existsSync(join(_pgdataDir(dataDir), 'PG_VERSION'));
556
557
  }
557
558
 
558
- async function _doEnsure(dataDir) {
559
+ async function _doEnsure(dataDir, signal) {
559
560
  const { healthcheckPg } = await _getPgProc();
560
561
  const pgdata = _pgdataDir(dataDir);
561
562
 
562
563
  // Resolve runtimeDir via runtime-fetcher (cache-hits immediately when already downloaded).
563
564
  const { ensureRuntime } = await import('../runtime-fetcher.mjs');
564
- const { runtimeDir } = await ensureRuntime(dataDir);
565
+ const { runtimeDir } = await ensureRuntime(dataDir, { signal });
566
+ // Cancelled while installing: start no cluster for callers that are gone.
567
+ signal.throwIfAborted();
565
568
 
566
569
  // One-shot v2 conf reconcile — idempotent. Covers attach paths (in-process
567
570
  // fast path / cross-process active-instance reuse) where startPg is never
@@ -713,10 +716,15 @@ async function _doEnsure(dataDir) {
713
716
  * Concurrent calls are deduplicated — exactly one spawn/recover sequence runs
714
717
  * at a time; additional callers await the same promise.
715
718
  *
719
+ * `signal` (optional) withdraws this caller: the shared ensure is cancelled
720
+ * (its runtime install included) only once every caller has withdrawn and
721
+ * none joined without a signal (createSharedAbortable).
722
+ *
716
723
  * @param {string} dataDir Mixdog data directory.
724
+ * @param {{ signal?: AbortSignal }} [opts]
717
725
  * @returns {Promise<{ host: string, port: number, runtimeDir: string, pgdataDir: string }>}
718
726
  */
719
- export function ensurePgInstance(dataDir) {
727
+ export function ensurePgInstance(dataDir, { signal = null } = {}) {
720
728
  // Once this process began stopping the cluster it owns, nothing may start
721
729
  // or re-attach one: a late connection-loss recovery would otherwise bring a
722
730
  // postmaster back up right after the stop and leave it running past exit.
@@ -727,12 +735,15 @@ export function ensurePgInstance(dataDir) {
727
735
  // in-process fast path — so this is the one place the sweep cannot be
728
736
  // skipped. Latched internally, so repeated calls schedule it only once.
729
737
  scheduleOrphanTempPostmasterSweep();
730
- if (!_ensureInFlight) {
731
- _ensureInFlight = _doEnsure(dataDir).finally(() => {
732
- _ensureInFlight = null;
738
+ if (!_ensureShared) {
739
+ const shared = createSharedAbortable((sharedSignal) => _doEnsure(dataDir, sharedSignal), {
740
+ onSettled: () => {
741
+ if (_ensureShared === shared) _ensureShared = null;
742
+ },
733
743
  });
744
+ _ensureShared = shared;
734
745
  }
735
- return _ensureInFlight;
746
+ return _ensureShared.join(signal);
736
747
  }
737
748
 
738
749
  /**
@@ -779,7 +790,7 @@ export async function stopPgForShutdown() {
779
790
  return;
780
791
  }
781
792
  const snap = _live;
782
- _ensureInFlight = null;
793
+ _ensureShared = null;
783
794
  try {
784
795
  const { stopPg } = await _getPgProc();
785
796
  await stopPg({ runtimeDir: snap.runtimeDir, pgdataDir: snap.pgdata });
@@ -865,10 +876,11 @@ export async function stopOwnedPgForShutdown({ timeoutMs = 6_000 } = {}) {
865
876
  // publishes its cluster only when it settles; stopping before that would
866
877
  // miss the postmaster it is about to own. Bounded: a cold first start can
867
878
  // be a download.
868
- if (_ensureInFlight) {
879
+ const inFlight = _ensureShared?.promise;
880
+ if (inFlight) {
869
881
  let timer = null;
870
882
  await Promise.race([
871
- _ensureInFlight.catch(() => {}),
883
+ inFlight.catch(() => {}),
872
884
  new Promise((resolveWait) => {
873
885
  timer = setTimeout(resolveWait, timeoutMs);
874
886
  timer.unref?.();
@@ -158,8 +158,9 @@ function runtimePaths(verDir) {
158
158
  // Download with retry
159
159
  // ---------------------------------------------------------------------------
160
160
 
161
- async function downloadWithRetry(url, destPath, expectedBytes) {
161
+ async function downloadWithRetry(url, destPath, expectedBytes, signal) {
162
162
  return downloadToFileWithRetry(url, destPath, {
163
+ signal,
163
164
  maxBytes: expectedBytes,
164
165
  expectedBytes,
165
166
  label: 'memory runtime download',
@@ -532,11 +533,12 @@ function publishRuntimeDir(runtimeBaseDir, stagingDir, key, sha256) {
532
533
  * staging lock, ending with the stale-version GC. Returns the installed
533
534
  * runtime-{version} directory.
534
535
  */
535
- async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey }) {
536
+ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey, signal }) {
536
537
  // tar is only required for the download/extract path. Probe here (not at
537
538
  // ensureRuntime entry) so a machine without tar can still reuse an
538
539
  // already-extracted, sha-matching cached runtime via the fast path.
539
540
  await probeTar();
541
+ signal?.throwIfAborted();
540
542
 
541
543
  __mixdogMemoryLog(`[runtime-fetcher] downloading runtime ${version} for ${pkey} (~${size} bytes) …\n`);
542
544
 
@@ -566,7 +568,7 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
566
568
  `[runtime-fetcher] retrying runtime download from fallback release repo — ${candidateUrl}\n`
567
569
  );
568
570
  }
569
- await downloadWithRetry(candidateUrl, tarPath, size);
571
+ await downloadWithRetry(candidateUrl, tarPath, size, signal);
570
572
  await verifySha256(tarPath, sha256);
571
573
  downloadOk = true;
572
574
  break;
@@ -575,9 +577,12 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
575
577
  try {
576
578
  rmSync(tarPath, { force: true });
577
579
  } catch {}
580
+ // A cancelled install tries no fallback repository.
581
+ signal?.throwIfAborted();
578
582
  }
579
583
  }
580
584
  if (!downloadOk && lastDownloadErr) throw lastDownloadErr;
585
+ signal?.throwIfAborted();
581
586
  await _extractRuntimeTarGz(tarPath, stagingDir, stagingDir);
582
587
  } finally {
583
588
  try {
@@ -591,6 +596,11 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
591
596
  } catch {}
592
597
  throw new Error(`[runtime-fetcher] download or verify failed for ${version}`);
593
598
  }
599
+ // Cancelled after the extract: drop the unpublished tree, publish nothing.
600
+ if (signal?.aborted) {
601
+ rmSync(stagingDir, { recursive: true, force: true });
602
+ signal.throwIfAborted();
603
+ }
594
604
 
595
605
  // Stamp sha256 inside staging dir.
596
606
  writeFileAtomicSync(join(stagingDir, '.version-sha256'), sha256);
@@ -615,6 +625,11 @@ async function installRuntimeVersion({ runtimeBaseDir, url, sha256, size, versio
615
625
  gcRuntimeDir(runtimeBaseDir, key);
616
626
  } finally {
617
627
  releaseStagingLock(stagingLock);
628
+ // Publishing is synchronous past the last cancellation check, so an
629
+ // aborted signal here means nothing was published.
630
+ if (signal?.aborted) {
631
+ __mixdogMemoryLog(`[runtime-fetcher] install of ${version} cancelled; its staging was removed\n`);
632
+ }
618
633
  }
619
634
 
620
635
  __mixdogMemoryLog(`[runtime-fetcher] runtime ready at ${verDir}\n`);
@@ -631,7 +646,10 @@ export const _runtimeLayoutInternals = {
631
646
  runtimeInstallKey,
632
647
  };
633
648
 
634
- export async function ensureRuntime(dataDir) {
649
+ /** `signal` cancels a download/install in progress: its retry waits end, its
650
+ * partial files and staging lock are removed and nothing is published, so the
651
+ * next call starts a fresh install. */
652
+ export async function ensureRuntime(dataDir, { signal = null } = {}) {
635
653
  const key = resolve(dataDir);
636
654
  if (runtimeCache.has(key)) return runtimeCache.get(key);
637
655
 
@@ -655,7 +673,7 @@ export async function ensureRuntime(dataDir) {
655
673
 
656
674
  const verDir =
657
675
  cachedRuntimeDir(runtimeBaseDir, version, sha256) ??
658
- (await installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey }));
676
+ (await installRuntimeVersion({ runtimeBaseDir, url, sha256, size, version, pkey, signal }));
659
677
 
660
678
  const result = { runtimeDir: verDir, ...runtimePaths(verDir), version };
661
679
  runtimeCache.set(key, result);
@@ -22,12 +22,7 @@ import {
22
22
  } from '../core/office-sessions.mjs';
23
23
  import { snapshotPdf } from '../pdf/pdf-adapter.mjs';
24
24
  import { inlineOfficeAudit } from '../quality/inline-audit.mjs';
25
- import {
26
- factsGate,
27
- parseAuthoringBrief,
28
- reviewBriefPromises,
29
- reviewSourceGrounding,
30
- } from './pptx-brief.mjs';
25
+ import { factsGate, parseAuthoringBrief, reviewBriefPromises, reviewSourceGrounding } from './pptx-brief.mjs';
31
26
  import { editsReplacedByAuthor, markAuthoredFromHtml } from './html-source-drift.mjs';
32
27
  import { hasSlideSections, htmlBriefScript, runPptxHtmlAuthoring } from './pptx-html-runner.mjs';
33
28
  import {
@@ -236,34 +236,36 @@ export function resolveOfficeArtDirection(
236
236
  String(format || '').toLowerCase() === 'xlsx'
237
237
  ? DIRECTION_BLUEPRINTS.filter((blueprint) => blueprint.backgroundMode !== 'dark')
238
238
  : DIRECTION_BLUEPRINTS;
239
- const candidates = blueprints.map((blueprint) => {
240
- const palette = directionPalette(baseHue, blueprint);
241
- const motif = rawSubject ? `${blueprint.motif} · ${rawSubject}` : blueprint.motif;
242
- return {
243
- id: blueprint.id,
244
- label: blueprint.label,
245
- rationale: `${blueprint.label} fits ${purpose} through ${blueprint.motif}.`,
246
- motif,
247
- palette,
248
- typography: { ...blueprint.typography },
249
- style: { ...blueprint.style, pageRhythm: [...blueprint.style.pageRhythm] },
250
- creativeSystem: creativeSystemOf(blueprint),
251
- deck: {
252
- backgroundMode: blueprint.backgroundMode,
239
+ const candidates = blueprints
240
+ .map((blueprint) => {
241
+ const palette = directionPalette(baseHue, blueprint);
242
+ const motif = rawSubject ? `${blueprint.motif} · ${rawSubject}` : blueprint.motif;
243
+ return {
244
+ id: blueprint.id,
245
+ label: blueprint.label,
246
+ rationale: `${blueprint.label} fits ${purpose} through ${blueprint.motif}.`,
253
247
  motif,
254
- imageTreatment: blueprint.imageTreatment,
255
- layoutBias: [...blueprint.layoutBias],
256
- ...creativeSystemOf(blueprint),
257
- },
258
- score: directionScore(blueprint, {
259
- purpose,
260
- expressionMode,
261
- tone: String(request.tone || ''),
262
- requestedId: String(requested.id || ''),
263
- seed,
264
- }),
265
- };
266
- }).sort((left, right) => right.score - left.score || left.id.localeCompare(right.id));
248
+ palette,
249
+ typography: { ...blueprint.typography },
250
+ style: { ...blueprint.style, pageRhythm: [...blueprint.style.pageRhythm] },
251
+ creativeSystem: creativeSystemOf(blueprint),
252
+ deck: {
253
+ backgroundMode: blueprint.backgroundMode,
254
+ motif,
255
+ imageTreatment: blueprint.imageTreatment,
256
+ layoutBias: [...blueprint.layoutBias],
257
+ ...creativeSystemOf(blueprint),
258
+ },
259
+ score: directionScore(blueprint, {
260
+ purpose,
261
+ expressionMode,
262
+ tone: String(request.tone || ''),
263
+ requestedId: String(requested.id || ''),
264
+ seed,
265
+ }),
266
+ };
267
+ })
268
+ .sort((left, right) => right.score - left.score || left.id.localeCompare(right.id));
267
269
  const selected = candidates[0];
268
270
  const hasSubject = Boolean(rawSubject || requested.seed || requested.id);
269
271
  const disabled = request.artDirection === false || requested.enabled === false;
@@ -890,7 +890,12 @@ function drawChartBlock(flow, block, following) {
890
890
  });
891
891
  flow.y -= rowH;
892
892
  });
893
- page.drawLine({ start: { x: left, y: top }, end: { x: left, y: flow.y }, thickness: 0.6, color: color(flow.ink.line) });
893
+ page.drawLine({
894
+ start: { x: left, y: top },
895
+ end: { x: left, y: flow.y },
896
+ thickness: 0.6,
897
+ color: color(flow.ink.line),
898
+ });
894
899
  } else {
895
900
  const baseline = flow.y - size * 1.6 - layout.plotH;
896
901
  values.forEach((value, index) => {
@@ -12,7 +12,13 @@ import {
12
12
  xmlDecode,
13
13
  } from './portable-xml.mjs';
14
14
  import { countDocxPropertyChanges, docxRevisionTree, flattenDocxRevisions } from './docx-revisions.mjs';
15
- import { docxParagraphSpacing, docxRunFont, nextPageOffset, softBreakFacts, statedRunFont } from './portable-snapshot-shared.mjs';
15
+ import {
16
+ docxParagraphSpacing,
17
+ docxRunFont,
18
+ nextPageOffset,
19
+ softBreakFacts,
20
+ statedRunFont,
21
+ } from './portable-snapshot-shared.mjs';
16
22
 
17
23
  const REVISION_TYPES = Object.freeze({
18
24
  ins: 'insertion',
@@ -123,7 +123,12 @@ export function populatedCellPagination({ options, page, selectedSheets, sheets,
123
123
 
124
124
  export function statedRunFont(xml) {
125
125
  const direct = docxRunFont(xml);
126
- return direct.size || direct.bold || direct.name || direct.color || direct.caps !== undefined || direct.letterSpacing !== undefined
126
+ return direct.size ||
127
+ direct.bold ||
128
+ direct.name ||
129
+ direct.color ||
130
+ direct.caps !== undefined ||
131
+ direct.letterSpacing !== undefined
127
132
  ? { font: direct }
128
133
  : {};
129
134
  }
@@ -152,7 +152,13 @@ export async function reviewRenderedOfficePages(
152
152
  // The cover/title page is short by design, and a page followed by a deliberate forced break ends where the
153
153
  // author ended it.
154
154
  const endsBeforeForcedBreak = forcedBreaks?.has(metric.page + 1) === true;
155
- if (flowing && metric.page > 1 && !endsBeforeForcedBreak && metric.page < lastPage && metric.bodyEnd < PAGE_BODY_END_MIN) {
155
+ if (
156
+ flowing &&
157
+ metric.page > 1 &&
158
+ !endsBeforeForcedBreak &&
159
+ metric.page < lastPage &&
160
+ metric.bodyEnd < PAGE_BODY_END_MIN
161
+ ) {
156
162
  const empty = Math.round((1 - metric.bodyEnd) * 100);
157
163
  issues.push(
158
164
  issue(
@@ -166,7 +172,8 @@ export async function reviewRenderedOfficePages(
166
172
  continue;
167
173
  }
168
174
  // A short chapter is the author's: the page ends before a forced break, or it is the last page and opens with one.
169
- const deliberateShort = endsBeforeForcedBreak || (forcedBreaks?.has(metric.page) === true && metric.page >= lastPage);
175
+ const deliberateShort =
176
+ endsBeforeForcedBreak || (forcedBreaks?.has(metric.page) === true && metric.page >= lastPage);
170
177
  if (
171
178
  ['docx', 'pdf'].includes(normalized) &&
172
179
  metric.page > 1 &&
@@ -12,7 +12,9 @@ function paragraphSize(paragraph) {
12
12
  }
13
13
 
14
14
  const median = (values) => {
15
- const sorted = values.filter((value) => value !== '' && value !== undefined && value !== null).sort((left, right) => (left < right ? -1 : left > right ? 1 : 0));
15
+ const sorted = values
16
+ .filter((value) => value !== '' && value !== undefined && value !== null)
17
+ .sort((left, right) => (left < right ? -1 : left > right ? 1 : 0));
16
18
  return sorted.length ? sorted[Math.floor(sorted.length / 2)] : undefined;
17
19
  };
18
20
  // Automatic colour is the effective default, black.
@@ -12,11 +12,7 @@ import {
12
12
  saturatedHueFamilies,
13
13
  } from '../design/design-discipline.mjs';
14
14
  import { authoredBackgroundLadder, isCardGridSlide, isOrnamentalStripe, slideSize } from './design-review-authored.mjs';
15
- import {
16
- reviewBriefPromises,
17
- reviewFactCoverage,
18
- reviewSourceGrounding,
19
- } from '../authoring/pptx-brief.mjs';
15
+ import { reviewBriefPromises, reviewFactCoverage, reviewSourceGrounding } from '../authoring/pptx-brief.mjs';
20
16
  import { isAdvisoryOfficeIssue } from './quality-pipeline.mjs';
21
17
  import { issue } from './assurance-issue.mjs';
22
18
  import { isPptxSpecimenSlide, isPptxStatementSlide } from './pptx-slide-roles.mjs';
@@ -1,11 +1,7 @@
1
1
  // A Word document or workbook held to its brief, as an authored deck is: every figure its words show has a fact with
2
2
  // a source, and a fact cites where a reader can open it. The brief is the deck's (`design.brief`, key: value lines);
3
3
  // the readings are the deck's own (pptx-brief.mjs), over the document's text instead of its slides.
4
- import {
5
- parseAuthoringBrief,
6
- reviewFactCoverage,
7
- reviewSourceGrounding,
8
- } from '../authoring/pptx-brief.mjs';
4
+ import { parseAuthoringBrief, reviewFactCoverage, reviewSourceGrounding } from '../authoring/pptx-brief.mjs';
9
5
  import { htmlBriefScript } from '../authoring/pptx-html-runner.mjs';
10
6
 
11
7
  /** The brief a docx/xlsx call names in design.brief (the HTML BRIEF's key: value lines), or null. */
@@ -25,9 +25,7 @@ const visibleText = (html) =>
25
25
 
26
26
  // A media query list reaches the printed page unless every query is screen-only.
27
27
  const appliesToPrint = (queries) =>
28
- queries
29
- .split(',')
30
- .some((query) => !/^\s*(?:only\s+)?screen\b/i.test(query) && !/^\s*not\s+print\b/i.test(query));
28
+ queries.split(',').some((query) => !/^\s*(?:only\s+)?screen\b/i.test(query) && !/^\s*not\s+print\b/i.test(query));
31
29
 
32
30
  // Style rules in source order, flattened out of @media blocks that do not apply in print.
33
31
  function cssRules(css, active, rules) {
@@ -38,7 +36,10 @@ function cssRules(css, active, rules) {
38
36
  let depth = 1;
39
37
  let close = open + 1;
40
38
  for (; close < css.length && depth > 0; close += 1) depth += css[close] === '{' ? 1 : css[close] === '}' ? -1 : 0;
41
- const head = css.slice(index, open).replace(/^(?:\s*@[^{;]*;)+/, '').trim();
39
+ const head = css
40
+ .slice(index, open)
41
+ .replace(/^(?:\s*@[^{;]*;)+/, '')
42
+ .trim();
42
43
  const inner = css.slice(open + 1, close - 1);
43
44
  if (/^@media\b/i.test(head)) cssRules(inner, active && appliesToPrint(head.slice(6)), rules);
44
45
  else if (active && head && !head.startsWith('@')) rules.push({ head, body: inner });
@@ -64,7 +65,8 @@ function breakDeclaration(body, rank) {
64
65
  }
65
66
 
66
67
  const beats = (a, b) => {
67
- for (let index = 0; index < a.rank.length; index += 1) if (a.rank[index] !== b.rank[index]) return a.rank[index] > b.rank[index];
68
+ for (let index = 0; index < a.rank.length; index += 1)
69
+ if (a.rank[index] !== b.rank[index]) return a.rank[index] > b.rank[index];
68
70
  return true;
69
71
  };
70
72
 
@@ -80,7 +82,8 @@ function breakSelectors(html) {
80
82
  const classes = match[3].split('.').filter(Boolean);
81
83
  const specificity = (match[2] ? 100 : 0) + classes.length * 10 + (match[1] ? 1 : 0);
82
84
  const declaration = breakDeclaration(body, [0, specificity, order]);
83
- if (declaration) selectors.push({ tag: (match[1] || '').toLowerCase(), id: match[2] || '', classes, declaration });
85
+ if (declaration)
86
+ selectors.push({ tag: (match[1] || '').toLowerCase(), id: match[2] || '', classes, declaration });
84
87
  }
85
88
  }
86
89
  }
@@ -289,7 +289,7 @@ const POLISH_GUIDANCE = Object.freeze({
289
289
  theme_background_drift:
290
290
  'Use only the ladder backgrounds (paper, paperAlt, dark, darkAlt); recolor the drifting slide.',
291
291
  theme_body_backgrounds:
292
- 'Advisory: body slides use several background colours; keep them to the concept\'s declared palette ladder, or declare the concept or palette in the brief when the colour fields are the design.',
292
+ "Advisory: body slides use several background colours; keep them to the concept's declared palette ladder, or declare the concept or palette in the brief when the colour fields are the design.",
293
293
  excessive_slide_text: "Cut the copy to the reading mode's budget (composition.md §4) or split the slide.",
294
294
  decorative_stripe: 'Remove the ornamental bar; a stripe that encodes nothing is decoration (composition.md §10).',
295
295
  // Visual critique contract (finalize).
@@ -6,9 +6,12 @@
6
6
  *
7
7
  * Rows are append-only: compaction may drop old messages from a session file,
8
8
  * but their search rows stay, so earlier conversation remains findable until
9
- * the session itself is deleted.
9
+ * the session itself is deleted. The one rewrite: a value marked sensitive
10
+ * replaces the rows that hold it (replaceSessionSearchMessages).
10
11
  */
11
12
 
13
+ import { randomBytes } from 'node:crypto';
14
+
12
15
  import { ensurePgInstance, withSchemaBootstrapLock } from '../memory/lib/pg/adapter.mjs';
13
16
  import { buildFtsPrefixQuery } from '../memory/lib/memory-text-utils.mjs';
14
17
  import {
@@ -91,13 +94,9 @@ export function sessionSearchRows(sessionId, messages) {
91
94
  return rows;
92
95
  }
93
96
 
94
- /** Idempotent append of a transcript's searchable messages; returns the count
95
- * of newly stored rows. Re-sending an already stored message is a no-op. */
96
- export async function appendSessionSearchMessages(sessionId, messages, { dataDir } = {}) {
97
- const rows = sessionSearchRows(sessionId, messages);
97
+ async function insertRows(queryable, rows) {
98
98
  if (rows.length === 0) return 0;
99
- const db = await getDb(dataDir);
100
- const result = await db.query(
99
+ const result = await queryable.query(
101
100
  `INSERT INTO session_search.messages (source_ref, session_id, ordinal, role, ts, content)
102
101
  SELECT * FROM unnest($1::text[], $2::text[], $3::int[], $4::text[], $5::bigint[], $6::text[])
103
102
  ON CONFLICT (source_ref) DO NOTHING`,
@@ -113,8 +112,73 @@ export async function appendSessionSearchMessages(sessionId, messages, { dataDir
113
112
  return Number(result?.rowCount) || 0;
114
113
  }
115
114
 
116
- export async function deleteSessionSearchMessages(sessionId, { dataDir } = {}) {
117
- const db = await getDb(dataDir);
115
+ /** Idempotent append of a transcript's searchable messages; returns the count
116
+ * of newly stored rows. Re-sending an already stored message is a no-op. */
117
+ export async function appendSessionSearchMessages(sessionId, messages, { dataDir, signal } = {}) {
118
+ const rows = sessionSearchRows(sessionId, messages);
119
+ if (rows.length === 0) return 0;
120
+ const db = await getDb(dataDir, { signal });
121
+ return insertRows(db, rows);
122
+ }
123
+
124
+ /** In one transaction: every stored row of `sessionId` whose content
125
+ * `redactText` changes is deleted, the rows of the transcript as stored
126
+ * (`redactedMessages`) are written, and a deleted row that is no message of
127
+ * the transcript is written again with its content redacted.
128
+ *
129
+ * A row is matched to its message by the row's own identity
130
+ * (stableSessionSourceRef: role, original timestamp or else ordinal, tool
131
+ * ids, content): the id `plainMessages` — the same transcript before
132
+ * redaction — gives that message. Every other deleted row (its message was
133
+ * compacted away, or is under an identity the transcript no longer has) has
134
+ * no message to derive an identity from; its replacement gets a fresh random
135
+ * id, so no two rows ever merge and no id is derived from the plaintext.
136
+ * Returns the count of deleted rows.
137
+ *
138
+ * FOR UPDATE locks only the rows that exist: a write of the same session still
139
+ * in flight is not seen, so callers must not overlap it with this one
140
+ * (session-search-ingest.mjs runs a session's writes one at a time). */
141
+ export async function replaceSessionSearchMessages(
142
+ sessionId,
143
+ plainMessages,
144
+ redactedMessages,
145
+ redactText,
146
+ { dataDir, signal } = {}
147
+ ) {
148
+ const rows = sessionSearchRows(sessionId, redactedMessages);
149
+ const previous = new Set(sessionSearchRows(sessionId, plainMessages).map((row) => row.sourceRef));
150
+ const db = await getDb(dataDir, { signal });
151
+ return db.transaction(async (tx) => {
152
+ const { rows: stored } = await tx.query(
153
+ `SELECT source_ref, ordinal, role, ts, content FROM session_search.messages
154
+ WHERE session_id = $1 FOR UPDATE`,
155
+ [sessionId]
156
+ );
157
+ const changed = stored
158
+ .map((row) => ({ row, content: redactText(String(row.content)) }))
159
+ .filter(({ row, content }) => content !== row.content);
160
+ if (changed.length) {
161
+ await tx.query(`DELETE FROM session_search.messages WHERE source_ref = ANY($1::text[])`, [
162
+ changed.map(({ row }) => row.source_ref),
163
+ ]);
164
+ }
165
+ const kept = changed
166
+ .filter(({ row }) => !previous.has(row.source_ref))
167
+ .map(({ row, content }) => ({
168
+ sourceRef: `session:${sessionId}:${randomBytes(12).toString('hex')}`,
169
+ sessionId,
170
+ ordinal: Number(row.ordinal),
171
+ role: row.role,
172
+ ts: row.ts == null ? null : Number(row.ts),
173
+ content,
174
+ }));
175
+ await insertRows(tx, [...rows, ...kept]);
176
+ return changed.length;
177
+ });
178
+ }
179
+
180
+ export async function deleteSessionSearchMessages(sessionId, { dataDir, signal } = {}) {
181
+ const db = await getDb(dataDir, { signal });
118
182
  await db.query(`DELETE FROM session_search.messages WHERE session_id = $1`, [sessionId]);
119
183
  await db.query(`DELETE FROM session_search.backfill WHERE session_id = $1`, [sessionId]);
120
184
  }