@selesai/code 0.5.19 → 0.5.21

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 (265) hide show
  1. package/dist/extensions/handoff-new.test.ts +8 -9
  2. package/dist/extensions/handoff-new.ts +6 -8
  3. package/dist/extensions/pi-intercom/broker/spawn.test.ts +31 -0
  4. package/dist/extensions/pi-intercom/broker/spawn.ts +5 -3
  5. package/dist/extensions/pi-subagents/CHANGELOG.md +1367 -0
  6. package/dist/extensions/pi-subagents/README.md +602 -220
  7. package/dist/extensions/pi-subagents/banner.png +0 -0
  8. package/dist/extensions/pi-subagents/index.ts +1 -0
  9. package/dist/extensions/pi-subagents/install.mjs +3 -3
  10. package/dist/extensions/pi-subagents/package-lock.json +3405 -0
  11. package/dist/extensions/pi-subagents/package.json +26 -14
  12. package/dist/extensions/pi-subagents/prompts/gather-context-and-clarify.md +1 -1
  13. package/dist/extensions/pi-subagents/prompts/parallel-cleanup.md +9 -9
  14. package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +3 -3
  15. package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +7 -7
  16. package/dist/extensions/pi-subagents/prompts/parallel-research.md +6 -6
  17. package/dist/extensions/pi-subagents/prompts/parallel-review.md +8 -8
  18. package/dist/extensions/pi-subagents/prompts/review-loop.md +13 -11
  19. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +267 -176
  20. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +89 -16
  21. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +19 -0
  22. package/dist/extensions/pi-subagents/src/agents/agents.ts +218 -120
  23. package/dist/extensions/pi-subagents/src/agents/frontmatter.ts +67 -13
  24. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +2 -2
  25. package/dist/extensions/pi-subagents/src/agents/skills.ts +25 -12
  26. package/dist/extensions/pi-subagents/src/api/background-work.ts +197 -0
  27. package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +17 -0
  28. package/dist/extensions/pi-subagents/src/api/delegation.ts +285 -0
  29. package/dist/extensions/pi-subagents/src/api/preflight.ts +399 -0
  30. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +165 -0
  31. package/dist/extensions/pi-subagents/src/extension/config.ts +7 -1
  32. package/dist/extensions/pi-subagents/src/extension/doctor.ts +15 -0
  33. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +3 -1
  34. package/dist/extensions/pi-subagents/src/extension/index.ts +113 -157
  35. package/dist/extensions/pi-subagents/src/extension/rpc.ts +41 -4
  36. package/dist/extensions/pi-subagents/src/extension/schemas.ts +45 -15
  37. package/dist/extensions/pi-subagents/src/extension/steering-notices.ts +35 -0
  38. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -15
  39. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +4 -3
  40. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +225 -29
  41. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +11 -0
  42. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +8 -10
  43. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +452 -62
  44. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +60 -9
  45. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +198 -52
  46. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +119 -21
  47. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +67 -0
  48. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -0
  49. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +16 -8
  50. package/dist/extensions/pi-subagents/src/runs/background/completion-batcher.ts +6 -4
  51. package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +2 -11
  52. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +260 -13
  53. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +32 -6
  54. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +171 -90
  55. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +280 -0
  56. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +149 -88
  57. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +14 -2
  58. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +33 -17
  59. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +9 -1
  60. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +38 -10
  61. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +237 -0
  62. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +1297 -307
  63. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +610 -0
  64. package/dist/extensions/pi-subagents/src/runs/background/top-level-async.ts +2 -1
  65. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +36 -0
  66. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +26 -0
  67. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +230 -0
  68. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +22 -6
  69. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +228 -140
  70. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +452 -138
  71. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +90 -0
  72. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1001 -416
  73. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +443 -132
  74. package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +38 -0
  75. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +178 -0
  76. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +121 -0
  77. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +41 -93
  78. package/dist/extensions/pi-subagents/src/runs/shared/context-mode.ts +44 -0
  79. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +11 -9
  80. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +4 -0
  81. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +12 -6
  82. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +36 -0
  83. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +44 -7
  84. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +4 -1
  85. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +154 -0
  86. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +18 -0
  87. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +174 -54
  88. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +38 -31
  89. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +90 -5
  90. package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +299 -0
  91. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +61 -6
  92. package/dist/extensions/pi-subagents/src/runs/shared/spawn-budget.ts +128 -0
  93. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +112 -7
  94. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +14 -6
  95. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +149 -36
  96. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +181 -0
  97. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +83 -0
  98. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +11 -5
  99. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +50 -4
  100. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +63 -14
  101. package/dist/extensions/pi-subagents/src/shared/accessible-dir.ts +25 -0
  102. package/dist/extensions/pi-subagents/src/shared/artifacts.ts +37 -7
  103. package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +18 -43
  104. package/dist/extensions/pi-subagents/src/shared/child-transcript.ts +52 -0
  105. package/dist/extensions/pi-subagents/src/shared/env.ts +16 -0
  106. package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +47 -0
  107. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +28 -3
  108. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +123 -0
  109. package/dist/extensions/pi-subagents/src/shared/model-info.ts +8 -5
  110. package/dist/extensions/pi-subagents/src/shared/settings.ts +9 -1
  111. package/dist/extensions/pi-subagents/src/shared/status-format.ts +7 -1
  112. package/dist/extensions/pi-subagents/src/shared/types.ts +522 -51
  113. package/dist/extensions/pi-subagents/src/shared/utils.ts +59 -53
  114. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +604 -0
  115. package/dist/extensions/pi-subagents/src/slash/delegation-json.ts +108 -0
  116. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +249 -0
  117. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +353 -345
  118. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +2 -2
  119. package/dist/extensions/pi-subagents/src/slash/selector.ts +147 -0
  120. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +265 -23
  121. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +2 -2
  122. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +428 -0
  123. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +362 -0
  124. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +472 -0
  125. package/dist/extensions/pi-subagents/src/tui/fleet.ts +664 -0
  126. package/dist/extensions/pi-subagents/src/tui/render.ts +115 -31
  127. package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +220 -0
  128. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +205 -0
  129. package/dist/extensions/pi-subagents/src/watchdog/emission-guard.ts +123 -0
  130. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +532 -0
  131. package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +167 -0
  132. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +117 -0
  133. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +433 -0
  134. package/dist/extensions/pi-subagents/src/watchdog/render.ts +54 -0
  135. package/dist/extensions/pi-subagents/src/watchdog/review.ts +298 -0
  136. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +714 -0
  137. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +528 -0
  138. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +155 -0
  139. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +161 -0
  140. package/dist/extensions/pi-subagents/src/watchdog/types.ts +188 -0
  141. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +73 -0
  142. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +130 -2
  143. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +439 -0
  144. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1632 -61
  145. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +54 -1
  146. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +112 -0
  147. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +98 -1
  148. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +179 -9
  149. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +16 -9
  150. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +6 -5
  151. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +589 -9
  152. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +528 -21
  153. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +227 -3
  154. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +235 -7
  155. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +27 -0
  156. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +172 -2
  157. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1502 -18
  158. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +993 -4
  159. package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +27 -0
  160. package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +7 -1
  161. package/dist/extensions/pi-subagents/test/support/helpers.ts +32 -0
  162. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +59 -2
  163. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +32 -6
  164. package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +25 -24
  165. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +59 -35
  166. package/dist/extensions/pi-subagents/test/support/session-lease-child.mjs +42 -0
  167. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +703 -69
  168. package/dist/extensions/pi-subagents/test/unit/accessible-dir.test.ts +82 -0
  169. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +15 -15
  170. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +66 -66
  171. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +478 -19
  172. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +228 -7
  173. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +1 -1
  174. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +198 -78
  175. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +15 -1
  176. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +102 -7
  177. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +439 -6
  178. package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +41 -1
  179. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +79 -0
  180. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +285 -0
  181. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +84 -0
  182. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +68 -0
  183. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +326 -0
  184. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +82 -0
  185. package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +46 -4
  186. package/dist/extensions/pi-subagents/test/unit/completion-batcher.test.ts +3 -1
  187. package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +9 -17
  188. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +175 -3
  189. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +10 -5
  190. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +126 -6
  191. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +219 -0
  192. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +913 -0
  193. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +13 -2
  194. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +3 -3
  195. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +351 -0
  196. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +280 -0
  197. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +575 -0
  198. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +65 -0
  199. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +94 -1
  200. package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +23 -0
  201. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +157 -0
  202. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +367 -5
  203. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +11 -0
  204. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +36 -0
  205. package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +25 -3
  206. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +1 -1
  207. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +341 -10
  208. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +16 -0
  209. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +52 -0
  210. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +168 -7
  211. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +85 -7
  212. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +175 -0
  213. package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +1 -1
  214. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +243 -16
  215. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +79 -36
  216. package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +174 -56
  217. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +322 -0
  218. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +204 -0
  219. package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +20 -12
  220. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +117 -4
  221. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +40 -7
  222. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +48 -1
  223. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +21 -3
  224. package/dist/extensions/pi-subagents/test/unit/selector.test.ts +57 -0
  225. package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +326 -0
  226. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +101 -2
  227. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +111 -1
  228. package/dist/extensions/pi-subagents/test/unit/spawn-budget.test.ts +124 -0
  229. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +6 -4
  230. package/dist/extensions/pi-subagents/test/unit/status-format.test.ts +7 -0
  231. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +397 -0
  232. package/dist/extensions/pi-subagents/test/unit/steering-notices.test.ts +58 -0
  233. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +173 -0
  234. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +25 -4
  235. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +390 -25
  236. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +837 -0
  237. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +86 -0
  238. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +15 -0
  239. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +47 -1
  240. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +56 -10
  241. package/dist/extensions/pi-subagents/test/unit/watchdog-change-signature.test.ts +387 -0
  242. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +110 -0
  243. package/dist/extensions/pi-subagents/test/unit/watchdog-emission-guard.test.ts +62 -0
  244. package/dist/extensions/pi-subagents/test/unit/watchdog-lsp-diagnostics.test.ts +144 -0
  245. package/dist/extensions/pi-subagents/test/unit/watchdog-model-selection.test.ts +121 -0
  246. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +76 -0
  247. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +327 -0
  248. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +863 -0
  249. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +290 -0
  250. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +91 -0
  251. package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +130 -0
  252. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +32 -4
  253. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +5 -1
  254. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +30 -0
  255. package/dist/extensions/question/batch.ts +39 -0
  256. package/dist/extensions/question/dialog-adapter.ts +23 -1
  257. package/dist/extensions/question/index.ts +237 -7
  258. package/dist/extensions/question/schemas.ts +28 -15
  259. package/dist/extensions/question/tests/batch.test.ts +26 -0
  260. package/dist/extensions/question/tests/ui-protocol.test.ts +23 -3
  261. package/dist/extensions/question/tui-adapter.ts +2 -3
  262. package/dist/extensions/question/types.ts +37 -0
  263. package/dist/extensions/question/ui-protocol.ts +3 -3
  264. package/dist/skills/batch-grill-me/SKILL.md +3 -1
  265. package/package.json +2 -1
