mixdog 1.4.2 → 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 (417) hide show
  1. package/package.json +2 -2
  2. package/scripts/build-shipped-history.mjs +15 -5
  3. package/scripts/gate-local.mjs +65 -19
  4. package/scripts/graph-parity.mjs +8 -3
  5. package/scripts/lib/gate-scheduler.mjs +2 -1
  6. package/scripts/lib/run-node-tests.mjs +17 -5
  7. package/scripts/lib/test-failure-summary.mjs +1 -8
  8. package/scripts/lib/test-spawn-ledger.mjs +33 -2
  9. package/scripts/post-release-check.mjs +26 -16
  10. package/scripts/provider-pingpong-live.mjs +1 -1
  11. package/scripts/prune-embedding-runtime.mjs +3 -1
  12. package/scripts/release-paths.mjs +7 -1
  13. package/src/defaults/shipped-history.json +20 -0
  14. package/src/defaults/skills/setup/SKILL.md +2 -2
  15. package/src/defaults/skills/setup/references/actions.md +16 -3
  16. package/src/defaults/skills/setup/references/surfaces.md +3 -0
  17. package/src/defaults/skills/setup-guide/SKILL.md +6 -1
  18. package/src/lib/instruction-text.cjs +36 -0
  19. package/src/lib/rules-builder.cjs +34 -20
  20. package/src/orchestration/balanced.md +23 -0
  21. package/src/orchestration/focused.md +22 -0
  22. package/src/orchestration/none.md +5 -0
  23. package/src/orchestration/swarm.md +24 -0
  24. package/src/rules/agent-mode/AGENT_MODE.md +3 -1
  25. package/src/rules/agent-mode/MIXY.md +2 -2
  26. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/session-prep.mjs +3 -3
  27. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +0 -1
  28. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +4 -2
  29. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +0 -9
  30. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +2 -2
  31. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +67 -0
  32. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +1 -0
  33. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -4
  34. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -1
  35. package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +199 -46
  36. package/src/runtime/agent/orchestrator/mcp/client-config.mjs +3 -5
  37. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +9 -3
  38. package/src/runtime/agent/orchestrator/mcp/client.mjs +3 -5
  39. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +1 -1
  40. package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +8 -2
  41. package/src/runtime/agent/orchestrator/mcp/oauth-probe.mjs +1 -1
  42. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +14 -0
  43. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +1 -1
  44. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  45. package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-stop.mjs +3 -3
  46. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  47. package/src/runtime/agent/orchestrator/providers/gemini-thinking.mjs +2 -2
  48. package/src/runtime/agent/orchestrator/providers/openai-compat-response-normalization.mjs +4 -6
  49. package/src/runtime/agent/orchestrator/providers/openai-compat-responses-head-parity.json +2784 -2872
  50. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +5 -8
  51. package/src/runtime/agent/orchestrator/providers/openai-responses-payload-parity.fixture.json +288 -300
  52. package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +10 -1
  53. package/src/runtime/agent/orchestrator/providers/xai-tool-search-head-parity.json +10 -30
  54. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +30 -0
  55. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +0 -11
  56. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-availability.mjs +8 -0
  57. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +17 -3
  58. package/src/runtime/agent/orchestrator/runtime-core/goal-control.mjs +47 -27
  59. package/src/runtime/agent/orchestrator/runtime-core/goal-deadlines.mjs +141 -10
  60. package/src/runtime/agent/orchestrator/runtime-core/goal-mutations.mjs +26 -63
  61. package/src/runtime/agent/orchestrator/runtime-core/goal-reminder.mjs +28 -3
  62. package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +36 -11
  63. package/src/runtime/agent/orchestrator/runtime-core/goal-state.mjs +88 -56
  64. package/src/runtime/agent/orchestrator/runtime-core/goal-storage.mjs +4 -1
  65. package/src/runtime/agent/orchestrator/runtime-core/goal-store.mjs +51 -32
  66. package/src/runtime/agent/orchestrator/runtime-core/goal-text.mjs +45 -145
  67. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -98
  68. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-exec.mjs +32 -99
  69. package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +23 -78
  70. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +69 -48
  71. package/src/runtime/agent/orchestrator/runtime-core/todo-list.mjs +367 -0
  72. package/src/runtime/agent/orchestrator/runtime-core/todo-tool-defs.mjs +47 -0
  73. package/src/runtime/agent/orchestrator/runtime-core/tool-availability.mjs +155 -0
  74. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +9 -0
  75. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +119 -35
  76. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -1
  77. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +1 -1
  78. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +28 -22
  79. package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +30 -0
  80. package/src/runtime/agent/orchestrator/session/attachment-preflight.mjs +1 -1
  81. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +2 -2
  82. package/src/runtime/agent/orchestrator/session/catalog-db/index.mjs +2 -2
  83. package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +1 -1
  84. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -1
  85. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +3 -0
  86. package/src/runtime/agent/orchestrator/session/compact/summary-route.mjs +1 -1
  87. package/src/runtime/agent/orchestrator/session/context-utils.mjs +8 -12
  88. package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +1 -1
  89. package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +1 -1
  91. package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +7 -3
  92. package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +1 -1
  93. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +1 -2
  94. package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +1 -1
  95. package/src/runtime/agent/orchestrator/session/image-strip-recovery.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +11 -1
  97. package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
  98. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
  99. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/todo-check.mjs +196 -0
  100. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +116 -50
  101. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +8 -1
  102. package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +1 -1
  104. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +3 -1
  105. package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +5 -6
  106. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +6 -1
  107. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  108. package/src/runtime/agent/orchestrator/session/loop/turn-report.mjs +35 -0
  109. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +1 -1
  110. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +57 -26
  111. package/src/runtime/agent/orchestrator/session/manager/ask-turn-auto-effort.mjs +9 -7
  112. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +21 -3
  113. package/src/runtime/agent/orchestrator/session/manager/ask-turn-failure.mjs +27 -11
  114. package/src/runtime/agent/orchestrator/session/manager/ask-turn-open.mjs +37 -34
  115. package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +15 -0
  116. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +25 -15
  117. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +79 -24
  118. package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +3 -0
  119. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +12 -1
  120. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +1 -1
  121. package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +6 -1
  122. package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +9 -1
  123. package/src/runtime/agent/orchestrator/session/manager/pending-spool-path.mjs +2 -2
  124. package/src/runtime/agent/orchestrator/session/manager/pending-spool-shard.mjs +1 -1
  125. package/src/runtime/agent/orchestrator/session/manager/prompt-settings.mjs +598 -0
  126. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +19 -0
  127. package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +19 -10
  128. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +5 -0
  129. package/src/runtime/agent/orchestrator/session/manager/session-fallback-title.mjs +1 -1
  130. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +31 -0
  131. package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +31 -0
  132. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +42 -6
  133. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +2 -0
  134. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +11 -1
  135. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +8 -9
  136. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +339 -88
  137. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-recovery.mjs +135 -11
  138. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +377 -104
  139. package/src/runtime/agent/orchestrator/session/manager/turn-durability.mjs +144 -0
  140. package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +1 -1
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +4 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +6 -0
  143. package/src/runtime/agent/orchestrator/session/mixy-name.mjs +1 -1
  144. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +8 -1
  145. package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +5 -1
  146. package/src/runtime/agent/orchestrator/session/store/canonical-reader.mjs +1 -1
  147. package/src/runtime/agent/orchestrator/session/store/liveness-veto.mjs +2 -2
  148. package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +23 -2
  149. package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +3 -3
  150. package/src/runtime/agent/orchestrator/session/store/transcript-durability.mjs +88 -0
  151. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +5 -0
  152. package/src/runtime/agent/orchestrator/session/store-summary-log.mjs +1 -1
  153. package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +14 -5
  154. package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +2 -2
  155. package/src/runtime/agent/orchestrator/session/store.mjs +5 -0
  156. package/src/runtime/agent/orchestrator/session/synthetic-user-envelope.mjs +7 -1
  157. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +9 -1
  158. package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
  159. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +3 -1
  160. package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +2 -2
  161. package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -5
  162. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +4 -1
  163. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +21 -3
  164. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  165. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/worktree-add-guard.mjs +77 -0
  166. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +0 -1
  167. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +7 -3
  168. package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +27 -9
  169. package/src/runtime/agent/orchestrator/tools/builtin/lib/search-input-helpers.mjs +2 -2
  170. package/src/runtime/agent/orchestrator/tools/builtin/read-range-index.mjs +1 -1
  171. package/src/runtime/agent/orchestrator/tools/builtin/read-single-fast-paths.mjs +0 -1
  172. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +0 -10
  173. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +1 -2
  174. package/src/runtime/agent/orchestrator/tools/builtin.mjs +1 -24
  175. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary/child-kill.mjs +4 -3
  176. package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +1 -2
  177. package/src/runtime/agent/orchestrator/tools/code-graph/modes/calls.mjs +1 -1
  178. package/src/runtime/agent/orchestrator/tools/code-graph/modes/symbols.mjs +2 -2
  179. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +4 -5
  180. package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +3 -4
  181. package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4 -22
  182. package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +2 -2
  183. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +1 -1
  184. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +0 -4
  185. package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +0 -1
  186. package/src/runtime/attachments/attachment-reference.mjs +1 -1
  187. package/src/runtime/attachments/pdf-extract.mjs +1 -1
  188. package/src/runtime/attachments/store.d.mts +1 -0
  189. package/src/runtime/attachments/store.mjs +2 -2
  190. package/src/runtime/channels/lib/config-reload-watch.mjs +42 -0
  191. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +29 -9
  192. package/src/runtime/channels/lib/scheduler.mjs +33 -0
  193. package/src/runtime/channels/lib/schedules-db.mjs +11 -4
  194. package/src/runtime/channels/lib/webhook/session-dispatch.mjs +4 -1
  195. package/src/runtime/channels/lib/webhooks-db.mjs +9 -3
  196. package/src/runtime/channels/lib/whisper-server.mjs +12 -12
  197. package/src/runtime/channels/lib/worker-main.mjs +9 -31
  198. package/src/runtime/computer-bridge/linux-readiness.mjs +10 -14
  199. package/src/runtime/connectors/connector-accounts-mcp.mjs +169 -33
  200. package/src/runtime/connectors/gmail-app-password.mjs +2 -2
  201. package/src/runtime/connectors/google-mcp.mjs +1 -1
  202. package/src/runtime/effort-judge/judge-client.mjs +2 -2
  203. package/src/runtime/effort-judge/judge-input.mjs +4 -4
  204. package/src/runtime/explore/explorer.mjs +0 -5
  205. package/src/runtime/explore/tool.mjs +3 -3
  206. package/src/runtime/local-provider/hardware.mjs +1 -1
  207. package/src/runtime/media/adapters/codex-image.mjs +3 -3
  208. package/src/runtime/media/adapters/gemini-video.mjs +1 -1
  209. package/src/runtime/media/media-usage.mjs +1 -1
  210. package/src/runtime/media/store.mjs +1 -1
  211. package/src/runtime/memory/index.mjs +11 -1
  212. package/src/runtime/memory/lib/embedding-reindex.mjs +27 -0
  213. package/src/runtime/memory/lib/memory-embed.mjs +83 -14
  214. package/src/runtime/memory/lib/memory-process-lock.mjs +159 -36
  215. package/src/runtime/memory/lib/memory-text-utils.mjs +6 -1
  216. package/src/runtime/memory/lib/memory.mjs +17 -0
  217. package/src/runtime/memory/lib/pg/process.mjs +1 -1
  218. package/src/runtime/memory/lib/pg/supervisor.mjs +16 -96
  219. package/src/runtime/memory/lib/recall-hybrid/hybrid-sql.mjs +12 -3
  220. package/src/runtime/office/authoring/docx-html-runner.mjs +1 -1
  221. package/src/runtime/office/authoring/pptx-author-action.mjs +1 -1
  222. package/src/runtime/office/authoring/xlsx-html-build.mjs +1 -1
  223. package/src/runtime/office/authoring/xlsx-html-runner.mjs +1 -1
  224. package/src/runtime/office/capabilities.mjs +1 -1
  225. package/src/runtime/office/core/office-core.mjs +1 -1
  226. package/src/runtime/office/design/content-model.mjs +3 -3
  227. package/src/runtime/office/design/docx/design-docx/section.mjs +6 -6
  228. package/src/runtime/office/design/xlsx/design-xlsx-components.mjs +1 -1
  229. package/src/runtime/office/design/xlsx/design-xlsx.mjs +1 -1
  230. package/src/runtime/office/pdf/ocr-engine.mjs +1 -1
  231. package/src/runtime/office/pdf/pdf-writer.mjs +4 -4
  232. package/src/runtime/office/portable/portable-docx-operations.mjs +2 -2
  233. package/src/runtime/office/portable/portable-soffice.mjs +8 -6
  234. package/src/runtime/office/portable/xlsx-contract.mjs +1 -1
  235. package/src/runtime/shared/atomic-file.d.mts +8 -0
  236. package/src/runtime/shared/background-tasks.mjs +22 -4
  237. package/src/runtime/shared/background-wait.mjs +66 -0
  238. package/src/runtime/shared/child-guardian.mjs +17 -7
  239. package/src/runtime/shared/config.mjs +313 -16
  240. package/src/runtime/shared/connector-catalog.d.mts +4 -5
  241. package/src/runtime/shared/connector-catalog.mjs +11 -1
  242. package/src/runtime/shared/file-lock.mjs +8 -3
  243. package/src/runtime/shared/git-runner.mjs +7 -2
  244. package/src/runtime/shared/idle-gc.mjs +30 -7
  245. package/src/runtime/shared/llm/http-agent.mjs +8 -5
  246. package/src/runtime/shared/llm/system-proxy.mjs +2 -1
  247. package/src/runtime/shared/llm/usage-ledger-quota.mjs +31 -12
  248. package/src/runtime/shared/llm/usage-ledger-rollup.mjs +84 -8
  249. package/src/runtime/shared/llm/usage-ledger.mjs +3 -0
  250. package/src/runtime/shared/llm/usage-rollup.mjs +48 -0
  251. package/src/runtime/shared/maintenance-schedule.mjs +109 -0
  252. package/src/runtime/shared/process-runner.mjs +8 -4
  253. package/src/runtime/shared/routine-trigger.d.mts +13 -0
  254. package/src/runtime/shared/routine-trigger.mjs +34 -0
  255. package/src/runtime/shared/run-child.d.mts +2 -1
  256. package/src/runtime/shared/run-child.mjs +70 -18
  257. package/src/runtime/shared/session-scratch.mjs +14 -2
  258. package/src/runtime/shared/shipped-definitions.mjs +7 -1
  259. package/src/runtime/shared/tool-card-model.golden.json +3 -12
  260. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  261. package/src/runtime/shared/tool-work-units.mjs +31 -6
  262. package/src/runtime/shared/turn-snapshot.mjs +26 -4
  263. package/src/runtime/shared/turn-worktree-snapshot.mjs +6 -11
  264. package/src/runtime/shared/worker-requests.mjs +17 -3
  265. package/src/runtime/shared/worktrees/branch-management.mjs +1 -5
  266. package/src/runtime/shared/worktrees/contract.mjs +16 -6
  267. package/src/runtime/shared/worktrees/dependencies.mjs +127 -89
  268. package/src/runtime/shared/worktrees/disk.mjs +79 -2
  269. package/src/runtime/shared/worktrees/git.mjs +44 -11
  270. package/src/runtime/shared/worktrees/include.mjs +6 -4
  271. package/src/runtime/shared/worktrees/maintenance.mjs +422 -30
  272. package/src/runtime/shared/worktrees/manager.mjs +772 -75
  273. package/src/runtime/shared/worktrees/settings.mjs +33 -7
  274. package/src/runtime/shared/worktrees/test-support.mjs +5 -1
  275. package/src/runtime/shared/worktrees/worker-snapshots.mjs +82 -0
  276. package/src/runtime/tidy/process.mjs +2 -1
  277. package/src/runtime/web-search/index.mjs +3 -22
  278. package/src/runtime/web-search/lib/web-tools.mjs +2 -2
  279. package/src/runtime/web-search/tool-defs.mjs +17 -26
  280. package/src/session-runtime/agent-profile-changes.mjs +55 -4
  281. package/src/session-runtime/boot/apis.mjs +27 -4
  282. package/src/session-runtime/boot/begin.mjs +2 -0
  283. package/src/session-runtime/boot/config.mjs +10 -1
  284. package/src/session-runtime/boot/facade.mjs +1 -0
  285. package/src/session-runtime/boot/providers.mjs +70 -3
  286. package/src/session-runtime/boot/session.mjs +2 -0
  287. package/src/session-runtime/boot/tools.mjs +69 -25
  288. package/src/session-runtime/channel-config-api.mjs +1 -0
  289. package/src/session-runtime/config-change-effects.mjs +179 -0
  290. package/src/session-runtime/config-lifecycle/config-writers.mjs +1 -0
  291. package/src/session-runtime/config-lifecycle.mjs +160 -24
  292. package/src/session-runtime/conversation-import/discovery.mjs +86 -7
  293. package/src/session-runtime/conversation-import/service.mjs +3 -2
  294. package/src/session-runtime/goal-facade-api.mjs +49 -3
  295. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +3 -0
  296. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +3 -2
  297. package/src/session-runtime/internal-tool-executor/feature-tools.mjs +3 -11
  298. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +18 -4
  299. package/src/session-runtime/internal-tool-executor.mjs +12 -19
  300. package/src/session-runtime/lifecycle/cold-heir.mjs +7 -0
  301. package/src/session-runtime/lifecycle/memory-ingest.mjs +3 -3
  302. package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +53 -5
  303. package/src/session-runtime/lifecycle/session-switch.mjs +13 -2
  304. package/src/session-runtime/lifecycle/teardown/session-close.mjs +4 -4
  305. package/src/session-runtime/lifecycle-api.mjs +1 -0
  306. package/src/session-runtime/mcp-glue/server-catalog.mjs +14 -3
  307. package/src/session-runtime/mcp-glue/server-connection.mjs +34 -8
  308. package/src/session-runtime/model-route/set-route.mjs +40 -7
  309. package/src/session-runtime/native-web-search/routes.mjs +3 -3
  310. package/src/session-runtime/provider-auth/refresh.mjs +6 -3
  311. package/src/session-runtime/provider-auth/setup.mjs +1 -1
  312. package/src/session-runtime/provider-readiness.mjs +53 -4
  313. package/src/session-runtime/resource-api.mjs +1 -1
  314. package/src/session-runtime/resource-extension-sync.mjs +4 -8
  315. package/src/session-runtime/resource-mcp-connector-accounts.mjs +5 -1
  316. package/src/session-runtime/resource-mcp-secrets.mjs +3 -3
  317. package/src/session-runtime/resource-plugins-api.mjs +4 -0
  318. package/src/session-runtime/routine-executor.mjs +152 -0
  319. package/src/session-runtime/routine-home-turn.mjs +46 -5
  320. package/src/session-runtime/runtime-facade.mjs +5 -0
  321. package/src/session-runtime/runtime-feature-gates.mjs +2 -11
  322. package/src/session-runtime/schedule-session-run.mjs +1 -0
  323. package/src/session-runtime/services/agent-tool/job-task-reconcile.mjs +6 -1
  324. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +7 -0
  325. package/src/session-runtime/services/agent-tool/send-flow.mjs +110 -6
  326. package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +12 -0
  327. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +5 -0
  328. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +24 -6
  329. package/src/session-runtime/services/agent-tool.mjs +51 -1
  330. package/src/session-runtime/services/channel-admin.mjs +18 -0
  331. package/src/session-runtime/services/hook-bus/command-handler.mjs +7 -11
  332. package/src/session-runtime/services/plugin-admin.mjs +4 -0
  333. package/src/session-runtime/services/seeds.mjs +7 -0
  334. package/src/session-runtime/services/usage-stats-model.mjs +32 -11
  335. package/src/session-runtime/session-create/materialize.mjs +4 -2
  336. package/src/session-runtime/session-create/session-options.mjs +2 -0
  337. package/src/session-runtime/settings-builtin-tools-api.mjs +1 -9
  338. package/src/session-runtime/setup-tool/connector-widen-approval.mjs +1 -1
  339. package/src/session-runtime/setup-tool/executor.mjs +8 -1
  340. package/src/session-runtime/setup-tool/extended-actions.mjs +2 -0
  341. package/src/session-runtime/setup-tool/settings-contract.mjs +28 -0
  342. package/src/session-runtime/setup-tool/tool-defs.mjs +26 -1
  343. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +40 -43
  344. package/src/session-runtime/tool-policy/mode-switch.mjs +1 -1
  345. package/src/session-runtime/tool-policy/policy-stage.mjs +106 -8
  346. package/src/session-runtime/tool-policy/workflow-overlay.mjs +2 -1
  347. package/src/session-runtime/tool-policy-refresh.mjs +182 -5
  348. package/src/session-runtime/tool-surface.mjs +38 -1
  349. package/src/session-runtime/turn/agent-ops.mjs +10 -2
  350. package/src/session-runtime/turn/session-ops.mjs +2 -0
  351. package/src/session-runtime/turn/turn-run/turn-prepare.mjs +5 -0
  352. package/src/session-runtime/turn/turn-run.mjs +1 -1
  353. package/src/session-runtime/webhook-session-run.mjs +2 -0
  354. package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +1 -4
  355. package/src/session-runtime/workflow-agents-api/agent-route.mjs +3 -10
  356. package/src/session-runtime/workflow-agents-api/instruction-files.mjs +165 -0
  357. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +5 -4
  358. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +2 -3
  359. package/src/session-runtime/workflow-agents-api.mjs +2 -0
  360. package/src/session-runtime/workspace/project-branches.mjs +1 -1
  361. package/src/session-runtime/workspace/session-view.mjs +1 -1
  362. package/src/session-runtime/workspace/transitions.mjs +20 -4
  363. package/src/session-runtime/workspace/worktree-maintenance.mjs +126 -6
  364. package/src/session-runtime/workspace/worktree-setup.mjs +13 -1
  365. package/src/session-runtime/workspace/worktree-tool.mjs +16 -0
  366. package/src/standalone/daemon-agent-control.mjs +25 -8
  367. package/src/standalone/daemon-desktop-runtime.mjs +6 -2
  368. package/src/standalone/daemon-lag-profiler.mjs +7 -7
  369. package/src/standalone/daemon.mjs +54 -2
  370. package/src/standalone/local-session-runtime.mjs +16 -0
  371. package/src/standalone/session-client/daemon-unavailable.mjs +1 -1
  372. package/src/standalone/session-protocol.mjs +11 -0
  373. package/src/standalone/session-service/agent-route-follow.mjs +23 -20
  374. package/src/standalone/session-service/agent-tree/agent-turns.mjs +18 -6
  375. package/src/standalone/session-service/quota-resume.mjs +9 -0
  376. package/src/standalone/session-service/session-calls/session-action.mjs +51 -1
  377. package/src/standalone/session-service/session-calls/session-turns.mjs +37 -18
  378. package/src/standalone/session-service/session-calls/turn-gate.mjs +34 -0
  379. package/src/standalone/session-service/session-calls.mjs +2 -1
  380. package/src/tui/App.jsx +8 -0
  381. package/src/tui/app/clipboard.mjs +1 -1
  382. package/src/tui/app/create-app-pickers.mjs +2 -0
  383. package/src/tui/app/doctor.mjs +2 -2
  384. package/src/tui/app/panel-signature.mjs +1 -1
  385. package/src/tui/app/settings-picker.mjs +53 -8
  386. package/src/tui/app/shell-layout/row-budgets.mjs +2 -2
  387. package/src/tui/app/slash-commands.mjs +1 -1
  388. package/src/tui/app/slash-dispatch/route-commands.mjs +1 -1
  389. package/src/tui/app/slash-dispatch/session-commands.mjs +1 -1
  390. package/src/tui/app/use-prompt-queue-history.mjs +2 -2
  391. package/src/tui/app/use-transcript-activity.mjs +1 -1
  392. package/src/tui/app/use-transcript-window/geometry.mjs +1 -1
  393. package/src/tui/components/prompt-input/escape-policy.d.mts +0 -1
  394. package/src/tui/components/prompt-input/escape-policy.mjs +1 -1
  395. package/src/tui/components/question-panel-model.mjs +4 -4
  396. package/src/tui/components/tool-execution/standard-card.jsx +3 -4
  397. package/src/tui/components/user-message-skills.mjs +1 -1
  398. package/src/tui/dist/index.mjs +309 -30
  399. package/src/tui/markdown/render-ansi.mjs +1 -1
  400. package/src/tui/session/agent-job-feed/notification-router.mjs +10 -0
  401. package/src/tui/session/agent-job-feed.mjs +2 -0
  402. package/src/tui/session/context-state.mjs +3 -0
  403. package/src/tui/session/quota-resume.mjs +1 -1
  404. package/src/tui/session/session-api/lifecycle/dispose.mjs +1 -0
  405. package/src/tui/session/session-api/lifecycle/session-reset.mjs +7 -0
  406. package/src/tui/session/session-api/routes-agent-definitions.mjs +5 -0
  407. package/src/tui/session/session-api/worktree.mjs +13 -1
  408. package/src/tui/session/session-flow/drain.mjs +11 -14
  409. package/src/tui/session/tool-card-results/grouped-result.mjs +2 -2
  410. package/src/tui/session/turn-quiet.mjs +1 -1
  411. package/src/tui/session/turn.mjs +3 -0
  412. package/src/tui/session/worktree-setup-notice.mjs +1 -1
  413. package/src/tui/spinner-meta.mjs +3 -3
  414. package/src/tui/spinner-verbs.mjs +2 -2
  415. package/src/defaults/skills/goal-management/SKILL.md +0 -169
  416. package/src/runtime/agent/orchestrator/runtime-core/goal-tasks.mjs +0 -156
  417. package/src/session-runtime/goal-tasks.mjs +0 -1
