mixdog 1.4.1 → 1.4.3

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 (630) hide show
  1. package/package.json +4 -3
  2. package/scripts/build-shipped-history.mjs +125 -33
  3. package/scripts/gate-local.mjs +220 -63
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +139 -32
  6. package/scripts/lib/gate-timing-reporter.mjs +16 -0
  7. package/scripts/lib/run-node-tests.mjs +71 -34
  8. package/scripts/lib/scoped-temp.mjs +1 -0
  9. package/scripts/lib/test-failure-records.mjs +14 -1
  10. package/scripts/lib/test-failure-summary.mjs +9 -4
  11. package/scripts/lib/test-spawn-ledger.mjs +43 -3
  12. package/scripts/post-release-check.mjs +26 -16
  13. package/scripts/pptx-kit-index.mjs +5 -6
  14. package/scripts/provider-pingpong-live.mjs +1 -1
  15. package/scripts/prune-embedding-runtime.mjs +3 -1
  16. package/scripts/release-paths.mjs +7 -1
  17. package/scripts/suite-health.mjs +110 -28
  18. package/scripts/test.mjs +9 -14
  19. package/src/agents/advisor/AGENT.md +4 -4
  20. package/src/agents/advisor/agent.json +1 -1
  21. package/src/agents/explore/AGENT.md +22 -0
  22. package/src/agents/explore/agent.json +6 -0
  23. package/src/cli.mjs +7 -0
  24. package/src/defaults/agents.json +7 -0
  25. package/src/defaults/shipped-history.json +38 -2
  26. package/src/defaults/skills/browser-use/SKILL.md +4 -1
  27. package/src/defaults/skills/code-tidy/SKILL.md +71 -102
  28. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
  29. package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
  30. package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
  31. package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
  32. package/src/defaults/skills/computer-use/SKILL.md +12 -2
  33. package/src/defaults/skills/setup/SKILL.md +2 -2
  34. package/src/defaults/skills/setup/references/actions.md +28 -9
  35. package/src/defaults/skills/setup/references/surfaces.md +5 -2
  36. package/src/defaults/skills/setup-guide/SKILL.md +11 -3
  37. package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
  38. package/src/defaults/skills/skill-creator/SKILL.md +85 -190
  39. package/src/defaults/skills/skill-creator/references/design.md +70 -162
  40. package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
  41. package/src/defaults/skills/test-suite/SKILL.md +194 -0
  42. package/src/defaults/skills/test-suite/references/case-management.md +51 -0
  43. package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
  44. package/src/defaults/skills/test-suite/references/reliability.md +49 -0
  45. package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
  46. package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
  47. package/src/defaults/skills/visualize/SKILL.md +6 -2
  48. package/src/lib/instruction-text.cjs +36 -0
  49. package/src/lib/rules-builder.cjs +40 -50
  50. package/src/orchestration/balanced.md +23 -0
  51. package/src/orchestration/focused.md +22 -0
  52. package/src/orchestration/none.md +5 -0
  53. package/src/orchestration/swarm.md +24 -0
  54. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  55. package/src/rules/agent-mode/MIXY.md +2 -2
  56. package/src/rules/lead/LEAD.md +3 -3
  57. package/src/rules/shared/20-research.md +3 -6
  58. package/src/rules/shared/40-editing.md +1 -0
  59. package/src/rules/shared/60-verification.md +10 -9
  60. package/src/rules/shared/70-delivery.md +4 -3
  61. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
  62. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  63. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -2
  64. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +132 -21
  65. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -9
  66. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  67. package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
  68. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  69. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  70. package/src/runtime/agent/orchestrator/config.mjs +12 -7
  71. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +7 -7
  72. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +9 -30
  73. package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
  74. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +124 -12
  75. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +204 -49
  76. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +16 -7
  77. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +157 -57
  78. package/src/runtime/agent/orchestrator/mcp/client.mjs +54 -23
  79. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  80. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  81. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +83 -52
  82. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  83. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  84. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +43 -27
  85. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +43 -8
  86. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +30 -28
  87. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  88. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
  89. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  90. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
  91. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
  92. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
  94. package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
  95. package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
  96. package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
  97. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
  98. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
  99. package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
  101. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +48 -31
  103. package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
  104. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
  105. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
  106. package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
  107. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
  108. package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  110. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  111. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +26 -28
  113. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +3 -1
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +1 -0
  116. package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
  117. package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
  118. package/src/runtime/agent/orchestrator/providers/registry.mjs +33 -2
  119. package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
  120. package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
  121. package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
  122. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +576 -0
  123. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  124. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +32 -0
  125. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  126. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  127. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  128. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  129. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  130. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  131. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  132. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  133. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  134. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  135. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  136. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  137. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  138. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  139. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  140. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -47
  141. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  142. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  143. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  144. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +12 -0
  145. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  146. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +4 -1
  147. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +15 -6
  148. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
  149. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  150. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  151. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
  152. package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
  153. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  154. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +94 -10
  155. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  156. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  157. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  158. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  159. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  160. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  161. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +4 -4
  162. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +11 -6
  163. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +6 -6
  164. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  165. package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +11 -1
  166. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
  167. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  168. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +37 -8
  169. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  170. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  172. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  173. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +5 -3
  174. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  175. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  176. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  177. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  178. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  179. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  180. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  181. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  182. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +27 -3
  183. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +18 -2
  184. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
  185. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
  186. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  187. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  188. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +103 -50
  189. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  190. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  191. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  192. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  193. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  194. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  195. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  196. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  197. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  198. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  199. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  200. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  201. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  202. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  203. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  204. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +20 -0
  205. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -14
  206. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +2 -0
  207. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +12 -0
  208. package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
  209. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  210. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +56 -14
  211. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  212. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +59 -20
  213. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  214. package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
  215. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
  216. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +18 -4
  217. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  218. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  219. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  220. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  221. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  222. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +48 -30
  223. package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
  224. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  225. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  226. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +12 -6
  227. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  228. package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +1 -1
  229. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  230. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  231. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  232. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  233. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  234. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  235. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  236. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  237. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +243 -38
  238. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
  239. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +177 -8
  240. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
  241. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  242. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  243. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  244. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  245. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  246. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  247. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  248. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  249. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
  250. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  251. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  252. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  253. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  254. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +42 -28
  255. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +30 -14
  256. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  257. package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
  258. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  259. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  260. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
  261. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  262. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +95 -20
  263. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
  264. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  265. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  266. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  267. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  268. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  269. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  270. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  271. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  272. package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
  273. package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
  274. package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
  275. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +105 -15
  276. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
  277. package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
  278. package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
  279. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +35 -11
  280. package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +2 -0
  281. package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
  282. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -6
  283. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  284. package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
  285. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  286. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  287. package/src/runtime/attachments/store.d.mts +1 -0
  288. package/src/runtime/attachments/store.mjs +2 -2
  289. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  290. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  291. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  292. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  293. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  294. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  295. package/src/runtime/channels/lib/whisper-port.mjs +19 -10
  296. package/src/runtime/channels/lib/whisper-server.mjs +22 -13
  297. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  298. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  299. package/src/runtime/connectors/connector-accounts-mcp.mjs +372 -103
  300. package/src/runtime/connectors/gmail-app-password.mjs +4 -4
  301. package/src/runtime/connectors/google-mcp.mjs +1 -1
  302. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  303. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  304. package/src/runtime/explore/explorer.mjs +88 -0
  305. package/src/runtime/explore/tool-defs.mjs +35 -0
  306. package/src/runtime/explore/tool.mjs +123 -0
  307. package/src/runtime/local-provider/hardware.mjs +1 -1
  308. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  309. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  310. package/src/runtime/media/media-usage.mjs +1 -1
  311. package/src/runtime/media/store.mjs +1 -1
  312. package/src/runtime/memory/index.mjs +15 -1
  313. package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
  314. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  315. package/src/runtime/memory/lib/embedding-worker.mjs +4 -0
  316. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  317. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  318. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  319. package/src/runtime/memory/lib/memory.mjs +17 -0
  320. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  321. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  322. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  323. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  324. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  325. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  326. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  327. package/src/runtime/office/capabilities.mjs +1 -1
  328. package/src/runtime/office/core/office-core.mjs +1 -1
  329. package/src/runtime/office/design/content-model.mjs +3 -3
  330. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  331. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  332. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  333. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  334. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  335. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  336. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  337. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  338. package/src/runtime/office/quality/assurance-structure-docx.mjs +1 -1
  339. package/src/runtime/shared/agent-route-config.mjs +17 -2
  340. package/src/runtime/shared/atomic-file.d.mts +8 -0
  341. package/src/runtime/shared/atomic-file.mjs +103 -2
  342. package/src/runtime/shared/background-tasks.mjs +37 -10
  343. package/src/runtime/shared/background-wait.mjs +66 -0
  344. package/src/runtime/shared/child-guardian.mjs +17 -7
  345. package/src/runtime/shared/config.mjs +313 -16
  346. package/src/runtime/shared/connector-accounts.mjs +5 -5
  347. package/src/runtime/shared/connector-catalog.d.mts +14 -8
  348. package/src/runtime/shared/connector-catalog.mjs +70 -52
  349. package/src/runtime/shared/custom-provider-keys.mjs +20 -0
  350. package/src/runtime/shared/file-has-data.mjs +26 -2
  351. package/src/runtime/shared/file-lock.mjs +21 -18
  352. package/src/runtime/shared/git-launch.d.mts +9 -0
  353. package/src/runtime/shared/git-launch.mjs +213 -0
  354. package/src/runtime/shared/git-runner-worker.mjs +2 -1
  355. package/src/runtime/shared/git-runner.mjs +7 -2
  356. package/src/runtime/shared/idle-gc.mjs +30 -7
  357. package/src/runtime/shared/llm/cost.mjs +6 -1
  358. package/src/runtime/shared/llm/http-agent.mjs +316 -29
  359. package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
  360. package/src/runtime/shared/llm/model-catalog.mjs +46 -6
  361. package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
  362. package/src/runtime/shared/llm/system-proxy.mjs +453 -0
  363. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  364. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  365. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  366. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  367. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  368. package/src/runtime/shared/process-runner.mjs +8 -4
  369. package/src/runtime/shared/provider-accounts.mjs +52 -2
  370. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  371. package/src/runtime/shared/routine-trigger.mjs +34 -0
  372. package/src/runtime/shared/run-child.d.mts +2 -1
  373. package/src/runtime/shared/run-child.mjs +70 -18
  374. package/src/runtime/shared/session-scratch.mjs +14 -2
  375. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  376. package/src/runtime/shared/staged-install-worker.mjs +5 -0
  377. package/src/runtime/shared/staged-update.mjs +47 -2
  378. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  379. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  380. package/src/runtime/shared/tool-surface.mjs +110 -36
  381. package/src/runtime/shared/tool-work-units.mjs +35 -6
  382. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  383. package/src/runtime/shared/turn-worktree-snapshot.mjs +409 -54
  384. package/src/runtime/shared/worker-requests.mjs +17 -3
  385. package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
  386. package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
  387. package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
  388. package/src/runtime/shared/worktrees/branch-management.mjs +5 -3
  389. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  390. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  391. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  392. package/src/runtime/shared/worktrees/git.mjs +97 -7
  393. package/src/runtime/shared/worktrees/include.mjs +6 -4
  394. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  395. package/src/runtime/shared/worktrees/manager.mjs +962 -197
  396. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  397. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  398. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  399. package/src/runtime/tidy/install.mjs +95 -15
  400. package/src/runtime/tidy/languages.mjs +17 -15
  401. package/src/runtime/tidy/process.mjs +9 -5
  402. package/src/runtime/tidy/resolve.mjs +19 -16
  403. package/src/runtime/tidy/runners/biome.mjs +3 -3
  404. package/src/runtime/tidy/tool.mjs +1 -1
  405. package/src/runtime/tidy/worktree.mjs +10 -6
  406. package/src/runtime/visualize-bridge/client.mjs +4 -1
  407. package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
  408. package/src/runtime/web-search/index.mjs +4 -23
  409. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  410. package/src/runtime/web-search/tool-defs.mjs +17 -26
  411. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  412. package/src/session-runtime/agent-task-sessions.mjs +410 -353
  413. package/src/session-runtime/boot/apis.mjs +27 -4
  414. package/src/session-runtime/boot/begin.mjs +2 -0
  415. package/src/session-runtime/boot/config.mjs +10 -1
  416. package/src/session-runtime/boot/facade.mjs +1 -0
  417. package/src/session-runtime/boot/providers.mjs +70 -3
  418. package/src/session-runtime/boot/session.mjs +2 -0
  419. package/src/session-runtime/boot/tools.mjs +71 -25
  420. package/src/session-runtime/bot-status.mjs +103 -103
  421. package/src/session-runtime/channel-config-api.mjs +1 -0
  422. package/src/session-runtime/config-change-effects.mjs +179 -0
  423. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  424. package/src/session-runtime/config-lifecycle.mjs +160 -24
  425. package/src/session-runtime/connector-merge-migration.mjs +18 -15
  426. package/src/session-runtime/conversation-import/discovery.mjs +245 -47
  427. package/src/session-runtime/conversation-import/service.mjs +12 -5
  428. package/src/session-runtime/goal-facade-api.mjs +49 -3
  429. package/src/session-runtime/handoff-attachments.mjs +1 -1
  430. package/src/session-runtime/held-requests.mjs +3 -1
  431. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  432. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  433. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -11
  434. package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
  435. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +161 -120
  436. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  437. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  438. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  439. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  440. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  441. package/src/session-runtime/lifecycle/teardown/session-close.mjs +10 -5
  442. package/src/session-runtime/lifecycle/teardown.mjs +1 -1
  443. package/src/session-runtime/lifecycle-api.mjs +1 -0
  444. package/src/session-runtime/mcp-glue/server-catalog.mjs +27 -10
  445. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  446. package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
  447. package/src/session-runtime/mixy-heartbeat.mjs +1 -1
  448. package/src/session-runtime/model-route/set-route.mjs +40 -7
  449. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  450. package/src/session-runtime/provider-auth/login.mjs +2 -2
  451. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  452. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  453. package/src/session-runtime/provider-readiness.mjs +53 -4
  454. package/src/session-runtime/resource-api.mjs +1 -1
  455. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  456. package/src/session-runtime/resource-mcp-api.mjs +98 -35
  457. package/src/session-runtime/resource-mcp-connector-accounts.mjs +49 -32
  458. package/src/session-runtime/resource-mcp-secrets.mjs +27 -10
  459. package/src/session-runtime/resource-mcp-servers.mjs +5 -4
  460. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  461. package/src/session-runtime/routine-executor.mjs +152 -0
  462. package/src/session-runtime/routine-home-turn.mjs +46 -5
  463. package/src/session-runtime/runtime-facade.mjs +5 -0
  464. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  465. package/src/session-runtime/schedule-session-run.mjs +1 -0
  466. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  467. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  468. package/src/session-runtime/services/agent-tool/send-flow.mjs +120 -8
  469. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  470. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  471. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
  472. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +28 -7
  473. package/src/session-runtime/services/agent-tool.mjs +51 -1
  474. package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
  475. package/src/session-runtime/services/channel-admin.mjs +18 -0
  476. package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
  477. package/src/session-runtime/services/daemon-candidate.mjs +4 -1
  478. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  479. package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
  480. package/src/session-runtime/services/plugin-admin.mjs +14 -6
  481. package/src/session-runtime/services/provider-admin.mjs +281 -10
  482. package/src/session-runtime/services/seeds.mjs +7 -0
  483. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  484. package/src/session-runtime/session-create/materialize.mjs +4 -2
  485. package/src/session-runtime/session-create/session-options.mjs +2 -0
  486. package/src/session-runtime/session-turn-api.mjs +2 -0
  487. package/src/session-runtime/settings-builtin-tools-api.mjs +5 -10
  488. package/src/session-runtime/settings-system-api.mjs +1 -1
  489. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
  490. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
  491. package/src/session-runtime/setup-tool/executor.mjs +14 -3
  492. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  493. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  494. package/src/session-runtime/setup-tool/tool-defs.mjs +28 -2
  495. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  496. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  497. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  498. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  499. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  500. package/src/session-runtime/tool-surface.mjs +38 -1
  501. package/src/session-runtime/turn/agent-ops.mjs +33 -2
  502. package/src/session-runtime/turn/session-ops.mjs +2 -0
  503. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  504. package/src/session-runtime/turn/turn-run.mjs +1 -1
  505. package/src/session-runtime/webhook-session-run.mjs +2 -0
  506. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +46 -11
  507. package/src/session-runtime/workflow-agents-api/agent-route.mjs +2 -0
  508. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  509. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  510. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  511. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  512. package/src/session-runtime/workspace/activity-guards.mjs +176 -0
  513. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  514. package/src/session-runtime/workspace/session-view.mjs +149 -0
  515. package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
  516. package/src/session-runtime/workspace/transition-runner.mjs +188 -0
  517. package/src/session-runtime/workspace/transitions.mjs +128 -1070
  518. package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
  519. package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
  520. package/src/session-runtime/workspace/worktree-maintenance.mjs +200 -0
  521. package/src/session-runtime/workspace/worktree-setup.mjs +97 -0
  522. package/src/session-runtime/workspace/worktree-tool.mjs +70 -54
  523. package/src/standalone/daemon-agent-control.mjs +25 -8
  524. package/src/standalone/daemon-desktop-runtime.mjs +8 -2
  525. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  526. package/src/standalone/daemon-session-control.mjs +151 -136
  527. package/src/standalone/daemon.mjs +61 -2
  528. package/src/standalone/desktop-service-registry.mjs +9 -0
  529. package/src/standalone/local-session-runtime.mjs +21 -1
  530. package/src/standalone/session-client/daemon-unavailable.mjs +4 -1
  531. package/src/standalone/session-client.mjs +5 -1
  532. package/src/standalone/session-frame-stream.mjs +83 -11
  533. package/src/standalone/session-protocol.mjs +15 -0
  534. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  535. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  536. package/src/standalone/session-service/agent-tree.mjs +45 -9
  537. package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
  538. package/src/standalone/session-service/quota-resume.mjs +9 -0
  539. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  540. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  541. package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
  542. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  543. package/src/standalone/session-service/session-calls.mjs +2 -1
  544. package/src/standalone/session-service/stored-reader.mjs +127 -40
  545. package/src/tui/App.jsx +162 -164
  546. package/src/tui/app/app-view/floating-panel.jsx +3 -0
  547. package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
  548. package/src/tui/app/clipboard.mjs +22 -11
  549. package/src/tui/app/create-app-pickers.mjs +2 -0
  550. package/src/tui/app/doctor.mjs +2 -2
  551. package/src/tui/app/panel-signature.mjs +1 -1
  552. package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
  553. package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
  554. package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
  555. package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
  556. package/src/tui/app/provider-setup/oauth-actions.mjs +25 -6
  557. package/src/tui/app/provider-setup-picker.mjs +20 -13
  558. package/src/tui/app/settings-picker.mjs +53 -8
  559. package/src/tui/app/shell-layout/row-budgets.mjs +14 -12
  560. package/src/tui/app/slash-commands.mjs +2 -1
  561. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  562. package/src/tui/app/slash-dispatch/session-commands.mjs +47 -1
  563. package/src/tui/app/slash-dispatch.mjs +1 -1
  564. package/src/tui/app/use-btw-panel.mjs +29 -0
  565. package/src/tui/app/use-context-panel-refresh.mjs +31 -0
  566. package/src/tui/app/use-model-catalog-cache.mjs +13 -10
  567. package/src/tui/app/use-mouse-input.mjs +11 -0
  568. package/src/tui/app/use-onboarding-start.mjs +8 -3
  569. package/src/tui/app/use-panel-transition.mjs +10 -1
  570. package/src/tui/app/use-pasted-buffers.mjs +28 -20
  571. package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
  572. package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
  573. package/src/tui/app/use-prompt-queue-history.mjs +5 -4
  574. package/src/tui/app/use-selection-focus.mjs +11 -2
  575. package/src/tui/app/use-selection-geometry.mjs +18 -9
  576. package/src/tui/app/use-selection-paint.mjs +4 -4
  577. package/src/tui/app/use-selection-stitch.mjs +3 -3
  578. package/src/tui/app/use-slash-palette.mjs +62 -0
  579. package/src/tui/app/use-terminal-chrome.mjs +2 -2
  580. package/src/tui/app/use-transcript-activity.mjs +48 -33
  581. package/src/tui/app/use-transcript-follow.mjs +12 -4
  582. package/src/tui/app/use-transcript-scroll.mjs +46 -17
  583. package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
  584. package/src/tui/app/use-transcript-window/geometry.mjs +20 -6
  585. package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
  586. package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
  587. package/src/tui/app/use-transcript-window.mjs +21 -11
  588. package/src/tui/app/use-tui-ready.mjs +18 -0
  589. package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
  590. package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
  591. package/src/tui/components/Picker.jsx +27 -3
  592. package/src/tui/components/SignInUrl.jsx +68 -0
  593. package/src/tui/components/TextEntryPanel.jsx +76 -46
  594. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  595. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  596. package/src/tui/components/question-panel-model.mjs +4 -4
  597. package/src/tui/components/sign-in-url-layout.mjs +24 -0
  598. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  599. package/src/tui/components/user-message-skills.mjs +1 -1
  600. package/src/tui/dist/index.mjs +2205 -1371
  601. package/src/tui/markdown/render-ansi.mjs +1 -1
  602. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  603. package/src/tui/session/agent-job-feed.mjs +2 -0
  604. package/src/tui/session/context-state.mjs +3 -0
  605. package/src/tui/session/goal-turn-state.mjs +6 -2
  606. package/src/tui/session/quota-resume.mjs +1 -1
  607. package/src/tui/session/session-api/controls.mjs +4 -0
  608. package/src/tui/session/session-api/extensions.mjs +8 -0
  609. package/src/tui/session/session-api/intake/abort.mjs +2 -1
  610. package/src/tui/session/session-api/intake.mjs +2 -0
  611. package/src/tui/session/session-api/integrations.mjs +2 -2
  612. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  613. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  614. package/src/tui/session/session-api/routes-agent-definitions.mjs +6 -0
  615. package/src/tui/session/session-api/settings.mjs +2 -2
  616. package/src/tui/session/session-api/worktree.mjs +13 -1
  617. package/src/tui/session/session-flow/drain.mjs +11 -14
  618. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  619. package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
  620. package/src/tui/session/transcript-spill.mjs +92 -4
  621. package/src/tui/session/transcript-store.mjs +2 -0
  622. package/src/tui/session/turn-quiet.mjs +1 -1
  623. package/src/tui/session/turn.mjs +3 -0
  624. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  625. package/src/tui/spinner-meta.mjs +3 -3
  626. package/src/tui/spinner-verbs.mjs +2 -2
  627. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  628. package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
  629. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  630. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -1,7 +1,11 @@
