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
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/tui-render-smoke.mjs — undeclared-identifier gate for the TUI bundle.
4
+ *
5
+ * Why: esbuild does not flag free (undeclared) identifiers in JSX modules —
6
+ * they may legitimately be runtime globals — and no smoke actually renders
7
+ * App. That gap shipped two ReferenceErrors (promptContentRows,
8
+ * TRANSCRIPT_WINDOW_OVERSCAN_ROWS) during the App.jsx split.
9
+ *
10
+ * How: parse src/tui/dist/index.mjs with acorn, run eslint-scope, and fail on
11
+ * any reference that resolves to no binding and is not a known JS/Node/DOM
12
+ * global. Static, deterministic, no terminal or engine session needed.
13
+ *
14
+ * Run: node scripts/tui-render-smoke.mjs (or `npm run smoke:tui`)
15
+ * Exit: 0 = clean, 1 = undeclared identifiers found or bundle missing.
16
+ */
17
+ import { readFileSync, existsSync } from 'node:fs';
18
+ import { dirname, join } from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+ import { parse } from 'acorn';
21
+ import { analyze } from 'eslint-scope';
22
+
23
+ const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
24
+ const BUNDLE = join(ROOT, 'src', 'tui', 'dist', 'index.mjs');
25
+
26
+ // Globals that are legal free identifiers in the bundle. Anything outside
27
+ // this set that resolves to no binding is a guaranteed ReferenceError at
28
+ // runtime (module scope is strict; there is no window fallback in node ESM).
29
+ const KNOWN_GLOBALS = new Set([
30
+ // ECMAScript builtins
31
+ 'Array', 'ArrayBuffer', 'Atomics', 'BigInt', 'BigInt64Array', 'BigUint64Array', 'Boolean',
32
+ 'DataView', 'Date', 'Error', 'EvalError', 'FinalizationRegistry', 'Float32Array',
33
+ 'Float64Array', 'Function', 'Infinity', 'Int8Array', 'Int16Array', 'Int32Array',
34
+ 'Intl', 'JSON', 'Map', 'Math', 'NaN', 'Number', 'Object', 'Promise', 'Proxy',
35
+ 'RangeError', 'ReferenceError', 'Reflect', 'RegExp', 'Set', 'SharedArrayBuffer',
36
+ 'String', 'Symbol', 'SyntaxError', 'TypeError', 'URIError', 'Uint8Array',
37
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'WeakRef', 'WeakSet',
38
+ 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'eval',
39
+ 'globalThis', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined',
40
+ // Node.js globals
41
+ 'AbortController', 'AbortSignal', 'Blob', 'Buffer', 'ByteLengthQueuingStrategy',
42
+ 'CompressionStream', 'CountQueuingStrategy', 'Crypto', 'CryptoKey', 'CustomEvent',
43
+ 'DecompressionStream', 'Event', 'EventTarget', 'File', 'FormData', 'Headers',
44
+ 'MessageChannel', 'MessageEvent', 'MessagePort', 'Navigator', 'PerformanceEntry',
45
+ 'PerformanceObserver', 'ReadableStream', 'ReadableStreamDefaultReader', 'Request',
46
+ 'Response', 'SubtleCrypto', 'TextDecoder', 'TextDecoderStream', 'TextEncoder',
47
+ 'TextEncoderStream', 'TransformStream', 'URL', 'URLSearchParams', 'WebAssembly',
48
+ 'WebSocket', 'WritableStream', 'atob', 'btoa', 'clearImmediate', 'clearInterval',
49
+ 'clearTimeout', 'console', 'crypto', 'fetch', 'navigator', 'performance',
50
+ 'process', 'queueMicrotask', 'require', 'setImmediate', 'setInterval',
51
+ 'setTimeout', 'structuredClone',
52
+ // Bundler/runtime artifacts occasionally referenced defensively
53
+ 'window', 'document', 'reportError',
54
+ ]);
55
+
56
+ if (!existsSync(BUNDLE)) {
57
+ console.error(`tui-render-smoke: FAIL — bundle not found at ${BUNDLE}; run \`npm run build:tui\` first`);
58
+ process.exit(1);
59
+ }
60
+
61
+ const source = readFileSync(BUNDLE, 'utf8');
62
+
63
+ let ast;
64
+ try {
65
+ ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module', locations: true, ranges: true });
66
+ } catch (err) {
67
+ console.error(`tui-render-smoke: FAIL — bundle does not parse: ${err.message}`);
68
+ process.exit(1);
69
+ }
70
+
71
+ const scopeManager = analyze(ast, { ecmaVersion: 2022, sourceType: 'module' });
72
+ const unresolved = scopeManager.globalScope.through.filter(
73
+ (ref) => !KNOWN_GLOBALS.has(ref.identifier.name),
74
+ );
75
+
76
+ if (unresolved.length > 0) {
77
+ const seen = new Map();
78
+ for (const ref of unresolved) {
79
+ const { name } = ref.identifier;
80
+ if (!seen.has(name)) seen.set(name, ref.identifier.loc?.start);
81
+ }
82
+ console.error(`tui-render-smoke: FAIL — ${seen.size} undeclared identifier(s) in src/tui/dist/index.mjs:`);
83
+ for (const [name, loc] of seen) {
84
+ console.error(` ${name} (dist/index.mjs:${loc ? `${loc.line}:${loc.column}` : '?'})`);
85
+ }
86
+ console.error('These throw ReferenceError when the TUI renders. Fix missing imports in src/tui/ and rebuild.');
87
+ process.exit(1);
88
+ }
89
+
90
+ console.log('tui-render-smoke: ok — no undeclared identifiers in TUI bundle');
@@ -0,0 +1,208 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import * as crypto from 'node:crypto';
4
+ import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ import { readMarkdownDocument } from '../src/runtime/shared/markdown-frontmatter.mjs';
8
+
9
+ // DATA_DIR resolves from MIXDOG_DATA_DIR at module import time (via
10
+ // ./config.mjs -> resolvePluginData), so the env var MUST be set before
11
+ // the first dynamic import of webhook.mjs.
12
+ const dataDir = mkdtempSync(join(tmpdir(), 'mixdog-webhook-test-'));
13
+ process.env.MIXDOG_DATA_DIR = dataDir;
14
+
15
+ const {
16
+ extractSignature,
17
+ verifySignature,
18
+ loadEndpointConfig,
19
+ STRIPE_TOLERANCE_MS,
20
+ } = await import('../src/runtime/channels/lib/webhook.mjs');
21
+
22
+ function hmacHex(secret, payload) {
23
+ return crypto.createHmac('sha256', secret).update(payload).digest('hex');
24
+ }
25
+
26
+ // ── verifySignature: github/generic hex HMAC ──────────────────────────
27
+
28
+ test('verifySignature: github parser accepts a valid sha256 hex signature', () => {
29
+ const secret = 'shh';
30
+ const body = '{"hello":"world"}';
31
+ const sig = hmacHex(secret, body);
32
+ assert.equal(verifySignature(secret, body, sig, 'github'), true);
33
+ });
34
+
35
+ test('verifySignature: generic parser accepts a valid sha256 hex signature', () => {
36
+ const secret = 'shh';
37
+ const body = '{"hello":"world"}';
38
+ const sig = hmacHex(secret, body);
39
+ assert.equal(verifySignature(secret, body, sig, 'generic'), true);
40
+ });
41
+
42
+ test('verifySignature: github/generic reject a wrong signature', () => {
43
+ const secret = 'shh';
44
+ const body = '{"hello":"world"}';
45
+ const wrong = hmacHex('other-secret', body);
46
+ assert.equal(verifySignature(secret, body, wrong, 'github'), false);
47
+ });
48
+
49
+ test('verifySignature: length-mismatch hex signature returns false without throwing', () => {
50
+ const secret = 'shh';
51
+ const body = 'payload';
52
+ // Valid hex, wrong byte length vs the 32-byte sha256 digest.
53
+ assert.doesNotThrow(() => {
54
+ assert.equal(verifySignature(secret, body, 'ab', 'github'), false);
55
+ });
56
+ });
57
+
58
+ test('verifySignature: malformed (non-hex) signature returns false without throwing', () => {
59
+ const secret = 'shh';
60
+ const body = 'payload';
61
+ assert.doesNotThrow(() => {
62
+ assert.equal(verifySignature(secret, body, 'not-hex-zzzz', 'github'), false);
63
+ });
64
+ });
65
+
66
+ // ── verifySignature: stripe t= / v1= scheme ───────────────────────────
67
+
68
+ test('verifySignature: stripe accepts a valid t+v1 pair', () => {
69
+ const secret = 'stripe-secret';
70
+ const body = '{"id":"evt_1"}';
71
+ const t = Math.floor(Date.now() / 1000);
72
+ const v1 = hmacHex(secret, `${t}.${body}`);
73
+ assert.equal(verifySignature(secret, body, `t=${t},v1=${v1}`, 'stripe'), true);
74
+ });
75
+
76
+ test('verifySignature: stripe rejects a header missing t=', () => {
77
+ const secret = 'stripe-secret';
78
+ const body = '{"id":"evt_1"}';
79
+ const t = Math.floor(Date.now() / 1000);
80
+ const v1 = hmacHex(secret, `${t}.${body}`);
81
+ assert.equal(verifySignature(secret, body, `v1=${v1}`, 'stripe'), false);
82
+ });
83
+
84
+ test('verifySignature: stripe rejects a header missing v1=', () => {
85
+ const secret = 'stripe-secret';
86
+ const body = '{"id":"evt_1"}';
87
+ const t = Math.floor(Date.now() / 1000);
88
+ assert.equal(verifySignature(secret, body, `t=${t}`, 'stripe'), false);
89
+ });
90
+
91
+ test('verifySignature: stripe rejects a stale timestamp beyond the tolerance window (replay)', () => {
92
+ const secret = 'stripe-secret';
93
+ const body = '{"id":"evt_1"}';
94
+ const staleT = Math.floor((Date.now() - STRIPE_TOLERANCE_MS - 60_000) / 1000);
95
+ const v1 = hmacHex(secret, `${staleT}.${body}`);
96
+ assert.equal(verifySignature(secret, body, `t=${staleT},v1=${v1}`, 'stripe'), false);
97
+ });
98
+
99
+ test('verifySignature: stripe rejects a tampered v1 (HMAC mismatch) with a fresh t', () => {
100
+ const secret = 'stripe-secret';
101
+ const body = '{"id":"evt_1"}';
102
+ const t = Math.floor(Date.now() / 1000);
103
+ const tamperedV1 = hmacHex('wrong-secret', `${t}.${body}`);
104
+ assert.equal(verifySignature(secret, body, `t=${t},v1=${tamperedV1}`, 'stripe'), false);
105
+ });
106
+
107
+ // ── extractSignature: parser mapping + fallback scan ──────────────────
108
+
109
+ test('extractSignature: github parser strips the sha256= prefix from x-hub-signature-256', () => {
110
+ const headers = { 'x-hub-signature-256': 'sha256=deadbeef' };
111
+ assert.equal(extractSignature(headers, 'github'), 'deadbeef');
112
+ });
113
+
114
+ test('extractSignature: generic parser strips the sha256= prefix from x-signature-256', () => {
115
+ const headers = { 'x-signature-256': 'sha256=cafebabe' };
116
+ assert.equal(extractSignature(headers, 'generic'), 'cafebabe');
117
+ });
118
+
119
+ test('extractSignature: stripe parser returns the raw stripe-signature value (no prefix)', () => {
120
+ const headers = { 'stripe-signature': 't=1,v1=abc123' };
121
+ assert.equal(extractSignature(headers, 'stripe'), 't=1,v1=abc123');
122
+ });
123
+
124
+ test('extractSignature: sentry parser returns the raw sentry-hook-signature value', () => {
125
+ const headers = { 'sentry-hook-signature': 'raw-sig-value' };
126
+ assert.equal(extractSignature(headers, 'sentry'), 'raw-sig-value');
127
+ });
128
+
129
+ test('extractSignature: unknown parser name falls back to scanning all known headers', () => {
130
+ const headers = { 'x-signature-256': 'sha256=fallback-hit' };
131
+ assert.equal(extractSignature(headers, 'no-such-parser'), 'fallback-hit');
132
+ });
133
+
134
+ test('extractSignature: no parser given scans known headers in declaration order', () => {
135
+ const headers = { 'x-hub-signature-256': 'sha256=github-hit' };
136
+ assert.equal(extractSignature(headers, undefined), 'github-hit');
137
+ });
138
+
139
+ test('extractSignature: returns null when no known signature header is present', () => {
140
+ const headers = { 'x-some-other-header': 'value' };
141
+ assert.equal(extractSignature(headers, 'github'), null);
142
+ });
143
+
144
+ // ── endpoint config loader: WEBHOOK.md frontmatter + secret side file ─
145
+
146
+ test('loadEndpointConfig: loads frontmatter + reads secret from side file', () => {
147
+ const name = 'my-endpoint';
148
+ const dir = join(dataDir, 'webhooks', name);
149
+ mkdirSync(dir, { recursive: true });
150
+ writeFileSync(
151
+ join(dir, 'WEBHOOK.md'),
152
+ [
153
+ '---',
154
+ 'channel: main',
155
+ 'parser: github',
156
+ 'enabled: true',
157
+ '---',
158
+ '',
159
+ 'Handle this webhook by summarizing the payload.',
160
+ '',
161
+ ].join('\n'),
162
+ 'utf8',
163
+ );
164
+ writeFileSync(join(dir, 'secret'), 'my-webhook-secret\n', 'utf8');
165
+
166
+ const cfg = loadEndpointConfig(name);
167
+ assert.equal(cfg.channel, 'main');
168
+ assert.equal(cfg.parser, 'github');
169
+ assert.equal(cfg.enabled, true);
170
+ });
171
+
172
+ test('loadEndpointConfig: enabled: false frontmatter casts to boolean false', () => {
173
+ const name = 'disabled-endpoint';
174
+ const dir = join(dataDir, 'webhooks', name);
175
+ mkdirSync(dir, { recursive: true });
176
+ writeFileSync(
177
+ join(dir, 'WEBHOOK.md'),
178
+ ['---', 'channel: main', 'enabled: false', '---', '', 'body text', ''].join('\n'),
179
+ 'utf8',
180
+ );
181
+ const cfg = loadEndpointConfig(name);
182
+ assert.equal(cfg.enabled, false);
183
+ });
184
+
185
+ test('loadEndpointConfig: returns null for a name with no WEBHOOK.md', () => {
186
+ assert.equal(loadEndpointConfig('never-registered'), null);
187
+ });
188
+
189
+ // loadEndpointConfig only surfaces the frontmatter (by design — see
190
+ // webhook.mjs comment above loadEndpointConfig); confirm the underlying
191
+ // shared parser it delegates to also recovers the markdown body, since
192
+ // the loader's frontmatter/body split is not independently exercised
193
+ // through the exported loadEndpointConfig surface.
194
+ test('readMarkdownDocument: WEBHOOK.md-shaped input yields frontmatter + body', () => {
195
+ const raw = [
196
+ '---',
197
+ 'channel: main',
198
+ 'parser: github',
199
+ '---',
200
+ '',
201
+ 'Handle this webhook by summarizing the payload.',
202
+ '',
203
+ ].join('\n');
204
+ const { frontmatter, body } = readMarkdownDocument(raw);
205
+ assert.equal(frontmatter.channel, 'main');
206
+ assert.equal(frontmatter.parser, 'github');
207
+ assert.equal(body, 'Handle this webhook by summarizing the payload.');
208
+ });
@@ -8,4 +8,7 @@ Root-cause analysis agent.
8
8
 