@@ -4,6 +4,7 @@
4
4
  // sessions that carry an active Goal after daemon replacement is wired in from
5
5
  // ./goal-recovery.mjs.
6
6
  import { createGoalRecovery } from './goal-recovery.mjs';
7
+ import { createSessionTurnGate } from './turn-gate.mjs';
7
8
  import {
8
9
  attachmentsForIntake,
9
10
  materializePromptSubmission,
@@ -54,6 +55,8 @@ export function createSessionTurnCalls(ctx) {
54
55
  const { log, readStoredGoal, listStoredActiveGoalSessionIds, hasAgentSession, sessionResult, advanceForCaller } = ctx;
55
56
  const { retainUnwatched } = ctx.retention;
56
57
  const { entryForSession } = ctx.entries;
58
+ // One gate per service, shared with the idle-only delete (session-calls.mjs).
59
+ const turnGate = ctx.turnGate ?? createSessionTurnGate();
57
60
 
58
61
  /** Publishes the step an action produced and keeps the entry on the retention clock. */
59
62
  const settleAction = (entry, reason) => {
@@ -66,16 +69,26 @@ export function createSessionTurnCalls(ctx) {
66
69
  // attachment conversion that has not yet become a turn.
67
70
  const intakeAborts = new Map();
68
71
 
69
- async function submitSession({
70
- sessionId,
71
- prompt,
72
- options = {},
73
- open: openHints = {},
74
- baseRevision = null,
75
- signal = null,
76
- } = {}) {
77
- const id = String(sessionId || '');
72
+ /** Run `start` as an admitted turn start of `sessionId` (turn-gate.mjs). */
73
+ async function admitted(sessionId, start) {
74
+ const leave = turnGate.enter(sessionId);
75
+ try {
76
+ return await start();
77
+ } finally {
78
+ leave();
79
+ }
80
+ }
81
+
82
+ async function submitSession(params = {}) {
83
+ const id = String(params?.sessionId || '');
78
84
  if (!id) throw new TypeError('sessionId is required');
85
+ return admitted(id, () => submitAdmitted(id, params));
86
+ }
87
+
88
+ async function submitAdmitted(
89
+ id,
90
+ { prompt, options = {}, open: openHints = {}, baseRevision = null, signal = null } = {}
91
+ ) {
79
92
  const entry = await entryForSession(id, openHints || {});
80
93
  const target = entry.runtime.submitAsync;
81
94
  if (typeof target !== 'function') throw new TypeError('session runtime must implement submitAsync');
@@ -150,9 +163,12 @@ export function createSessionTurnCalls(ctx) {
150
163
  async function materializeSession(sessionId, openHints = {}) {
151
164
  const id = String(sessionId || '');
152
165
  if (!id) throw new TypeError('sessionId is required');
153
- const entry = await entryForSession(id, openHints || {});
154
- retainUnwatched(entry, 'daemon session owner');
155
- return entry.runtime;
166
+ // Its callers start work on the runtime (Goal and quota resumes, bots).
167
+ return admitted(id, async () => {
168
+ const entry = await entryForSession(id, openHints || {});
169
+ retainUnwatched(entry, 'daemon session owner');
170
+ return entry.runtime;
171
+ });
156
172
  }
157
173
 
158
174
  const recoverActiveGoals = createGoalRecovery({
@@ -196,12 +212,15 @@ export function createSessionTurnCalls(ctx) {
196
212
  async function approveSession({ sessionId, approvalId, decision, open: openHints = {}, baseRevision = null } = {}) {
197
213
  const id = String(sessionId || '');
198
214
  if (!id) throw new TypeError('sessionId is required');
199
- const entry = await entryForSession(id, openHints || {});
200
- const target = entry.runtime.resolveToolApproval;
201
- if (typeof target !== 'function') {
202
- throw new TypeError('session action resolveToolApproval is unavailable');
203
- }
204
- const approved = await target.call(entry.runtime, approvalId, decision);
215
+ // An answer resumes the turn: an admitted start.
216
+ const { entry, approved } = await admitted(id, async () => {
217
+ const hosted = await entryForSession(id, openHints || {});
218
+ const target = hosted.runtime.resolveToolApproval;
219
+ if (typeof target !== 'function') {
220
+ throw new TypeError('session action resolveToolApproval is unavailable');
221
+ }
222
+ return { entry: hosted, approved: await target.call(hosted.runtime, approvalId, decision) };
223
+ });
205
224
  const step = settleAction(entry, 'headless session approval');
206
225
  return sessionResult(entry, step, baseRevision, { approved: approved === true });
207
226
  }
@@ -0,0 +1,34 @@
1
+ // session-calls/turn-gate.mjs
2
+ // The service's turn starts per session (a submit's intake, an approval that
3
+ // resumes a turn, a materialization for a Goal or quota resume) against the
4
+ // desktop's idle-only delete: the delete closes a session to new starts only
5
+ // while none is being admitted, and a start refuses while it is closed.
6
+ import { SessionClosedError } from '../../../runtime/agent/orchestrator/session/manager/session-errors.mjs';
7
+
8
+ export function createSessionTurnGate() {
9
+ const starting = new Map(); // sessionId -> admissions in flight
10
+ const fenced = new Set();
11
+ return {
12
+ /** Admit a turn start of `sessionId`; the returned release ends it. */
13
+ enter(sessionId) {
14
+ if (fenced.has(sessionId)) {
15
+ throw new SessionClosedError(sessionId, 'session is being deleted', 'auto-retention-delete');
16
+ }
17
+ starting.set(sessionId, (starting.get(sessionId) || 0) + 1);
18
+ let left = false;
19
+ return () => {
20
+ if (left) return;
21
+ left = true;
22
+ const count = (starting.get(sessionId) || 1) - 1;
23
+ if (count > 0) starting.set(sessionId, count);
24
+ else starting.delete(sessionId);
25
+ };
26
+ },
27
+ /** Close `sessionId` to turn starts; null while one is being admitted. */
28
+ fence(sessionId) {
29
+ if (starting.has(sessionId) || fenced.has(sessionId)) return null;
30
+ fenced.add(sessionId);
31
+ return () => fenced.delete(sessionId);
32
+ },
33
+ };
34
+ }
@@ -14,6 +14,7 @@
14
14
  import { createSessionActionCalls } from './session-calls/session-action.mjs';
15
15
  import { createSessionTurnCalls } from './session-calls/session-turns.mjs';
16
16
  import { createSessionViewCalls } from './session-calls/session-views.mjs';
17
+ import { createSessionTurnGate } from './session-calls/turn-gate.mjs';
17
18
 
18
19
  /**
19
20
  * @param {object} deps
@@ -54,7 +55,7 @@ export function createSessionCalls(deps) {
54
55
  return step;
55
56
  }
56
57
 
57
- const ctx = { ...deps, sessionResult, responseSessionId, advanceForCaller };
58
+ const ctx = { ...deps, sessionResult, responseSessionId, advanceForCaller, turnGate: createSessionTurnGate() };
58
59
  const actions = createSessionActionCalls(ctx);
59
60
  const views = createSessionViewCalls({ ...ctx, runSessionAction: actions.runSessionAction });
60
61
  const turns = createSessionTurnCalls(ctx);
package/src/tui/App.jsx CHANGED
@@ -242,6 +242,13 @@ export function App({ store, initialStatusLine = '', forceOnboarding = false, on
242
242
  // it, so a slow (daemon) snapshot from a superseded build cannot re-open the
243
243
  // panel after it was closed.
244
244
  const settingsRequestRef = useRef(0);
245
+ // The open Settings panel's re-read (null-op once another panel took over or
246
+ // it closed): a settings change applied by the runtime (any writer) or the
247
+ // setup tool repaints it.
248
+ const settingsLiveRefreshRef = useRef(null);
249
+ useEffect(() => {
250
+ if (state.setupChanged) settingsLiveRefreshRef.current?.();
251
+ }, [state.setupChanged]);
245
252
  const [providerPrompt, setProviderPrompt] = useState(null);
246
253
  const oauthSubmitRef = useRef(false);
247
254
  const [settingsPrompt, setSettingsPrompt] = useState(null);
@@ -371,6 +378,7 @@ export function App({ store, initialStatusLine = '', forceOnboarding = false, on
371
378
  onboardingPrefetchSeqRef,
372
379
  settingsHeavyCacheRef,
373
380
  settingsRequestRef,
381
+ settingsLiveRefreshRef,
374
382
  livePickerRef,
375
383
  disabledSkills,
376
384
  setDisabledSkills,
@@ -47,7 +47,7 @@ const LINUX_CLIPBOARD_HINT =
47
47
  'install wl-clipboard (Wayland) or xclip (X11), for example `sudo apt install wl-clipboard xclip`';
48
48
 
49
49
  /** A clipboard helper that is not installed, named with the package to add. */
50
- export function clipboardHelperError(cmd, error) {
50
+ function clipboardHelperError(cmd, error) {
51
51
  if (error?.code !== 'ENOENT' || process.platform !== 'linux') return error;
52
52
  return new Error(`${cmd} is not installed; ${LINUX_CLIPBOARD_HINT}`);
53
53
  }
@@ -47,6 +47,7 @@ export function createAppPickers({
47
47
  onboardingPrefetchSeqRef,
48
48
  settingsHeavyCacheRef,
49
49
  settingsRequestRef,
50
+ settingsLiveRefreshRef,
50
51
  livePickerRef,
51
52
  disabledSkills,
52
53
  setDisabledSkills,
@@ -180,6 +181,7 @@ export function createAppPickers({
180
181
  setSettingsPrompt,
181
182
  settingsHeavyCacheRef,
182
183
  settingsRequestRef,
184
+ settingsLiveRefreshRef,
183
185
  formatDuration,
184
186
  displayModelName,
185
187
  routeModelLabel,
@@ -23,10 +23,10 @@ import { dirname, join } from 'node:path';
23
23
  import { fileURLToPath } from 'node:url';
24
24
 
25
25
  const GLYPH = { ok: '✓', warn: '⚠', fail: '✗' };
26
- export const DOCTOR_CHECK_TIMEOUT_MS = 8000;
26
+ const DOCTOR_CHECK_TIMEOUT_MS = 8000;
27
27
  // Per-process log siblings are pruned by the channel worker; far above its
28
28
  // cap means pruning is not running.
29
- export const DOCTOR_LOG_FILE_WARN = 300;
29
+ const DOCTOR_LOG_FILE_WARN = 300;
30
30
 
31
31
  // Only the stable ^major.minor.patch and >=major.minor.patch alternatives
32
32
  // used by our Node engine contract are supported. Fail open to "unverified",
@@ -20,7 +20,7 @@ export const PANEL_LAYOUT_SIG = {
20
20
  // Queued steering band rows (full wrapped height, see queuedBandRows).
21
21
  QUEUED: 10,
22
22
  };
23
- export const PROJECT_TEXT_ENTRY_KINDS = new Set(['project-new', 'project-create-confirm', 'project-rename']);
23
+ const PROJECT_TEXT_ENTRY_KINDS = new Set(['project-new', 'project-create-confirm', 'project-rename']);
24
24
  export const CORE_MULTILINE_TEXT_ENTRY_KINDS = new Set(['core-add', 'core-edit']);
25
25
 
26
26
  export function panelSignatureFlags(signature) {
@@ -13,6 +13,16 @@ import { settingsHandoffPanel, createSettingsNavigation } from './settings-picke
13
13
  import { buildSettingsItems, readSettingsView } from './settings-picker/settings-rows.mjs';
14
14
  import { createSettingsToggles } from './settings-picker/settings-toggles.mjs';
15
15
 
16
+ // The factory is rebuilt every render, so the heavy-read gate lives beside the
17
+ // App-owned cache ref it protects: `running` is the one heavy read in flight,
18
+ // `queued` the single follow-up owed to changes that arrived meanwhile, and
19
+ // `freshWrites` counts heavy reads that wrote the cache.
20
+ const heavyGates = new WeakMap();
21
+ const heavyGateOf = (cacheRef) => {
22
+ if (!heavyGates.has(cacheRef)) heavyGates.set(cacheRef, { running: false, queued: false, freshWrites: 0 });
23
+ return heavyGates.get(cacheRef);
24
+ };
25
+
16
26
  export function createSettingsPicker({
17
27
  store,
18
28
  state,
@@ -21,6 +31,7 @@ export function createSettingsPicker({
21
31
  setSettingsPrompt,
22
32
  settingsHeavyCacheRef,
23
33
  settingsRequestRef,
34
+ settingsLiveRefreshRef,
24
35
  formatDuration,
25
36
  displayModelName,
26
37
  routeModelLabel,
@@ -51,16 +62,31 @@ export function createSettingsPicker({
51
62
  // destination synchronously before the daemon snapshot so the empty-chat
52
63
  // welcome logo cannot appear between the old panel and Settings.
53
64
  if (!light && !own.paint(settingsHandoffPanel())) return;
54
- const heavyCache = light ? settingsHeavyCacheRef.current : null;
65
+ // `heavy` re-reads MCP/plugin/skill status even on a light (no handoff
66
+ // paint) build: the cached values would otherwise win over a fresh snapshot.
67
+ const heavyCache = light && opts.heavy !== true ? settingsHeavyCacheRef.current : null;
55
68
  // ONE round-trip for the whole panel: on a daemon-backed store each getter
56
69
  // below is a serialized remote call, and reading them synchronously handed
57
70
  // back promises (every row rendered its default). getSettingsSnapshot runs
58
71
  // the same getters engine-side and answers once.
72
+ const gate = heavyGateOf(settingsHeavyCacheRef);
73
+ const freshWritesAtStart = gate.freshWrites;
59
74
  const snapshot = (await store.getSettingsSnapshot?.({ heavy: !heavyCache })) || {};
60
- const view = readSettingsView({ snapshot, heavyCache, state });
75
+ const view = readSettingsView({ snapshot, heavyCache, state }); // A superseded build (newer open/refresh) or one whose panel was already
76
+ // closed with Esc must never paint, clear prompts or write the cache: an
77
+ // older response settling late would otherwise roll the cache back for
78
+ // every later light refresh.
79
+ if (!isCurrentSettingsRequest(requestId)) {
80
+ // Its fresh heavy rows were dropped; unless a newer heavy read already
81
+ // refreshed the cache, owe the still-open panel one follow-up read.
82
+ if (!heavyCache && own.owns() && gate.freshWrites === freshWritesAtStart) gate.queued = true;
83
+ return;
84
+ }
85
+ if (!own.owns()) return;
61
86
  // Refresh the cache every build (light or full) so the next light
62
87
  // refresh reuses whatever was most recently known.
63
88
  settingsHeavyCacheRef.current = { mcp: view.mcp, plugins: view.plugins, skills: view.skills };
89
+ if (!heavyCache) gate.freshWrites += 1;
64
90
  const toggles = createSettingsToggles({
65
91
  store,
66
92
  view,
@@ -85,10 +111,6 @@ export function createSettingsPicker({
85
111
  routeModelLabel,
86
112
  workflowDisplayName,
87
113
  });
88
- // A superseded build (newer open/refresh) or one whose panel was already
89
- // closed with Esc must never paint or clear prompts.
90
- if (!isCurrentSettingsRequest(requestId)) return;
91
- if (!own.owns()) return;
92
114
  setProviderPrompt(null);
93
115
  setSettingsPrompt(null);
94
116
  own.paint({
@@ -116,6 +138,11 @@ export function createSettingsPicker({
116
138
  own.close();
117
139
  },
118
140
  });
141
+ // A settings change from elsewhere re-reads this panel while it is still
142
+ // the one on screen (the claim's epoch guards a closed or replaced panel).
143
+ // The change names no section (MCP servers, plugins and skills may have
144
+ // moved), so unlike a post-write refresh it re-reads the heavy rows too.
145
+ if (settingsLiveRefreshRef) settingsLiveRefreshRef.current = own.defer(() => refreshSettings({ heavy: true }));
119
146
  };
120
147
 
121
148
  // Public entry point. NEVER rejects: callers fire it detached
@@ -130,8 +157,26 @@ export function createSettingsPicker({
130
157
  store.pushNotice(`settings unavailable: ${error?.message || error}`, 'error');
131
158
  }
132
159
  };
133
- const refreshSettings = () => {
134
- void openSettingsPicker({ light: true });
160
+ // One heavy read at a time; changes arriving meanwhile share a single
161
+ // follow-up, which goes through the live-refresh callback so it is a no-op
162
+ // once the panel was closed or replaced.
163
+ const refreshHeavy = () => {
164
+ const gate = heavyGateOf(settingsHeavyCacheRef);
165
+ if (gate.running) {
166
+ gate.queued = true;
167
+ return;
168
+ }
169
+ gate.running = true;
170
+ void openSettingsPicker({ light: true, heavy: true }).finally(() => {
171
+ gate.running = false;
172
+ if (!gate.queued) return;
173
+ gate.queued = false;
174
+ settingsLiveRefreshRef?.current?.();
175
+ });
176
+ };
177
+ const refreshSettings = ({ heavy = false } = {}) => {
178
+ if (heavy) refreshHeavy();
179
+ else void openSettingsPicker({ light: true });
135
180
  };
136
181
  const navigation = createSettingsNavigation({ openers, openSettingsPicker, setSettingsPrompt });
137
182
 
@@ -139,8 +139,8 @@ function floatingPanelBudget({
139
139
  else if (btwPanel) desiredFloatingPanelRows = btwPanelRows(btwPanel, frameColumns);
140
140
  const floatingPanelRows = desiredFloatingPanelRows > 0 ? Math.min(desiredFloatingPanelRows, maxFloatingPanelRows) : 0;
141
141
  // Give the list every content row the panel exposes. The panel already grew
142
- // by OPTION_PANEL_EXTRA_ROWS; previously that growth was subtracted back out
143
- // here, so the rows leaked into an empty flexGrow gap instead of the list.
142
+ // by OPTION_PANEL_EXTRA_ROWS; subtracting that growth back out would leak the
143
+ // rows into an empty flexGrow gap instead of the list.
144
144
  // Reserving only PICKER_CHROME_ROWS lets the list occupy the full interior
145
145
  // (the footer's own reservation is handled inside Picker).
146
146
  const pickerVisibleRows = picker ? Math.max(1, floatingPanelRows - PICKER_CHROME_ROWS) : PANEL_MAX_VISIBLE;
@@ -24,7 +24,7 @@ export const SLASH_COMMANDS = [
24
24
  {
25
25
  name: 'goal',
26
26
  usage: '/goal',
27
- params: '[objective --time 1h --time-mode max|status|pause|resume|edit|stop]',
27
+ params: '[objective --time 1h|status|pause|resume|edit|stop]',
28
28
  description: 'Run and manage a durable session Goal',
29
29
  },
30
30
  {
@@ -139,7 +139,7 @@ export const routeCommands = {
139
139
 
140
140
  effort(ctx, arg) {
141
141
  const { state, store, openSlashPanel, deps } = ctx;
142
- // A running turn no longer blocks the switch: the in-flight turn keeps
142
+ // A running turn does not block the switch: the in-flight turn keeps
143
143
  // the effort it started with, and the new level applies from the next
144
144
  // turn. Same for /fast below.
145
145
  const pendingTurn = state.busy ? ' (applies from the next turn)' : '';
@@ -85,7 +85,7 @@ export const sessionCommands = {
85
85
  store.pushNotice('Goal is unavailable.', 'warn');
86
86
  return;
87
87
  }
88
- store.pushNotice(result.message || 'Goal updated.', 'info');
88
+ store.pushNotice(result.message || 'Goal updated.', result.ok === false ? 'warn' : 'info');
89
89
  })
90
90
  .catch((error) => store.pushNotice(`Goal failed: ${error?.message || error}`, 'error'));
91
91
  return true;
@@ -86,8 +86,8 @@ export function usePromptQueueHistory({
86
86
 
87
87
  const recentPromptHistory = useMemo(() => {
88
88
  // The engine maintains this list incrementally (rebuilt only when a user
89
- // item is appended or the transcript is bulk-swapped), so App no longer
90
- // rescans all items on every transcript change. Fall back to a local scan
89
+ // item is appended or the transcript is bulk-swapped), so App does not
90
+ // rescan all items on every transcript change. Fall back to a local scan
91
91
  // only if the engine did not publish it (older snapshot).
92
92
  if (Array.isArray(state.promptHistoryList)) return state.promptHistoryList;
93
93
  return scanPromptHistory(Array.isArray(state.items) ? state.items : []);
@@ -59,7 +59,7 @@ export function useTranscriptActivity({ state }) {
59
59
  // the StatusLine effect only re-fires when the numbers actually change.
60
60
  const activeToolsSignature = useMemo(() => {
61
61
  // The engine maintains this signature incrementally (updated on tool
62
- // start/early-complete/result/turn-end), so App no longer scans every
62
+ // start/early-complete/result/turn-end), so App does not scan every
63
63
  // transcript item on each change. Prefer it; fall back to the local scan
64
64
  // only when the engine did not publish it (older snapshot).
65
65
  if (state.activeToolSummary !== undefined) return state.activeToolSummary || '';
@@ -59,7 +59,7 @@ export function useTranscriptGeometry(state, props) {
59
59
  transcriptGeomRef,
60
60
  maxScrollRowsRef,
61
61
  } = refs;
62
- // The settled array no longer changes during streaming. Geometry is keyed by
62
+ // The settled array does not change during streaming. Geometry is keyed by
63
63
  // the engine revision plus the live tail's resolved height, so same-height
64
64
  // text flushes do not copy/walk the settled prefix or rerun heavy memos.
65
65
  const streamingTailItem = streamingTail?.kind === 'assistant' && streamingTail.streaming ? streamingTail : null;
@@ -1,4 +1,3 @@
1
- export const PROMPT_ESCAPE_CLEAR_WINDOW_MS: number;
2
1
  export const PROMPT_ESCAPE_HINT_TIMEOUT_MS: number;
3
2
 
4
3
  export type PromptEscapeAction =
@@ -1,4 +1,4 @@
1
- export const PROMPT_ESCAPE_CLEAR_WINDOW_MS = 800;
1
+ const PROMPT_ESCAPE_CLEAR_WINDOW_MS = 800;
2
2
  export const PROMPT_ESCAPE_HINT_TIMEOUT_MS = 1000;
3
3
 
4
4
  /**
@@ -7,8 +7,8 @@ import wrapAnsi from 'wrap-ansi';
7
7
  import { truncatePanelText } from './panel-cell-text.mjs';
8
8
 
9
9
  export const CUSTOM_LABEL = '직접 입력…';
10
- export const RECOMMENDED_SUFFIX = ' (추천)';
11
- export const MULTI_HINT = ' (여러 개 선택 가능)';
10
+ const RECOMMENDED_SUFFIX = ' (추천)';
11
+ const MULTI_HINT = ' (여러 개 선택 가능)';
12
12
  // border(2) + title + blank + blank-after-question; question rows added separately.
13
13
  const FIXED_ROWS = 5;
14
14
  // Panel interior = frame − 2 border − 2 paddingX.
@@ -60,7 +60,7 @@ export function optionLayout(question, columns) {
60
60
  return { rows, prefixCells, avail, indexCells };
61
61
  }
62
62
 
63
- export const MAX_ANSWER_CHARS = 4000;
63
+ const MAX_ANSWER_CHARS = 4000;
64
64
  const MIN_OPTION_ROWS = 3;
65
65
 
66
66
  // Append `text` to `base`, never exceeding MAX_ANSWER_CHARS UTF-16 units (the
@@ -74,7 +74,7 @@ export function appendCapped(base, text) {
74
74
  return out;
75
75
  }
76
76
 
77
- export function questionLines(question, columns) {
77
+ function questionLines(question, columns) {
78
78
  const shown = `${question?.question ?? ''}${question?.multi_select ? MULTI_HINT : ''}`;
79
79
  return wrapAnsi(shown, Math.max(1, columns - CHROME_COLUMNS), { trim: false, hard: true }).split('\n');
80
80
  }
@@ -191,10 +191,9 @@ export function renderStandardToolCard(card) {
191
191
  summaryOut = truncatedSummary ? ` (${truncatedSummary})` : '';
192
192
  }
193
193
  // Keep trailing content (ctrl+o hint only; pending elapsed lives on the detail
194
- // row) attached directly after the body for the whole lifecycle. The
195
- // fixed-column pin previously used for elapsed is what made the trailing text
196
- // jump to the right edge and snap back on the pending→done flip, so there is no
197
- // pad. `avail` stays reserved (rightReserve) so the body clip point never reflows.
194
+ // row) attached directly after the body for the whole lifecycle. A
195
+ // fixed-column pin would make the trailing text jump to the right edge and
196
+ // snap back on the pending→done flip, so there is no pad. `avail` stays reserved (rightReserve) so the body clip point never reflows.
198
197
  return (
199
198
  <Box flexDirection="column" marginTop={attached ? 0 : 1} width={rowWidth} overflow="hidden">
200
199
  <Box flexDirection="row" width="100%">
@@ -10,7 +10,7 @@
10
10
  import { skillMentions } from '../../runtime/shared/skill-mentions.mjs';
11
11
 
12
12
  /** The applied skill names of a row value: non-empty strings only. */
13
- export function appliedSkillNames(value) {
13
+ function appliedSkillNames(value) {
14
14
  return (Array.isArray(value) ? value : []).filter((name) => typeof name === 'string' && name);
15
15
  }
16
16