mixdog 0.9.3 → 0.9.5

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 (382) hide show
  1. package/README.md +112 -38
  2. package/package.json +10 -3
  3. package/scripts/bench/lead-review-tasks-r3.json +20 -0
  4. package/scripts/bench/lead-review-tasks.json +20 -0
  5. package/scripts/bench/r4-mixed-tasks.json +20 -0
  6. package/scripts/bench/r5-orchestrated-task.json +7 -0
  7. package/scripts/bench/review-tasks.json +20 -0
  8. package/scripts/bench/round-codex.json +114 -0
  9. package/scripts/bench/round-mixdog-lead-r3.json +269 -0
  10. package/scripts/bench/round-mixdog-lead.json +269 -0
  11. package/scripts/bench/round-mixdog.json +126 -0
  12. package/scripts/bench/round-r10-bigsample.json +679 -0
  13. package/scripts/bench/round-r11-codexalign.json +257 -0
  14. package/scripts/bench/round-r13-clientmeta.json +464 -0
  15. package/scripts/bench/round-r14-betafeatures.json +466 -0
  16. package/scripts/bench/round-r15-fulldefault.json +462 -0
  17. package/scripts/bench/round-r16-sessionid.json +466 -0
  18. package/scripts/bench/round-r17-wirebytes.json +456 -0
  19. package/scripts/bench/round-r18-prewarm.json +468 -0
  20. package/scripts/bench/round-r19-clean.json +472 -0
  21. package/scripts/bench/round-r20-prewarm-clean.json +475 -0
  22. package/scripts/bench/round-r21-delta-retry.json +473 -0
  23. package/scripts/bench/round-r22-full-probe.json +693 -0
  24. package/scripts/bench/round-r23-itemprobe.json +701 -0
  25. package/scripts/bench/round-r24-shapefix.json +677 -0
  26. package/scripts/bench/round-r25-serial.json +464 -0
  27. package/scripts/bench/round-r26-parallel3.json +671 -0
  28. package/scripts/bench/round-r27-parallel10.json +894 -0
  29. package/scripts/bench/round-r28-parallel10-stagger.json +882 -0
  30. package/scripts/bench/round-r29-parallel10-stagger166.json +886 -0
  31. package/scripts/bench/round-r30-instid.json +253 -0
  32. package/scripts/bench/round-r31-upgradeprobe.json +256 -0
  33. package/scripts/bench/round-r32-vs-codex-lead.json +254 -0
  34. package/scripts/bench/round-r33-vs-codex-codex.json +115 -0
  35. package/scripts/bench/round-r34-orchestrated.json +120 -0
  36. package/scripts/bench/round-r35-orchestrated-codex.json +61 -0
  37. package/scripts/bench/round-r36-orchestrated-capped.json +128 -0
  38. package/scripts/bench/round-r4-codex.json +114 -0
  39. package/scripts/bench/round-r4-mixed.json +225 -0
  40. package/scripts/bench/round-r5-gpt-lead.json +259 -0
  41. package/scripts/bench/round-r6-codex.json +114 -0
  42. package/scripts/bench/round-r6-solo.json +257 -0
  43. package/scripts/bench/round-r7-full.json +254 -0
  44. package/scripts/bench/round-r8-fulldefault.json +255 -0
  45. package/scripts/bench-run.mjs +251 -32
  46. package/scripts/freevar-smoke.mjs +95 -0
  47. package/scripts/internal-comms-bench.mjs +3 -4
  48. package/scripts/internal-comms-smoke.mjs +10 -9
  49. package/scripts/model-catalog-audit.mjs +209 -0
  50. package/scripts/model-list-sanitize-test.mjs +37 -0
  51. package/scripts/mouse-probe.mjs +45 -0
  52. package/scripts/output-style-bench.mjs +13 -6
  53. package/scripts/output-style-smoke.mjs +4 -4
  54. package/scripts/provider-toolcall-test.mjs +7 -3
  55. package/scripts/recall-bench.mjs +76 -13
  56. package/scripts/recall-quality-cases.json +12 -0
  57. package/scripts/recall-usecase-cases.json +18 -0
  58. package/scripts/session-bench.mjs +152 -6
  59. package/scripts/tool-smoke.mjs +25 -65
  60. package/scripts/tui-render-smoke.mjs +90 -0
  61. package/scripts/webhook-smoke.mjs +208 -0
  62. package/src/agents/debugger/AGENT.md +4 -1
  63. package/src/agents/heavy-worker/AGENT.md +9 -8
  64. package/src/agents/maintainer/AGENT.md +4 -0
  65. package/src/agents/reviewer/AGENT.md +2 -1
  66. package/src/agents/scheduler-task/AGENT.md +2 -3
  67. package/src/agents/webhook-handler/AGENT.md +2 -3
  68. package/src/agents/worker/AGENT.md +10 -7
  69. package/src/app.mjs +12 -1
  70. package/src/headless-role.mjs +7 -1
  71. package/src/lib/rules-builder.cjs +4 -0
  72. package/src/mixdog-session-runtime.mjs +647 -2056
  73. package/src/output-styles/default.md +30 -9
  74. package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
  75. package/src/output-styles/minimal.md +8 -6
  76. package/src/output-styles/simple.md +21 -7
  77. package/src/rules/agent/00-common.md +6 -3
  78. package/src/rules/agent/30-explorer.md +16 -5
  79. package/src/rules/lead/01-general.md +5 -5
  80. package/src/rules/lead/lead-brief.md +15 -0
  81. package/src/rules/lead/lead-tool.md +6 -15
  82. package/src/rules/shared/01-tool.md +17 -21
  83. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +8 -3
  84. package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
  85. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
  86. package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
  87. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
  88. package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
  89. package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
  90. package/src/runtime/agent/orchestrator/config.mjs +69 -2
  91. package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +62 -20
  92. package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
  93. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
  94. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +81 -1281
  95. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
  96. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +32 -3
  97. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
  98. package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
  99. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
  100. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
  101. package/src/runtime/agent/orchestrator/providers/gemini.mjs +43 -1013
  102. package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +17 -3
  103. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +105 -11
  104. package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +356 -0
  105. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
  107. package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
  108. package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
  109. package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +40 -1143
  110. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +740 -0
  111. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
  112. package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +349 -2131
  113. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +143 -1002
  114. package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +229 -0
  115. package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
  116. package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +465 -0
  117. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
  118. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
  119. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +80 -0
  120. package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
  121. package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
  122. package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
  123. package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
  124. package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
  125. package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
  126. package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
  127. package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
  128. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +14 -2
  129. package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
  130. package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -3
  131. package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +275 -0
  132. package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
  133. package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
  134. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
  135. package/src/runtime/agent/orchestrator/session/loop.mjs +278 -402
  136. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
  137. package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +7 -4
  138. package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +12 -0
  139. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
  140. package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
  141. package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
  142. package/src/runtime/agent/orchestrator/session/manager.mjs +166 -1087
  143. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
  144. package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
  145. package/src/runtime/agent/orchestrator/stall-policy.mjs +20 -1
  146. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
  147. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
  148. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +35 -44
  149. package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
  150. package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
  151. package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
  152. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
  153. package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -92
  154. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
  155. package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
  156. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +28 -265
  157. package/src/runtime/agent/orchestrator/tools/builtin.mjs +0 -6
  158. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +57 -3
  159. package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
  160. package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +10 -122
  161. package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
  162. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  163. package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
  164. package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
  165. package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
  166. package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
  167. package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
  168. package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
  169. package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
  170. package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
  171. package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
  172. package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
  173. package/src/runtime/agent/orchestrator/tools/progress-message.mjs +0 -21
  174. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +9 -72
  175. package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
  176. package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
  177. package/src/runtime/channels/backends/discord-access.mjs +32 -0
  178. package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
  179. package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
  180. package/src/runtime/channels/backends/discord.mjs +27 -318
  181. package/src/runtime/channels/backends/telegram.mjs +8 -12
  182. package/src/runtime/channels/index.mjs +247 -701
  183. package/src/runtime/channels/lib/backend-dispatch.mjs +46 -0
  184. package/src/runtime/channels/lib/config.mjs +37 -149
  185. package/src/runtime/channels/lib/event-pipeline.mjs +22 -5
  186. package/src/runtime/channels/lib/event-queue.mjs +78 -13
  187. package/src/runtime/channels/lib/inbound-routing.mjs +74 -0
  188. package/src/runtime/channels/lib/interaction-workflows.mjs +5 -113
  189. package/src/runtime/channels/lib/output-forwarder.mjs +1 -1
  190. package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
  191. package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
  192. package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
  193. package/src/runtime/channels/lib/scheduler.mjs +27 -113
  194. package/src/runtime/channels/lib/session-discovery.mjs +56 -4
  195. package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
  196. package/src/runtime/channels/lib/tool-format.mjs +1 -1
  197. package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
  198. package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
  199. package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
  200. package/src/runtime/channels/lib/webhook/deliveries.mjs +313 -0
  201. package/src/runtime/channels/lib/webhook/log.mjs +42 -0
  202. package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
  203. package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
  204. package/src/runtime/channels/lib/webhook.mjs +43 -616
  205. package/src/runtime/channels/tool-defs.mjs +11 -130
  206. package/src/runtime/memory/index.mjs +210 -1948
  207. package/src/runtime/memory/lib/core-memory-store.mjs +5 -1
  208. package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
  209. package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
  210. package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
  211. package/src/runtime/memory/lib/ko-morph.mjs +195 -0
  212. package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
  213. package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
  214. package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
  215. package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
  216. package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
  217. package/src/runtime/memory/lib/memory-cycle2.mjs +24 -842
  218. package/src/runtime/memory/lib/memory-embed.mjs +149 -0
  219. package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
  220. package/src/runtime/memory/lib/memory-recall-store.mjs +69 -12
  221. package/src/runtime/memory/lib/memory-text-utils.mjs +46 -0
  222. package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
  223. package/src/runtime/memory/lib/query-handlers.mjs +802 -0
  224. package/src/runtime/memory/lib/recall-format.mjs +55 -0
  225. package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
  226. package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
  227. package/src/runtime/memory/tool-defs.mjs +5 -13
  228. package/src/runtime/search/lib/http-fetch.mjs +274 -0
  229. package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
  230. package/src/runtime/search/lib/web-tools.mjs +24 -602
  231. package/src/runtime/shared/atomic-file.mjs +26 -1
  232. package/src/runtime/shared/config.mjs +14 -4
  233. package/src/runtime/shared/launcher-control.mjs +2 -2
  234. package/src/runtime/shared/markdown-frontmatter.mjs +19 -0
  235. package/src/runtime/shared/schedules-store.mjs +13 -3
  236. package/src/runtime/shared/tool-execution-contract.mjs +2 -2
  237. package/src/runtime/shared/tool-primitives.mjs +308 -0
  238. package/src/runtime/shared/tool-result-summary.mjs +515 -0
  239. package/src/runtime/shared/tool-surface.mjs +80 -898
  240. package/src/runtime/shared/transcript-writer.mjs +23 -0
  241. package/src/runtime/shared/update-checker.mjs +7 -4
  242. package/src/session-runtime/config-helpers.mjs +119 -2
  243. package/src/session-runtime/config-lifecycle.mjs +232 -0
  244. package/src/session-runtime/cwd-plugins.mjs +226 -0
  245. package/src/session-runtime/mcp-glue.mjs +177 -0
  246. package/src/session-runtime/model-recency.mjs +111 -0
  247. package/src/session-runtime/native-search.mjs +247 -0
  248. package/src/session-runtime/output-styles.mjs +11 -9
  249. package/src/session-runtime/prewarm.mjs +142 -0
  250. package/src/session-runtime/provider-models.mjs +278 -0
  251. package/src/session-runtime/provider-usage.mjs +120 -0
  252. package/src/session-runtime/quick-model-rows.mjs +205 -0
  253. package/src/session-runtime/quick-search-models.mjs +47 -0
  254. package/src/session-runtime/session-hooks.mjs +93 -0
  255. package/src/session-runtime/settings-api.mjs +352 -0
  256. package/src/session-runtime/tool-catalog.mjs +29 -29
  257. package/src/session-runtime/tool-defs.mjs +84 -0
  258. package/src/session-runtime/warmup-schedulers.mjs +201 -0
  259. package/src/session-runtime/workflow.mjs +1 -1
  260. package/src/standalone/agent-tool/helpers.mjs +237 -0
  261. package/src/standalone/agent-tool/notify.mjs +107 -0
  262. package/src/standalone/agent-tool/provider-init.mjs +143 -0
  263. package/src/standalone/agent-tool/render.mjs +152 -0
  264. package/src/standalone/agent-tool/tool-def.mjs +55 -0
  265. package/src/standalone/agent-tool.mjs +138 -669
  266. package/src/standalone/channel-admin.mjs +102 -90
  267. package/src/standalone/channel-worker.mjs +4 -7
  268. package/src/standalone/explore-tool.mjs +64 -14
  269. package/src/standalone/hook-bus/config.mjs +207 -0
  270. package/src/standalone/hook-bus/constants.mjs +90 -0
  271. package/src/standalone/hook-bus/handlers.mjs +481 -0
  272. package/src/standalone/hook-bus/payload.mjs +31 -0
  273. package/src/standalone/hook-bus/rules.mjs +77 -0
  274. package/src/standalone/hook-bus.mjs +77 -870
  275. package/src/standalone/memory-runtime-proxy.mjs +7 -0
  276. package/src/standalone/opencode-go-login.mjs +5 -1
  277. package/src/standalone/provider-admin.mjs +1 -16
  278. package/src/standalone/usage-dashboard.mjs +3 -1
  279. package/src/tui/App.jsx +1059 -8110
  280. package/src/tui/app/app-format.mjs +213 -0
  281. package/src/tui/app/channel-pickers.mjs +508 -0
  282. package/src/tui/app/clipboard.mjs +67 -0
  283. package/src/tui/app/core-memory-picker.mjs +210 -0
  284. package/src/tui/app/extension-pickers.mjs +506 -0
  285. package/src/tui/app/input-parsers.mjs +193 -0
  286. package/src/tui/app/maintenance-pickers.mjs +356 -0
  287. package/src/tui/app/model-options.mjs +334 -0
  288. package/src/tui/app/model-picker.mjs +365 -0
  289. package/src/tui/app/onboarding-steps.mjs +400 -0
  290. package/src/tui/app/project-picker.mjs +247 -0
  291. package/src/tui/app/provider-setup-picker.mjs +580 -0
  292. package/src/tui/app/resume-picker.mjs +55 -0
  293. package/src/tui/app/route-pickers.mjs +419 -0
  294. package/src/tui/app/settings-picker.mjs +489 -0
  295. package/src/tui/app/slash-commands.mjs +101 -0
  296. package/src/tui/app/slash-dispatch.mjs +427 -0
  297. package/src/tui/app/text-layout.mjs +46 -0
  298. package/src/tui/app/theme-effort-pickers.mjs +154 -0
  299. package/src/tui/app/transcript-window.mjs +677 -0
  300. package/src/tui/app/use-mouse-input.mjs +460 -0
  301. package/src/tui/app/use-prompt-handlers.mjs +310 -0
  302. package/src/tui/app/use-transcript-scroll.mjs +512 -0
  303. package/src/tui/app/use-transcript-window.mjs +607 -0
  304. package/src/tui/components/ConfirmBar.jsx +10 -7
  305. package/src/tui/components/Picker.jsx +64 -15
  306. package/src/tui/components/PromptInput.jsx +33 -102
  307. package/src/tui/components/SlashCommandPalette.jsx +8 -1
  308. package/src/tui/components/StatusLine.jsx +69 -15
  309. package/src/tui/components/TextEntryPanel.jsx +11 -0
  310. package/src/tui/components/ToolExecution.jsx +52 -594
  311. package/src/tui/components/TranscriptItem.jsx +105 -0
  312. package/src/tui/components/UsagePanel.jsx +18 -4
  313. package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
  314. package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
  315. package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
  316. package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
  317. package/src/tui/components/tool-execution/text-format.mjs +161 -0
  318. package/src/tui/display-width.mjs +20 -3
  319. package/src/tui/dist/index.mjs +13553 -12384
  320. package/src/tui/engine/agent-job-feed.mjs +133 -0
  321. package/src/tui/engine/notification-plan.mjs +76 -0
  322. package/src/tui/engine/render-timing.mjs +17 -0
  323. package/src/tui/engine/tool-approval.mjs +94 -0
  324. package/src/tui/engine/tool-card-results.mjs +234 -0
  325. package/src/tui/engine/tool-result-status.mjs +135 -0
  326. package/src/tui/engine.mjs +170 -574
  327. package/src/tui/figures.mjs +5 -0
  328. package/src/tui/index.jsx +65 -1
  329. package/src/tui/input-editing.mjs +2 -2
  330. package/src/tui/markdown/format-token.mjs +4 -1
  331. package/src/tui/statusline-ansi-bridge.mjs +11 -3
  332. package/src/tui/theme.mjs +6 -0
  333. package/src/ui/statusline-agents.mjs +213 -0
  334. package/src/ui/statusline-format.mjs +146 -0
  335. package/src/ui/statusline-segments.mjs +148 -0
  336. package/src/ui/statusline.mjs +77 -501
  337. package/src/ui/tool-card.mjs +0 -1
  338. package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
  339. package/src/workflows/default/WORKFLOW.md +16 -18
  340. package/src/workflows/sequential/WORKFLOW.md +16 -18
  341. package/vendor/ink/build/display-width.js +19 -3
  342. package/vendor/ink/build/ink.js +112 -7
  343. package/vendor/ink/build/log-update.js +17 -3
  344. package/vendor/ink/build/wrap-text.js +125 -0
  345. package/scripts/_test-folder-dialog.mjs +0 -30
  346. package/scripts/fix-brief-fn.mjs +0 -35
  347. package/scripts/fix-format-tool-surface.mjs +0 -24
  348. package/scripts/fix-tool-exec-visible.mjs +0 -42
  349. package/scripts/patch-agent-brief.mjs +0 -48
  350. package/scripts/patch-app.mjs +0 -21
  351. package/scripts/patch-app2.mjs +0 -18
  352. package/scripts/patch-dist-brief.mjs +0 -96
  353. package/scripts/patch-tool-exec.mjs +0 -70
  354. package/src/examples/schedules/SCHEDULE.example.md +0 -32
  355. package/src/examples/webhooks/WEBHOOK.example.md +0 -40
  356. package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
  357. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
  358. package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
  359. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +0 -162
  360. package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
  361. package/src/runtime/channels/lib/holidays.mjs +0 -138
  362. package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
  363. package/src/runtime/shared/task-notification-envelope.test.mjs +0 -107
  364. package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
  365. package/src/standalone/agent-task-status.test.mjs +0 -76
  366. package/src/tui/components/tool-output-format.test.mjs +0 -399
  367. package/src/tui/display-width.test.mjs +0 -35
  368. package/src/tui/engine-runtime-notification.test.mjs +0 -115
  369. package/src/tui/engine-tool-result-text.test.mjs +0 -75
  370. package/src/tui/input-editing.selection.test.mjs +0 -75
  371. package/src/tui/markdown/format-token.test.mjs +0 -354
  372. package/src/tui/markdown/render-ansi.test.mjs +0 -108
  373. package/src/tui/markdown/stream-fence.test.mjs +0 -26
  374. package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
  375. package/src/tui/paste-fix.test.mjs +0 -119
  376. package/src/tui/prompt-history-store.test.mjs +0 -52
  377. package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
  378. package/src/tui/transcript-tool-failures.test.mjs +0 -111
  379. package/src/ui/markdown.test.mjs +0 -70
  380. package/src/ui/statusline-context-label.test.mjs +0 -15
  381. package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
  382. package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