@@ -68,20 +68,20 @@ describe("builtin agent overrides", () => {
68
68
  subagents: {
69
69
  defaultModel: "deepseek-v4-flash",
70
70
  agentOverrides: {
71
- oracle: { model: "deepseek-v4-pro" },
72
- reviewer: { model: false },
71
+ commentator: { model: "deepseek-v4-pro" },
72
+ builder: { model: false },
73
73
  },
74
74
  },
75
75
  });
76
76
 
77
77
  const builtins = discoverAgentsAll(tempProject).builtin;
78
- const scout = builtins.find((agent) => agent.name === "scout");
79
- assert.equal(scout?.model, "deepseek-v4-flash");
80
- assert.equal(scout?.modelSource?.type, "subagents.defaultModel");
81
- assert.equal(scout?.modelSource?.scope, "user");
82
- assert.equal(builtins.find((agent) => agent.name === "worker")?.model, "deepseek-v4-flash");
83
- assert.equal(builtins.find((agent) => agent.name === "oracle")?.model, "deepseek-v4-pro");
84
- assert.equal(builtins.find((agent) => agent.name === "reviewer")?.model, undefined);
78
+ const architect = builtins.find((agent) => agent.name === "architect");
79
+ assert.equal(architect?.model, "deepseek-v4-flash");
80
+ assert.equal(architect?.modelSource?.type, "subagents.defaultModel");
81
+ assert.equal(architect?.modelSource?.scope, "user");
82
+ assert.equal(builtins.find((agent) => agent.name === "explorer")?.model, "deepseek-v4-flash");
83
+ assert.equal(builtins.find((agent) => agent.name === "commentator")?.model, "deepseek-v4-pro");
84
+ assert.equal(builtins.find((agent) => agent.name === "builder")?.model, undefined);
85
85
  });