1
1
  // Process lock for the standalone memory MCP entry.
2
2
  // A direct entry (including the isolated daemon child) owns this lock.
3
3
  import fs from 'node:fs';
4
- import { execFileSync } from 'node:child_process';
4
+ import { spawnSync } from 'node:child_process';
5
+ import { killProcessTreesSync } from '../../agent/orchestrator/mcp/child-tree.mjs';
6
+
7
+ // Windows: the tree kill's whole pass (a table read under load included).
8
+ const PREVIOUS_SERVER_KILL_TIMEOUT_MS = 10_000;
5
9
 
6
10
  export function parsePositivePid(value) {
7
11
  const pid = Number(value);
@@ -18,42 +22,158 @@ export function isPidAliveLocal(pid) {
18
22
  }
19
23
  }
20
24
 
21
- function killPreviousServer(pid, log = () => {}) {
25
+ const POSIX_ENV = () => ({ ...process.env, LC_ALL: 'C', LANG: 'C' });
26
+
27
+ // When a process was created, as epoch-ms bounds { low, high } around the true
28
+ // time, or null when it cannot be read. Linux: /proc/<pid>/stat starttime
29
+ // (clock ticks since boot) against /proc/uptime, both read at `now`; the
30
+ // margin covers one tick, uptime's centiseconds and the read skew.
31
+ export function linuxCreatedBounds(statText, uptimeText, clockTicks, now) {
32
+ const ticks = linuxStartTicks(statText);
33
+ const startTicks = Number(ticks);
34
+ const uptime = Number(String(uptimeText || '').split(' ')[0]);
35
+ if (ticks === null || !Number.isFinite(uptime) || !(clockTicks > 0)) return null;
36
+ const created = now - (uptime - startTicks / clockTicks) * 1000;
37
+ const margin = 1000 / clockTicks + 20;
38
+ return { low: created - margin, high: created + margin };
39
+ }
40
+
41
+ // Elsewhere: `ps -o lstart=` under the C locale, whole seconds.
42
+ export function lstartCreatedBounds(text) {
43
+ const started = Date.parse(String(text || '').trim());
44
+ return Number.isFinite(started) ? { low: started, high: started + 1000 } : null;
45
+ }
46
+
47
+ // /proc/<pid>/stat's starttime field (clock ticks since boot), as its digits.
48
+ function linuxStartTicks(statText) {
49
+ const stat = String(statText || '');
50
+ if (!stat.includes(')')) return null;
51
+ const ticks = stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19];
52
+ return /^\d+$/.test(ticks || '') ? ticks : null;
53
+ }
54
+
55
+ /** A process's start token, as recorded in the lock and compared on
56
+ * recovery, or null when it cannot be read: Linux `/proc/<pid>/stat`
57
+ * starttime, elsewhere `ps -o lstart=` under the C locale. The two sources
58
+ * never mix (each is prefixed), and both are read from the same host. */
59
+ export function linuxStartToken(statText) {
60
+ const ticks = linuxStartTicks(statText);
61
+ return ticks ? `proc:${ticks}` : null;
62
+ }
63
+ export function lstartStartToken(text) {
64
+ const started = String(text || '').trim();
65
+ return Number.isFinite(Date.parse(started)) ? `lstart:${started}` : null;
66
+ }
67
+
68
+ function posixStartToken(pid) {
69
+ try {
70
+ if (process.platform === 'linux') return linuxStartToken(fs.readFileSync(`/proc/${pid}/stat`, 'utf8'));
71
+ const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], {
72
+ encoding: 'utf8',
73
+ env: POSIX_ENV(),
74
+ timeout: 5000,
75
+ });
76
+ return lstartStartToken(r.stdout);
77
+ } catch {
78
+ return null;
79
+ }
80
+ }
81
+
82
+ function posixCreatedBounds(pid) {
83
+ const env = POSIX_ENV();
84
+ try {
85
+ if (process.platform === 'linux') {
86
+ const ticks = Number(spawnSync('getconf', ['CLK_TCK'], { encoding: 'utf8', env, timeout: 5000 }).stdout);
87
+ const now = Date.now();
88
+ return linuxCreatedBounds(
89
+ fs.readFileSync(`/proc/${pid}/stat`, 'utf8'),
90
+ fs.readFileSync('/proc/uptime', 'utf8'),
91
+ ticks,
92
+ now
93
+ );
94
+ }
95
+ const r = spawnSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', env, timeout: 5000 });
96
+ return lstartCreatedBounds(r.stdout);
97
+ } catch {
98
+ return null;
99
+ }
100
+ }
101
+
102
+ /** Who holds a lock's pid, from the start token the writer recorded and the
103
+ * pid's current one: 'writer' (the same token: the server that wrote the
104
+ * lock), 'other' (a different one: the writer is gone and its pid reused) or
105
+ * 'unproven' (the current token cannot be read). */
106
+ export function lockHolderTokenVerdict(recordedToken, currentToken) {
107
+ if (!currentToken) return 'unproven';
108
+ return currentToken === recordedToken ? 'writer' : 'other';
109
+ }
110
+
111
+ /** The legacy verdict, for a lock written without a start token: from the
112
+ * holder's creation bounds, 'writer' (created before the lock was written),
113
+ * 'other' (created after) or 'unproven' (unreadable, or too close to the
114
+ * write to tell). Only 'writer' may be signalled, and only 'other' or a dead
115
+ * pid lets the lock be recovered. */
116
+ export function lockHolderVerdict(bounds, lockWrittenAt) {
117
+ if (!bounds) return 'unproven';
118
+ if (bounds.high <= lockWrittenAt) return 'writer';
119
+ if (bounds.low > lockWrittenAt) return 'other';
120
+ return 'unproven';
121
+ }
122
+
123
+ /** The lock's text: the writer's pid, then (POSIX) its start token on the
124
+ * next line. */
125
+ export function formatLock(pid, token) {
126
+ return token ? `${pid}\n${token}` : String(pid);
127
+ }
128
+ export function parseLock(text) {
129
+ const [pidLine = '', token = ''] = String(text || '').split(/\r?\n/);
130
+ return { pid: Number(pidLine.trim()), token: token.trim() || null };
131
+ }
132
+
133
+ // The lock names its writer only while that writer lives. A POSIX writer
134
+ // recorded its start token; the pid's holder is the writer exactly when its
135
+ // token is still the same. Accepted: lstart has whole seconds, so a writer
136
+ // that died within its first second, its pid reused in that same second,
137
+ // would pass as the writer; sequential pid allocation makes that impractical,
138
+ // and treating same-second tokens as unproven would block every restart.
139
+ // Windows compares the holder's creation time against
140
+ // the lock's write time inside the shared tree kill: its creation times are
141
+ // sub-millisecond, and a pid is only reused after the writer died, after the
142
+ // write. A lock without a token (an older writer) keeps the creation-bounds
143
+ // verdict. A pid taken over since is never signalled; one whose identity
144
+ // cannot be proven is neither signalled nor evicted (fail closed).
145
+ function killPreviousServer(pid, recordedToken, lockWrittenAt, log = () => {}) {
22
146
  if (pid <= 0 || pid === process.pid) return false;
23
147
  if (process.platform === 'win32') {
24
- try {
25
- execFileSync('taskkill', ['/F', '/T', '/PID', String(pid)], {
26
- encoding: 'utf8',
27
- timeout: 5000,
28
- windowsHide: true,
29
- });
148
+ const status = killProcessTreesSync([pid], {
149
+ aliveAt: lockWrittenAt,
150
+ timeoutMs: PREVIOUS_SERVER_KILL_TIMEOUT_MS,
151
+ });
152
+ if (status === 0) {
30
153
  log(`[memory-service] Killed previous server PID ${pid}\n`);
31
154
  return true;
32
- } catch (e) {
33
- // Exit code 128 = process not found; treat stale lock as already-dead = success.
34
- // Status 128 reliably means "process not found" regardless of locale; no text match needed.
35
- // Status 1 with English text match handles edge cases on some Windows versions.
36
- const notFoundText =
37
- /not found|no running instance/i.test(e.stdout || '') ||
38
- /not found|no running instance/i.test(e.stderr || '') ||
39
- /not found|no running instance/i.test(e.message || '');
40
- const alreadyDead = e.status === 128 || (e.status === 1 && notFoundText);
41
- if (alreadyDead) {
42
- log(`[memory-service] PID ${pid} already dead (stale lock), proceeding\n`);
43
- return true;
44
- }
45
- log(`[memory-service] taskkill failed for PID ${pid}: ${e.message}\n`);
46
- return false;
47
155
  }
156
+ if (status === 128) {
157
+ log(`[memory-service] PID ${pid} is not the lock's writer any more (stale lock), proceeding\n`);
158
+ return true;
159
+ }
160
+ log(`[memory-service] Killing previous server PID ${pid} failed (status ${status})\n`);
161
+ return false;
48
162
  } else {
49
- // Pre-flight: if the process is already gone, treat stale lock as success.
50
- try {
51
- process.kill(pid, 0);
52
- } catch (e) {
53
- if (e.code === 'ESRCH') {
54
- log(`[memory-service] PID ${pid} already dead (stale lock), proceeding\n`);
55
- return true;
56
- }
163
+ const verdict = !isPidAliveLocal(pid)
164
+ ? 'gone'
165
+ : recordedToken
166
+ ? lockHolderTokenVerdict(recordedToken, posixStartToken(pid))
167
+ : lockHolderVerdict(posixCreatedBounds(pid), lockWrittenAt);
168
+ if (verdict === 'gone' || verdict === 'other' || (verdict === 'unproven' && !isPidAliveLocal(pid))) {
169
+ log(`[memory-service] PID ${pid} is not the lock's writer any more (stale lock), proceeding\n`);
170
+ return true;
171
+ }
172
+ if (verdict === 'unproven') {
173
+ log(
174
+ `[memory-service] PID ${pid} may still be the lock's writer and cannot be proven otherwise; leaving it running\n`
175
+ );
176
+ return false;
57
177
  }
58
178
  try {
59
179
  process.kill(pid, 'SIGTERM');
@@ -86,9 +206,10 @@ export function acquireLock(lockFile, log = () => {}) {
86
206
  if (process.env.MIXDOG_MULTI_INSTANCE === '1') return;
87
207
  try {
88
208
  if (fs.existsSync(lockFile)) {
89
- const lockedPid = Number(fs.readFileSync(lockFile, 'utf8').trim());
209
+ const lockWrittenAt = fs.statSync(lockFile).mtimeMs;
210
+ const { pid: lockedPid, token } = parseLock(fs.readFileSync(lockFile, 'utf8'));
90
211
  if (lockedPid > 0 && lockedPid !== process.pid) {
91
- const killed = killPreviousServer(lockedPid, log);
212
+ const killed = killPreviousServer(lockedPid, token, lockWrittenAt, log);
92
213
  if (!killed) {
93
214
  log(`[memory-service] Could not kill previous server PID ${lockedPid}, aborting\n`);
94
215
  process.exit(1);
@@ -98,9 +219,12 @@ export function acquireLock(lockFile, log = () => {}) {
98
219
  } catch {}
99
220
  }
100
221
  }
222
+ // Read before the lock exists: an unreadable token leaves a pid-only lock,
223
+ // which a successor judges by the legacy verdict.
224
+ const token = process.platform === 'win32' ? null : posixStartToken(process.pid);
101
225
  const fd = fs.openSync(lockFile, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL, 0o600);
102
226
  try {
103
- fs.writeSync(fd, String(process.pid));
227
+ fs.writeSync(fd, formatLock(process.pid, token));
104
228
  } finally {
105
229
  fs.closeSync(fd);
106
230
  }
@@ -116,7 +240,6 @@ export function acquireLock(lockFile, log = () => {}) {
116
240
 
117
241
  export function releaseLock(lockFile) {
118
242
  try {
119
- const content = fs.readFileSync(lockFile, 'utf8').trim();
120
- if (Number(content) === process.pid) fs.unlinkSync(lockFile);
243
+ if (parseLock(fs.readFileSync(lockFile, 'utf8')).pid === process.pid) fs.unlinkSync(lockFile);
121
244
  } catch {}
122
245
  }
@@ -130,7 +130,12 @@ export function mergeRecallConceptTokens(text, conceptTokens, limit = 24) {
130
130
  const entityConcepts = concepts.filter(isEntityConcept);
131
131
  const rankingEntityConcepts = entityConcepts.filter((token) => !isStructuralTimeToken(token));
132
132
  const useEntityConcepts = rankingEntityConcepts.some(isIdentifierToken) || rankingEntityConcepts.length > 2;
133
- const rankingConcepts = useEntityConcepts ? entityConcepts : concepts;
133
+ // Entity-heavy queries rank their entities first, but the Korean content
134
+ // words stay: dropping them left a mixed query ("웹 검색 원인 Claude Codex
135
+ // Hermes 비교") matching only on product names that half the history shares.
136
+ const rankingConcepts = useEntityConcepts
137
+ ? [...entityConcepts, ...concepts.filter((token) => !isEntityConcept(token))]
138
+ : concepts;
134
139
  const source =
135
140
  concepts.length > 0
136
141
  ? [...raw.filter((token) => isIdentifierToken(token) || isConceptCompound(token, concepts)), ...rankingConcepts]
@@ -309,6 +309,22 @@ async function removeReviewAndPromotionCycleState(db) {
309
309
  }
310
310
  }
311
311
 
312
+ // Root vectors now cover the chunk's first message as well as its summary
313
+ // (memory-embed.mjs rootEmbedText). Vectors written under the older text stay
314
+ // in place and are replaced by a paced background sweep (sweepRootEmbedText)
315
+ // that walks roots below this starting cursor, newest first. One statement, so
316
+ // the start is atomic; ON CONFLICT keeps an existing sweep's progress.
317
+ export const ROOT_EMBED_SWEEP_META_KEY = 'embedding.root_text_v2';
318
+ export async function startRootEmbedSweep(db) {
319
+ await db.query(
320
+ `INSERT INTO meta(key, value)
321
+ SELECT $1, jsonb_build_object('cursor', COALESCE(MAX(id), 0) + 1, 'done', false)
322
+ FROM entries WHERE is_root = 1
323
+ ON CONFLICT (key) DO NOTHING`,
324
+ [ROOT_EMBED_SWEEP_META_KEY]
325
+ );
326
+ }
327
+
312
328
  export async function ensureCurrentSchemaExtensions(db, dims, embeddingIdentity = null) {
313
329
  await removeAttachmentPlaceholderRows(db);
314
330
  await removeRuntimeNotificationRowsOnce(db);
@@ -413,6 +429,7 @@ export async function openDatabase(dataDir, dims, embeddingIdentity = null) {
413
429
  }
414
430
  await ensureCurrentSchemaExtensions(db, Number(dims), embeddingIdentity);
415
431
  await validateEmbeddingDims(db, Number(dims));
432
+ await withSchemaBootstrapLock(pool, () => startRootEmbedSweep(db));
416
433
 
417
434
  dbs.set(key, db);
418
435
  return db;
@@ -400,7 +400,7 @@ async function startAndWaitReady({ pgctl, startArgs, env, pgdataDir, port }) {
400
400
  // so the postmaster is already reparented OUT of the Node process tree —
401
401
  // detached only isolated the short-lived pg_ctl. Shutdown/reuse target
402
402
  // pgdata/postmaster.pid (pg_ctl stop -D, tryReusePgInstance), not a
403
- // Node-tree taskkill, so `windowsHide` alone is correct on all platforms.
403
+ // Node-tree kill, so `windowsHide` alone is correct on all platforms.
404
404
  const child = spawn(pgctl, startArgs, { env, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
405
405
  child.unref?.();
406
406
  const run = { stdout: '', stderr: '', closed: false, exitCode: null };
@@ -20,7 +20,7 @@ import { __mixdogMemoryLog } from '../memory-log.mjs';
20
20
  */
21
21
 
22
22
  import { createServer } from 'node:net';
23
- import { existsSync, unlinkSync, readFileSync, writeFileSync, renameSync, statSync, mkdirSync } from 'node:fs';
23
+ import { existsSync, unlinkSync, readFileSync, renameSync, statSync, mkdirSync } from 'node:fs';
24
24
  import { join, resolve } from 'node:path';
25
25
  import {
26
26
  discoveryPath as _pgDiscoveryPath,
@@ -28,6 +28,7 @@ import {
28
28
  writeServiceAdvert as _writePgServiceAdvert,
29
29
  } from '../../../shared/service-discovery.mjs';
30
30
  import { withFileLockSync } from '../../../shared/atomic-file.mjs';
31
+ import { withFileLock } from '../../../shared/file-lock.mjs';
31
32
  import { isPidAlive } from '../../../shared/pid-liveness.mjs';
32
33
  import { envFlag } from '../../../shared/env.mjs';
33
34
  import { createSharedAbortable } from '../../../shared/abort-race.mjs';
@@ -64,92 +65,11 @@ let _ownedExitStopInstalled = false;
64
65
  const PG_PORT_MIN = 55432;
65
66
  const PG_PORT_MAX = 55632;
66
67
  const PG_LOG_MAX_BYTES = 10 * 1024 * 1024; // 10 MB
67
- const SPAWN_LOCK_NAME = 'pg-spawn.lock';
68
- const LOCK_WAIT_MS = 30_000;
69
- const LOCK_POLL_MS = 100;
70
- const LOCK_WARN_MS = 5_000;
71
- const LOCK_WAIT_CODES = new Set(['EEXIST', 'EPERM', 'EACCES', 'EBUSY']);
72
68
 
73
69
  function attachOnlyMode() {
74
70
  return envFlag('MIXDOG_PG_ATTACH_ONLY') || envFlag('MIXDOG_MEMORY_SECONDARY');
75
71
  }
76
72
 
77
- // ── File lock (O_EXCL pattern from dispatch-persist.mjs / run-mcp.mjs) ───────
78
-
79
- /**
80
- * Acquire `${dataDir}/pg-spawn.lock`.
81
- * Returns the lock-file path on success, or null on timeout (caller proceeds
82
- * best-effort — worst case: two supervisors race initdb on the same pgdata,
83
- * but the second will fail pg_ctl start gracefully and healthcheck will
84
- * converge on the first's port).
85
- */
86
- async function acquireSpawnLock(dataDir, blockedProbe = null) {
87
- const lp = join(dataDir, SPAWN_LOCK_NAME);
88
- const deadline = Date.now() + LOCK_WAIT_MS;
89
- const body = JSON.stringify({ pid: process.pid, startedAt: Date.now() });
90
- let warned = false;
91
- for (;;) {
92
- try {
93
- // 'wx' = O_CREAT | O_EXCL — atomic, fails with EEXIST if held.
94
- writeFileSync(lp, body, { flag: 'wx' });
95
- return { lockPath: lp, reuse: null };
96
- } catch (err) {
97
- if (!LOCK_WAIT_CODES.has(err?.code)) {
98
- __mixdogMemoryLog(`[supervisor-pg] spawn lock error: ${err?.code || err?.message}\n`);
99
- return { lockPath: null, reuse: null };
100
- }
101
- if (blockedProbe) {
102
- try {
103
- const reuse = await blockedProbe();
104
- if (reuse) return { lockPath: null, reuse };
105
- } catch {}
106
- }
107
- // Dead-holder detection: same as run-mcp.mjs acquireLock().
108
- try {
109
- const holder = JSON.parse(readFileSync(lp, 'utf8'));
110
- if (holder?.pid) {
111
- try {
112
- process.kill(holder.pid, 0);
113
- } catch (ke) {
114
- if (ke.code === 'ESRCH') {
115
- try {
116
- unlinkSync(lp);
117
- } catch {}
118
- continue; // retry immediately after removing stale lock
119
- }
120
- }
121
- }
122
- const ageMs = Date.now() - Number(holder?.startedAt || 0);
123
- if (!warned && ageMs >= LOCK_WARN_MS) {
124
- warned = true;
125
- __mixdogMemoryLog(
126
- `[supervisor-pg] waiting for spawn lock holder pid=${holder?.pid || 'unknown'} ageMs=${ageMs}\n`
127
- );
128
- }
129
- } catch {
130
- /* unreadable — fall through and wait */
131
- }
132
- if (Date.now() >= deadline) {
133
- if (blockedProbe) {
134
- try {
135
- const reuse = await blockedProbe();
136
- if (reuse) return { lockPath: null, reuse };
137
- } catch {}
138
- }
139
- throw new Error(`[supervisor-pg] spawn-lock acquire timeout (concurrent supervisor risk)`);
140
- }
141
- await new Promise((r) => setTimeout(r, LOCK_POLL_MS));
142
- }
143
- }
144
- }
145
-
146
- function releaseSpawnLock(lp) {
147
- if (!lp) return;
148
- try {
149
- unlinkSync(lp);
150
- } catch {}
151
- }
152
-
153
73
  // ── Port allocation ──────────────────────────────────────────────────────────
154
74
 
155
75
  function _probePort(port) {
@@ -602,18 +522,10 @@ async function _doEnsure(dataDir, signal) {
602
522
  throw new Error('secondary memory runtime requires an existing PG instance');
603
523
  }
604
524
 
605
- // ── Acquire spawn lock to serialize initdb races ─────────────────────────
606
- const acquired = await acquireSpawnLock(dataDir, () =>
607
- tryReusePgInstance({
608
- pgdata,
609
- runtimeDir,
610
- healthcheckPg,
611
- source: 'lock-wait',
612
- })
613
- );
614
- if (acquired?.reuse) return acquired.reuse;
615
- const lp = acquired?.lockPath ?? null;
616
- try {
525
+ // ── Spawn lock serializes initdb races (see withFileLock below) ──────────
526
+ let lockEntered = false;
527
+ const spawnUnderLock = async () => {
528
+ lockEntered = true;
617
529
  // ── Reuse path: another supervisor already started PG ─────────────────
618
530
  const lockedReuse = await tryReusePgInstance({
619
531
  pgdata,
@@ -701,8 +613,16 @@ async function _doEnsure(dataDir, signal) {
701
613
  // ── Allocate a fresh port and spawn ───────────────────────────────────
702
614
  const port = await allocatePort();
703
615
  return await _startFresh(dataDir, pgdata, port, runtimeDir);
704
- } finally {
705
- releaseSpawnLock(lp);
616
+ };
617
+ try {
618
+ return await withFileLock(join(dataDir, 'pg-spawn.lock'), spawnUnderLock, { timeoutMs: 30_000 });
619
+ } catch (err) {
620
+ // Only an acquisition timeout (spawnUnderLock never ran) falls back to
621
+ // reuse; failures from inside the locked region propagate untouched.
622
+ if (lockEntered || err?.code !== 'ELOCKTIMEOUT') throw err;
623
+ const reuse = await tryReusePgInstance({ pgdata, runtimeDir, healthcheckPg, source: 'lock-wait' });
624
+ if (reuse) return reuse;
625
+ throw new Error('[supervisor-pg] spawn-lock acquire timeout (concurrent supervisor risk)', { cause: err });
706
626
  }
707
627
  }
708
628
 
@@ -119,6 +119,11 @@ exact AS (
119
119
  WHERE false
120
120
  ),`;
121
121
  }
122
+ // Each row is lowercased once (OFFSET 0 keeps the subquery from being
123
+ // inlined into the per-term condition) and every term is a literal strpos
124
+ // on that text. Per-term ILIKE re-lowercased the whole content for every
125
+ // term, so a natural-language query's 10+ terms multiplied the scan cost.
126
+ // Terms arrive lowercased from buildExactTerms.
122
127
  return `
123
128
  exact_matches AS (
124
129
  SELECT ee.id,
@@ -126,10 +131,14 @@ exact_matches AS (
126
131
  q.term,
127
132
  COUNT(*) OVER (PARTITION BY q.term)::float8 AS term_df
128
133
  FROM entries ee
134
+ CROSS JOIN LATERAL (
135
+ SELECT lower(ee.content) AS content, lower(ee.element) AS element, lower(ee.summary) AS summary
136
+ OFFSET 0
137
+ ) lc
129
138
  JOIN LATERAL unnest($${exactTermsParam}::text[]) AS q(term) ON (
130
- ee.content ILIKE '%' || q.term || '%'
131
- OR ${recallSubstringPredicate('ee.element', 'q.term')}
132
- OR ${recallSubstringPredicate('ee.summary', 'q.term')}
139
+ strpos(lc.content, q.term) > 0
140
+ OR strpos(lc.element, q.term) > 0
141
+ OR strpos(lc.summary, q.term) > 0
133
142
  )
134
143
  WHERE true
135
144
  ${filters.exactFilterClause}
@@ -17,7 +17,7 @@ import { renderPdfPages } from '../pdf/pdf-render.mjs';
17
17
  const PX_TO_PT = 0.75;
18
18
 
19
19
  /** Artifacts kept beside the document: its HTML and the browser's print of it. */
20
- export function docxHtmlArtifacts(target) {
20
+ function docxHtmlArtifacts(target) {
21
21
  return {
22
22
  source: `${target}.mixdog-source.html`,
23
23
  print: `${target}.mixdog-html.pdf`,
@@ -34,7 +34,7 @@ const PPTX_AUTHOR_NEEDS_SOURCE =
34
34
  'author requires script: HTML slides or a pptxgenjs script (without one it re-authors from <deck>.pptx.mixdog-source.html, and none is there). Load the `pptx` Skill first (Skill name:"pptx"): it carries the authoring workflow, the HTML contract, the composition grammar, and the device kit, then call author again with path and script.';
35
35
 
36
36
  // HTML opens with markup (a doctype, a comment, an element); a pptxgenjs script never does.
37
- export function isHtmlSource(source) {
37
+ function isHtmlSource(source) {
38
38
  return /^\s*</.test(String(source || ''));
39
39
  }
40
40
 
@@ -140,7 +140,7 @@ function resolveRange(text, cells, notes) {
140
140
  }
141
141
 
142
142
  /** The operations that write one measured workbook; formulas and charts come after every sheet's values. */
143
- export function xlsxOperationsFromSheets(sheets, { captures = new Map(), notes = [] } = {}) {
143
+ function xlsxOperationsFromSheets(sheets, { captures = new Map(), notes = [] } = {}) {
144
144
  const first = [];
145
145
  const later = [];
146
146
  const chartData = [];
@@ -49,7 +49,7 @@ function fillRangeCharts() {
49
49
  }
50
50
 
51
51
  /** Artifacts kept beside the workbook: its HTML and the browser's picture of each sheet. */
52
- export function xlsxHtmlArtifacts(target) {
52
+ function xlsxHtmlArtifacts(target) {
53
53
  return {
54
54
  source: `${target}.mixdog-source.html`,
55
55
  shot: (sheet) => `${target}.mixdog-html-sheet-${sheet}.png`,
@@ -430,7 +430,7 @@ function docxStyleDefinitionFault(format, name, operation, index) {
430
430
 
431
431
  // A Word table has two alignments that read alike: `alignment` places the
432
432
  // table on the page and `columnAlignments` sets the text of each column.
433
- // A list written into the first used to be serialized verbatim into the
433
+ // A list written into the first would be serialized verbatim into the
434
434
  // table's justification and refused by Word's schema at finalize.
435
435
  function docxTableAlignmentFaults(format, name, operation, index) {
436
436
  const properties = operation.properties;
@@ -118,7 +118,7 @@ export async function ensureOfficeSessionDesign(
118
118
  session.designRequest = mergeOfficeDesignRequest(session.designRequest, args.design);
119
119
  // A native document stays native: the `design` a later call carries is the
120
120
  // page review (reviewed, reviewToken, critique) or content, not a request
121
- // for a preset. Resolving it as one used to hand a Word or Excel file the
121
+ // for a preset. Resolving it as one would hand a Word or Excel file the
122
122
  // default profile's palette and art direction it never asked for, and put
123
123
  // the preset review's gates in front of finalize.
124
124
  session.design =
@@ -108,9 +108,9 @@ export function normalizeOfficeContentModel(value) {
108
108
  const id = safeId(claim.id, 'claim id', `claim ${index + 1}${claim?.text ? `: ${claim.text}` : ''}`);
109
109
  if (claimIds.has(id)) throw new Error(`Office content model has duplicate claim id ${id}`);
110
110
  claimIds.add(id);
111
- // The references are the point of a claim: naming them "facts" instead of
112
- // factIds used to bind the claim to nothing at all, and the deck then
113
- // reported the figure it carried as unsourced.
111
+ // The references are the point of a claim, so `facts` is accepted as an
112
+ // alias of `factIds`: a claim written with either name stays bound to its
113
+ // sources instead of reporting the figure it carried as unsourced.
114
114
  let references = [];
115
115
  if (Array.isArray(claim.factIds)) references = claim.factIds;
116
116
  else if (Array.isArray(claim.facts)) references = claim.facts;
@@ -39,10 +39,10 @@ function writeSectionHeading(w, section) {
39
39
  function writeSectionList(w, section, sectionKind, blockFollows = false) {
40
40
  const { append, colors, type, bodySize, spacing } = w;
41
41
  const sectionBullets = strings(section.bullets);
42
- // A section that names steps draws them. They used to reach the page only
43
- // when the section also declared kind:'roadmap', so a plan section landed as
44
- // a heading with nothing under it - and the audit reported the orphan heading
45
- // the composer had just written.
42
+ // A section that names steps draws them. Reaching the page only with
43
+ // kind:'roadmap' would land a plan section as a heading with nothing under
44
+ // it - and the audit would report the orphan heading the composer had just
45
+ // written.
46
46
  const sectionSteps = Array.isArray(section.steps) ? section.steps : [];
47
47
  const stepSource = sectionSteps.length ? sectionSteps : sectionBullets;
48
48
  const drewSteps =
@@ -76,8 +76,8 @@ function writeSectionList(w, section, sectionKind, blockFollows = false) {
76
76
  });
77
77
  }
78
78
 
79
- // What a section can carry. A field outside this list used to vanish: a plan written as `roadmap:[…]` reached the
80
- // page as a heading with nothing under it, and the composer reported success.
79
+ // What a section can carry. A field outside this list would vanish: a plan written as `roadmap:[…]` would reach the
80
+ // page as a heading with nothing under it, and the composer would report success.
81
81
  const SECTION_FIELDS = new Set([
82
82
  'heading',
83
83
  'title',
@@ -197,7 +197,7 @@ export function addXlsxDecisionPanel(
197
197
  cursor += 1;
198
198
  });
199
199
  }
200
- // The actions follow the gates rather than stand in for them: given both, the actions used to be dropped.
200
+ // The actions follow the gates rather than stand in for them: given both, the actions would be dropped.
201
201
  if (gateRows.length && strings(actions).length) cursor += 1;
202
202
  for (const action of strings(actions).slice(0, 4)) {
203
203
  mergedBlock(output, {
@@ -417,7 +417,7 @@ function metricLabelStyle({ colors, type, dashboard }) {
417
417
  // metric is the one the strip paints as the headline, so the wider card reads
418
418
  // as emphasis rather than as a card that ran out of room.
419
419
  // More cards than columns wrap onto a second strip rather than pulling the
420
- // canvas past the table: a three-metric strip over a two-column table used to
420
+ // canvas past the table: a three-metric strip over a two-column table would
421
421
  // make every band half again as wide as the table under it.
422
422
  // The text a card's value shows under its number format ("47.0%" for 0.47 under 0.0%, "12명" for 12 under 0"명").
423
423
  function metricDisplayText(metric) {
@@ -9,7 +9,7 @@ import { workerExecArgv } from '../../shared/worker-exec-argv.mjs';
9
9
  const ENGINE_URL = new URL('./ocr-engine-worker.mjs', import.meta.url);
10
10
 
11
11
  /** The start includes the first-use download; without network it fails or hangs. */
12
- export const OCR_ENGINE_START_TIMEOUT_MS = 90_000;
12
+ const OCR_ENGINE_START_TIMEOUT_MS = 90_000;
13
13
 
14
14
  const engines = new Map();
15
15
 
@@ -13,10 +13,10 @@ const HEADING_SIZES = Object.freeze({ 1: 16, 2: 13, 3: 12 });
13
13
 
14
14
  const FLOW_FIELDS = ['before', 'after', 'x', 'width', 'color', 'align'];
15
15
 
16
- // What each block actually takes. A block the writer cannot read used to flow
17
- // as an empty paragraph: a table or a list written under the wrong key left no
18
- // mark on the page and no word in the result, so the report shipped without
19
- // the evidence it was asked for.
16
+ // What each block actually takes. A block the writer cannot read would flow
17
+ // as an empty paragraph: a table or a list written under the wrong key would
18
+ // leave no mark on the page and no word in the result, so the report would ship
19
+ // without the evidence it was asked for.
20
20
  const BLOCK_FIELDS = Object.freeze({
21
21
  paragraph: Object.freeze({ required: ['text'], optional: [...FLOW_FIELDS, 'size', 'lineHeight'] }),
22
22
  heading: Object.freeze({ required: ['text'], optional: [...FLOW_FIELDS, 'size', 'lineHeight', 'level'] }),
@@ -825,8 +825,8 @@ function styledDocxCell(cell, op) {
825
825
  }
826
826
 
827
827
  // A merged cell keeps what it carried (its shading, its borders, the bottom alignment a header row sits on, as Word
828
- // keeps them) and takes the spans; its width becomes the widths it joins. The whole tcPr used to be replaced, and a
829
- // two-level header's merged labels rose to the top of their cells on this backend only. Children stay in schema
828
+ // keeps them) and takes the spans; its width becomes the widths it joins. Replacing the whole tcPr would make a
829
+ // two-level header's merged labels rise to the top of their cells on this backend only. Children stay in schema
830
830
  // order: cnfStyle, tcW, gridSpan, vMerge, then the rest.
831
831
  function mergedCellXml(joined, spans) {
832
832
  const existing = /<w:tcPr(?:\s[^>]*)?>([\s\S]*?)<\/w:tcPr>/.exec(joined[0])?.[1] || '';