@@ -7,21 +7,42 @@ keep-coding-instructions: true
7
7
 
8
8
  # Output Style
9
9
 
10
- Mixdog default — the most detailed of the three styles, but only as long as the
11
- task warrants.
10
+ Mixdog default — the most detailed style, but always summary-form, never
11
+ essay-form. Depth comes from picking the right facts, not explaining more.
12
12
 
13
- - Lead with the outcome, then add the supporting detail that matters: what
14
- changed, key evidence (paths, commands, errors, verification), and important
15
- context. Include trade-offs or follow-up only when they actually matter.
16
- - Use a few bullets or short paragraphs when they add signal; this style may run
17
- longer than Simple, but match length to the work do not pad a small change
18
- into a full report. Cut anything that does not earn its place.
13
+ Content
14
+ - Lead with the outcome in one short sentence, then only the detail that
15
+ matters: what changed, key evidence (paths, commands, errors, verification).
16
+ - Summarize at the concept level: name the problem/behavior and direction, not
17
+ the code path. Cite a symbol/path only as an anchor, never as the explanation.
18
+ - Compress by cutting content (filler, hedging, connective padding, restated
19
+ facts), not by clipping grammar: keep natural, complete sentences in the
20
+ user's language — never telegraph-style stub endings. Technical terms and
21
+ code stay exact.
22
+ - State conclusions, not reasoning: no mechanism walkthroughs, background, or
23
+ chained qualifiers unless asked. One decisive fact beats three hedges.
24
+ - Say each point once: problem and fix in ONE compact statement, not a restated
25
+ pair. Prefer fewer, denser items over covering every nuance.
26
+ - Size budget: roughly TWICE the Simple style — per point about 2 rendered
27
+ lines, whole report ~10–15 lines. Spend the extra room on evidence and
28
+ context Simple would drop, not on longer sentences.
19
29
  - Use labels such as `바뀐 점`, `확인한 것`, and `남은 리스크/다음 단계`