86
86
 
87
87
  it("prefers project subagents.defaultModel over user defaultModel", () => {
@@ -93,9 +93,70 @@ describe("builtin agent overrides", () => {
93
93
  subagents: { defaultModel: "deepseek-v4-pro" },
94
94
  });
95
95
 
96
- const worker = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "worker");
97
- assert.ok(worker);
98
- assert.equal(worker.model, "deepseek-v4-pro");
96
+ const explorer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "explorer");
97
+ assert.ok(explorer);
98
+ assert.equal(explorer.model, "deepseek-v4-pro");
99
+ });
100
+
101
+ it("applies subagents.defaultThinking only when thinking is unset", () => {
102
+ writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
103
+ subagents: {
104
+ defaultThinking: " low ",
105
+ agentOverrides: {
106
+ recapper: { thinking: "xhigh" },
107
+ },
108
+ },
109
+ });
110
+ writeUserAgent(tempHome, "user-default", `---\nname: user-default\ndescription: User agent\n---\n\nUse the default.\n`);
111
+ writeProjectAgent(tempProject, "project-default", `---\nname: project-default\ndescription: Project agent\n---\n\nUse the default.\n`);
112
+ writeProjectAgent(tempProject, "explicit-off", `---\nname: explicit-off\ndescription: Explicitly disabled\nthinking: false\n---\n\nStay off.\n`);
113
+
114
+ const discovered = discoverAgentsAll(tempProject);
115
+ assert.equal(discovered.builtin.find((agent) => agent.name === "recapper")?.thinking, "xhigh");
116
+ assert.equal(discovered.builtin.find((agent) => agent.name === "builder")?.thinking, "high");
117
+ assert.equal(discovered.user.find((agent) => agent.name === "user-default")?.thinking, "low");
118
+ assert.equal(discovered.project.find((agent) => agent.name === "project-default")?.thinking, "low");
119
+ assert.equal(discovered.project.find((agent) => agent.name === "explicit-off")?.thinking, false);
120
+ });
121
+
122
+ it("prefers project subagents.defaultThinking over user defaultThinking", () => {
123
+ fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
124
+ writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
125
+ subagents: { defaultThinking: "low" },
126
+ });
127
+ writeJson(path.join(tempProject, ".selesai", "settings.json"), {
128
+ subagents: { defaultThinking: "high" },
129
+ });
130
+
131
+ const recapper = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "recapper");
132
+ assert.ok(recapper);
133
+ assert.equal(recapper.thinking, "high");
134
+ });
135
+
136
+ it("preserves custom-agent thinking when disableThinking clears builtin defaults", () => {
137
+ writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
138
+ subagents: { defaultThinking: "low", disableThinking: true },
139
+ });
140
+ writeProjectAgent(tempProject, "custom-default", `---\nname: custom-default\ndescription: Custom default\n---\n\nUse the default.\n`);
141
+ writeProjectAgent(tempProject, "custom-explicit", `---\nname: custom-explicit\ndescription: Custom explicit\nthinking: high\n---\n\nUse the explicit level.\n`);
142
+
143
+ const discovered = discoverAgentsAll(tempProject);
144
+ assert.equal(discovered.builtin.find((agent) => agent.name === "builder")?.thinking, undefined);
145
+ assert.equal(discovered.project.find((agent) => agent.name === "custom-default")?.thinking, "low");
146
+ assert.equal(discovered.project.find((agent) => agent.name === "custom-explicit")?.thinking, "high");
147
+ });
148
+
149
+ it("surfaces malformed defaultThinking settings", () => {
150
+ const settingsPath = path.join(tempHome, ".selesai", "agent", "settings.json");
151
+ for (const defaultThinking of ["", 42]) {
152
+ writeJson(settingsPath, { subagents: { defaultThinking } });
153
+ assert.throws(
154
+ () => discoverAgents(tempProject, "both"),
155
+ (error: unknown) => error instanceof Error
156
+ && error.message.includes(settingsPath)
157
+ && error.message.includes("defaultThinking"),
158
+ );
159
+ }
99
160
  });