9
9
  Smallest confirmed cause chain before fixes. Return likely cause, evidence
10
10
  (`file:line`), smallest next check/fix. Mark confirmed facts vs inferences;
11
- avoid broad speculation.
11
+ avoid broad speculation. Fragments only; no narration, no report bloat.
12
+
13
+ Converge, don't sweep: when new reads stop adding evidence, report the best
14
+ cause chain so far — a partial/blocked report is a valid completion.
@@ -8,13 +8,14 @@ Broad implementation agent.
8
8
  Bounded slices; smallest coherent change, not rewrite. Stop: unclear scope,
9
9
  growing blast radius, or Lead-only verification.
10
10
 
11
- EDIT-FIRST DISCIPLINE. Survey the slice with ONE batched read/grep round,
12
- then start patching the first bounded piece — broad scope means edit
13
- incrementally, not read exhaustively. NEVER "one more confirming read": if
14
- an anchor is plausible, the next call is `apply_patch`. 3+ consecutive
15
- read-only calls without an edit = stalling patch the piece you understand
16
- or stop and report blocked. Self-check comes AFTER edits; deep verification
17
- is Lead's.
11
+ EDIT-FIRST DISCIPLINE. Survey the slice with ONE batched read/grep round, then
12
+ patch the first bounded piece — broad scope means edit incrementally, not read
13
+ exhaustively. NEVER "one more confirming read": if an anchor is plausible, the
14
+ next call is `apply_patch`. Repeated read-only turns without an edit = stalling;
15
+ any runtime reminder is your cue to patch the piece you understand or report
16
+ blocked a blocked report is a valid completion. Self-check comes AFTER edits;
17
+ deep verification is Lead's.
18
18
 