20
30
  in final reports to structure the summary; skip labels on interim progress.
21
31
  - Collapse trivial tasks to a couple of sentences instead of forcing sections.
22
32
  - Synthesize agent or retrieval results; never forward raw reports, long file
23
33
  lists, tool traces, or session metadata.
24
34
  - Do not hide blockers, failed verification, or required follow-up; surface them
25
- explicitly rather than omitting them.
35
+ in one short clause.
26
36
  - Keep paths, commands, symbols, API names, code, and exact errors verbatim.
37
+
38
+ Layout (hard rules)
39
+ - One bullet or numbered item = one idea, at most 2 rendered lines including its
40
+ sub-bullet. If it needs more, cut the detail — do not add lines.
41
+ - Open each item with a short **bold key point**, then the brief elaboration —
42
+ never bury the point mid-sentence.
43
+ - Insert a blank line between numbered items, and between any list items running
44
+ past one line (loose list). Never emit a wall of consecutive multi-line items.
45
+ - Keep paragraphs to ~3 lines max, with a blank line between paragraphs, lists,
46
+ and code blocks.
47
+ - Nest at most one sub-level; deeper detail means you are over-explaining.
27
48
  - Never name this style unless asked.
@@ -1,14 +1,15 @@
1
1
  ---
2
- name: oneline
3
- title: Oneline
2
+ name: extreme-minimal
3
+ title: Extreme Minimal
4
4
  description: Single sentence under 100 characters