100
161
 
101
162
  it("applies subagents.defaultModel to custom agents without a frontmatter model", () => {
@@ -109,24 +170,25 @@ describe("builtin agent overrides", () => {
109
170
  });
110
171
  writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\n---\n\nDrive the failing test first.\n`);
111
172
  writeProjectAgent(tempProject, "auditor", `---\nname: auditor\ndescription: Audit code\nmodel: google/gemini-3-pro\n---\n\nAudit the code.\n`);
112
- writeProjectAgent(tempProject, "scout-copy", `---\nname: scout-copy\ndescription: Scout code\n---\n\nScout the code.\n`);
173
+ writeProjectAgent(tempProject, "architect-copy", `---\nname: architect-copy\ndescription: Scout code\n---\n\nScout the code.\n`);
113
174
 
114
175
  const agents = discoverAgents(tempProject, "both").agents;
115
176
  assert.equal(agents.find((agent) => agent.name === "implementer")?.model, "deepseek-v4-pro");
116
177
  assert.equal(agents.find((agent) => agent.name === "auditor")?.model, "google/gemini-3-pro");
117
- assert.equal(agents.find((agent) => agent.name === "scout-copy")?.model, "deepseek-v4-flash");
178
+ assert.equal(agents.find((agent) => agent.name === "architect-copy")?.model, "deepseek-v4-flash");
118
179
  });
119
180
 
120
181
  it("applies user settings overrides to builtin agents", () => {
121
182
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
122
183
  subagents: {
123
184
  agentOverrides: {
124
- reviewer: {
185
+ builder: {
125
186
  model: "openai/gpt-5.4",
126
187
  thinking: "xhigh",
127
188
  systemPromptMode: "replace",
128
189
  inheritProjectContext: true,
129
190
  inheritSkills: true,
191
+ acceptanceRole: "writer",
130
192
  subagentOnlyExtensions: ["./tools/child-review.ts"],
131
193
  completionGuard: false,
132
194
  },
@@ -134,18 +196,19 @@ describe("builtin agent overrides", () => {
134
196
  },
135
197
  });
136
198
 
137
- const reviewer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "reviewer");
138
- assert.ok(reviewer);
139
- assert.equal(reviewer.source, "builtin");
140
- assert.equal(reviewer.model, "openai/gpt-5.4");
141
- assert.equal(reviewer.thinking, "xhigh");
142
- assert.equal(reviewer.systemPromptMode, "replace");
143
- assert.equal(reviewer.inheritProjectContext, true);
144
- assert.equal(reviewer.inheritSkills, true);
145
- assert.deepEqual(reviewer.subagentOnlyExtensions, ["./tools/child-review.ts"]);
146
- assert.equal(reviewer.completionGuard, false);
147
- assert.equal(reviewer.override?.scope, "user");
148
- assert.equal(reviewer.override?.path, path.join(tempHome, ".selesai", "agent", "settings.json"));
199
+ const builder = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "builder");
200
+ assert.ok(builder);
201
+ assert.equal(builder.source, "builtin");
202
+ assert.equal(builder.model, "openai/gpt-5.4");
203
+ assert.equal(builder.thinking, "xhigh");
204
+ assert.equal(builder.systemPromptMode, "replace");
205
+ assert.equal(builder.inheritProjectContext, true);
206
+ assert.equal(builder.inheritSkills, true);
207
+ assert.equal(builder.acceptanceRole, "writer");
208
+ assert.deepEqual(builder.subagentOnlyExtensions, ["./tools/child-review.ts"]);
209
+ assert.equal(builder.completionGuard, false);
210
+ assert.equal(builder.override?.scope, "user");
211
+ assert.equal(builder.override?.path, path.join(tempHome, ".selesai", "agent", "settings.json"));
149
212
  });
150
213
 
151
214
  it("globally disables builtin thinking suffix defaults from user settings", () => {
@@ -156,7 +219,7 @@ describe("builtin agent overrides", () => {
156
219
  });
157
220
 
158
221
  const builtins = discoverAgentsAll(tempProject).builtin;
159
- assert.ok(builtins.some((agent) => agent.name === "reviewer"));
222
+ assert.ok(builtins.some((agent) => agent.name === "builder"));
160
223
  assert.deepEqual(
161
224
  builtins
162
225
  .filter((agent) => agent.thinking !== undefined)
@@ -164,7 +227,7 @@ describe("builtin agent overrides", () => {
164
227
  [],
165
228
  );
166
229
  assert.equal(
167
- builtins.find((agent) => agent.name === "reviewer")?.override?.path,
230
+ builtins.find((agent) => agent.name === "builder")?.override?.path,
168
231
  path.join(tempHome, ".selesai", "agent", "settings.json"),
169
232
  );
170
233
  });
@@ -174,7 +237,7 @@ describe("builtin agent overrides", () => {
174
237
  subagents: {
175
238
  disableThinking: true,
176
239
  agentOverrides: {
177
- reviewer: {
240
+ builder: {
178
241
  thinking: "high",
179
242
  },
180
243
  },
@@ -182,12 +245,12 @@ describe("builtin agent overrides", () => {
182
245
  });
183
246
 
184
247
  const agents = discoverAgents(tempProject, "both").agents;
185
- const reviewer = agents.find((agent) => agent.name === "reviewer");
186
- const worker = agents.find((agent) => agent.name === "worker");
187
- assert.ok(reviewer);
188
- assert.ok(worker);
189
- assert.equal(reviewer.thinking, "high");
190
- assert.equal(worker.thinking, undefined);
248
+ const builder = agents.find((agent) => agent.name === "builder");
249
+ const explorer = agents.find((agent) => agent.name === "explorer");
250
+ assert.ok(builder);
251
+ assert.ok(explorer);
252
+ assert.equal(builder.thinking, "high");
253
+ assert.equal(explorer.thinking, undefined);
191
254
  });
192
255
 
193
256
  it("lets project settings disable builtin thinking even when user overrides request it", () => {
@@ -195,7 +258,7 @@ describe("builtin agent overrides", () => {
195
258
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
196
259
  subagents: {
197
260
  agentOverrides: {
198
- reviewer: {
261
+ builder: {
199
262
  thinking: "xhigh",
200
263
  },
201
264
  },
@@ -207,9 +270,9 @@ describe("builtin agent overrides", () => {
207
270
  },
208
271
  });
209
272
 
210
- const reviewer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "reviewer");
211
- assert.ok(reviewer);
212
- assert.equal(reviewer.thinking, undefined);
273
+ const builder = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "builder");
274
+ assert.ok(builder);
275
+ assert.equal(builder.thinking, undefined);
213
276
  });
214
277
 
215
278
  it("surfaces malformed subagent default model settings", () => {
@@ -247,45 +310,74 @@ describe("builtin agent overrides", () => {
247
310
  it("prefers project settings overrides over user settings overrides", () => {
248
311
  fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
249
312
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
250
- subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
313
+ subagents: { agentOverrides: { builder: { model: "openai/gpt-5.4" } } },
314
+ });
315
+ writeJson(path.join(tempProject, ".selesai", "settings.json"), {
316
+ subagents: { agentOverrides: { builder: { model: "openai-codex/gpt-5.4-mini", thinking: "high" } } },
317
+ });
318
+
319
+ const builder = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "builder");
320
+ assert.ok(builder);
321
+ assert.equal(builder.model, "openai-codex/gpt-5.4-mini");
322
+ assert.equal(builder.thinking, "high");
323
+ assert.equal(builder.override?.scope, "project");
324
+ assert.equal(builder.override?.path, path.join(tempProject, ".selesai", "settings.json"));
325
+ });
326
+
327
+ it("applies acceptance role precedence and false clearing to builtin and custom agents", () => {
328
+ writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
329
+ subagents: {
330
+ agentOverrides: {
331
+ builder: { acceptanceRole: "read-only" },
332
+ architect: { acceptanceRole: "read-only" },
333
+ implementer: { acceptanceRole: "read-only" },
334
+ },
335
+ },
251
336
  });
337
+ fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
252
338
  writeJson(path.join(tempProject, ".selesai", "settings.json"), {
253
- subagents: { agentOverrides: { reviewer: { model: "openai-codex/gpt-5.4-mini", thinking: "high" } } },
339
+ subagents: {
340
+ agentOverrides: {
341
+ builder: { acceptanceRole: "writer" },
342
+ architect: { acceptanceRole: false },
343
+ implementer: { acceptanceRole: false },
344
+ },
345
+ },
254
346
  });
347
+ writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\n---\n\nDrive the failing test first.\n`);
255
348
 
256
- const reviewer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "reviewer");
257
- assert.ok(reviewer);
258
- assert.equal(reviewer.model, "openai-codex/gpt-5.4-mini");
259
- assert.equal(reviewer.thinking, "high");
260
- assert.equal(reviewer.override?.scope, "project");
261
- assert.equal(reviewer.override?.path, path.join(tempProject, ".selesai", "settings.json"));
349
+ const agents = discoverAgents(tempProject, "both").agents;
350
+ assert.equal(agents.find((agent) => agent.name === "builder")?.acceptanceRole, "writer");
351
+ assert.equal(agents.find((agent) => agent.name === "architect")?.acceptanceRole, undefined);
352
+ assert.equal(agents.find((agent) => agent.name === "implementer")?.acceptanceRole, undefined);
353
+ assert.equal(agents.find((agent) => agent.name === "implementer")?.override?.scope, "project");
262
354
  });