19
- Minimal checks + how-to-verify.
19
+ Minimal checks + how-to-verify. Hand off outcome as fragments anchored to
20
+ `file:line`; no narration, no report bloat.
20
21
 
@@ -5,3 +5,7 @@ permission: read-write
5
5
  # Maintainer
6
6
 
7
7
  Maintenance and cleanup agent.
8
+
9
+ Smallest coherent change; no scope growth. Repeated read-only turns without
10
+ an edit = stalling; patch or return blocked — a blocked report is a valid
11
+ completion. Hand off as fragments (`file:line`); no narration.
@@ -8,4 +8,5 @@ Regression/risk review agent.
8
8
 
9
9
  Find actionable correctness/regression/security/verification risks. Findings
10
10
  first, severity-ordered, one line with `file:line`; skip non-risky nits. If
11
- clean, one line + only material residual risk.
11
+ clean, one line + only material residual risk. Fragments only; no narration,
12
+ no report bloat.
@@ -7,6 +7,5 @@ toolSchemaProfile: read-write-search
7
7
 
8
8
  Scheduled task execution agent.
9
9
 
10
- Output a concise English handoff for Lead: outcome, action taken or skipped,
11
- notable evidence, and any remaining risk. If there is nothing actionable, use
12
- the skip protocol.
10
+ Concise English handoff for Lead: outcome, action taken or skipped, notable
11
+ evidence, remaining risk. Nothing actionable use the skip protocol.
@@ -7,6 +7,5 @@ toolSchemaProfile: read-write-search
7
7
 