5
- aliases: one-line, one line, mono
5
+ aliases: extreme, oneline, one-line, one line, mono
6
6
  keep-coding-instructions: true
7
7
  ---
8
8
 
9
9
  # Output Style
10
10
 
11
- Oneline — the most minimal style: exactly one sentence, under 100 characters.
11
+ Extreme minimal — the most compressed style: exactly one sentence, under 100
12
+ characters.
12
13
 
13
14
  - Reply with a SINGLE sentence, always under 100 characters. Never a second
14
15
  sentence, clause pile-up, or run-on that smuggles in extra facts.
@@ -2,7 +2,6 @@
2
2
  name: minimal
3
3
  title: Minimal
4
4
  description: One- or two-sentence summary
5
- aliases: extreme, extreme-simple
6
5
  keep-coding-instructions: true
7
6
  ---
8
7
 
@@ -12,12 +11,15 @@ Minimal — a very short summary: one or two sentences, nothing more.
12
11
 
13
12
  - Summarize only the net result in one short sentence; add a second short
14
13
  sentence only if a second fact (verification, blocker) genuinely needs it.
15
- Never cram unrelated facts into one run-on line just to stay at one sentence.
16
- - Summarize, never itemize: do not describe which files changed or how they were
17
- edited. State only what the change accomplishes.
14
+ Never cram unrelated facts into a run-on just to stay at one sentence.
15
+ - Size budget: roughly HALF the Simple style 1–2 plain sentences, ~2–3
16
+ rendered lines at most, however large the task was.
17
+ - Compress by cutting content, not grammar: natural, complete sentences only.
18
+ Concept-level only — never walk through code or mechanisms.
19
+ - Summarize, never itemize: do not describe which files changed or how. State
20
+ only what the change accomplishes.
18
21
  - No headings, bullets, numbered lists, labels, or sections — plain sentences
19
- only. This holds even when the request says "report" or "summary"; keep it to
20
- one or two sentences regardless.
22
+ only, even when the request says "report" or "summary".
21
23
  - Preferred pattern: `<target> 변경되었습니다. <verification> 통과 완료입니다.`
22
24
  - If verification was not run, say the change is done and verification was not
23
25
  run.
@@ -8,16 +8,30 @@ keep-coding-instructions: true
8
8
 
9
9
  # Output Style
10
10
 
11
- Practical concise — outcome-first handoffs for coding work: summarize the result,
12
- do not narrate the change.
11
+ Practical concise — outcome-first handoffs for coding work: summarize the
12
+ result, do not narrate or explain the change.
13
13
 
14
14
  - Open with the outcome in one sentence: done, blocked, or awaiting a decision.
15
+ - Summarize at the concept level: name the behavior and direction, not the code
16
+ path. Cite a symbol/path only as an anchor, never as the explanation.
17
+ - Compress by cutting content (filler, hedging, pleasantries, restated facts),
18
+ not by clipping grammar: keep natural, complete sentences in the user's
19
+ language — never telegraph-style stub endings. Technical terms and code stay
20
+ exact.
15
21
  - Summarize what the change accomplishes rather than listing every file and how
16
22
  each was edited. Name a path (`file_path:line_number`) only when the reader
17
23
  truly needs it to navigate — not as a per-file changelog.
18
- - Keep controlled detail: usually 1–3 short bullets or 2–4 sentences total. No
19
- step-by-step narration, no exhaustive file/line inventory. Expand only when the
20
- user asks, scope is ambiguous, or a blocker needs concrete next steps.
24
+ - Keep controlled detail: usually 1–3 short bullets or 2–3 sentences total.
25
+ State each point once outcome or fix direction, not both restated. No
26
+ step-by-step narration or file/line inventory.
27
+ - Size budget: roughly HALF the Default style and TWICE Minimal — per point one
28
+ rendered line, whole reply ~5–7 lines. Above that you are writing Default;
29
+ below ~3 lines consider whether prose (Minimal) reads better.
30
+ - Layout: one idea per bullet, ONE line each (two only when a verbatim
31
+ path/error forces it). Lead each item with a short bold key phrase. Put a
32
+ blank line between multi-line list items — never emit a dense wall of text.
33
+ - If a point runs past one line, cut the elaboration instead of wrapping; detail
34
+ beyond the key phrase + one clause belongs to the Default style.
21
35
  - On final handoffs, optional labels such as `바뀐 점`, `확인한 것`, and
22
36
  `남은 리스크/다음 단계` fit Korean-facing profiles; use plain English labels
23
37
  when the thread is English. Do not label interim progress.
@@ -26,6 +40,6 @@ do not narrate the change.
26
40
  - Do not hide blockers, failed verification, or required follow-up; state them
27
41
  in one short clause.
28
42
  - Keep paths, commands, symbols, API names, code, and exact errors verbatim.