263
355
 
264
356
  it("does not apply project settings overrides when scope is user", () => {
265
357
  fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
266
358
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
267
- subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
359
+ subagents: { agentOverrides: { builder: { model: "openai/gpt-5.4" } } },
268
360
  });
269
361
  writeJson(path.join(tempProject, ".selesai", "settings.json"), {
270
- subagents: { agentOverrides: { reviewer: { model: "openai-codex/gpt-5.4-mini" } } },
362
+ subagents: { agentOverrides: { builder: { model: "openai-codex/gpt-5.4-mini" } } },
271
363
  });
272
364
 
273
- const reviewer = discoverAgents(tempProject, "user").agents.find((agent) => agent.name === "reviewer");
274
- assert.ok(reviewer);
275
- assert.equal(reviewer.model, "openai/gpt-5.4");
276
- assert.equal(reviewer.override?.scope, "user");
365
+ const builder = discoverAgents(tempProject, "user").agents.find((agent) => agent.name === "builder");
366
+ assert.ok(builder);
367
+ assert.equal(builder.model, "openai/gpt-5.4");
368
+ assert.equal(builder.override?.scope, "user");
277
369
  });
278
370
 
279
371
  it("does not apply user settings overrides when scope is project", () => {
280
372
  fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
281
373
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
282
- subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
374
+ subagents: { agentOverrides: { builder: { model: "openai/gpt-5.4" } } },
283
375
  });