8
8
  Inbound webhook event analysis agent.
9
9
 
10
- Output a concise English handoff for Lead: event outcome, action taken or
11
- skipped, notable evidence, and any remaining risk. If there is nothing
12
- actionable, use the skip protocol.
10
+ Concise English handoff for Lead: event outcome, action taken or skipped,
11
+ notable evidence, remaining risk. Nothing actionable use the skip protocol.
@@ -7,11 +7,14 @@ Scoped implementation agent.
7
7
 
8
8
  Smallest scoped change; no drive-by cleanup. Stop when done/blocked.
9
9
 
10
- EDIT-FIRST DISCIPLINE. Brief anchors (`file:line`) are pre-verified — trust
11
- them and patch. No anchor: locate with AT MOST 1-2 reads, then edit. NEVER
12
- "one more confirming read": if you know the file and the change, the next
13
- call is `apply_patch`. 3+ read-only calls without an edit = you are stalling
14
- either patch now or return blocked with what's missing. Confidence
15
- threshold is "plausible", not "proven"; self-check comes AFTER the edit, and
16
- Lead/Reviewer own final verification.
10
+ EDIT-FIRST DISCIPLINE. Brief anchors (`file:line`) are pre-verified — trust and
11
+ patch. No anchor: locate with AT MOST 1-2 reads, then edit. NEVER "one more
12
+ confirming read": if you know the file and the change, the next call is
13
+ `apply_patch`. Repeated read-only turns without an edit = stalling; any runtime
14
+ reminder is your cue to patch now or return blocked with what's missing — a
15
+ blocked report is a valid completion. Threshold is "plausible", not "proven";
16
+ self-check comes AFTER the edit, and Lead/Reviewer own final verification.
17
+
18
+ Hand off outcome as fragments anchored to `file:line`; no narration, no report
19
+ bloat.
17
20
 