29
- - Skip filler, acknowledgments, and repeated conclusions; if verification was
30
- not run, say so once.
43
+ - Skip filler, acknowledgments, hedging, and repeated conclusions; if
44
+ verification was not run, say so once.
31
45
  - Never name this style unless asked.
@@ -3,15 +3,18 @@
3
3
  - Use English for agent task communication.
4
4
  - Do not touch git/Ship. Even when the brief instructs `git add` / `commit` /
5
5
  `push` / `stash`, refuse with `git operations deferred to Lead`.
6
- - NEVER PREAMBLE. Do not generate preamble tokens, including tool-call
7
- preambles, status/progress narration, "I will..." setup text, or transition
8
- text before tool calls.
6
+ - NEVER PREAMBLE: no tool-call preambles, status/progress narration, "I
7
+ will..." setup, or transition text before tool calls.
9
8
  - If tools are needed, call them immediately. Emit text only for the final
10
9
  handoff after tool work is done.
11
10
  - Final handoff: minimum characters, maximum information for Lead. Follow the
12
11
  role's stricter output contract if defined; else emit fragments — outcome
13
12
  (1 line), key `file:line`(s), verification result, material risks (only if
14
13
  any).
14
+ - Handoff cap ~30 lines unless `Deliver:` raises it. Overflow goes to a file;
15
+ hand off path + fragments.
15
16
  - Banned as pure cost: report headings, markdown tables (unless requested),
16
17
  prose narration, raw logs/tool traces, speculative next-checks, restated
17
18
  brief, articles/politeness.
19
+ - Exception: a runtime wrap-up directive (exploration budget reached) overrides
20
+ this — then summarize done/remaining/blocking as instructed.
@@ -8,11 +8,22 @@ kind: retrieval
8
8
 
9
9
  You are a one-shot locator, not a researcher.
10
10
 
11
- Procedure: send ONE turn containing one `grep` (all synonyms in one
12
- `pattern:[...]`, output_mode content_with_context) plus one `code_graph`
13
- call. The results contain path:line — answer immediately from them.
14
- If both miss, answer `EXPLORATION_FAILED`. Do not send a second lookup turn.
11
+ Find code anchors fast. Batch independent lookups in turn 1: one `grep`
12
+ with all literal strings/errors/identifier guesses, plus `code_graph`/`find`
13
+ or `glob` when useful.
14
+
15
+ Prefer user-visible strings and identifiers. `dist`/generated hits are leads,
16
+ not answers: trace them back to source. On miss, derive new tokens from
17
+ returned paths/names or widen scope; do not repeat synonyms. NEVER issue
18
+ serial single-tool turns: every turn after the first must batch ALL remaining
19
+ candidate lookups in one shot.
20
+
21
+ Budget: 4 tool turns. The FIRST credible `path:line` ends the search — answer
22
+ with what you have; more anchors are not more value. Spend remaining turns
23
+ only while you have zero anchors, and buy coverage with wider batches, never
24
+ with extra serial turns. On ANY iteration warning, answer immediately with
25
+ best anchors or `EXPLORATION_FAILED`.
15
26
 
16
27
  Answer format, nothing else:
17
- - up to 5 lines of `path:line — symbol/name — short reason` (append `?` if weak)
28
+ - up to 5 lines: `path:line — symbol/name — short reason` (append `?` if weak)
18
29
  - or `EXPLORATION_FAILED`
@@ -1,11 +1,11 @@
1
1
  # General
2
2
 
3
3
  - Omit direct names, honorifics, headings, and labels in preambles.
4
- - Preambles are optional: use them only when they add user-visible value, keep
5
- them to one short sentence, and skip routine lookup narration.
4
+ - Preambles are optional: use only when they add user-visible value, keep to
5
+ one short sentence, skip routine lookup narration.
6
6
  - Destructive/hard-to-reverse actions require explicit confirmation.
7
7
  - Never push, build, or deploy without an explicit user request.
8
8
  Implementation approval is not deploy approval.