284
376
 
285
- const reviewer = discoverAgents(tempProject, "project").agents.find((agent) => agent.name === "reviewer");
286
- assert.ok(reviewer);
287
- assert.notEqual(reviewer.model, "openai/gpt-5.4");
288
- assert.equal(reviewer.override, undefined);
377
+ const builder = discoverAgents(tempProject, "project").agents.find((agent) => agent.name === "builder");
378
+ assert.ok(builder);
379
+ assert.notEqual(builder.model, "openai/gpt-5.4");
380
+ assert.equal(builder.override, undefined);
289
381
  });
290
382
 
291
383
  it("does not read malformed out-of-scope settings files", () => {
@@ -293,27 +385,27 @@ describe("builtin agent overrides", () => {
293
385
  fs.mkdirSync(path.join(tempHome, ".selesai", "agent"), { recursive: true });
294
386
  fs.writeFileSync(path.join(tempHome, ".selesai", "agent", "settings.json"), '{"subagents":', "utf-8");
295
387
  writeJson(path.join(tempProject, ".selesai", "settings.json"), {
296
- subagents: { agentOverrides: { reviewer: { model: "openai-codex/gpt-5.4-mini" } } },
388
+ subagents: { agentOverrides: { builder: { model: "openai-codex/gpt-5.4-mini" } } },
297
389
  });
298
390
 
299
- const reviewer = discoverAgents(tempProject, "project").agents.find((agent) => agent.name === "reviewer");
300
- assert.ok(reviewer);
301
- assert.equal(reviewer.model, "openai-codex/gpt-5.4-mini");
302
- assert.equal(reviewer.override?.scope, "project");
391
+ const builder = discoverAgents(tempProject, "project").agents.find((agent) => agent.name === "builder");
392
+ assert.ok(builder);
393
+ assert.equal(builder.model, "openai-codex/gpt-5.4-mini");
394
+ assert.equal(builder.override?.scope, "project");
303
395
  });
304
396
 
305
397
  it("frontmatter wins per-field over agentOverrides for a shadowing project agent", () => {
306
398
  fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
307
399
  writeJson(path.join(tempProject, ".selesai", "settings.json"), {
308
- subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
400
+ subagents: { agentOverrides: { builder: { model: "openai/gpt-5.4" } } },
309
401
  });
310
- writeProjectAgent(tempProject, "reviewer", `---\nname: reviewer\ndescription: Project reviewer\nmodel: google/gemini-3-pro\n---\n\nUse the project reviewer.\n`);
402
+ writeProjectAgent(tempProject, "builder", `---\nname: builder\ndescription: Project builder\nmodel: google/gemini-3-pro\n---\n\nUse the project builder.\n`);
311
403
 
312
- const reviewer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "reviewer");
313
- assert.ok(reviewer);
314
- assert.equal(reviewer.source, "project");
315
- assert.equal(reviewer.model, "google/gemini-3-pro");
316
- assert.equal(reviewer.override, undefined);
404
+ const builder = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "builder");
405
+ assert.ok(builder);
406
+ assert.equal(builder.source, "project");
407
+ assert.equal(builder.model, "google/gemini-3-pro");
408
+ assert.equal(builder.override, undefined);
317
409
  });