package/src/app.mjs CHANGED
@@ -4,8 +4,12 @@ import { fileURLToPath } from 'node:url';
4
4
  import { performance } from 'node:perf_hooks';
5
5
 
6
6
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
- const VALUE_OPTIONS = new Set(['--provider', '--model']);
7
+ // --workflow is consumed (with its value) but ignored on the headless role
8
+ // path: workflow selection is Lead-session-scoped. Accepting it keeps a
9
+ // mistakenly passed `--workflow X` from leaking "X" into the role message.
10
+ const VALUE_OPTIONS = new Set(['--provider', '--model', '--effort', '--workflow']);
8
11
  const FLAG_OPTIONS = new Set(['--readonly', '--help', '-h', '--plain', '--react', '--remote', '--onboarding']);
12
+ const HEADLESS_FLAG_OPTIONS = new Set(['--fast']);
9
13
  const HEADLESS_ROLE_ALIASES = new Map([
10
14
  ['explorer', 'explore'],
11
15
  ['explore', 'explore'],
@@ -52,6 +56,7 @@ function unknownOption(argv) {
52
56
  continue;
53
57
  }
54
58
  if (FLAG_OPTIONS.has(arg)) continue;
59
+ if (HEADLESS_FLAG_OPTIONS.has(arg)) continue;
55
60
  if (String(arg || '').startsWith('-')) return arg;
56
61
  }
57
62
  return null;
@@ -66,6 +71,7 @@ function positionalArgs(argv) {
66
71
  continue;
67
72
  }
68
73
  if (FLAG_OPTIONS.has(arg)) continue;
74
+ if (HEADLESS_FLAG_OPTIONS.has(arg)) continue;
69
75
  if (String(arg || '').startsWith('-')) continue;
70
76
  out.push(arg);
71
77
  }