9
- - Rather than deferring checks or work to the user, proactively handle whatever
10
- you can first, and propose only the parts that need a decision in a
11
- consultative tone ("Shall we proceed this way?").
9
+ - Proactively handle what you can first rather than deferring to the user;
10
+ propose only the parts needing a decision, consultatively ("Shall we
11
+ proceed this way?").
@@ -0,0 +1,15 @@
1
+ # Lead Brief Contract
2
+
3
+ - Brief = one-line fragments `Goal:` `Anchors:` `Allow/Forbid:` `Deliver:`
4
+ `Verify:` (+`Stop:` heavy-worker). No role-known rules, background, or
5
+ motivation — minimum characters, maximum information.
6
+ - `Deliver:` states output size/shape (e.g. "fragments <=15 lines", "verdict
7
+ + top-3 risks", "detail to file, path only"). Never request a long report
8
+ in the handoff itself.
9
+ - Full brief only on fresh spawn or `respawned: true` (dead-tag send = cold
10
+ session; re-supply anchors). Live-session follow-ups = delta only; never
11
+ restate Goal/rules.
12
+ - Never `send` mid-run; batch all adjustments into ONE follow-up after
13
+ completion. Interrupt only to cancel.
14
+ - All agent communication in English.
15
+ - Referenced spec/test file beats its summary in the brief.
@@ -1,17 +1,8 @@
1
1
  # Lead Tool Use
2
2
 
3
- - Lead owns repo-local shell work: run git/build/test/verification commands via
4
- `shell` directly; do not delegate them to agents.
5
- - Use the current project/workspace selected by the session. Only change the work project when the user asks for a different project or a tool call explicitly needs another project root.
6
- - Use `agent` for scoped implementation, research, review, and debugging, not for git commit/push/stash or Ship.
7
- - A `send` to a reaped/dead tag auto-respawns a FRESH session under the same
8
- tag (result carries `respawned: true`). That worker has no prior session
9
- context — treat the message as a cold brief and re-supply anchors
10
- (`file:line`) on it or the next send.
11
- - Briefs: minimum characters, maximum information. Fixed one-line fragment
12
- fields — `Goal:` `Anchors:` `Allow/Forbid:` `Deliver:` `Verify:` (+`Stop:` for
13
- heavy-worker). Omit role-known rules (git/preamble bans, output format),
14
- background, motivation; non-actionable tokens are wasted cost.
15
- - Bridge language is ALWAYS English: every brief, follow-up `send`, and
16
- steering message to an agent is written in English regardless of the
17
- user-facing language.
3
+ - Lead owns repo-local shell work: run git/build/test/verification via `shell`
4
+ directly; do not delegate to agents.
5
+ - Use the session's current project/workspace. Change the work project only
6
+ when the user asks for another project or a tool call needs another root.
7
+ - Use `agent` for scoped implementation, research, review, and debugging not
8
+ for git commit/push/stash or Ship.
@@ -1,25 +1,21 @@
1
1
  # Tool Use
2
2
 
3
- - Independent lookups MUST batch in one turn; serialize only when a call needs
4
- a prior result. This includes edit loops: batch the post-edit verification
5
- read with the next target's lookup instead of emitting single-call turns.
6
- - Target validity comes first: symbols/callers/deps → `code_graph`; exact text in
7
- a verified scope → `grep`; unknown path/name → `find`; structure → `glob`;
8
- dirs → `list`; verified file → `read`; broad unknown with no anchor →
9
- `explore`. Never call `grep`/`read` on guessed paths.
10
- - Concept normalization comes first: one concept gets one batched
11
- `grep pattern:[...]` with `output_mode:"content_with_context"` (or one
12
- `code_graph symbols[]`). Refine from returned paths; do not repeat equivalent
13
- patterns or scopes.
3
+ - Batch independent lookups in one turn; serialize only when a call needs a
4
+ prior result including edit loops: batch the post-edit verification read
5
+ with the next target's lookup.
6
+ - Pick by target: symbols/callers/deps → `code_graph`; exact text in a verified
7
+ scope → `grep`; unknown path/name → `find`; structure → `glob`; dirs →
8
+ `list`; verified file → `read`; broad unknown with no anchor → `explore`.
9
+ Never `grep`/`read` guessed paths.
10
+ - One concept one batched `grep pattern:[...]` with
11
+ `output_mode:"content_with_context"` (or one `code_graph symbols[]`). Refine
12
+ from returned paths; never repeat equivalent patterns or scopes.
14
13
  - On miss/error, normalize the target once and switch tool; on a plausible hit,
15
- stop searching and answer from the framed context.
16
- - Lookup budget: retrieval exists to reach the NEXT action (edit, answer,
17
- handoff), not to build certainty. One anchor is enough to act on; re-reading
18
- or re-grepping an area you already saw this session is waste. When acting
19
- and looking are both possible, act.
20
- - Avoid read fragmentation: `read` uses `offset`/`limit` only. If you need 2+
21
- spans from one or more known files, make one batched `read` call with
22
- `{path,offset,limit}` region objects instead of serial reads. Adjacent spans
23
- in the same file (within a few hundred lines) are ONE window, not repeated
24
- reads.
14
+ stop and answer from the framed context.
15
+ - Retrieval serves the NEXT action (edit, answer, handoff), not certainty. One
16
+ anchor is enough to act on; re-reading/re-grepping an area seen this session
17
+ is waste. When acting and looking are both possible, act.
18
+ - `read` uses `offset`/`limit` only. For 2+ spans from known file(s), make one
19
+ batched `read` with `{path,offset,limit}` region objects. Adjacent spans in
20
+ one file (within a few hundred lines) are ONE window, not repeated reads.
25
21
  - Don't mix `apply_patch` with shell or other state-changing calls in one turn.
@@ -356,6 +356,10 @@ export function makeAgentDispatch(opts = {}) {
356
356
  if (_idleController) {
357
357
  try { _linkSignal(session.id, _idleController.signal); } catch { /* ignore */ }
358
358
  }
359
+ // Watchdog blind spot guard: when the runtime snapshot is missing AND
360
+ // no progress timestamp exists (pre-liveness hang, swept runtime), the
361
+ // dispatch start time anchors staleness so the abort still fires.
362
+ const _watchdogAnchorTs = Date.now();
359
363
  const _idleTimer = (_idleController && (typeof _getProgressSnapshot === 'function' || typeof _getLastProgressAt === 'function'))
360
364
  ? setInterval(() => {
361
365
  const now = Date.now();
@@ -363,9 +367,10 @@ export function makeAgentDispatch(opts = {}) {
363
367
  const abortErr = snapshot
364
368
  ? evaluateAgentWatchdogAbort(snapshot, now, _watchdogPolicy)
365
369
  : null;
366
- if (!abortErr && !snapshot && typeof _getLastProgressAt === 'function') {
367
- const last = _getLastProgressAt(session.id);
368
- if (_watchdogPolicy.idleStaleMs > 0 && last && now - last > _watchdogPolicy.idleStaleMs) {
370
+ if (!abortErr && !snapshot) {
371
+ const reported = typeof _getLastProgressAt === 'function' ? _getLastProgressAt(session.id) : 0;
372
+ const last = reported || _watchdogAnchorTs;
373
+ if (_watchdogPolicy.idleStaleMs > 0 && now - last > _watchdogPolicy.idleStaleMs) {
369
374
  try { _idleController.abort(new Error(`agent task stale (${_watchdogPolicy.idleStaleMs}ms without progress)`)); } catch { /* ignore */ }
370
375
  }
371
376
  return;
@@ -17,6 +17,31 @@ function envPositiveInt(name, fallback) {
17
17
  // to raise/lower the safety ceiling, never used as a per-agent task budget.
18
18
  export const LEAD_MAX_LOOP_ITERATIONS = envPositiveInt('MIXDOG_AGENT_MAX_LOOP', 200);
19
19
 
20
+ // Worker soft cap — behavior-based ONLY. There is intentionally no fixed
21
+ // iteration threshold: a legitimately long worker task (many edit/verify
22
+ // rounds) must never be cut off by a count. The wrap-up is armed exclusively
23
+ // by the steering ladder's early-cap signal (repeated ignored level-2 steers
24
+ // with zero edits = confirmed read-only stall), after the ladder's own
25
+ // warnings have gone out. The env knob remains as an opt-in count for
26
+ // operators who want one; by default it is effectively disabled.
27
+ export const WORKER_SOFT_CAP_ITERATIONS = envPositiveInt('MIXDOG_AGENT_SOFT_CAP', Number.MAX_SAFE_INTEGER);
28
+
29
+ // Agents subject to the soft cap: implementation workers that should wrap up
30
+ // once the exploration budget is spent. Reviewer and hidden long-runner agents
31
+ // (explorer / cycle / scheduler / …) are legitimately read-only long-running
32
+ // and are EXEMPT — capping them would truncate a valid long read pass.
33
+ const SOFT_CAP_AGENTS = new Set(['worker', 'heavy-worker', 'maintainer', 'debugger']);
34
+
35
+ /**
36
+ * Is this session a delegated worker subject to the soft cap?
37
+ * Only worker/heavy-worker/maintainer/debugger. Lead, TUI (no agent),
38
+ * reviewer, and hidden agents return false.
39
+ */
40
+ export function isWorkerSoftCapSession(sessionRef) {
41
+ const agent = sessionRef?.agent;
42
+ return typeof agent === 'string' && SOFT_CAP_AGENTS.has(agent);
43
+ }
44
+
20
45
  /**
21
46
  * Resolve the hard cap used by agentLoop for this session.
22
47
  *
@@ -10,7 +10,8 @@
10
10
  * BP_1 system#1 (1h) — shared tool policy + compact skill manifest
11
11
  * BP_2 system#2 (1h) — role/system rules (Lead / agent / hidden role)
12
12
  * BP_3 system#3 (1h) — stable memory/meta marker (sessionMarker system block; tier3)
13
- * BP_4 messages (5m) — sliding tool_result / prior user-text tail
13
+ * BP_4 messages (5m agents/hidden; Lead linked to autoClear — see below) —
14
+ * sliding tool_result / prior user-text tail
14
15
  *
15
16
  * Tool schemas still sit before system in the provider prompt prefix. We do
16
17
  * not spend a separate cache_control slot on tools; the first system BP covers
@@ -51,10 +52,14 @@ import { getHiddenAgent } from '../internal-agents.mjs';
51
52
  */
52
53
  function isOneShotMaintenanceAgent(agent) {
53
54
  const hidden = getHiddenAgent(agent);
55
+ // Shipped cycle1/2/3 declare toolSchemaProfile:'none' (no tool schema at
56
+ // all); 'llm-only' is the legacy alias for the same one-shot LLM-only
57
+ // pattern. Multi-turn maintenance roles (scheduler-task/webhook-handler)
58
+ // are 'read-write-search' and stay excluded.
54
59
  return Boolean(
55
60
  hidden
56
61
  && hidden.kind === 'maintenance'
57
- && hidden.toolSchemaProfile === 'llm-only',
62
+ && (hidden.toolSchemaProfile === 'llm-only' || hidden.toolSchemaProfile === 'none'),
58
63
  );
59
64
  }
60
65
 
@@ -71,8 +76,16 @@ function isOneShotMaintenanceAgent(agent) {
71
76
  * warm window survives per-session gaps. The volatile message tail (BP4) is
72
77
  * per-session and trace data (2026-06) shows request gaps are p99 ≈ 4.5min —
73
78
  * 5m+ gaps mean a cold tail anyway, and the smart-compact path rebuilds the
74
- * history at that boundary. So every session's tail uses the cheaper 5m TTL
75
- * (1.25x write vs 2x), aligned with the 5m terminal-reap window for agents.
79
+ * history at that boundary. So hidden-agent and public-agent sessions keep
80
+ * the cheaper 5m tail TTL (1.25x write vs 2x), aligned with the 5m
81
+ * terminal-reap window for agents.
82
+ *
83
+ * Lead sessions are linked to the user's autoClear idle-sweep config
84
+ * instead of the fixed 5m default (see resolveLeadMessagesTtl): a Lead
85
+ * session that autoClear will only reap after a long/never idle window
86
+ * benefits from the 1h tail TTL (fewer writes over a long-lived session),
87
+ * while a short idle-sweep window means the tail is going cold anyway and
88
+ * 5m is cheaper to write.
76
89
  * (Tail TTL only affects explicit-breakpoint providers — Anthropic; no-op
77
90
  * elsewhere.)
78
91
  *
@@ -84,15 +97,41 @@ function isOneShotMaintenanceAgent(agent) {
84
97
  * the 1h TTL expiry (writes every run, 0 reads). All layers go 'none' for
85
98
  * these roles — single-iteration calls pay the write premium with no reuse.
86
99
  */
87
- export function resolveCacheStrategy(agent) {
100
+
101
+ /**
102
+ * Lead-session BP4 (messages tail) TTL, linked to the autoClear idle-sweep
103
+ * config (config.mjs `autoClear: { enabled, idleMs }`, normalized via
104
+ * session-runtime/config-helpers.mjs normalizeAutoClearConfig):
105
+ * - autoClear disabled → '1h' (session may live indefinitely;
106
+ * amortize the 2x write premium over a long-lived tail)
107
+ * - idleMs >= 1h (3_600_000ms) → '1h' (idle-sweep window is at least
108
+ * as long as the 1h TTL, so the longer TTL is never wasted)
109
+ * - otherwise (shorter idle-sweep) → '5m' (session reaps before a 1h
110
+ * write would ever be re-read; cheaper 5m write wins)
111
+ */
112
+ export function resolveLeadMessagesTtl(autoClear) {
113
+ if (autoClear && autoClear.enabled === false) return '1h';
114
+ const idleMs = Number(autoClear?.idleMs);
115
+ if (Number.isFinite(idleMs) && idleMs >= 3_600_000) return '1h';
116
+ return '5m';
117
+ }
118
+
119
+ export function resolveCacheStrategy(agent, { autoClear } = {}) {
88
120
  if (isOneShotMaintenanceAgent(agent)) {
89
121
  return { tools: 'none', system: 'none', tier3: 'none', messages: 'none' };
90
122
  }
91
123
  if (getHiddenAgent(agent)) {
92
124
  return { tools: 'none', system: '1h', tier3: '1h', messages: '5m' };
93
125
  }
94
- // Lead + public agents: per-session volatile tail -> 5m (see doc above).
95
- return { tools: 'none', system: '1h', tier3: '1h', messages: '5m' };
126
+ if (agent && agent !== 'lead') {
127
+ // Public (non-hidden, non-lead) agents keep the flat 5m tail — only
128
+ // the Lead session's tail is linked to autoClear.
129
+ return { tools: 'none', system: '1h', tier3: '1h', messages: '5m' };
130
+ }
131
+ // Lead session (agent === 'lead', or no agent — raw/CLI callers default
132
+ // to Lead behavior): message tail TTL is linked to autoClear (see
133
+ // resolveLeadMessagesTtl).
134
+ return { tools: 'none', system: '1h', tier3: '1h', messages: resolveLeadMessagesTtl(autoClear) };
96
135
  }
97
136
 
98
137
  /**
@@ -200,6 +239,25 @@ function normalizePromptCacheNamespace(value) {
200
239
  return s.replace(/[^A-Za-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '') || 'mixdog-shared';
201
240
  }
202
241
 
242
+ function fitPromptCacheKey(value, fallback = 'mixdog-shared') {
243
+ const s = normalizePromptCacheNamespace(value || fallback);
244
+ if (s.length <= 64) return s;
245
+ const hash = shortHash(s, 12);
246
+ const head = s.slice(0, Math.max(1, 64 - hash.length - 1));
247
+ return `${head}-${hash}`;
248
+ }
249
+
250
+ function codexThreadPromptCacheKey(opts, namespace) {
251
+ const explicit = cleanString(opts?.providerCacheKey)
252
+ || cleanString(opts?.promptCacheKey)
253
+ || cleanString(opts?.session?.promptCacheKey);
254
+ if (process.env.MIXDOG_OAI_CACHE_KEY_SHARED === '1') {
255
+ return fitPromptCacheKey(explicit || namespace, 'mixdog-codex');
256
+ }
257
+ const sessionKey = cleanString(opts?.sessionId || opts?.session?.id);
258
+ return fitPromptCacheKey(sessionKey || explicit || namespace, namespace);
259
+ }
260
+
203
261
  function summarizePromptCacheTools(tools) {
204
262
  return (tools || []).map(t => ({
205
263
  type: cleanString(t?.type) || 'function',
@@ -211,13 +269,19 @@ function summarizePromptCacheTools(tools) {
211
269
 
212
270
  /**
213
271
  * Build a stable, prefix-scoped prompt_cache_key for OpenAI-style key-prefix
214
- * providers. The base namespace still comes from resolveProviderCacheKey()
215
- * (so overrides keep working), but a model/system/tools hash is appended so
216
- * unrelated main/worker prefixes do not evict each other inside one shared
217
- * provider lane.
272
+ * providers. OpenAI OAuth follows Codex's thread-scoped key by default:
273
+ * prompt_cache_key is the session/thread identity, clamped to the backend's
274
+ * 64-character limit. Other OpenAI-style providers keep the older
275
+ * namespace+prefix-hash key shape, but no longer get a shard suffix unless an
276
+ * explicit cache-lane override opts into it.
218
277
  */
219
278
  export function buildStableProviderPromptCacheKey(provider, opts, prefix = {}) {
220
279
  const namespace = normalizePromptCacheNamespace(resolveProviderCacheKey(opts, provider));
280
+ if (provider === 'openai-oauth'
281
+ && process.env.MIXDOG_OAI_CODEX_THREAD_CACHE_KEY !== '0'
282
+ && String(process.env.MIXDOG_OAI_CODEX_THREAD_CACHE_KEY || '').toLowerCase() !== 'false') {
283
+ return codexThreadPromptCacheKey(opts, namespace);
284
+ }
221
285
  const rawShards = prefix.cacheLaneShards ?? opts?.promptCacheLane?.shards ?? opts?.cacheLaneShards;
222
286
  const rawShardMode = String(rawShards ?? '').trim().toLowerCase();
223
287
  const autoLane = prefix.cacheLaneAuto === true
@@ -243,6 +307,16 @@ export function buildStableProviderPromptCacheKey(provider, opts, prefix = {}) {
243
307
  parallelToolCalls: prefix.parallelToolCalls === false ? false : true,
244
308
  cacheLaneSlot: laneEnabled ? shardSlot : null,
245
309
  cacheLaneShards: autoLane ? 'auto' : shardCount > 1 ? shardCount : null,
310
+ // Per-session cache-key isolation. R8 A/B (2026-07-03) showed parallel
311
+ // sessions sharing one prompt_cache_key evict each other's transcript
312
+ // body on the server cache node (same key -> same node; bodies differ),
313
+ // producing 8-23% genuine mid-session misses at tens of thousands of
314
+ // uncached tokens each. Mixing sessionId in costs only the small static
315
+ // prefix hit (~2-4k tokens) on a session's FIRST call — every later
316
+ // call's body cache is protected. Opt out: MIXDOG_OAI_CACHE_KEY_SHARED=1.
317
+ session: process.env.MIXDOG_OAI_CACHE_KEY_SHARED === '1'
318
+ ? null
319
+ : cleanString(opts?.sessionId || opts?.session?.id || '') || null,
246
320
  };
247
321
  const hash = shortHash(seed);
248
322
  const head = namespace.slice(0, Math.max(1, 64 - hash.length - laneSuffix.length - 1));
@@ -255,7 +329,7 @@ function providerEnvKey(provider) {
255
329
 
256
330
  const providerPromptCacheLaneAssignments = new Map();
257
331
  const PROVIDER_PROMPT_CACHE_LANE_MAX_ASSIGNMENTS = 4096;
258
- const DEFAULT_PROVIDER_PROMPT_CACHE_LANE_SHARDS = 12;
332
+ const DEFAULT_PROVIDER_PROMPT_CACHE_LANE_SHARDS = 1;
259
333
 
260
334
  function promptCacheLaneGroupKey(provider, opts) {
261
335
  return [
@@ -282,6 +356,10 @@ function parsePromptCacheLaneLimit(raw, fallback = DEFAULT_PROVIDER_PROMPT_CACHE
282
356
  return Math.floor(n);
283
357
  }
284
358
 
359
+ function defaultPromptCacheLaneShards(_provider) {
360
+ return DEFAULT_PROVIDER_PROMPT_CACHE_LANE_SHARDS;
361
+ }
362
+
285
363
  function assignPromptCacheLaneSlot(provider, opts, shards, seed, { auto = false } = {}) {
286
364
  const explicit = opts?.promptCacheLaneSlot ?? opts?.cacheLaneSlot;
287
365
  const explicitSlot = Number(explicit);
@@ -308,14 +386,9 @@ function assignPromptCacheLaneSlot(provider, opts, shards, seed, { auto = false
308
386
  }
309
387
 
310
388
  /**
311
- * Resolve a stable cache-lane slot for OpenAI-style prompt cache sharding.
312
- * The shard count is the maximum same-prefix parallelism; each final shard key
313
- * is still internally queued and rate-shaped by the transport for stable server
314
- * cache hits. OpenAI's prompt caching guide says one prefix+prompt_cache_key
315
- * combination can overflow around 15 RPM, so transport owns that timing gate.
316
- * Default to the safer 12-lane pool. Explicit 0/auto/unbounded keeps the
317
- * no-cap execution mode for callers that prefer throughput over stricter
318
- * same-key serialization.
389
+ * Resolve an optional cache-lane slot for OpenAI-style prompt cache sharding.
390
+ * Codex does not shard prompt_cache_key by default, so every provider now gets
391
+ * one un-suffixed key unless an env/config override opts into shards.
319
392
  */
320
393
  export function resolveProviderPromptCacheLane(provider, opts = {}, config = {}) {
321
394
  const envKey = providerEnvKey(provider);
@@ -338,7 +411,7 @@ export function resolveProviderPromptCacheLane(provider, opts = {}, config = {})
338
411
  ?? env[`MIXDOG_${envKey}_CACHE_MAX_PARALLEL`]
339
412
  ?? env.MIXDOG_OPENAI_CACHE_LANE_SHARDS
340
413
  ?? env.MIXDOG_OPENAI_CACHE_MAX_PARALLEL);
341
- const shards = parsePromptCacheLaneLimit(rawLimit, DEFAULT_PROVIDER_PROMPT_CACHE_LANE_SHARDS);
414
+ const shards = parsePromptCacheLaneLimit(rawLimit, defaultPromptCacheLaneShards(provider));
342
415
  const auto = shards <= 0;
343
416
  const seed = cleanString(
344
417
  opts?.promptCacheLaneSeed
@@ -359,8 +432,8 @@ export function resolveProviderPromptCacheLane(provider, opts = {}, config = {})
359
432
  };
360
433
  }
361
434
 
362
- export function buildProviderCacheOpts(provider, sessionId, agent) {
363
- const ttls = resolveCacheStrategy(agent);
435
+ export function buildProviderCacheOpts(provider, sessionId, agent, options = {}) {
436
+ const ttls = resolveCacheStrategy(agent, options);
364
437
  const capability = cacheCapabilityForProvider(provider);
365
438
  if (capability === 'explicit-breakpoint') {
366
439
  // 2026-03-06 Anthropic dropped default TTL 1h→5m. We send
@@ -368,6 +441,10 @@ export function buildProviderCacheOpts(provider, sessionId, agent) {
368
441
  // Verified 2026-04-17 (ephemeral_1h_input_tokens=4722).
369
442
  return { cacheStrategy: ttls };
370
443
  }
444
+ // NOTE: createSession's direct-call site (manager.mjs) only invokes this
445
+ // for explicit-breakpoint (Anthropic-family) providers, so this branch
446
+ // stays reachable only from other callers (none in-tree today) — keeping
447
+ // it here preserves the documented public API/behavior of this function.
371
448
  if (provider === 'openai') {
372
449
  // Public OpenAI API: prompt_cache_retention extends prefix retention.
373
450
  // openai-oauth rejects the header — falls through to default.