318
410
 
319
411
  it("fills in unset fields on a custom project agent from project agentOverrides", () => {
@@ -329,6 +421,7 @@ describe("builtin agent overrides", () => {
329
421
  inheritProjectContext: true,
330
422
  inheritSkills: true,
331
423
  defaultContext: "fork",
424
+ acceptanceRole: "writer",
332
425
  tools: ["bash", "mcp:xcodebuild_list_sims"],
333
426
  skills: ["tdd"],
334
427
  subagentOnlyExtensions: ["./tools/child-review.ts"],
@@ -349,6 +442,7 @@ describe("builtin agent overrides", () => {
349
442
  assert.equal(implementer.inheritProjectContext, true);
350
443
  assert.equal(implementer.inheritSkills, true);
351
444
  assert.equal(implementer.defaultContext, "fork");
445
+ assert.equal(implementer.acceptanceRole, "writer");
352
446
  assert.deepEqual(implementer.tools, ["bash"]);
353
447
  assert.deepEqual(implementer.mcpDirectTools, ["xcodebuild_list_sims"]);
354
448
  assert.deepEqual(implementer.skills, ["tdd"]);
@@ -412,12 +506,13 @@ describe("builtin agent overrides", () => {
412
506
  skills: ["override-skill"],
413
507
  inheritProjectContext: true,
414
508
  defaultContext: "fork",
509
+ acceptanceRole: "writer",
415
510
  completionGuard: true,
416
511
  },
417
512
  },
418
513
  },
419
514
  });
420
- writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\nmodel: google/gemini-3-pro\nthinking: medium\ntools: read, mcp:local_tool\nskills: agent-skill\ninheritProjectContext: false\ndefaultContext: fresh\ncompletionGuard: false\n---\n\nDrive the failing test first.\n`);
515
+ writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\nmodel: google/gemini-3-pro\nthinking: medium\ntools: read, mcp:local_tool\nskills: agent-skill\ninheritProjectContext: false\ndefaultContext: fresh\nacceptanceRole: read-only\ncompletionGuard: false\n---\n\nDrive the failing test first.\n`);
421
516
 
422
517
  const implementer = discoverAgents(tempProject, "both").agents.find((agent) => agent.name === "implementer");
423
518
  assert.ok(implementer);
@@ -428,13 +523,14 @@ describe("builtin agent overrides", () => {
428
523
  assert.deepEqual(implementer.skills, ["agent-skill"]);
429
524
  assert.equal(implementer.inheritProjectContext, false);
430
525
  assert.equal(implementer.defaultContext, "fresh");
526
+ assert.equal(implementer.acceptanceRole, "read-only");
431
527
  assert.equal(implementer.completionGuard, false);
432
528
  assert.equal(implementer.override, undefined);
433
529
  });
434
530
 
435
531
  it("leaves a custom agent untouched when no agentOverrides entry matches its name", () => {
436
532
  writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
437
- subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
533
+ subagents: { agentOverrides: { builder: { model: "openai/gpt-5.4" } } },
438
534
  });
439
535
  writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\n---\n\nDrive the failing test first.\n`);
440
536
 
@@ -458,7 +554,7 @@ describe("builtin agent overrides", () => {
458
554
  it("does not create a settings file when removing a non-existent override", () => {
459
555
  const settingsPath = path.join(tempHome, ".selesai", "agent", "settings.json");
460
556
  assert.equal(fs.existsSync(settingsPath), false);
461
- removeBuiltinAgentOverride(tempProject, "reviewer", "user");
557
+ removeBuiltinAgentOverride(tempProject, "builder", "user");
462
558
  assert.equal(fs.existsSync(settingsPath), false);
463
559
  });
464
560
 
@@ -492,7 +588,7 @@ describe("builtin agent overrides", () => {
492
588
  writeJson(settingsPath, {
493
589
  subagents: {
494
590
  agentOverrides: {
495
- reviewer: {
591
+ builder: {
496
592
  inheritProjectContext: "true",
497
593
  },
498
594
  },
@@ -503,17 +599,38 @@ describe("builtin agent overrides", () => {
503
599
  () => discoverAgents(tempProject, "both"),
504
600
  (error: unknown) => error instanceof Error
505
601
  && error.message.includes(settingsPath)
506
- && error.message.includes("reviewer")
602
+ && error.message.includes("builder")
507
603
  && error.message.includes("inheritProjectContext"),
508
604
  );
509
605
  });
510
606
 
607
+ it("surfaces malformed acceptance role override values", () => {
608
+ const settingsPath = path.join(tempHome, ".selesai", "agent", "settings.json");
609
+ writeJson(settingsPath, {
610
+ subagents: {
611
+ agentOverrides: {
612
+ builder: {
613
+ acceptanceRole: "observer",
614
+ },
615
+ },
616
+ },
617
+ });
618
+
619
+ assert.throws(
620
+ () => discoverAgents(tempProject, "both"),
621
+ (error: unknown) => error instanceof Error
622
+ && error.message.includes(settingsPath)
623
+ && error.message.includes("builder")
624
+ && error.message.includes("acceptanceRole"),
625
+ );
626
+ });
627
+
511
628
  it("surfaces malformed completion guard override values", () => {
512
629
  const settingsPath = path.join(tempHome, ".selesai", "agent", "settings.json");
513
630
  writeJson(settingsPath, {
514
631
  subagents: {
515
632
  agentOverrides: {
516
- reviewer: {
633
+ builder: {
517
634
  completionGuard: "false",
518
635
  },
519
636
  },
@@ -524,7 +641,7 @@ describe("builtin agent overrides", () => {
524
641
  () => discoverAgents(tempProject, "both"),
525
642
  (error: unknown) => error instanceof Error
526
643
  && error.message.includes(settingsPath)
527
- && error.message.includes("reviewer")
644
+ && error.message.includes("builder")
528
645
  && error.message.includes("completionGuard"),
529
646
  );
530
647
  });
@@ -539,6 +656,7 @@ describe("builtin agent overrides", () => {
539
656
  inheritProjectContext: true,
540
657
  inheritSkills: false,
541
658
  defaultContext: "fork",
659
+ acceptanceRole: "read-only",
542
660
  systemPrompt: "Base prompt",
543
661
  skills: ["safe-bash"],
544
662
  tools: ["bash"],
@@ -554,6 +672,7 @@ describe("builtin agent overrides", () => {
554
672
  inheritProjectContext: false,
555
673
  inheritSkills: false,
556
674
  defaultContext: undefined,
675
+ acceptanceRole: undefined,
557
676
  systemPrompt: "Base prompt",
558
677
  skills: undefined,
559
678
  tools: undefined,
@@ -570,6 +689,7 @@ describe("builtin agent overrides", () => {
570
689
  systemPromptMode: "replace",
571
690
  inheritProjectContext: false,
572
691
  defaultContext: false,
692
+ acceptanceRole: false,
573
693
  skills: false,
574
694
  tools: false,
575
695
  subagentOnlyExtensions: false,
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import * as path from "node:path";
3
3
  import { describe, it } from "node:test";
4
- import { buildAsyncRunnerSteps, resolveAsyncRunnerLogPaths } from "../../src/runs/background/async-execution.ts";
4
+ import { buildAsyncRunnerSteps, formatAsyncStartedMessage, resolveAsyncRunnerLogPaths } from "../../src/runs/background/async-execution.ts";
5
5
  import type { AgentConfig } from "../../src/agents/agents.ts";
6
6
 
7
7
  const agent = (name: string, toolBudget?: AgentConfig["toolBudget"]): AgentConfig => ({
@@ -25,6 +25,18 @@ const ctx = {
25
25
  };
26
26
 
27
27
  describe("async runner execution", () => {
28
+ it("formats interactive yield and headless auto-drain guidance separately", () => {
29
+ const interactive = formatAsyncStartedMessage("Async: worker [interactive]", true);
30
+ assert.match(interactive, /interactive session[\s\S]*return control/i);
31
+ assert.match(interactive, /do not call subagent_wait\(\) merely to wait/i);
32
+ assert.doesNotMatch(interactive, /auto-drains current-session background work/i);
33
+
34
+ const headless = formatAsyncStartedMessage("Async: worker [headless]", false);
35
+ assert.match(headless, /non-interactive run.*auto-drains current-session background work at agent_end/i);
36
+ assert.match(headless, /call subagent_wait\(\).*results before it ends/i);
37
+ assert.doesNotMatch(headless, /By default, return control to the user/i);
38
+ });
39
+
28
40
  it("places detached runner stdio logs in the async run directory", () => {
29
41
  const asyncDir = path.join("tmp", "async-run");
30
42
  assert.deepEqual(resolveAsyncRunnerLogPaths({ asyncDir }), {
@@ -47,12 +59,14 @@ describe("async runner execution", () => {
47
59
  ctx,
48
60
  asyncDir: path.join(process.cwd(), ".tmp-async-test"),
49
61
  maxSubagentDepth: 2,
62
+ waitToolEnabled: false,
50
63
  toolBudget: { hard: 3, block: ["find"] },
51
64
  configToolBudget: { hard: 5, block: ["ls"] },
52
65
  });
53
66
 
54
67
  assert.ok("steps" in result, "expected successful step build");
55
68
  assert.deepEqual(result.steps[0]?.toolBudget, { hard: 3, block: ["find"] });
69
+ assert.equal(result.steps[0]?.waitToolEnabled, false);
56
70
  assert.deepEqual(result.steps[1]?.toolBudget, { hard: 2, block: ["grep"] });
57
71
  });
58
72