@@ -109,12 +115,15 @@ export async function run(argv = []) {
109
115
 
110
116
  const provIdx = argv.indexOf('--provider');
111
117
  const modelIdx = argv.indexOf('--model');
118
+ const effortIdx = argv.indexOf('--effort');
112
119
  const toolMode = argv.includes('--readonly') ? 'readonly' : 'full';
113
120
  const remote = argv.includes('--remote');
114
121
  const forceOnboarding = argv.includes('--onboarding');
115
122
  const opts = {
116
123
  provider: provIdx >= 0 ? argv[provIdx + 1] : undefined,
117
124
  model: modelIdx >= 0 ? argv[modelIdx + 1] : undefined,
125
+ effort: effortIdx >= 0 ? argv[effortIdx + 1] : undefined,
126
+ fast: argv.includes('--fast'),
118
127
  toolMode,
119
128
  remote,
120
129
  forceOnboarding,
@@ -150,6 +159,8 @@ export async function run(argv = []) {
150
159
  message: headless.message,
151
160
  provider: opts.provider,
152
161
  model: opts.model,
162
+ effort: opts.effort,
163
+ fast: opts.fast,
153
164
  cwd: process.cwd(),
154
165
  });
155
166
  }
@@ -25,7 +25,7 @@ function makeTag(agent) {
25
25
  .replace(/^-+|-+$/g, '');
26
26
  }
27
27
 
28
- export function buildHeadlessSpawnArgs({ agent, tag, cwd, message, provider, model } = {}) {
28
+ export function buildHeadlessSpawnArgs({ agent, tag, cwd, message, provider, model, effort, fast } = {}) {
29
29
  const spawnArgs = {
30
30
  type: 'spawn',
31
31
  agent: clean(agent),
@@ -35,6 +35,8 @@ export function buildHeadlessSpawnArgs({ agent, tag, cwd, message, provider, mod
35
35
  };
36
36
  if (clean(provider)) spawnArgs.provider = clean(provider);
37
37
  if (clean(model)) spawnArgs.model = clean(model);
38
+ if (clean(effort)) spawnArgs.effort = clean(effort);
39
+ if (fast === true) spawnArgs.fast = true;
38
40
  return spawnArgs;
39
41
  }
40
42
 
@@ -56,6 +58,8 @@ export async function runHeadlessRole({
56
58
  message,
57
59
  provider,
58
60
  model,
61
+ effort,
62
+ fast,
59
63
  cwd = process.cwd(),
60
64
  write = (text) => stdout.write(text),
61
65
  writeErr = (text) => stderr.write(text),
@@ -86,6 +90,8 @@ export async function runHeadlessRole({
86
90
  message: cleanMessage,
87
91
  provider,
88
92
  model,
93
+ effort,
94
+ fast,
89
95
  });
90
96
 
91
97
  let taskId = null;
@@ -21,6 +21,7 @@
21
21
  * Source files (rules/):
22
22
  * - shared/01-tool.md — universal tool policy (Lead + agent BP1, identical full set)
23
23
  * - lead/lead-tool.md — Lead-specific control-tower / delegation / ToolSearch guidance
24
+ * - lead/lead-brief.md — Lead brief contract (agent handoff briefs)
24
25
  * - lead/01-02 — Lead general / channels
25
26
  * - output-styles/<name>.md — Lead output style, selected by config outputStyle
26
27
  * - agent/00-common.md — agent common behavior + universal worker contract (BP2)
@@ -275,6 +276,9 @@ function buildLeadRoleContent({ PLUGIN_ROOT, DATA_DIR }) {
275
276
  const toolLead = readOptional(path.join(LEAD_DIR, 'lead-tool.md'));
276
277
  if (toolLead) parts.push(toolLead);
277
278
 
279
+ const briefLead = readOptional(path.join(LEAD_DIR, 'lead-brief.md'));
280
+ if (briefLead) parts.push(briefLead);
281
+
278
282
  if (generalSplit.role) parts.push(generalSplit.role);
279
283
 
280
284
  const channels = readOptional(path.join(LEAD_DIR, '02-channels.md'));