@ashx-j/lunr-dev 0.2.13-dev.4.1 → 0.2.13-dev.7.1

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 (208) hide show
  1. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  2. package/dist/builtin-extensions/ashxj-tui.js +4 -4
  3. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  4. package/dist/builtin-extensions/index.d.ts.map +1 -1
  5. package/dist/builtin-extensions/index.js +2 -0
  6. package/dist/builtin-extensions/index.js.map +1 -1
  7. package/dist/builtin-extensions/lunr-settings-tools.d.ts +4 -0
  8. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +1 -0
  9. package/dist/builtin-extensions/lunr-settings-tools.js +120 -0
  10. package/dist/builtin-extensions/lunr-settings-tools.js.map +1 -0
  11. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts +2 -2
  12. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts.map +1 -1
  13. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.js.map +1 -1
  14. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js +3 -3
  16. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts +2 -2
  18. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +2 -1
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +5 -11
  25. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +12 -15
  27. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  29. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +14 -27
  31. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +6 -4
  34. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -1
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +6 -4
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js +4 -2
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js +3 -35
  46. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +5 -12
  49. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +14 -31
  52. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +2 -0
  54. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +28 -22
  56. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  58. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +9 -4
  62. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +2 -2
  66. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +4 -7
  68. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts +3 -3
  72. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js +7 -6
  74. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js +3 -3
  77. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +1 -1
  79. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +6 -4
  81. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  82. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  84. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +15 -10
  85. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.d.ts.map +1 -1
  87. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js +3 -2
  88. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js.map +1 -1
  89. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -2
  90. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +75 -43
  92. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  93. package/dist/catalog/models.json +1 -1
  94. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  95. package/dist/catalog/providers/anthropic.json +1 -1
  96. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  97. package/dist/catalog/providers/fireworks.json +1 -1
  98. package/dist/catalog/providers/github-copilot.json +1 -1
  99. package/dist/catalog/providers/google-vertex.json +1 -1
  100. package/dist/catalog/providers/google.json +1 -1
  101. package/dist/catalog/providers/huggingface.json +1 -1
  102. package/dist/catalog/providers/nvidia.json +1 -1
  103. package/dist/catalog/providers/opencode-go.json +1 -1
  104. package/dist/catalog/providers/opencode.json +1 -1
  105. package/dist/catalog/providers/openrouter.json +1 -1
  106. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  107. package/dist/catalog/publication.json +3 -3
  108. package/dist/core/agent-session-runtime.d.ts +5 -1
  109. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  110. package/dist/core/agent-session-runtime.js +7 -2
  111. package/dist/core/agent-session-runtime.js.map +1 -1
  112. package/dist/core/agent-session.d.ts +2 -0
  113. package/dist/core/agent-session.d.ts.map +1 -1
  114. package/dist/core/agent-session.js +20 -5
  115. package/dist/core/agent-session.js.map +1 -1
  116. package/dist/core/context-breakdown.d.ts +2 -0
  117. package/dist/core/context-breakdown.d.ts.map +1 -1
  118. package/dist/core/context-breakdown.js +6 -2
  119. package/dist/core/context-breakdown.js.map +1 -1
  120. package/dist/core/injected-prompt.d.ts +3 -3
  121. package/dist/core/injected-prompt.d.ts.map +1 -1
  122. package/dist/core/injected-prompt.js +2 -7
  123. package/dist/core/injected-prompt.js.map +1 -1
  124. package/dist/core/large-subagent-launch.d.ts +13 -0
  125. package/dist/core/large-subagent-launch.d.ts.map +1 -0
  126. package/dist/core/large-subagent-launch.js +54 -0
  127. package/dist/core/large-subagent-launch.js.map +1 -0
  128. package/dist/core/model-instructions.d.ts +24 -0
  129. package/dist/core/model-instructions.d.ts.map +1 -0
  130. package/dist/core/model-instructions.js +123 -0
  131. package/dist/core/model-instructions.js.map +1 -0
  132. package/dist/core/permissions.d.ts +11 -10
  133. package/dist/core/permissions.d.ts.map +1 -1
  134. package/dist/core/permissions.js +61 -45
  135. package/dist/core/permissions.js.map +1 -1
  136. package/dist/core/plan-mode.d.ts.map +1 -1
  137. package/dist/core/plan-mode.js +10 -1
  138. package/dist/core/plan-mode.js.map +1 -1
  139. package/dist/core/resource-loader.d.ts +3 -0
  140. package/dist/core/resource-loader.d.ts.map +1 -1
  141. package/dist/core/resource-loader.js +13 -4
  142. package/dist/core/resource-loader.js.map +1 -1
  143. package/dist/core/runtime-bridges.d.ts +4 -0
  144. package/dist/core/runtime-bridges.d.ts.map +1 -0
  145. package/dist/core/runtime-bridges.js +16 -0
  146. package/dist/core/runtime-bridges.js.map +1 -0
  147. package/dist/core/sdk.d.ts.map +1 -1
  148. package/dist/core/sdk.js +1 -0
  149. package/dist/core/sdk.js.map +1 -1
  150. package/dist/core/session-manager.d.ts.map +1 -1
  151. package/dist/core/session-manager.js +17 -16
  152. package/dist/core/session-manager.js.map +1 -1
  153. package/dist/core/settings-manager.d.ts +13 -0
  154. package/dist/core/settings-manager.d.ts.map +1 -1
  155. package/dist/core/settings-manager.js +32 -0
  156. package/dist/core/settings-manager.js.map +1 -1
  157. package/dist/core/settings-tools-bridge.d.ts +35 -0
  158. package/dist/core/settings-tools-bridge.d.ts.map +1 -0
  159. package/dist/core/settings-tools-bridge.js +56 -0
  160. package/dist/core/settings-tools-bridge.js.map +1 -0
  161. package/dist/core/swarm.d.ts +0 -31
  162. package/dist/core/swarm.d.ts.map +1 -1
  163. package/dist/core/swarm.js +2 -76
  164. package/dist/core/swarm.js.map +1 -1
  165. package/dist/core/system-prompt.d.ts.map +1 -1
  166. package/dist/core/system-prompt.js +1 -1
  167. package/dist/core/system-prompt.js.map +1 -1
  168. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  169. package/dist/gateway/agent-bridge.js +3 -2
  170. package/dist/gateway/agent-bridge.js.map +1 -1
  171. package/dist/gateway/approval.d.ts.map +1 -1
  172. package/dist/gateway/approval.js +4 -3
  173. package/dist/gateway/approval.js.map +1 -1
  174. package/dist/gateway/cron.d.ts.map +1 -1
  175. package/dist/gateway/cron.js +3 -2
  176. package/dist/gateway/cron.js.map +1 -1
  177. package/dist/gateway/router.d.ts +1 -1
  178. package/dist/gateway/router.d.ts.map +1 -1
  179. package/dist/gateway/router.js +1 -1
  180. package/dist/gateway/router.js.map +1 -1
  181. package/dist/main.d.ts.map +1 -1
  182. package/dist/main.js +3 -9
  183. package/dist/main.js.map +1 -1
  184. package/dist/migrations.d.ts.map +1 -1
  185. package/dist/migrations.js +4 -0
  186. package/dist/migrations.js.map +1 -1
  187. package/dist/modes/interactive/components/injected-prompt-message.d.ts +1 -1
  188. package/dist/modes/interactive/components/injected-prompt-message.d.ts.map +1 -1
  189. package/dist/modes/interactive/components/injected-prompt-message.js +1 -1
  190. package/dist/modes/interactive/components/injected-prompt-message.js.map +1 -1
  191. package/dist/modes/interactive/components/settings-selector.d.ts +8 -1
  192. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  193. package/dist/modes/interactive/components/settings-selector.js +61 -1
  194. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  195. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  196. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  197. package/dist/modes/interactive/interactive-mode.js +31 -23
  198. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  199. package/dist/startup/interactive-shell.d.ts.map +1 -1
  200. package/dist/startup/interactive-shell.js +2 -1
  201. package/dist/startup/interactive-shell.js.map +1 -1
  202. package/docs/features.md +7 -6
  203. package/docs/quickstart.md +3 -2
  204. package/docs/settings.md +3 -1
  205. package/docs/termux.md +1 -1
  206. package/docs/usage.md +2 -1
  207. package/examples/extensions/subagent/README.md +1 -1
  208. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"chain-execution.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.ts"],"names":[],"mappings":"AACA;;GAEG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAKhE,OAAO,EAcN,KAAK,SAAS,EAMd,MAAM,0BAA0B,CAAC;AAiBlC,OAAO,EACN,KAAK,aAAa,EAElB,KAAK,cAAc,EAEnB,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAGrB,MAAM,uBAAuB,CAAC;AA8W/B,UAAU,oBAAoB;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,GAAG,EAAE,gBAAgB,CAAC;IACtB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACzD,mBAAmB,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3D,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrG,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,kBAAkB,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IAClI,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,qBAAqB,CAAC;IACrC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3E,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,oBAAoB,CAAC,EAAE,aAAa,CAAC;QACrC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;KAC1B,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/D,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kHAAkH;IAClH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,UAAU,oBAAoB;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,cAAc,CAAC,EAAE;QAChB,KAAK,EAAE,SAAS,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAk2B9F","sourcesContent":["// @ts-nocheck\n/**\n * Chain execution logic for subagent tool\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport type { ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport type { ChildRuntimeConfig } from \"../../shared/types.ts\";\nimport { normalizeChildSpec } from \"../../shared/child-spec.ts\";\nimport { snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { ChainClarifyComponent, type ChainClarifyResult, type BehaviorOverride } from \"./chain-clarify.ts\";\nimport { toModelInfo, type ModelInfo } from \"../../shared/model-info.ts\";\nimport {\n\tresolveChainTemplates,\n\tcreateChainDir,\n\tremoveChainDir,\n\tresolveStepBehavior,\n\tresolveParallelBehaviors,\n\tbuildChainInstructions,\n\twriteInitialProgressFile,\n\tcreateParallelDirs,\n\tsuppressProgressForReadOnlyTask,\n\taggregateParallelOutputs,\n\tisDynamicParallelStep,\n\tisParallelStep,\n\ttype StepOverrides,\n\ttype ChainStep,\n\ttype ParallelStep,\n\ttype SequentialStep,\n\ttype ParallelTaskResult,\n\ttype ResolvedStepBehavior,\n\ttype ResolvedTemplates,\n} from \"../../shared/settings.ts\";\nimport { discoverAvailableSkills, normalizeSkillInput } from \"../../agents/skills.ts\";\nimport { INTERCOM_BRIDGE_MARKER } from \"../../intercom/intercom-bridge.ts\";\nimport { runSync } from \"./execution.ts\";\nimport { buildChainSummary } from \"../../shared/formatters.ts\";\nimport { compactForegroundDetails, getSingleResultOutput, mapConcurrent, resolveChildCwd, sumResultsCost, sumResultsUsage } from \"../../shared/utils.ts\";\nimport { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from \"../shared/parallel-utils.ts\";\nimport { recordRun } from \"../shared/run-history.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport {\n\ttype ActivityState,\n\ttype AgentProgress,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype ControlEvent,\n\ttype Details,\n\ttype IntercomEventBus,\n\ttype NestedRouteInfo,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SingleResult,\n\ttype ToolBudgetConfig,\n\tMAX_CONCURRENCY,\n\tresolveChildMaxSubagentDepth,\n} from \"../../shared/types.ts\";\nimport { captureModelSelection, resolveEffectiveSubagentModel, resolveTierModelOverride } from \"../shared/model-fallback.ts\";\nimport type { ModelScopeConfig } from \"../shared/model-scope.ts\";\nimport { injectSingleOutputInstruction, validateFileOnlyOutputMode } from \"../shared/single-output.ts\";\nimport { buildWorkflowGraphSnapshot } from \"../shared/workflow-graph.ts\";\nimport { ChainOutputValidationError, outputEntryFromResult, resolveOutputReferences, validateChainOutputBindings } from \"../shared/chain-outputs.ts\";\nimport { createStructuredOutputRuntime } from \"../shared/structured-output.ts\";\nimport { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection, type DynamicCollectedResult } from \"../shared/dynamic-fanout.ts\";\nimport { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance, resolveEffectiveAcceptance } from \"../shared/acceptance.ts\";\nimport type { ChainOutputMap } from \"../../shared/types.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\n\ninterface ChainExecutionDetailsInput {\n\tresults: SingleResult[];\n\tincludeProgress?: boolean;\n\tallProgress: AgentProgress[];\n\tallArtifactPaths: ArtifactPaths[];\n\tartifactsDir: string;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tcurrentStepIndex?: number;\n\trunId: string;\n\toutputs?: ChainOutputMap;\n\tcurrentFlatIndex?: number;\n\tdynamicChildren?: Record<number, Array<{ agent: string; label?: string; flatIndex: number; itemKey: string; outputName?: string; structured?: boolean; error?: string }>>;\n\tdynamicGroupStatuses?: Record<number, { status: \"pending\" | \"running\" | \"completed\" | \"failed\" | \"paused\" | \"stopped\" | \"detached\"; error?: string; acceptance?: SingleResult[\"acceptance\"] }>;\n}\n\ninterface ParallelChainRunInput {\n\tstep: ParallelStep;\n\tparallelTemplates: string[];\n\tparallelBehaviors: ResolvedStepBehavior[];\n\tagents: ChildRuntimeConfig[];\n\tstepIndex: number;\n\tavailableModels: ModelInfo[];\n\tmodelScope?: ModelScopeConfig;\n\tchainDir: string;\n\tprev: string;\n\toriginalTask: string;\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tcwd?: string;\n\trunId: string;\n\tglobalTaskIndex: number;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (agentName: string, idx?: number, modelOverride?: string) => ChildRuntimeConfig[\"thinking\"] | undefined;\n\tshareEnabled: boolean;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\tsignal?: AbortSignal;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: {\n\t\tupdatedAt: number;\n\t\tcurrentAgent?: string;\n\t\tcurrentChildId?: string;\n\t\tcurrentIndex?: number;\n\t\tcurrentActivityState?: ActivityState;\n\t\tlastActivityAt?: number;\n\t\tcurrentTool?: string;\n\t\tcurrentToolStartedAt?: number;\n\t\tcurrentPath?: string;\n\t\tturnCount?: number;\n\t\ttokens?: number;\n\t\ttoolCount?: number;\n\t\tinterrupt?: () => boolean;\n\t};\n\tresults: SingleResult[];\n\tallProgress: AgentProgress[];\n\toutputs: ChainOutputMap;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tdynamicChildren?: ChainExecutionDetailsInput[\"dynamicChildren\"];\n\tdynamicGroupStatuses?: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"];\n\tworktreeSetup?: WorktreeSetup;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ToolBudgetConfig;\n\tglobalSemaphore?: Semaphore;\n\tdynamic?: boolean;\n}\n\nfunction buildChainExecutionDetails(input: ChainExecutionDetailsInput): Details {\n\treturn compactForegroundDetails({\n\t\tmode: \"chain\",\n\t\tresults: input.results,\n\t\tprogress: input.includeProgress ? input.allProgress : undefined,\n\t\tartifacts: input.allArtifactPaths.length ? { dir: input.artifactsDir, files: input.allArtifactPaths } : undefined,\n\t\tchainAgents: input.chainAgents,\n\t\ttotalSteps: input.totalSteps,\n\t\tcurrentStepIndex: input.currentStepIndex,\n\t\toutputs: input.outputs,\n\t\ttotalChildUsage: sumResultsUsage(input.results),\n\t\ttotalCost: sumResultsCost(input.results),\n\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\trunId: input.runId,\n\t\t\tmode: \"chain\",\n\t\t\tsteps: input.chainSteps,\n\t\t\tresults: input.results,\n\t\t\tcurrentStepIndex: input.currentStepIndex,\n\t\t\tcurrentFlatIndex: input.currentFlatIndex,\n\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t}),\n\t});\n}\n\nfunction buildChainExecutionErrorResult(message: string, input: ChainExecutionDetailsInput): ChainExecutionResult {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tisError: true,\n\t\tdetails: buildChainExecutionDetails(input),\n\t};\n}\n\nfunction ensureParallelProgressFile(\n\tchainDir: string,\n\tprogressCreated: boolean,\n\tparallelBehaviors: ResolvedStepBehavior[],\n): boolean {\n\tif (progressCreated || !parallelBehaviors.some((behavior) => behavior.progress)) {\n\t\treturn progressCreated;\n\t}\n\twriteInitialProgressFile(chainDir);\n\treturn true;\n}\n\nfunction appendParallelWorktreeSummary(\n\toutput: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tdiffsDir: string,\n\tagents: string[],\n): string {\n\tif (!worktreeSetup) return output;\n\tconst diffs = diffWorktrees(worktreeSetup, agents, diffsDir);\n\tconst diffSummary = formatWorktreeDiffSummary(diffs);\n\tif (!diffSummary) return output;\n\treturn `${output}\\n\\n${diffSummary}`;\n}\n\nfunction resolveChainToolBudget(input: { stepBudget?: ToolBudgetConfig; runBudget?: ResolvedToolBudget; agentBudget?: ToolBudgetConfig; configBudget?: ToolBudgetConfig }): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tif (input.stepBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.stepBudget, \"toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tif (input.runBudget !== undefined) return { toolBudget: input.runBudget };\n\tif (input.agentBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.agentBudget, \"agent.toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tconst resolved = validateToolBudgetConfig(input.configBudget, \"config.toolBudget\");\n\treturn { toolBudget: resolved.budget, error: resolved.error };\n}\n\nasync function runParallelChainTasks(input: ParallelChainRunInput): Promise<SingleResult[]> {\n\tconst concurrency = input.step.concurrency ?? MAX_CONCURRENCY;\n\tconst failFast = input.step.failFast ?? false;\n\tlet aborted = false;\n\tconst effectiveModels = input.step.parallel.map((task) => {\n\t\tconst taskChildConfig = input.agents.find((child) => child.name === task.agent);\n\t\treturn resolveEffectiveSubagentModel(\n\t\t\t// lunr: model tiers — explicit per-task model wins; otherwise resolve task.tier via the tier bridge.\n\t\t\ttask.model ?? resolveTierModelOverride(task.tier),\n\t\t\ttaskChildConfig?.model,\n\t\t\tinput.ctx.model,\n\t\t\tinput.availableModels,\n\t\t\tinput.ctx.model?.provider,\n\t\t\t{ scope: input.modelScope },\n\t\t);\n\t});\n\tfor (let taskIndex = 0; taskIndex < input.step.parallel.length; taskIndex++) {\n\t\tconst task = input.step.parallel[taskIndex]!;\n\t\tinput.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModels[taskIndex]);\n\t}\n\n\tconst parallelResults = await mapConcurrent(\n\t\tinput.step.parallel,\n\t\tconcurrency,\n\t\tasync (task, taskIndex) => {\n\t\t\tif (aborted && failFast) {\n\t\t\t\treturn {\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\ttask: \"(skipped)\",\n\t\t\t\t\texitCode: -1,\n\t\t\t\t\tmessages: [],\n\t\t\t\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },\n\t\t\t\t\terror: \"Skipped due to fail-fast\",\n\t\t\t\t} as SingleResult;\n\t\t\t}\n\n\t\t\tconst taskTemplate = input.parallelTemplates[taskIndex] ?? \"{previous}\";\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(input.parallelBehaviors[taskIndex]!, taskTemplate, input.originalTask);\n\t\t\tconst taskChildConfig = input.agents.find((child) => child.name === task.agent);\n\t\t\tconst templateHasPrevious = taskTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tinput.chainDir,\n\t\t\t\tfalse,\n\t\t\t\ttemplateHasPrevious ? undefined : input.prev,\n\t\t\t);\n\n\t\t\tlet taskStr = resolveOutputReferences(taskTemplate, input.outputs);\n\t\t\ttaskStr = taskStr.replace(/\\{task\\}/g, input.originalTask);\n\t\t\ttaskStr = taskStr.replace(/\\{previous\\}/g, input.prev);\n\t\t\ttaskStr = taskStr.replace(/\\{chain_dir\\}/g, input.chainDir);\n\t\t\tconst cleanTask = taskStr;\n\t\t\ttaskStr = prefix + taskStr + suffix;\n\n\t\t\tconst effectiveModel = effectiveModels[taskIndex];\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(input.maxSubagentDepth, taskChildConfig?.maxSubagentDepth);\n\t\t\tconst toolBudget = resolveChainToolBudget({ stepBudget: task.toolBudget, runBudget: input.toolBudget, agentBudget: taskChildConfig?.toolBudget, configBudget: input.configToolBudget });\n\t\t\tif (toolBudget.error) throw new Error(toolBudget.error);\n\n\t\t\tconst taskCwd = input.worktreeSetup\n\t\t\t\t? input.worktreeSetup.worktrees[taskIndex]!.agentCwd\n\t\t\t\t: resolveChildCwd(input.cwd ?? input.ctx.cwd, task.cwd);\n\n\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(input.chainDir, behavior.output))\n\t\t\t\t: undefined;\n\t\t\ttaskStr = injectSingleOutputInstruction(taskStr, outputPath, taskChildConfig);\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (input.foregroundControl) {\n\t\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\t\tinput.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;\n\t\t\t\tinput.foregroundControl.currentActivityState = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\tinput.foregroundControl.interrupt = () => {\n\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\tinput.foregroundControl!.currentActivityState = undefined;\n\t\t\t\t\tinput.foregroundControl!.updatedAt = Date.now();\n\t\t\t\t\treturn true;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst structuredRuntime = task.outputSchema\n\t\t\t\t? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, \"structured-output\"))\n\t\t\t\t: undefined;\n\t\t\tconst result = await runSync(input.ctx.cwd, normalizeChildSpec({\n\t\t\t\ttask: taskStr,\n\t\t\t\tdescription: task.description,\n\t\t\t\tpermissions: task.permissions,\n\t\t\t\tmodel: effectiveModel ?? task.model,\n\t\t\t\ttier: task.tier,\n\t\t\t\tmodelSelection: captureModelSelection({ model: task.model, tier: task.tier }),\n\t\t\t\tskill: task.skill,\n\t\t\t\tcwd: taskCwd,\n\t\t\t\toutput: task.output,\n\t\t\t\toutputMode: task.outputMode,\n\t\t\t\tacceptance: task.acceptance,\n\t\t\t\ttoolBudget: task.toolBudget,\n\t\t\t}, { parentMode: snapshotParentPermissionMode(input.ctx.sessionManager.getSessionId() ?? undefined), runId: input.runId, index: input.globalTaskIndex + taskIndex }), {\n\t\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcwd: taskCwd,\n\t\t\t\tsignal: input.signal,\n\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\tallowIntercomDetach: taskChildConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\tintercomEvents: input.intercomEvents,\n\t\t\t\trunId: input.runId,\n\t\t\t\tindex: input.globalTaskIndex + taskIndex,\n\t\t\t\tsessionDir: input.sessionDirForIndex(input.globalTaskIndex + taskIndex),\n\t\t\t\tsessionFile: input.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModel)\n\t\t\t\t\t?? input.sessionFileForIndex?.(input.globalTaskIndex + taskIndex),\n\t\t\t\tthinkingOverride: input.thinkingOverrideForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModel),\n\t\t\t\tshare: input.shareEnabled,\n\t\t\t\tartifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,\n\t\t\t\tartifactConfig: input.artifactConfig,\n\t\t\t\toutputPath,\n\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\tcontrolConfig: input.controlConfig,\n\t\t\t\tonControlEvent: input.onControlEvent,\n\t\t\t\tintercomSessionName: input.childIntercomTarget?.(task.agent, input.globalTaskIndex + taskIndex),\n\t\t\t\torchestratorIntercomTarget: input.orchestratorIntercomTarget,\n\t\t\t\tnestedRoute: input.nestedRoute,\n\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\tavailableModels: input.availableModels,\n\t\t\t\tpreferredModelProvider: input.ctx.model?.provider,\n\t\t\t\tmodelScope: input.modelScope,\n\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\tacceptance: task.acceptance,\n\t\t\t\tacceptanceContext: { mode: \"chain\", dynamic: input.dynamic && task.acceptance === undefined },\n\t\t\t\ttimeoutMs: input.timeoutMs,\n\t\t\t\tdeadlineAt: input.deadlineAt,\n\t\t\t\tturnBudget: input.turnBudget,\n\t\t\t\tonDetachedExit: input.onDetachedExit\n\t\t\t\t\t? (result) => input.onDetachedExit?.(input.globalTaskIndex + taskIndex, result)\n\t\t\t\t\t: undefined,\n\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\tonUpdate: input.onUpdate\n\t\t\t\t\t? (progressUpdate) => {\n\t\t\t\t\t\tconst stepResults = progressUpdate.details?.results || [];\n\t\t\t\t\t\tconst stepProgress = progressUpdate.details?.progress || [];\n\t\t\t\t\t\tif (input.foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\t\t\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\t\t\t\t\tinput.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;\n\t\t\t\t\t\t\tinput.foregroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\t\tinput.foregroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\t\tinput.foregroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\t\tinput.foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\t\tinput.foregroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\t\tinput.foregroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\t\tinput.foregroundControl.tokens = current?.tokens;\n\t\t\t\t\t\t\tinput.foregroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinput.onUpdate?.({\n\t\t\t\t\t\t\t...progressUpdate,\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\tprogress: input.allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\tcontrolEvents: progressUpdate.details?.controlEvents,\n\t\t\t\t\t\t\t\tchainAgents: input.chainAgents,\n\t\t\t\t\t\t\t\ttotalSteps: input.totalSteps,\n\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\toutputs: input.outputs,\n\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\trunId: input.runId,\n\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\tsteps: input.chainSteps,\n\t\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\t\tcurrentFlatIndex: input.globalTaskIndex + taskIndex,\n\t\t\t\t\t\t\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\t\t\t\t\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t});\n\t\t\tif (input.foregroundControl?.currentIndex === input.globalTaskIndex + taskIndex) {\n\t\t\t\tinput.foregroundControl.interrupt = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t}\n\n\t\t\tif (result.exitCode !== 0 && failFast) {\n\t\t\t\taborted = true;\n\t\t\t}\n\t\t\trecordRun(task.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0);\n\t\t\treturn result;\n\t\t},\n\t\tinput.globalSemaphore,\n\t);\n\n\treturn parallelResults;\n}\n\ninterface ChainExecutionParams {\n\tchain: ChainStep[];\n\ttask?: string;\n\tagents: ChildRuntimeConfig[];\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tsignal?: AbortSignal;\n\trunId: string;\n\tcwd?: string;\n\tshareEnabled: boolean;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (agentName: string, idx?: number, modelOverride?: string) => ChildRuntimeConfig[\"thinking\"] | undefined;\n\tartifactsDir: string;\n\tartifactConfig: ArtifactConfig;\n\tincludeProgress?: boolean;\n\tclarify?: boolean;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: {\n\t\tupdatedAt: number;\n\t\tcurrentAgent?: string;\n\t\tcurrentChildId?: string;\n\t\tcurrentIndex?: number;\n\t\tcurrentActivityState?: ActivityState;\n\t\tlastActivityAt?: number;\n\t\tcurrentTool?: string;\n\t\tcurrentToolStartedAt?: number;\n\t\tcurrentPath?: string;\n\t\tturnCount?: number;\n\t\ttokens?: number;\n\t\ttoolCount?: number;\n\t\tinterrupt?: () => boolean;\n\t};\n\tchainSkills?: string[];\n\tchainDir?: string;\n\tdynamicFanoutMaxItems?: number;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\tworktreeSetupHook?: string;\n\tworktreeSetupHookTimeoutMs?: number;\n\tworktreeBaseDir?: string;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ToolBudgetConfig;\n\t/** Global cap on simultaneously-running tasks within this chain. Defaults to DEFAULT_GLOBAL_CONCURRENCY_LIMIT. */\n\tglobalConcurrencyLimit?: number;\n}\n\ninterface ChainExecutionResult {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: Details;\n\tisError?: boolean;\n\t/** User requested async execution via TUI - caller should dispatch to executeAsyncChain */\n\trequestedAsync?: {\n\t\tchain: ChainStep[];\n\t\tchainSkills: string[];\n\t};\n}\n\n/**\n * Execute a chain of subagent steps\n */\nexport async function executeChain(params: ChainExecutionParams): Promise<ChainExecutionResult> {\n\tconst {\n\t\tchain: chainSteps,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tcwd,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tincludeProgress,\n\t\tclarify,\n\t\tonUpdate,\n\t\tonControlEvent,\n\t\tcontrolConfig,\n\t\tonDetachedExit,\n\t\tchildIntercomTarget,\n\t\torchestratorIntercomTarget,\n\t\tforegroundControl,\n\t\tintercomEvents,\n\t\tchainSkills: chainSkillsParam,\n\t\tchainDir: chainDirBase,\n\t\tmodelScope,\n\t} = params;\n\tconst chainSkills = chainSkillsParam ?? [];\n\n\tconst results: SingleResult[] = [];\n\tconst outputs: ChainOutputMap = {};\n\tconst dynamicChildren: ChainExecutionDetailsInput[\"dynamicChildren\"] = {};\n\tconst dynamicGroupStatuses: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"] = {};\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\n\tconst chainAgents: string[] = chainSteps.map((step) =>\n\t\tisParallelStep(step)\n\t\t\t? `[${step.parallel.map((t) => t.description || t.label || t.agent || \"child\").join(\"+\")}]`\n\t\t\t: isDynamicParallelStep(step)\n\t\t\t\t? `expand:${step.parallel.description || step.parallel.label || step.parallel.agent || \"child\"}`\n\t\t\t: ((step as SequentialStep).description || (step as SequentialStep).label || (step as SequentialStep).agent || \"child\"),\n\t);\n\tconst totalSteps = chainSteps.length;\n\n\tconst makeDetailsInput = (overrides: Pick<Partial<ChainExecutionDetailsInput>, \"currentStepIndex\" | \"currentFlatIndex\"> = {}): ChainExecutionDetailsInput => ({\n\t\tresults,\n\t\t...(includeProgress !== undefined ? { includeProgress } : {}),\n\t\tallProgress,\n\t\tallArtifactPaths,\n\t\tartifactsDir,\n\t\tchainAgents,\n\t\tchainSteps,\n\t\ttotalSteps,\n\t\trunId,\n\t\toutputs,\n\t\tdynamicChildren,\n\t\tdynamicGroupStatuses,\n\t\t...overrides,\n\t});\n\n\tconst firstStep = chainSteps[0]!;\n\tconst originalTask = params.task\n\t\t?? (isParallelStep(firstStep)\n\t\t\t? firstStep.parallel[0]!.task!\n\t\t\t: isDynamicParallelStep(firstStep)\n\t\t\t\t? firstStep.parallel.task!\n\t\t\t\t: (firstStep as SequentialStep).task!);\n\ttry {\n\t\tvalidateChainOutputBindings(chainSteps, { maxItems: params.dynamicFanoutMaxItems });\n\t} catch (error) {\n\t\tif (error instanceof ChainOutputValidationError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: error.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\n\tconst chainDir = createChainDir(runId, chainDirBase);\n\tconst hasParallelSteps = chainSteps.some((step) => isParallelStep(step) || isDynamicParallelStep(step));\n\tlet templates: ResolvedTemplates = resolveChainTemplates(chainSteps);\n\tconst shouldClarify = clarify === true && ctx.hasUI && !hasParallelSteps;\n\tlet tuiBehaviorOverrides: (BehaviorOverride | undefined)[] | undefined;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst availableSkills = discoverAvailableSkills(cwd ?? ctx.cwd);\n\n\tif (shouldClarify) {\n\t\tconst seqSteps = chainSteps as SequentialStep[];\n\t\tconst agentConfigs: ChildRuntimeConfig[] = [];\n\t\tfor (const step of seqSteps) {\n\t\t\tconst config = agents.find((a) => a.name === step.agent);\n\t\t\tif (!config) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${step.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: seqSteps.indexOf(step) })),\n\t\t\t\t};\n\t\t\t}\n\t\t\tagentConfigs.push(config);\n\t\t}\n\n\t\tconst stepOverrides: StepOverrides[] = seqSteps.map((step) => ({\n\t\t\toutput: step.output,\n\t\t\toutputMode: step.outputMode,\n\t\t\treads: step.reads,\n\t\t\tprogress: step.progress,\n\t\t\tskills: normalizeSkillInput(step.skill),\n\t\t\tmodel: step.model,\n\t\t}));\n\n\t\tconst resolvedBehaviors = agentConfigs.map((_config, i) =>\n\t\t\tresolveStepBehavior(stepOverrides[i]!, chainSkills),\n\t\t);\n\t\tconst flatTemplates = templates as string[];\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui,\n\t\t\t\t\ttheme,\n\t\t\t\t\tagentConfigs,\n\t\t\t\t\tflatTemplates,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tresolvedBehaviors,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\toverlay: true,\n\t\t\t\toverlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" },\n\t\t\t},\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Chain cancelled\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\n\t\tif (result.runInBackground) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\tconst updatedChain: ChainStep[] = chainSteps.map((step, i) => {\n\t\t\t\tif (isParallelStep(step)) return step;\n\t\t\t\tconst override = result.behaviorOverrides[i];\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\ttask: result.templates[i]!,\n\t\t\t\t\t...(override?.model !== undefined ? { model: override.model } : {}),\n\t\t\t\t\t...(override?.output !== undefined ? { output: override.output } : {}),\n\t\t\t\t\t...(\"outputMode\" in step && step.outputMode !== undefined ? { outputMode: step.outputMode } : {}),\n\t\t\t\t\t...(override?.reads !== undefined ? { reads: override.reads } : {}),\n\t\t\t\t\t...(override?.progress !== undefined ? { progress: override.progress } : {}),\n\t\t\t\t\t...(override?.skills !== undefined ? { skill: override.skills } : {}),\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Launching in background...\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t\trequestedAsync: { chain: updatedChain, chainSkills },\n\t\t\t};\n\t\t}\n\n\t\ttemplates = result.templates;\n\t\ttuiBehaviorOverrides = result.behaviorOverrides;\n\t}\n\n\tconst deadlineAt = params.deadlineAt ?? (params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined);\n\tconst globalSemaphore = new Semaphore(params.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);\n\tlet prev = \"\";\n\tlet globalTaskIndex = 0;\n\tlet progressCreated = false;\n\n\tfor (let stepIndex = 0; stepIndex < chainSteps.length; stepIndex++) {\n\t\tconst step = chainSteps[stepIndex]!;\n\t\tconst stepTemplates = templates[stepIndex]!;\n\n\t\tif (isParallelStep(step)) {\n\t\t\tconst parallelTemplates = stepTemplates as string[];\n\t\t\tconst parallelCwd = resolveChildCwd(cwd ?? ctx.cwd, step.cwd);\n\t\t\tlet worktreeSetup: WorktreeSetup | undefined;\n\t\t\tif (step.worktree) {\n\t\t\t\tconst worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(step.parallel, parallelCwd);\n\t\t\t\tif (worktreeTaskCwdConflict) {\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\t`parallel chain step ${stepIndex + 1}: ${formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, parallelCwd)}`,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tworktreeSetup = createWorktrees(parallelCwd, `${runId}-s${stepIndex}`, step.parallel.length, {\n\t\t\t\t\t\tagents: step.parallel.map((task) => task.agent),\n\t\t\t\t\t\tsetupHook: params.worktreeSetupHook\n\t\t\t\t\t\t\t? { hookPath: params.worktreeSetupHook, timeoutMs: params.worktreeSetupHookTimeoutMs }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tbaseDir: params.worktreeBaseDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst agentNames = step.parallel.map((task) => task.agent);\n\t\t\t\tconst parallelBehaviors = resolveParallelBehaviors(step.parallel, stepIndex, chainSkills)\n\t\t\t\t\t.map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? step.parallel[taskIndex]?.task, originalTask));\n\t\t\t\tfor (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {\n\t\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Parallel chain step ${stepIndex + 1} task ${taskIndex + 1} (${step.parallel[taskIndex]!.agent})`);\n\t\t\t\t\tif (validationError) return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));\n\t\t\t\t}\n\t\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\t\tcreateParallelDirs(chainDir, stepIndex, step.parallel.length, agentNames);\n\n\t\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\t\tstep,\n\t\t\t\t\tparallelTemplates,\n\t\t\t\t\tparallelBehaviors,\n\t\t\t\t\tagents,\n\t\t\t\t\tstepIndex,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tmodelScope,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tprev,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tctx,\n\t\t\t\t\tintercomEvents,\n\t\t\t\t\tcwd,\n\t\t\t\t\trunId,\n\t\t\t\t\tglobalTaskIndex,\n\t\t\t\t\tsessionDirForIndex,\n\t\t\t\t\tsessionFileForIndex,\n\t\t\t\t\tsessionFileForTask,\n\t\t\t\t\tthinkingOverrideForTask,\n\t\t\t\t\tshareEnabled,\n\t\t\t\t\tartifactConfig,\n\t\t\t\t\tartifactsDir,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonUpdate,\n\t\t\t\t\tresults,\n\t\t\t\t\tallProgress,\n\t\t\t\t\toutputs,\n\t\t\t\t\tchainAgents,\n\t\t\t\t\tchainSteps,\n\t\t\t\t\ttotalSteps,\n\t\t\t\t\tdynamicChildren,\n\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\tcontrolConfig,\n\t\t\t\t\tonControlEvent,\n\t\t\t\t\tchildIntercomTarget,\n\t\t\t\t\torchestratorIntercomTarget,\n\t\t\t\t\tforegroundControl,\n\t\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\t\tworktreeSetup,\n\t\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\t\tdeadlineAt,\n\t\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\t\tonDetachedExit,\n\t\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\t\tglobalSemaphore,\n\t\t\t\t});\n\t\t\t\tglobalTaskIndex += step.parallel.length;\n\n\t\t\t\tfor (const result of parallelResults) {\n\t\t\t\t\tresults.push(result);\n\t\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t\t}\n\t\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\t\tif (interrupted) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + interruptedIndexInStep,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\t\tif (detached) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + detachedIndexInStep,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst failures = parallelResults\n\t\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\t\tif (failures.length > 0) {\n\t\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t\t.map((failure) => `- Task ${failure.originalIndex + 1} (${failure.agent}): ${failure.error || \"failed\"}`)\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tconst errorMsg = `Parallel step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + failures[0]!.originalIndex,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfor (let taskIndex = 0; taskIndex < parallelResults.length; taskIndex++) {\n\t\t\t\t\tconst outputName = step.parallel[taskIndex]?.as;\n\t\t\t\t\tif (outputName) outputs[outputName] = outputEntryFromResult(parallelResults[taskIndex]!, stepIndex);\n\t\t\t\t}\n\n\t\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => {\n\t\t\t\t\tconst outputTarget = parallelBehaviors[i]?.output;\n\t\t\t\t\tconst outputTargetPath = typeof outputTarget === \"string\"\n\t\t\t\t\t\t? (path.isAbsolute(outputTarget) ? outputTarget : path.join(chainDir, outputTarget))\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tagent: result.agent,\n\t\t\t\t\t\ttaskIndex: i,\n\t\t\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\t\t\texitCode: result.exitCode,\n\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\ttimedOut: result.timedOut,\n\t\t\t\t\t\toutputTargetPath,\n\t\t\t\t\t\toutputTargetExists: outputTargetPath ? fs.existsSync(outputTargetPath) : undefined,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tprev = aggregateParallelOutputs(taskResults);\n\t\t\t\tprev = appendParallelWorktreeSummary(\n\t\t\t\t\tprev,\n\t\t\t\t\tworktreeSetup,\n\t\t\t\t\tpath.join(chainDir, \"worktree-diffs\", `step-${stepIndex}`),\n\t\t\t\t\tagentNames,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tif (worktreeSetup) cleanupWorktrees(worktreeSetup);\n\t\t\t}\n\t\t} else if (isDynamicParallelStep(step)) {\n\t\t\tconst dynamicStartIndex = globalTaskIndex;\n\t\t\tconst reservedDynamicItems = step.expand.maxItems ?? params.dynamicFanoutMaxItems ?? 0;\n\t\t\tlet materialized: ReturnType<typeof materializeDynamicParallelStep>;\n\t\t\ttry {\n\t\t\t\tmaterialized = materializeDynamicParallelStep(step, outputs, stepIndex, { maxItems: params.dynamicFanoutMaxItems });\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t}\n\n\t\t\tdynamicChildren[stepIndex] = materialized.items.map((item, itemIndex) => ({\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tlabel: materialized.parallel[itemIndex]?.label,\n\t\t\t\tflatIndex: globalTaskIndex + itemIndex,\n\t\t\t\titemKey: item.key,\n\t\t\t\tstructured: Boolean(step.parallel.outputSchema),\n\t\t\t}));\n\n\t\t\tif (materialized.parallel.length === 0) {\n\t\t\t\tconst collection: DynamicCollectedResult[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collection);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t}\n\t\t\t\toutputs[step.collect.as] = {\n\t\t\t\t\ttext: JSON.stringify(collection),\n\t\t\t\t\tstructured: collection,\n\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\tstepIndex,\n\t\t\t\t};\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\t\tif (step.acceptance !== undefined) {\n\t\t\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\t\t\texplicit: step.acceptance,\n\t\t\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\t\t\ttask: (step.parallel.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"),\n\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\tdynamicGroup: true,\n\t\t\t\t\t});\n\t\t\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\t\t\tresults: [],\n\t\t\t\t\t\t\tnotes: \"Dynamic fanout produced 0 results.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tdynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;\n\t\t\t\t\tconst groupAcceptanceFailure = acceptanceFailureMessage(groupAcceptance);\n\t\t\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: groupAcceptanceFailure, acceptance: groupAcceptance };\n\t\t\t\t\t\treturn buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprev = \"Dynamic fanout produced 0 results.\";\n\t\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst dynamicParallelStep: ParallelStep = {\n\t\t\t\tparallel: materialized.parallel,\n\t\t\t\tconcurrency: step.concurrency,\n\t\t\t\tfailFast: step.failFast,\n\t\t\t};\n\t\t\tconst parallelTemplates = materialized.parallel.map((task) => task.task ?? \"{previous}\");\n\t\t\tconst parallelBehaviors = resolveParallelBehaviors(dynamicParallelStep.parallel, stepIndex, chainSkills)\n\t\t\t\t.map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? dynamicParallelStep.parallel[taskIndex]?.task, originalTask));\n\n\t\t\tfor (let taskIndex = 0; taskIndex < dynamicParallelStep.parallel.length; taskIndex++) {\n\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t\t: undefined;\n\t\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Dynamic chain step ${stepIndex + 1} item ${taskIndex + 1} (${dynamicParallelStep.parallel[taskIndex]!.agent})`);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: validationError };\n\t\t\t\t\treturn buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\tcreateParallelDirs(chainDir, stepIndex, dynamicParallelStep.parallel.length, dynamicParallelStep.parallel.map((task) => task.agent));\n\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\tstep: dynamicParallelStep,\n\t\t\t\tparallelTemplates,\n\t\t\t\tparallelBehaviors,\n\t\t\t\tagents,\n\t\t\t\tstepIndex,\n\t\t\t\tavailableModels,\n\t\t\t\tmodelScope,\n\t\t\t\tchainDir,\n\t\t\t\tprev,\n\t\t\t\toriginalTask,\n\t\t\t\tctx,\n\t\t\t\tintercomEvents,\n\t\t\t\tcwd,\n\t\t\t\trunId,\n\t\t\t\tglobalTaskIndex,\n\t\t\t\tsessionDirForIndex,\n\t\t\t\tsessionFileForIndex,\n\t\t\t\tsessionFileForTask,\n\t\t\t\tthinkingOverrideForTask,\n\t\t\t\tshareEnabled,\n\t\t\t\tartifactConfig,\n\t\t\t\tartifactsDir,\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t\tresults,\n\t\t\t\tallProgress,\n\t\t\t\toutputs,\n\t\t\t\tchainAgents,\n\t\t\t\tchainSteps,\n\t\t\t\ttotalSteps,\n\t\t\t\tdynamicChildren,\n\t\t\t\tdynamicGroupStatuses,\n\t\t\t\tcontrolConfig,\n\t\t\t\tonControlEvent,\n\t\t\t\tchildIntercomTarget,\n\t\t\t\torchestratorIntercomTarget,\n\t\t\t\tforegroundControl,\n\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\tdeadlineAt,\n\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\tonDetachedExit,\n\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\tglobalSemaphore,\n\t\t\t\tdynamic: true,\n\t\t\t});\n\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\n\t\t\tfor (const result of parallelResults) {\n\t\t\t\tresults.push(result);\n\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t}\n\t\t\tconst collected = collectDynamicResults(step, materialized.items, parallelResults);\n\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\tif (interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + interruptedIndexInStep,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\tif (detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + detachedIndexInStep,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst failures = parallelResults\n\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\tif (failures.length > 0) {\n\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t.map((failure) => `- Item ${failure.originalIndex + 1} (${failure.agent}, key ${materialized.items[failure.originalIndex]?.key ?? failure.originalIndex}): ${failure.error || \"failed\"}`)\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tconst errorMsg = `Dynamic step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: errorMsg };\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: errorMsg,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + failures[0]!.originalIndex,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collected);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: dynamicStartIndex }));\n\t\t\t}\n\t\t\toutputs[step.collect.as] = {\n\t\t\t\ttext: JSON.stringify(collected),\n\t\t\t\tstructured: collected,\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tstepIndex,\n\t\t\t};\n\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\texplicit: step.acceptance,\n\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\ttask: materialized.parallel\n\t\t\t\t\t.map((task) => (task.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"))\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\t\tmode: \"chain\",\n\t\t\t\tdynamicGroup: true,\n\t\t\t});\n\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\toutput: \"\",\n\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\tnotes: `Dynamic fanout collected ${collected.length} result(s) into ${step.collect.as}.`,\n\t\t\t\t}),\n\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t});\n\t\t\tdynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;\n\t\t\tconst groupAcceptanceFailure = effectiveGroupAcceptance.explicit ? acceptanceFailureMessage(groupAcceptance) : undefined;\n\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: groupAcceptanceFailure, acceptance: groupAcceptance };\n\t\t\t\treturn buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex - dynamicParallelStep.parallel.length }));\n\t\t\t}\n\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => ({\n\t\t\t\tagent: result.agent,\n\t\t\t\ttaskIndex: i,\n\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\terror: result.error,\n\t\t\t\ttimedOut: result.timedOut,\n\t\t\t}));\n\t\t\tprev = aggregateParallelOutputs(taskResults, (i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`);\n\t\t} else {\n\t\t\tconst seqStep = step as SequentialStep;\n\t\t\tconst stepTemplate = stepTemplates as string;\n\n\t\t\tconst agentConfig = agents.find((a) => a.name === seqStep.agent);\n\t\t\tif (!agentConfig) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${seqStep.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex })),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst tuiOverride = tuiBehaviorOverrides?.[stepIndex];\n\t\t\tconst stepOverride: StepOverrides = {\n\t\t\t\toutput: tuiOverride?.output !== undefined ? tuiOverride.output : seqStep.output,\n\t\t\t\toutputMode: seqStep.outputMode,\n\t\t\t\treads: tuiOverride?.reads !== undefined ? tuiOverride.reads : seqStep.reads,\n\t\t\t\tprogress: tuiOverride?.progress !== undefined ? tuiOverride.progress : seqStep.progress,\n\t\t\t\tskills:\n\t\t\t\t\ttuiOverride?.skills !== undefined\n\t\t\t\t\t\t? tuiOverride.skills\n\t\t\t\t\t\t: normalizeSkillInput(seqStep.skill),\n\t\t\t};\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(resolveStepBehavior(stepOverride, chainSkills), stepTemplate, originalTask);\n\n\t\t\tconst isFirstProgress = behavior.progress && !progressCreated;\n\t\t\tif (isFirstProgress) {\n\t\t\t\tprogressCreated = true;\n\t\t\t}\n\n\t\t\tconst templateHasPrevious = stepTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tchainDir,\n\t\t\t\tisFirstProgress,\n\t\t\t\ttemplateHasPrevious ? undefined : prev,\n\t\t\t);\n\n\t\t\tlet stepTask = resolveOutputReferences(stepTemplate, outputs);\n\t\t\tstepTask = stepTask.replace(/\\{task\\}/g, originalTask);\n\t\t\tstepTask = stepTask.replace(/\\{previous\\}/g, prev);\n\t\t\tstepTask = stepTask.replace(/\\{chain_dir\\}/g, chainDir);\n\t\t\tconst cleanTask = stepTask;\n\t\t\tstepTask = prefix + stepTask + suffix;\n\n\t\t\t// lunr: model tiers — explicit step model wins; otherwise resolve seqStep.tier via the tier bridge.\n\t\t\tconst explicitStepModel = tuiOverride?.model ?? seqStep.model ?? resolveTierModelOverride(seqStep.tier);\n\t\t\tconst effectiveModel = resolveEffectiveSubagentModel(\n\t\t\t\texplicitStepModel,\n\t\t\t\tagentConfig.model,\n\t\t\t\tctx.model,\n\t\t\t\tavailableModels,\n\t\t\t\tctx.model?.provider,\n\t\t\t\t{ scope: modelScope },\n\t\t\t);\n\n\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t: undefined;\n\t\t\tstepTask = injectSingleOutputInstruction(stepTask, outputPath, agentConfig);\n\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Chain step ${stepIndex + 1} (${seqStep.agent})`);\n\t\t\tif (validationError) {\n\t\t\t\treturn buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t}\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(params.maxSubagentDepth, agentConfig.maxSubagentDepth);\n\t\t\tconst childIndex = globalTaskIndex;\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (foregroundControl) {\n\t\t\t\tforegroundControl.currentAgent = seqStep.description || seqStep.agent;\n\t\t\t\tforegroundControl.currentChildId = seqStep.agent;\n\t\t\t\tforegroundControl.currentIndex = childIndex;\n\t\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\tforegroundControl.interrupt = () => {\n\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\t\treturn true;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst structuredRuntime = seqStep.outputSchema\n\t\t\t\t? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, \"structured-output\"))\n\t\t\t\t: undefined;\n\t\t\tconst toolBudget = resolveChainToolBudget({ stepBudget: seqStep.toolBudget, runBudget: params.toolBudget, agentBudget: agentConfig?.toolBudget, configBudget: params.configToolBudget });\n\t\t\tif (toolBudget.error) return buildChainExecutionErrorResult(toolBudget.error, {\n\t\t\t\tresults,\n\t\t\t\tincludeProgress,\n\t\t\t\tallProgress,\n\t\t\t\tallArtifactPaths,\n\t\t\t\tartifactsDir: params.artifactsDir,\n\t\t\t\tchainAgents,\n\t\t\t\tchainSteps,\n\t\t\t\ttotalSteps,\n\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\trunId: params.runId,\n\t\t\t\toutputs,\n\t\t\t\tcurrentFlatIndex: globalTaskIndex,\n\t\t\t\tdynamicChildren,\n\t\t\t\tdynamicGroupStatuses,\n\t\t\t});\n\t\t\tconst r = await runSync(ctx.cwd, normalizeChildSpec({\n\t\t\t\ttask: stepTask,\n\t\t\t\tdescription: seqStep.description,\n\t\t\t\tpermissions: seqStep.permissions,\n\t\t\t\tmodel: effectiveModel ?? seqStep.model,\n\t\t\t\ttier: seqStep.tier,\n\t\t\t\tmodelSelection: tuiOverride?.model !== undefined\n\t\t\t\t\t? captureModelSelection({ model: tuiOverride.model })\n\t\t\t\t\t: captureModelSelection({ model: seqStep.model, tier: seqStep.tier }),\n\t\t\t\tskill: seqStep.skill,\n\t\t\t\tcwd: seqStep.cwd,\n\t\t\t\toutput: seqStep.output,\n\t\t\t\toutputMode: seqStep.outputMode,\n\t\t\t\tacceptance: seqStep.acceptance,\n\t\t\t\ttoolBudget: seqStep.toolBudget,\n\t\t\t}, { parentMode: snapshotParentPermissionMode(ctx.sessionManager.getSessionId() ?? undefined), runId, index: childIndex }), {\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcwd: resolveChildCwd(cwd ?? ctx.cwd, seqStep.cwd),\n\t\t\t\tsignal,\n\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\tallowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\tintercomEvents,\n\t\t\t\trunId,\n\t\t\t\tindex: childIndex,\n\t\t\t\tsessionDir: sessionDirForIndex(childIndex),\n\t\t\t\tsessionFile: sessionFileForTask?.(seqStep.agent, childIndex, effectiveModel)\n\t\t\t\t\t?? sessionFileForIndex?.(childIndex),\n\t\t\t\tthinkingOverride: thinkingOverrideForTask?.(seqStep.agent, childIndex, effectiveModel),\n\t\t\t\tshare: shareEnabled,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\toutputPath,\n\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\tcontrolConfig,\n\t\t\t\tonControlEvent,\n\t\t\t\tintercomSessionName: childIntercomTarget?.(seqStep.agent, childIndex),\n\t\t\t\torchestratorIntercomTarget,\n\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\tavailableModels,\n\t\t\t\tpreferredModelProvider: ctx.model?.provider,\n\t\t\t\tmodelScope,\n\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\tacceptance: seqStep.acceptance,\n\t\t\t\tacceptanceContext: { mode: \"chain\" },\n\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\tdeadlineAt,\n\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\tonDetachedExit: onDetachedExit\n\t\t\t\t\t? (result) => onDetachedExit(childIndex, result)\n\t\t\t\t\t: undefined,\n\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\tonUpdate: onUpdate\n\t\t\t\t\t? (p) => {\n\t\t\t\t\t\tconst stepResults = p.details?.results || [];\n\t\t\t\t\t\tconst stepProgress = p.details?.progress || [];\n\t\t\t\t\t\tif (foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\t\tforegroundControl.currentAgent = seqStep.description || seqStep.agent;\n\t\t\t\t\t\t\tforegroundControl.currentChildId = seqStep.agent;\n\t\t\t\t\t\t\tforegroundControl.currentIndex = childIndex;\n\t\t\t\t\t\t\tforegroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\t\tforegroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\t\tforegroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\t\tforegroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\t\tforegroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\t\tforegroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\t\tforegroundControl.tokens = current?.tokens;\n\t\t\t\t\t\t\tforegroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonUpdate({\n\t\t\t\t\t\t\t...p,\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\tprogress: allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\tcontrolEvents: p.details?.controlEvents,\n\t\t\t\t\t\t\t\tchainAgents,\n\t\t\t\t\t\t\t\ttotalSteps,\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\toutputs,\n\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\trunId,\n\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\tsteps: chainSteps,\n\t\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\t\tcurrentFlatIndex: childIndex,\n\t\t\t\t\t\t\t\t\tdynamicChildren,\n\t\t\t\t\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t});\n\t\t\tif (foregroundControl?.currentIndex === childIndex) {\n\t\t\t\tforegroundControl.interrupt = undefined;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t\trecordRun(seqStep.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);\n\n\t\t\tglobalTaskIndex++;\n\t\t\tresults.push(r);\n\t\t\tif (r.progress) allProgress.push(r.progress);\n\t\t\tif (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);\n\n\t\t\tif (r.interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${r.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (r.detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${r.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (r.exitCode !== 0) {\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: r.error || \"Chain failed\",\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (behavior.output) {\n\t\t\t\ttry {\n\t\t\t\t\tconst expectedPath = path.isAbsolute(behavior.output)\n\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t: path.join(chainDir, behavior.output);\n\t\t\t\t\tif (!fs.existsSync(expectedPath)) {\n\t\t\t\t\t\tconst dirFiles = fs.readdirSync(chainDir);\n\t\t\t\t\t\tconst mdFiles = dirFiles.filter((file) => file.endsWith(\".md\") && file !== \"progress.md\");\n\t\t\t\t\t\tconst warning = mdFiles.length > 0\n\t\t\t\t\t\t\t? `Agent wrote to different file(s): ${mdFiles.join(\", \")} instead of ${behavior.output}`\n\t\t\t\t\t\t\t: `Agent did not create expected output file: ${behavior.output}`;\n\t\t\t\t\t\tr.error = r.error ? `${r.error}\\n${warning}` : warning;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore validation errors; this diagnostic should not mask successful chain output.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (seqStep.as) outputs[seqStep.as] = outputEntryFromResult(r, stepIndex);\n\t\t\tprev = getSingleResultOutput(r);\n\t\t}\n\t}\n\n\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"completed\");\n\n\treturn {\n\t\tcontent: [{ type: \"text\", text: summary }],\n\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t};\n}\n"]}
1
+ {"version":3,"file":"chain-execution.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.ts"],"names":[],"mappings":"AACA;;GAEG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAKhE,OAAO,EAcN,KAAK,SAAS,EAMd,MAAM,0BAA0B,CAAC;AAiBlC,OAAO,EACN,KAAK,aAAa,EAElB,KAAK,cAAc,EAEnB,KAAK,YAAY,EACjB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAGrB,MAAM,uBAAuB,CAAC;AAsW/B,UAAU,oBAAoB;IAC7B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,GAAG,EAAE,gBAAgB,CAAC;IACtB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,kBAAkB,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACzD,mBAAmB,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3D,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrG,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,KAAK,kBAAkB,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;IAClI,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,qBAAqB,CAAC;IACrC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3E,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iBAAiB,CAAC,EAAE;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,oBAAoB,CAAC,EAAE,aAAa,CAAC;QACrC,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;KAC1B,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/D,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,kHAAkH;IAClH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,UAAU,oBAAoB;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2FAA2F;IAC3F,cAAc,CAAC,EAAE;QAChB,KAAK,EAAE,SAAS,EAAE,CAAC;QACnB,WAAW,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;CACF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAs1B9F","sourcesContent":["// @ts-nocheck\n/**\n * Chain execution logic for subagent tool\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentToolResult } from \"@ashx-j/lunr-agent\";\nimport type { ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport type { ChildRuntimeConfig } from \"../../shared/types.ts\";\nimport { normalizeChildSpec } from \"../../shared/child-spec.ts\";\nimport { snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { ChainClarifyComponent, type ChainClarifyResult, type BehaviorOverride } from \"./chain-clarify.ts\";\nimport { toModelInfo, type ModelInfo } from \"../../shared/model-info.ts\";\nimport {\n\tresolveChainTemplates,\n\tcreateChainDir,\n\tremoveChainDir,\n\tresolveStepBehavior,\n\tresolveParallelBehaviors,\n\tbuildChainInstructions,\n\twriteInitialProgressFile,\n\tcreateParallelDirs,\n\tsuppressProgressForReadOnlyTask,\n\taggregateParallelOutputs,\n\tisDynamicParallelStep,\n\tisParallelStep,\n\ttype StepOverrides,\n\ttype ChainStep,\n\ttype ParallelStep,\n\ttype SequentialStep,\n\ttype ParallelTaskResult,\n\ttype ResolvedStepBehavior,\n\ttype ResolvedTemplates,\n} from \"../../shared/settings.ts\";\nimport { discoverAvailableSkills, normalizeSkillInput } from \"../../agents/skills.ts\";\nimport { INTERCOM_BRIDGE_MARKER } from \"../../intercom/intercom-bridge.ts\";\nimport { runSync } from \"./execution.ts\";\nimport { buildChainSummary } from \"../../shared/formatters.ts\";\nimport { compactForegroundDetails, getSingleResultOutput, mapConcurrent, resolveChildCwd, sumResultsCost, sumResultsUsage } from \"../../shared/utils.ts\";\nimport { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from \"../shared/parallel-utils.ts\";\nimport { recordRun } from \"../shared/run-history.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport {\n\ttype ActivityState,\n\ttype AgentProgress,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype ControlEvent,\n\ttype Details,\n\ttype IntercomEventBus,\n\ttype NestedRouteInfo,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SingleResult,\n\ttype ToolBudgetConfig,\n\tMAX_CONCURRENCY,\n\tresolveChildMaxSubagentDepth,\n} from \"../../shared/types.ts\";\nimport { captureModelSelection, resolveRequiredTierModel } from \"../shared/model-fallback.ts\";\nimport type { ModelScopeConfig } from \"../shared/model-scope.ts\";\nimport { injectSingleOutputInstruction, validateFileOnlyOutputMode } from \"../shared/single-output.ts\";\nimport { buildWorkflowGraphSnapshot } from \"../shared/workflow-graph.ts\";\nimport { ChainOutputValidationError, outputEntryFromResult, resolveOutputReferences, validateChainOutputBindings } from \"../shared/chain-outputs.ts\";\nimport { createStructuredOutputRuntime } from \"../shared/structured-output.ts\";\nimport { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection, type DynamicCollectedResult } from \"../shared/dynamic-fanout.ts\";\nimport { acceptanceFailureMessage, aggregateAcceptanceReport, evaluateAcceptance, resolveEffectiveAcceptance } from \"../shared/acceptance.ts\";\nimport type { ChainOutputMap } from \"../../shared/types.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\n\ninterface ChainExecutionDetailsInput {\n\tresults: SingleResult[];\n\tincludeProgress?: boolean;\n\tallProgress: AgentProgress[];\n\tallArtifactPaths: ArtifactPaths[];\n\tartifactsDir: string;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tcurrentStepIndex?: number;\n\trunId: string;\n\toutputs?: ChainOutputMap;\n\tcurrentFlatIndex?: number;\n\tdynamicChildren?: Record<number, Array<{ agent: string; label?: string; flatIndex: number; itemKey: string; outputName?: string; structured?: boolean; error?: string }>>;\n\tdynamicGroupStatuses?: Record<number, { status: \"pending\" | \"running\" | \"completed\" | \"failed\" | \"paused\" | \"stopped\" | \"detached\"; error?: string; acceptance?: SingleResult[\"acceptance\"] }>;\n}\n\ninterface ParallelChainRunInput {\n\tstep: ParallelStep;\n\tparallelTemplates: string[];\n\tparallelBehaviors: ResolvedStepBehavior[];\n\tagents: ChildRuntimeConfig[];\n\tstepIndex: number;\n\tavailableModels: ModelInfo[];\n\tmodelScope?: ModelScopeConfig;\n\tchainDir: string;\n\tprev: string;\n\toriginalTask: string;\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tcwd?: string;\n\trunId: string;\n\tglobalTaskIndex: number;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (agentName: string, idx?: number, modelOverride?: string) => ChildRuntimeConfig[\"thinking\"] | undefined;\n\tshareEnabled: boolean;\n\tartifactConfig: ArtifactConfig;\n\tartifactsDir: string;\n\tsignal?: AbortSignal;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: {\n\t\tupdatedAt: number;\n\t\tcurrentAgent?: string;\n\t\tcurrentChildId?: string;\n\t\tcurrentIndex?: number;\n\t\tcurrentActivityState?: ActivityState;\n\t\tlastActivityAt?: number;\n\t\tcurrentTool?: string;\n\t\tcurrentToolStartedAt?: number;\n\t\tcurrentPath?: string;\n\t\tturnCount?: number;\n\t\ttokens?: number;\n\t\ttoolCount?: number;\n\t\tinterrupt?: () => boolean;\n\t};\n\tresults: SingleResult[];\n\tallProgress: AgentProgress[];\n\toutputs: ChainOutputMap;\n\tchainAgents: string[];\n\tchainSteps: ChainStep[];\n\ttotalSteps: number;\n\tdynamicChildren?: ChainExecutionDetailsInput[\"dynamicChildren\"];\n\tdynamicGroupStatuses?: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"];\n\tworktreeSetup?: WorktreeSetup;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ToolBudgetConfig;\n\tglobalSemaphore?: Semaphore;\n\tdynamic?: boolean;\n}\n\nfunction buildChainExecutionDetails(input: ChainExecutionDetailsInput): Details {\n\treturn compactForegroundDetails({\n\t\tmode: \"chain\",\n\t\tresults: input.results,\n\t\tprogress: input.includeProgress ? input.allProgress : undefined,\n\t\tartifacts: input.allArtifactPaths.length ? { dir: input.artifactsDir, files: input.allArtifactPaths } : undefined,\n\t\tchainAgents: input.chainAgents,\n\t\ttotalSteps: input.totalSteps,\n\t\tcurrentStepIndex: input.currentStepIndex,\n\t\toutputs: input.outputs,\n\t\ttotalChildUsage: sumResultsUsage(input.results),\n\t\ttotalCost: sumResultsCost(input.results),\n\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\trunId: input.runId,\n\t\t\tmode: \"chain\",\n\t\t\tsteps: input.chainSteps,\n\t\t\tresults: input.results,\n\t\t\tcurrentStepIndex: input.currentStepIndex,\n\t\t\tcurrentFlatIndex: input.currentFlatIndex,\n\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t}),\n\t});\n}\n\nfunction buildChainExecutionErrorResult(message: string, input: ChainExecutionDetailsInput): ChainExecutionResult {\n\treturn {\n\t\tcontent: [{ type: \"text\", text: message }],\n\t\tisError: true,\n\t\tdetails: buildChainExecutionDetails(input),\n\t};\n}\n\nfunction ensureParallelProgressFile(\n\tchainDir: string,\n\tprogressCreated: boolean,\n\tparallelBehaviors: ResolvedStepBehavior[],\n): boolean {\n\tif (progressCreated || !parallelBehaviors.some((behavior) => behavior.progress)) {\n\t\treturn progressCreated;\n\t}\n\twriteInitialProgressFile(chainDir);\n\treturn true;\n}\n\nfunction appendParallelWorktreeSummary(\n\toutput: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tdiffsDir: string,\n\tagents: string[],\n): string {\n\tif (!worktreeSetup) return output;\n\tconst diffs = diffWorktrees(worktreeSetup, agents, diffsDir);\n\tconst diffSummary = formatWorktreeDiffSummary(diffs);\n\tif (!diffSummary) return output;\n\treturn `${output}\\n\\n${diffSummary}`;\n}\n\nfunction resolveChainToolBudget(input: { stepBudget?: ToolBudgetConfig; runBudget?: ResolvedToolBudget; agentBudget?: ToolBudgetConfig; configBudget?: ToolBudgetConfig }): { toolBudget?: ResolvedToolBudget; error?: string } {\n\tif (input.stepBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.stepBudget, \"toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tif (input.runBudget !== undefined) return { toolBudget: input.runBudget };\n\tif (input.agentBudget !== undefined) {\n\t\tconst resolved = validateToolBudgetConfig(input.agentBudget, \"agent.toolBudget\");\n\t\treturn { toolBudget: resolved.budget, error: resolved.error };\n\t}\n\tconst resolved = validateToolBudgetConfig(input.configBudget, \"config.toolBudget\");\n\treturn { toolBudget: resolved.budget, error: resolved.error };\n}\n\nasync function runParallelChainTasks(input: ParallelChainRunInput): Promise<SingleResult[]> {\n\tconst concurrency = input.step.concurrency ?? MAX_CONCURRENCY;\n\tconst failFast = input.step.failFast ?? false;\n\tlet aborted = false;\n\tconst effectiveModels = input.step.parallel.map((task) => {\n\t\tconst taskChildConfig = input.agents.find((child) => child.name === task.agent);\n\t\treturn resolveRequiredTierModel(task.tier, input.availableModels, input.ctx.model?.provider);\n\t});\n\tfor (let taskIndex = 0; taskIndex < input.step.parallel.length; taskIndex++) {\n\t\tconst task = input.step.parallel[taskIndex]!;\n\t\tinput.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModels[taskIndex]);\n\t}\n\n\tconst parallelResults = await mapConcurrent(\n\t\tinput.step.parallel,\n\t\tconcurrency,\n\t\tasync (task, taskIndex) => {\n\t\t\tif (aborted && failFast) {\n\t\t\t\treturn {\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\ttask: \"(skipped)\",\n\t\t\t\t\texitCode: -1,\n\t\t\t\t\tmessages: [],\n\t\t\t\t\tusage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 },\n\t\t\t\t\terror: \"Skipped due to fail-fast\",\n\t\t\t\t} as SingleResult;\n\t\t\t}\n\n\t\t\tconst taskTemplate = input.parallelTemplates[taskIndex] ?? \"{previous}\";\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(input.parallelBehaviors[taskIndex]!, taskTemplate, input.originalTask);\n\t\t\tconst taskChildConfig = input.agents.find((child) => child.name === task.agent);\n\t\t\tconst templateHasPrevious = taskTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tinput.chainDir,\n\t\t\t\tfalse,\n\t\t\t\ttemplateHasPrevious ? undefined : input.prev,\n\t\t\t);\n\n\t\t\tlet taskStr = resolveOutputReferences(taskTemplate, input.outputs);\n\t\t\ttaskStr = taskStr.replace(/\\{task\\}/g, input.originalTask);\n\t\t\ttaskStr = taskStr.replace(/\\{previous\\}/g, input.prev);\n\t\t\ttaskStr = taskStr.replace(/\\{chain_dir\\}/g, input.chainDir);\n\t\t\tconst cleanTask = taskStr;\n\t\t\ttaskStr = prefix + taskStr + suffix;\n\n\t\t\tconst effectiveModel = effectiveModels[taskIndex];\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(input.maxSubagentDepth, taskChildConfig?.maxSubagentDepth);\n\t\t\tconst toolBudget = resolveChainToolBudget({ stepBudget: task.toolBudget, runBudget: input.toolBudget, agentBudget: taskChildConfig?.toolBudget, configBudget: input.configToolBudget });\n\t\t\tif (toolBudget.error) throw new Error(toolBudget.error);\n\n\t\t\tconst taskCwd = input.worktreeSetup\n\t\t\t\t? input.worktreeSetup.worktrees[taskIndex]!.agentCwd\n\t\t\t\t: resolveChildCwd(input.cwd ?? input.ctx.cwd, task.cwd);\n\n\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(input.chainDir, behavior.output))\n\t\t\t\t: undefined;\n\t\t\ttaskStr = injectSingleOutputInstruction(taskStr, outputPath, taskChildConfig);\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (input.foregroundControl) {\n\t\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\t\tinput.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;\n\t\t\t\tinput.foregroundControl.currentActivityState = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\tinput.foregroundControl.interrupt = () => {\n\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\tinput.foregroundControl!.currentActivityState = undefined;\n\t\t\t\t\tinput.foregroundControl!.updatedAt = Date.now();\n\t\t\t\t\treturn true;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst structuredRuntime = task.outputSchema\n\t\t\t\t? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, \"structured-output\"))\n\t\t\t\t: undefined;\n\t\t\tconst result = await runSync(input.ctx.cwd, normalizeChildSpec({\n\t\t\t\ttask: taskStr,\n\t\t\t\tdescription: task.description,\n\t\t\t\tpermissions: task.permissions,\n\t\t\t\tmodel: effectiveModel ?? task.model,\n\t\t\t\ttier: task.tier,\n\t\t\t\tmodelSelection: captureModelSelection({ tier: task.tier }),\n\t\t\t\tskill: task.skill,\n\t\t\t\tcwd: taskCwd,\n\t\t\t\toutput: task.output,\n\t\t\t\toutputMode: task.outputMode,\n\t\t\t\tacceptance: task.acceptance,\n\t\t\t\ttoolBudget: task.toolBudget,\n\t\t\t}, { parentMode: snapshotParentPermissionMode(input.ctx.sessionManager.getSessionId() ?? undefined), runId: input.runId, index: input.globalTaskIndex + taskIndex }), {\n\t\t\t\tparentSessionId: input.ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcwd: taskCwd,\n\t\t\t\tsignal: input.signal,\n\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\tallowIntercomDetach: taskChildConfig?.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\tintercomEvents: input.intercomEvents,\n\t\t\t\trunId: input.runId,\n\t\t\t\tindex: input.globalTaskIndex + taskIndex,\n\t\t\t\tsessionDir: input.sessionDirForIndex(input.globalTaskIndex + taskIndex),\n\t\t\t\tsessionFile: input.sessionFileForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModel)\n\t\t\t\t\t?? input.sessionFileForIndex?.(input.globalTaskIndex + taskIndex),\n\t\t\t\tthinkingOverride: input.thinkingOverrideForTask?.(task.agent, input.globalTaskIndex + taskIndex, effectiveModel),\n\t\t\t\tshare: input.shareEnabled,\n\t\t\t\tartifactsDir: input.artifactConfig.enabled ? input.artifactsDir : undefined,\n\t\t\t\tartifactConfig: input.artifactConfig,\n\t\t\t\toutputPath,\n\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\tcontrolConfig: input.controlConfig,\n\t\t\t\tonControlEvent: input.onControlEvent,\n\t\t\t\tintercomSessionName: input.childIntercomTarget?.(task.agent, input.globalTaskIndex + taskIndex),\n\t\t\t\torchestratorIntercomTarget: input.orchestratorIntercomTarget,\n\t\t\t\tnestedRoute: input.nestedRoute,\n\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\tavailableModels: input.availableModels,\n\t\t\t\tpreferredModelProvider: input.ctx.model?.provider,\n\t\t\t\tmodelScope: input.modelScope,\n\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\tacceptance: task.acceptance,\n\t\t\t\tacceptanceContext: { mode: \"chain\", dynamic: input.dynamic && task.acceptance === undefined },\n\t\t\t\ttimeoutMs: input.timeoutMs,\n\t\t\t\tdeadlineAt: input.deadlineAt,\n\t\t\t\tturnBudget: input.turnBudget,\n\t\t\t\tonDetachedExit: input.onDetachedExit\n\t\t\t\t\t? (result) => input.onDetachedExit?.(input.globalTaskIndex + taskIndex, result)\n\t\t\t\t\t: undefined,\n\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\tonUpdate: input.onUpdate\n\t\t\t\t\t? (progressUpdate) => {\n\t\t\t\t\t\tconst stepResults = progressUpdate.details?.results || [];\n\t\t\t\t\t\tconst stepProgress = progressUpdate.details?.progress || [];\n\t\t\t\t\t\tif (input.foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\t\tinput.foregroundControl.currentAgent = task.description || task.agent;\n\t\t\t\t\t\t\tinput.foregroundControl.currentChildId = task.agent;\n\t\t\t\t\t\t\tinput.foregroundControl.currentIndex = input.globalTaskIndex + taskIndex;\n\t\t\t\t\t\t\tinput.foregroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\t\tinput.foregroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\t\tinput.foregroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\t\tinput.foregroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\t\tinput.foregroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\t\tinput.foregroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\t\tinput.foregroundControl.tokens = current?.tokens;\n\t\t\t\t\t\t\tinput.foregroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinput.onUpdate?.({\n\t\t\t\t\t\t\t...progressUpdate,\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\tprogress: input.allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\tcontrolEvents: progressUpdate.details?.controlEvents,\n\t\t\t\t\t\t\t\tchainAgents: input.chainAgents,\n\t\t\t\t\t\t\t\ttotalSteps: input.totalSteps,\n\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\toutputs: input.outputs,\n\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\trunId: input.runId,\n\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\tsteps: input.chainSteps,\n\t\t\t\t\t\t\t\t\tresults: input.results.concat(stepResults),\n\t\t\t\t\t\t\t\t\tcurrentStepIndex: input.stepIndex,\n\t\t\t\t\t\t\t\t\tcurrentFlatIndex: input.globalTaskIndex + taskIndex,\n\t\t\t\t\t\t\t\t\tdynamicChildren: input.dynamicChildren,\n\t\t\t\t\t\t\t\t\tdynamicGroupStatuses: input.dynamicGroupStatuses,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t});\n\t\t\tif (input.foregroundControl?.currentIndex === input.globalTaskIndex + taskIndex) {\n\t\t\t\tinput.foregroundControl.interrupt = undefined;\n\t\t\t\tinput.foregroundControl.updatedAt = Date.now();\n\t\t\t}\n\n\t\t\tif (result.exitCode !== 0 && failFast) {\n\t\t\t\taborted = true;\n\t\t\t}\n\t\t\trecordRun(task.agent, cleanTask, result.exitCode, result.progressSummary?.durationMs ?? 0);\n\t\t\treturn result;\n\t\t},\n\t\tinput.globalSemaphore,\n\t);\n\n\treturn parallelResults;\n}\n\ninterface ChainExecutionParams {\n\tchain: ChainStep[];\n\ttask?: string;\n\tagents: ChildRuntimeConfig[];\n\tctx: ExtensionContext;\n\tintercomEvents?: IntercomEventBus;\n\tsignal?: AbortSignal;\n\trunId: string;\n\tcwd?: string;\n\tshareEnabled: boolean;\n\tsessionDirForIndex: (idx?: number) => string | undefined;\n\tsessionFileForIndex?: (idx?: number) => string | undefined;\n\tsessionFileForTask?: (agentName: string, idx?: number, modelOverride?: string) => string | undefined;\n\tthinkingOverrideForTask?: (agentName: string, idx?: number, modelOverride?: string) => ChildRuntimeConfig[\"thinking\"] | undefined;\n\tartifactsDir: string;\n\tartifactConfig: ArtifactConfig;\n\tincludeProgress?: boolean;\n\tclarify?: boolean;\n\tonUpdate?: (r: AgentToolResult<Details>) => void;\n\tonControlEvent?: (event: ControlEvent) => void;\n\tcontrolConfig: ResolvedControlConfig;\n\tchildIntercomTarget?: (agent: string, index: number) => string | undefined;\n\torchestratorIntercomTarget?: string;\n\tforegroundControl?: {\n\t\tupdatedAt: number;\n\t\tcurrentAgent?: string;\n\t\tcurrentChildId?: string;\n\t\tcurrentIndex?: number;\n\t\tcurrentActivityState?: ActivityState;\n\t\tlastActivityAt?: number;\n\t\tcurrentTool?: string;\n\t\tcurrentToolStartedAt?: number;\n\t\tcurrentPath?: string;\n\t\tturnCount?: number;\n\t\ttokens?: number;\n\t\ttoolCount?: number;\n\t\tinterrupt?: () => boolean;\n\t};\n\tchainSkills?: string[];\n\tchainDir?: string;\n\tdynamicFanoutMaxItems?: number;\n\tmaxSubagentDepth: number;\n\tnestedRoute?: NestedRouteInfo;\n\tworktreeSetupHook?: string;\n\tworktreeSetupHookTimeoutMs?: number;\n\tworktreeBaseDir?: string;\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\tonDetachedExit?: (index: number, result: SingleResult) => void;\n\ttoolBudget?: ResolvedToolBudget;\n\tconfigToolBudget?: ToolBudgetConfig;\n\t/** Global cap on simultaneously-running tasks within this chain. Defaults to DEFAULT_GLOBAL_CONCURRENCY_LIMIT. */\n\tglobalConcurrencyLimit?: number;\n}\n\ninterface ChainExecutionResult {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: Details;\n\tisError?: boolean;\n\t/** User requested async execution via TUI - caller should dispatch to executeAsyncChain */\n\trequestedAsync?: {\n\t\tchain: ChainStep[];\n\t\tchainSkills: string[];\n\t};\n}\n\n/**\n * Execute a chain of subagent steps\n */\nexport async function executeChain(params: ChainExecutionParams): Promise<ChainExecutionResult> {\n\tconst {\n\t\tchain: chainSteps,\n\t\tagents,\n\t\tctx,\n\t\tsignal,\n\t\trunId,\n\t\tcwd,\n\t\tshareEnabled,\n\t\tsessionDirForIndex,\n\t\tsessionFileForIndex,\n\t\tsessionFileForTask,\n\t\tthinkingOverrideForTask,\n\t\tartifactsDir,\n\t\tartifactConfig,\n\t\tincludeProgress,\n\t\tclarify,\n\t\tonUpdate,\n\t\tonControlEvent,\n\t\tcontrolConfig,\n\t\tonDetachedExit,\n\t\tchildIntercomTarget,\n\t\torchestratorIntercomTarget,\n\t\tforegroundControl,\n\t\tintercomEvents,\n\t\tchainSkills: chainSkillsParam,\n\t\tchainDir: chainDirBase,\n\t\tmodelScope,\n\t} = params;\n\tconst chainSkills = chainSkillsParam ?? [];\n\n\tconst results: SingleResult[] = [];\n\tconst outputs: ChainOutputMap = {};\n\tconst dynamicChildren: ChainExecutionDetailsInput[\"dynamicChildren\"] = {};\n\tconst dynamicGroupStatuses: ChainExecutionDetailsInput[\"dynamicGroupStatuses\"] = {};\n\tconst allProgress: AgentProgress[] = [];\n\tconst allArtifactPaths: ArtifactPaths[] = [];\n\n\tconst chainAgents: string[] = chainSteps.map((step) =>\n\t\tisParallelStep(step)\n\t\t\t? `[${step.parallel.map((t) => t.description || t.label || t.agent || \"child\").join(\"+\")}]`\n\t\t\t: isDynamicParallelStep(step)\n\t\t\t\t? `expand:${step.parallel.description || step.parallel.label || step.parallel.agent || \"child\"}`\n\t\t\t: ((step as SequentialStep).description || (step as SequentialStep).label || (step as SequentialStep).agent || \"child\"),\n\t);\n\tconst totalSteps = chainSteps.length;\n\n\tconst makeDetailsInput = (overrides: Pick<Partial<ChainExecutionDetailsInput>, \"currentStepIndex\" | \"currentFlatIndex\"> = {}): ChainExecutionDetailsInput => ({\n\t\tresults,\n\t\t...(includeProgress !== undefined ? { includeProgress } : {}),\n\t\tallProgress,\n\t\tallArtifactPaths,\n\t\tartifactsDir,\n\t\tchainAgents,\n\t\tchainSteps,\n\t\ttotalSteps,\n\t\trunId,\n\t\toutputs,\n\t\tdynamicChildren,\n\t\tdynamicGroupStatuses,\n\t\t...overrides,\n\t});\n\n\tconst firstStep = chainSteps[0]!;\n\tconst originalTask = params.task\n\t\t?? (isParallelStep(firstStep)\n\t\t\t? firstStep.parallel[0]!.task!\n\t\t\t: isDynamicParallelStep(firstStep)\n\t\t\t\t? firstStep.parallel.task!\n\t\t\t\t: (firstStep as SequentialStep).task!);\n\ttry {\n\t\tvalidateChainOutputBindings(chainSteps, { maxItems: params.dynamicFanoutMaxItems });\n\t} catch (error) {\n\t\tif (error instanceof ChainOutputValidationError) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: error.message }],\n\t\t\t\tisError: true,\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\t\tthrow error;\n\t}\n\n\tconst chainDir = createChainDir(runId, chainDirBase);\n\tconst hasParallelSteps = chainSteps.some((step) => isParallelStep(step) || isDynamicParallelStep(step));\n\tlet templates: ResolvedTemplates = resolveChainTemplates(chainSteps);\n\tconst shouldClarify = clarify === true && ctx.hasUI && !hasParallelSteps;\n\tlet tuiBehaviorOverrides: (BehaviorOverride | undefined)[] | undefined;\n\tconst availableModels: ModelInfo[] = ctx.modelRegistry.getAvailable().map(toModelInfo);\n\tconst availableSkills = discoverAvailableSkills(cwd ?? ctx.cwd);\n\n\tif (shouldClarify) {\n\t\tconst seqSteps = chainSteps as SequentialStep[];\n\t\tconst agentConfigs: ChildRuntimeConfig[] = [];\n\t\tfor (const step of seqSteps) {\n\t\t\tconst config = agents.find((a) => a.name === step.agent);\n\t\t\tif (!config) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${step.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: seqSteps.indexOf(step) })),\n\t\t\t\t};\n\t\t\t}\n\t\t\tagentConfigs.push(config);\n\t\t}\n\n\t\tconst stepOverrides: StepOverrides[] = seqSteps.map((step) => ({\n\t\t\toutput: step.output,\n\t\t\toutputMode: step.outputMode,\n\t\t\treads: step.reads,\n\t\t\tprogress: step.progress,\n\t\t\tskills: normalizeSkillInput(step.skill),\n\t\t\tmodel: step.model,\n\t\t}));\n\n\t\tconst resolvedBehaviors = agentConfigs.map((_config, i) =>\n\t\t\tresolveStepBehavior(stepOverrides[i]!, chainSkills),\n\t\t);\n\t\tconst flatTemplates = templates as string[];\n\n\t\tconst result = await ctx.ui.custom<ChainClarifyResult>(\n\t\t\t(tui, theme, _kb, done) =>\n\t\t\t\tnew ChainClarifyComponent(\n\t\t\t\t\ttui,\n\t\t\t\t\ttheme,\n\t\t\t\t\tagentConfigs,\n\t\t\t\t\tflatTemplates,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tresolvedBehaviors,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tctx.model?.provider,\n\t\t\t\t\tavailableSkills,\n\t\t\t\t\tdone,\n\t\t\t\t),\n\t\t\t{\n\t\t\t\toverlay: true,\n\t\t\t\toverlayOptions: { anchor: \"center\", width: 84, maxHeight: \"80%\" },\n\t\t\t},\n\t\t);\n\n\t\tif (!result || !result.confirmed) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Chain cancelled\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t};\n\t\t}\n\n\t\tif (result.runInBackground) {\n\t\t\tremoveChainDir(chainDir);\n\t\t\tconst updatedChain: ChainStep[] = chainSteps.map((step, i) => {\n\t\t\t\tif (isParallelStep(step)) return step;\n\t\t\t\tconst override = result.behaviorOverrides[i];\n\t\t\t\treturn {\n\t\t\t\t\t...step,\n\t\t\t\t\ttask: result.templates[i]!,\n\t\t\t\t\t...(override?.output !== undefined ? { output: override.output } : {}),\n\t\t\t\t\t...(\"outputMode\" in step && step.outputMode !== undefined ? { outputMode: step.outputMode } : {}),\n\t\t\t\t\t...(override?.reads !== undefined ? { reads: override.reads } : {}),\n\t\t\t\t\t...(override?.progress !== undefined ? { progress: override.progress } : {}),\n\t\t\t\t\t...(override?.skills !== undefined ? { skill: override.skills } : {}),\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Launching in background...\" }],\n\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t\t\t\trequestedAsync: { chain: updatedChain, chainSkills },\n\t\t\t};\n\t\t}\n\n\t\ttemplates = result.templates;\n\t\ttuiBehaviorOverrides = result.behaviorOverrides;\n\t}\n\n\tconst deadlineAt = params.deadlineAt ?? (params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined);\n\tconst globalSemaphore = new Semaphore(params.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);\n\tlet prev = \"\";\n\tlet globalTaskIndex = 0;\n\tlet progressCreated = false;\n\n\tfor (let stepIndex = 0; stepIndex < chainSteps.length; stepIndex++) {\n\t\tconst step = chainSteps[stepIndex]!;\n\t\tconst stepTemplates = templates[stepIndex]!;\n\n\t\tif (isParallelStep(step)) {\n\t\t\tconst parallelTemplates = stepTemplates as string[];\n\t\t\tconst parallelCwd = resolveChildCwd(cwd ?? ctx.cwd, step.cwd);\n\t\t\tlet worktreeSetup: WorktreeSetup | undefined;\n\t\t\tif (step.worktree) {\n\t\t\t\tconst worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(step.parallel, parallelCwd);\n\t\t\t\tif (worktreeTaskCwdConflict) {\n\t\t\t\t\treturn buildChainExecutionErrorResult(\n\t\t\t\t\t\t`parallel chain step ${stepIndex + 1}: ${formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, parallelCwd)}`,\n\t\t\t\t\t\tmakeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tworktreeSetup = createWorktrees(parallelCwd, `${runId}-s${stepIndex}`, step.parallel.length, {\n\t\t\t\t\t\tagents: step.parallel.map((task) => task.agent),\n\t\t\t\t\t\tsetupHook: params.worktreeSetupHook\n\t\t\t\t\t\t\t? { hookPath: params.worktreeSetupHook, timeoutMs: params.worktreeSetupHookTimeoutMs }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tbaseDir: params.worktreeBaseDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst agentNames = step.parallel.map((task) => task.agent);\n\t\t\t\tconst parallelBehaviors = resolveParallelBehaviors(step.parallel, stepIndex, chainSkills)\n\t\t\t\t\t.map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? step.parallel[taskIndex]?.task, originalTask));\n\t\t\t\tfor (let taskIndex = 0; taskIndex < step.parallel.length; taskIndex++) {\n\t\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Parallel chain step ${stepIndex + 1} task ${taskIndex + 1} (${step.parallel[taskIndex]!.agent})`);\n\t\t\t\t\tif (validationError) return buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));\n\t\t\t\t}\n\t\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\t\tcreateParallelDirs(chainDir, stepIndex, step.parallel.length, agentNames);\n\n\t\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\t\tstep,\n\t\t\t\t\tparallelTemplates,\n\t\t\t\t\tparallelBehaviors,\n\t\t\t\t\tagents,\n\t\t\t\t\tstepIndex,\n\t\t\t\t\tavailableModels,\n\t\t\t\t\tmodelScope,\n\t\t\t\t\tchainDir,\n\t\t\t\t\tprev,\n\t\t\t\t\toriginalTask,\n\t\t\t\t\tctx,\n\t\t\t\t\tintercomEvents,\n\t\t\t\t\tcwd,\n\t\t\t\t\trunId,\n\t\t\t\t\tglobalTaskIndex,\n\t\t\t\t\tsessionDirForIndex,\n\t\t\t\t\tsessionFileForIndex,\n\t\t\t\t\tsessionFileForTask,\n\t\t\t\t\tthinkingOverrideForTask,\n\t\t\t\t\tshareEnabled,\n\t\t\t\t\tartifactConfig,\n\t\t\t\t\tartifactsDir,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonUpdate,\n\t\t\t\t\tresults,\n\t\t\t\t\tallProgress,\n\t\t\t\t\toutputs,\n\t\t\t\t\tchainAgents,\n\t\t\t\t\tchainSteps,\n\t\t\t\t\ttotalSteps,\n\t\t\t\t\tdynamicChildren,\n\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\tcontrolConfig,\n\t\t\t\t\tonControlEvent,\n\t\t\t\t\tchildIntercomTarget,\n\t\t\t\t\torchestratorIntercomTarget,\n\t\t\t\t\tforegroundControl,\n\t\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\t\tworktreeSetup,\n\t\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\t\tdeadlineAt,\n\t\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\t\tonDetachedExit,\n\t\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\t\tglobalSemaphore,\n\t\t\t\t});\n\t\t\t\tglobalTaskIndex += step.parallel.length;\n\n\t\t\t\tfor (const result of parallelResults) {\n\t\t\t\t\tresults.push(result);\n\t\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t\t}\n\t\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\t\tif (interrupted) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + interruptedIndexInStep,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\t\tif (detached) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + detachedIndexInStep,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst failures = parallelResults\n\t\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\t\tif (failures.length > 0) {\n\t\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t\t.map((failure) => `- Task ${failure.originalIndex + 1} (${failure.agent}): ${failure.error || \"failed\"}`)\n\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\tconst errorMsg = `Parallel step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t});\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\tcurrentFlatIndex: globalTaskIndex - step.parallel.length + failures[0]!.originalIndex,\n\t\t\t\t\t\t})),\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tfor (let taskIndex = 0; taskIndex < parallelResults.length; taskIndex++) {\n\t\t\t\t\tconst outputName = step.parallel[taskIndex]?.as;\n\t\t\t\t\tif (outputName) outputs[outputName] = outputEntryFromResult(parallelResults[taskIndex]!, stepIndex);\n\t\t\t\t}\n\n\t\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => {\n\t\t\t\t\tconst outputTarget = parallelBehaviors[i]?.output;\n\t\t\t\t\tconst outputTargetPath = typeof outputTarget === \"string\"\n\t\t\t\t\t\t? (path.isAbsolute(outputTarget) ? outputTarget : path.join(chainDir, outputTarget))\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tagent: result.agent,\n\t\t\t\t\t\ttaskIndex: i,\n\t\t\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\t\t\texitCode: result.exitCode,\n\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\ttimedOut: result.timedOut,\n\t\t\t\t\t\toutputTargetPath,\n\t\t\t\t\t\toutputTargetExists: outputTargetPath ? fs.existsSync(outputTargetPath) : undefined,\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t\tprev = aggregateParallelOutputs(taskResults);\n\t\t\t\tprev = appendParallelWorktreeSummary(\n\t\t\t\t\tprev,\n\t\t\t\t\tworktreeSetup,\n\t\t\t\t\tpath.join(chainDir, \"worktree-diffs\", `step-${stepIndex}`),\n\t\t\t\t\tagentNames,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tif (worktreeSetup) cleanupWorktrees(worktreeSetup);\n\t\t\t}\n\t\t} else if (isDynamicParallelStep(step)) {\n\t\t\tconst dynamicStartIndex = globalTaskIndex;\n\t\t\tconst reservedDynamicItems = step.expand.maxItems ?? params.dynamicFanoutMaxItems ?? 0;\n\t\t\tlet materialized: ReturnType<typeof materializeDynamicParallelStep>;\n\t\t\ttry {\n\t\t\t\tmaterialized = materializeDynamicParallelStep(step, outputs, stepIndex, { maxItems: params.dynamicFanoutMaxItems });\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t}\n\n\t\t\tdynamicChildren[stepIndex] = materialized.items.map((item, itemIndex) => ({\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tlabel: materialized.parallel[itemIndex]?.label,\n\t\t\t\tflatIndex: globalTaskIndex + itemIndex,\n\t\t\t\titemKey: item.key,\n\t\t\t\tstructured: Boolean(step.parallel.outputSchema),\n\t\t\t}));\n\n\t\t\tif (materialized.parallel.length === 0) {\n\t\t\t\tconst collection: DynamicCollectedResult[] = [];\n\t\t\t\ttry {\n\t\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collection);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t}\n\t\t\t\toutputs[step.collect.as] = {\n\t\t\t\t\ttext: JSON.stringify(collection),\n\t\t\t\t\tstructured: collection,\n\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\tstepIndex,\n\t\t\t\t};\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\t\tif (step.acceptance !== undefined) {\n\t\t\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\t\t\texplicit: step.acceptance,\n\t\t\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\t\t\ttask: (step.parallel.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"),\n\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\tdynamicGroup: true,\n\t\t\t\t\t});\n\t\t\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\t\t\tresults: [],\n\t\t\t\t\t\t\tnotes: \"Dynamic fanout produced 0 results.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t\t\t});\n\t\t\t\t\tdynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;\n\t\t\t\t\tconst groupAcceptanceFailure = acceptanceFailureMessage(groupAcceptance);\n\t\t\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: groupAcceptanceFailure, acceptance: groupAcceptance };\n\t\t\t\t\t\treturn buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprev = \"Dynamic fanout produced 0 results.\";\n\t\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst dynamicParallelStep: ParallelStep = {\n\t\t\t\tparallel: materialized.parallel,\n\t\t\t\tconcurrency: step.concurrency,\n\t\t\t\tfailFast: step.failFast,\n\t\t\t};\n\t\t\tconst parallelTemplates = materialized.parallel.map((task) => task.task ?? \"{previous}\");\n\t\t\tconst parallelBehaviors = resolveParallelBehaviors(dynamicParallelStep.parallel, stepIndex, chainSkills)\n\t\t\t\t.map((behavior, taskIndex) => suppressProgressForReadOnlyTask(behavior, parallelTemplates[taskIndex] ?? dynamicParallelStep.parallel[taskIndex]?.task, originalTask));\n\n\t\t\tfor (let taskIndex = 0; taskIndex < dynamicParallelStep.parallel.length; taskIndex++) {\n\t\t\t\tconst behavior = parallelBehaviors[taskIndex]!;\n\t\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t\t: undefined;\n\t\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Dynamic chain step ${stepIndex + 1} item ${taskIndex + 1} (${dynamicParallelStep.parallel[taskIndex]!.agent})`);\n\t\t\t\tif (validationError) {\n\t\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: validationError };\n\t\t\t\t\treturn buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex + taskIndex }));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprogressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);\n\t\t\tcreateParallelDirs(chainDir, stepIndex, dynamicParallelStep.parallel.length, dynamicParallelStep.parallel.map((task) => task.agent));\n\t\t\tconst parallelResults = await runParallelChainTasks({\n\t\t\t\tstep: dynamicParallelStep,\n\t\t\t\tparallelTemplates,\n\t\t\t\tparallelBehaviors,\n\t\t\t\tagents,\n\t\t\t\tstepIndex,\n\t\t\t\tavailableModels,\n\t\t\t\tmodelScope,\n\t\t\t\tchainDir,\n\t\t\t\tprev,\n\t\t\t\toriginalTask,\n\t\t\t\tctx,\n\t\t\t\tintercomEvents,\n\t\t\t\tcwd,\n\t\t\t\trunId,\n\t\t\t\tglobalTaskIndex,\n\t\t\t\tsessionDirForIndex,\n\t\t\t\tsessionFileForIndex,\n\t\t\t\tsessionFileForTask,\n\t\t\t\tthinkingOverrideForTask,\n\t\t\t\tshareEnabled,\n\t\t\t\tartifactConfig,\n\t\t\t\tartifactsDir,\n\t\t\t\tsignal,\n\t\t\t\tonUpdate,\n\t\t\t\tresults,\n\t\t\t\tallProgress,\n\t\t\t\toutputs,\n\t\t\t\tchainAgents,\n\t\t\t\tchainSteps,\n\t\t\t\ttotalSteps,\n\t\t\t\tdynamicChildren,\n\t\t\t\tdynamicGroupStatuses,\n\t\t\t\tcontrolConfig,\n\t\t\t\tonControlEvent,\n\t\t\t\tchildIntercomTarget,\n\t\t\t\torchestratorIntercomTarget,\n\t\t\t\tforegroundControl,\n\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\tmaxSubagentDepth: params.maxSubagentDepth,\n\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\tdeadlineAt,\n\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\tonDetachedExit,\n\t\t\t\ttoolBudget: params.toolBudget,\n\t\t\t\tconfigToolBudget: params.configToolBudget,\n\t\t\t\tglobalSemaphore,\n\t\t\t\tdynamic: true,\n\t\t\t});\n\t\t\tglobalTaskIndex = dynamicStartIndex + reservedDynamicItems;\n\n\t\t\tfor (const result of parallelResults) {\n\t\t\t\tresults.push(result);\n\t\t\t\tif (result.progress) allProgress.push(result.progress);\n\t\t\t\tif (result.artifactPaths) allArtifactPaths.push(result.artifactPaths);\n\t\t\t}\n\t\t\tconst collected = collectDynamicResults(step, materialized.items, parallelResults);\n\t\t\tconst interruptedIndexInStep = parallelResults.findIndex((result) => result.interrupted);\n\t\t\tconst interrupted = interruptedIndexInStep >= 0 ? parallelResults[interruptedIndexInStep] : undefined;\n\t\t\tif (interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${interrupted.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + interruptedIndexInStep,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst detachedIndexInStep = parallelResults.findIndex((result) => result.detached);\n\t\t\tconst detached = detachedIndexInStep >= 0 ? parallelResults[detachedIndexInStep] : undefined;\n\t\t\tif (detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${detached.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + detachedIndexInStep,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst failures = parallelResults\n\t\t\t\t.map((result, originalIndex) => ({ ...result, originalIndex }))\n\t\t\t\t.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\tif (failures.length > 0) {\n\t\t\t\tconst failureSummary = failures\n\t\t\t\t\t.map((failure) => `- Item ${failure.originalIndex + 1} (${failure.agent}, key ${materialized.items[failure.originalIndex]?.key ?? failure.originalIndex}): ${failure.error || \"failed\"}`)\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tconst errorMsg = `Dynamic step ${stepIndex + 1} failed:\\n${failureSummary}`;\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: errorMsg };\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: errorMsg,\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({\n\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\tcurrentFlatIndex: dynamicStartIndex + failures[0]!.originalIndex,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collected);\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: message };\n\t\t\t\treturn buildChainExecutionErrorResult(message, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: dynamicStartIndex }));\n\t\t\t}\n\t\t\toutputs[step.collect.as] = {\n\t\t\t\ttext: JSON.stringify(collected),\n\t\t\t\tstructured: collected,\n\t\t\t\tagent: step.parallel.agent,\n\t\t\t\tstepIndex,\n\t\t\t};\n\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"completed\" };\n\t\t\tconst effectiveGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\texplicit: step.acceptance,\n\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\tacceptanceRole: agents.find((agent) => agent.name === step.parallel.agent)?.acceptanceRole,\n\t\t\t\ttask: materialized.parallel\n\t\t\t\t\t.map((task) => (task.task ?? originalTask ?? \"\").replace(/\\{task\\}/g, originalTask ?? \"\"))\n\t\t\t\t\t.join(\"\\n\"),\n\t\t\t\tmode: \"chain\",\n\t\t\t\tdynamicGroup: true,\n\t\t\t});\n\t\t\tconst groupAcceptance = await evaluateAcceptance({\n\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\toutput: \"\",\n\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\tnotes: `Dynamic fanout collected ${collected.length} result(s) into ${step.collect.as}.`,\n\t\t\t\t}),\n\t\t\t\tcwd: cwd ?? ctx.cwd,\n\t\t\t});\n\t\t\tdynamicGroupStatuses[stepIndex].acceptance = groupAcceptance;\n\t\t\tconst groupAcceptanceFailure = effectiveGroupAcceptance.explicit ? acceptanceFailureMessage(groupAcceptance) : undefined;\n\t\t\tif (groupAcceptanceFailure) {\n\t\t\t\tdynamicGroupStatuses[stepIndex] = { status: \"failed\", error: groupAcceptanceFailure, acceptance: groupAcceptance };\n\t\t\t\treturn buildChainExecutionErrorResult(groupAcceptanceFailure, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex - dynamicParallelStep.parallel.length }));\n\t\t\t}\n\t\t\tconst taskResults: ParallelTaskResult[] = parallelResults.map((result, i) => ({\n\t\t\t\tagent: result.agent,\n\t\t\t\ttaskIndex: i,\n\t\t\t\toutput: getSingleResultOutput(result),\n\t\t\t\texitCode: result.exitCode,\n\t\t\t\terror: result.error,\n\t\t\t\ttimedOut: result.timedOut,\n\t\t\t}));\n\t\t\tprev = aggregateParallelOutputs(taskResults, (i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`);\n\t\t} else {\n\t\t\tconst seqStep = step as SequentialStep;\n\t\t\tconst stepTemplate = stepTemplates as string;\n\n\t\t\tconst agentConfig = agents.find((a) => a.name === seqStep.agent);\n\t\t\tif (!agentConfig) {\n\t\t\t\tremoveChainDir(chainDir);\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Unknown agent: ${seqStep.agent}` }],\n\t\t\t\t\tisError: true,\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex })),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst tuiOverride = tuiBehaviorOverrides?.[stepIndex];\n\t\t\tconst stepOverride: StepOverrides = {\n\t\t\t\toutput: tuiOverride?.output !== undefined ? tuiOverride.output : seqStep.output,\n\t\t\t\toutputMode: seqStep.outputMode,\n\t\t\t\treads: tuiOverride?.reads !== undefined ? tuiOverride.reads : seqStep.reads,\n\t\t\t\tprogress: tuiOverride?.progress !== undefined ? tuiOverride.progress : seqStep.progress,\n\t\t\t\tskills:\n\t\t\t\t\ttuiOverride?.skills !== undefined\n\t\t\t\t\t\t? tuiOverride.skills\n\t\t\t\t\t\t: normalizeSkillInput(seqStep.skill),\n\t\t\t};\n\t\t\tconst behavior = suppressProgressForReadOnlyTask(resolveStepBehavior(stepOverride, chainSkills), stepTemplate, originalTask);\n\n\t\t\tconst isFirstProgress = behavior.progress && !progressCreated;\n\t\t\tif (isFirstProgress) {\n\t\t\t\tprogressCreated = true;\n\t\t\t}\n\n\t\t\tconst templateHasPrevious = stepTemplate.includes(\"{previous}\");\n\t\t\tconst { prefix, suffix } = buildChainInstructions(\n\t\t\t\t{ ...behavior, output: false },\n\t\t\t\tchainDir,\n\t\t\t\tisFirstProgress,\n\t\t\t\ttemplateHasPrevious ? undefined : prev,\n\t\t\t);\n\n\t\t\tlet stepTask = resolveOutputReferences(stepTemplate, outputs);\n\t\t\tstepTask = stepTask.replace(/\\{task\\}/g, originalTask);\n\t\t\tstepTask = stepTask.replace(/\\{previous\\}/g, prev);\n\t\t\tstepTask = stepTask.replace(/\\{chain_dir\\}/g, chainDir);\n\t\t\tconst cleanTask = stepTask;\n\t\t\tstepTask = prefix + stepTask + suffix;\n\n\t\t\tconst effectiveModel = resolveRequiredTierModel(seqStep.tier, availableModels, ctx.model?.provider);\n\n\t\t\tconst outputPath = typeof behavior.output === \"string\"\n\t\t\t\t? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))\n\t\t\t\t: undefined;\n\t\t\tstepTask = injectSingleOutputInstruction(stepTask, outputPath, agentConfig);\n\t\t\tconst validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Chain step ${stepIndex + 1} (${seqStep.agent})`);\n\t\t\tif (validationError) {\n\t\t\t\treturn buildChainExecutionErrorResult(validationError, makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: globalTaskIndex }));\n\t\t\t}\n\t\t\tconst maxSubagentDepth = resolveChildMaxSubagentDepth(params.maxSubagentDepth, agentConfig.maxSubagentDepth);\n\t\t\tconst childIndex = globalTaskIndex;\n\t\t\tconst interruptController = new AbortController();\n\t\t\tif (foregroundControl) {\n\t\t\t\tforegroundControl.currentAgent = seqStep.description || seqStep.agent;\n\t\t\t\tforegroundControl.currentChildId = seqStep.agent;\n\t\t\t\tforegroundControl.currentIndex = childIndex;\n\t\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\tforegroundControl.interrupt = () => {\n\t\t\t\t\tif (interruptController.signal.aborted) return false;\n\t\t\t\t\tinterruptController.abort();\n\t\t\t\t\tforegroundControl.currentActivityState = undefined;\n\t\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\t\treturn true;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst structuredRuntime = seqStep.outputSchema\n\t\t\t\t? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, \"structured-output\"))\n\t\t\t\t: undefined;\n\t\t\tconst toolBudget = resolveChainToolBudget({ stepBudget: seqStep.toolBudget, runBudget: params.toolBudget, agentBudget: agentConfig?.toolBudget, configBudget: params.configToolBudget });\n\t\t\tif (toolBudget.error) return buildChainExecutionErrorResult(toolBudget.error, {\n\t\t\t\tresults,\n\t\t\t\tincludeProgress,\n\t\t\t\tallProgress,\n\t\t\t\tallArtifactPaths,\n\t\t\t\tartifactsDir: params.artifactsDir,\n\t\t\t\tchainAgents,\n\t\t\t\tchainSteps,\n\t\t\t\ttotalSteps,\n\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\trunId: params.runId,\n\t\t\t\toutputs,\n\t\t\t\tcurrentFlatIndex: globalTaskIndex,\n\t\t\t\tdynamicChildren,\n\t\t\t\tdynamicGroupStatuses,\n\t\t\t});\n\t\t\tconst r = await runSync(ctx.cwd, normalizeChildSpec({\n\t\t\t\ttask: stepTask,\n\t\t\t\tdescription: seqStep.description,\n\t\t\t\tpermissions: seqStep.permissions,\n\t\t\t\tmodel: effectiveModel ?? seqStep.model,\n\t\t\t\ttier: seqStep.tier,\n\t\t\t\tmodelSelection: captureModelSelection({ tier: seqStep.tier }),\n\t\t\t\tskill: seqStep.skill,\n\t\t\t\tcwd: seqStep.cwd,\n\t\t\t\toutput: seqStep.output,\n\t\t\t\toutputMode: seqStep.outputMode,\n\t\t\t\tacceptance: seqStep.acceptance,\n\t\t\t\ttoolBudget: seqStep.toolBudget,\n\t\t\t}, { parentMode: snapshotParentPermissionMode(ctx.sessionManager.getSessionId() ?? undefined), runId, index: childIndex }), {\n\t\t\t\tparentSessionId: ctx.sessionManager.getSessionId() ?? undefined,\n\t\t\t\tcwd: resolveChildCwd(cwd ?? ctx.cwd, seqStep.cwd),\n\t\t\t\tsignal,\n\t\t\t\tinterruptSignal: interruptController.signal,\n\t\t\t\tallowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,\n\t\t\t\tintercomEvents,\n\t\t\t\trunId,\n\t\t\t\tindex: childIndex,\n\t\t\t\tsessionDir: sessionDirForIndex(childIndex),\n\t\t\t\tsessionFile: sessionFileForTask?.(seqStep.agent, childIndex, effectiveModel)\n\t\t\t\t\t?? sessionFileForIndex?.(childIndex),\n\t\t\t\tthinkingOverride: thinkingOverrideForTask?.(seqStep.agent, childIndex, effectiveModel),\n\t\t\t\tshare: shareEnabled,\n\t\t\t\tartifactsDir: artifactConfig.enabled ? artifactsDir : undefined,\n\t\t\t\tartifactConfig,\n\t\t\t\toutputPath,\n\t\t\t\toutputMode: behavior.outputMode,\n\t\t\t\tmaxSubagentDepth,\n\t\t\t\tcontrolConfig,\n\t\t\t\tonControlEvent,\n\t\t\t\tintercomSessionName: childIntercomTarget?.(seqStep.agent, childIndex),\n\t\t\t\torchestratorIntercomTarget,\n\t\t\t\tnestedRoute: params.nestedRoute,\n\t\t\t\tmodelOverride: effectiveModel,\n\t\t\t\tavailableModels,\n\t\t\t\tpreferredModelProvider: ctx.model?.provider,\n\t\t\t\tmodelScope,\n\t\t\t\tskills: behavior.skills === false ? [] : behavior.skills,\n\t\t\t\tstructuredOutput: structuredRuntime,\n\t\t\t\tacceptance: seqStep.acceptance,\n\t\t\t\tacceptanceContext: { mode: \"chain\" },\n\t\t\t\ttimeoutMs: params.timeoutMs,\n\t\t\t\tdeadlineAt,\n\t\t\t\tturnBudget: params.turnBudget,\n\t\t\t\tonDetachedExit: onDetachedExit\n\t\t\t\t\t? (result) => onDetachedExit(childIndex, result)\n\t\t\t\t\t: undefined,\n\t\t\t\ttoolBudget: toolBudget.toolBudget,\n\t\t\t\tonUpdate: onUpdate\n\t\t\t\t\t? (p) => {\n\t\t\t\t\t\tconst stepResults = p.details?.results || [];\n\t\t\t\t\t\tconst stepProgress = p.details?.progress || [];\n\t\t\t\t\t\tif (foregroundControl && stepProgress.length > 0) {\n\t\t\t\t\t\t\tconst current = stepProgress[0];\n\t\t\t\t\t\t\tforegroundControl.currentAgent = seqStep.description || seqStep.agent;\n\t\t\t\t\t\t\tforegroundControl.currentChildId = seqStep.agent;\n\t\t\t\t\t\t\tforegroundControl.currentIndex = childIndex;\n\t\t\t\t\t\t\tforegroundControl.currentActivityState = current?.activityState;\n\t\t\t\t\t\t\tforegroundControl.lastActivityAt = current?.lastActivityAt;\n\t\t\t\t\t\t\tforegroundControl.currentTool = current?.currentTool;\n\t\t\t\t\t\t\tforegroundControl.currentToolStartedAt = current?.currentToolStartedAt;\n\t\t\t\t\t\t\tforegroundControl.currentPath = current?.currentPath;\n\t\t\t\t\t\t\tforegroundControl.turnCount = current?.turnCount;\n\t\t\t\t\t\t\tforegroundControl.tokens = current?.tokens;\n\t\t\t\t\t\t\tforegroundControl.toolCount = current?.toolCount;\n\t\t\t\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonUpdate({\n\t\t\t\t\t\t\t...p,\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\tprogress: allProgress.concat(stepProgress),\n\t\t\t\t\t\t\t\tcontrolEvents: p.details?.controlEvents,\n\t\t\t\t\t\t\t\tchainAgents,\n\t\t\t\t\t\t\t\ttotalSteps,\n\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\toutputs,\n\t\t\t\t\t\t\t\tworkflowGraph: buildWorkflowGraphSnapshot({\n\t\t\t\t\t\t\t\t\trunId,\n\t\t\t\t\t\t\t\t\tmode: \"chain\",\n\t\t\t\t\t\t\t\t\tsteps: chainSteps,\n\t\t\t\t\t\t\t\t\tresults: results.concat(stepResults),\n\t\t\t\t\t\t\t\t\tcurrentStepIndex: stepIndex,\n\t\t\t\t\t\t\t\t\tcurrentFlatIndex: childIndex,\n\t\t\t\t\t\t\t\t\tdynamicChildren,\n\t\t\t\t\t\t\t\t\tdynamicGroupStatuses,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t: undefined,\n\t\t\t});\n\t\t\tif (foregroundControl?.currentIndex === childIndex) {\n\t\t\t\tforegroundControl.interrupt = undefined;\n\t\t\t\tforegroundControl.updatedAt = Date.now();\n\t\t\t}\n\t\t\trecordRun(seqStep.agent, cleanTask, r.exitCode, r.progressSummary?.durationMs ?? 0);\n\n\t\t\tglobalTaskIndex++;\n\t\t\tresults.push(r);\n\t\t\tif (r.progress) allProgress.push(r.progress);\n\t\t\tif (r.artifactPaths) allArtifactPaths.push(r.artifactPaths);\n\n\t\t\tif (r.interrupted) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain paused after interrupt at step ${stepIndex + 1} (${r.agent}). Waiting for explicit next action.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (r.detached) {\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Chain detached for intercom coordination at step ${stepIndex + 1} (${r.agent}). Reply to the supervisor request first, then wait with subagent_wait({ id: \"${runId}\" }). Use subagent({ action: \"status\", id: \"${runId}\" }) to recover the result; do not resume or launch a replacement while it remains detached.` }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (r.exitCode !== 0) {\n\t\t\t\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"failed\", {\n\t\t\t\t\tindex: stepIndex,\n\t\t\t\t\terror: r.error || \"Chain failed\",\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: summary }],\n\t\t\t\t\tdetails: buildChainExecutionDetails(makeDetailsInput({ currentStepIndex: stepIndex, currentFlatIndex: childIndex })),\n\t\t\t\t\tisError: true,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (behavior.output) {\n\t\t\t\ttry {\n\t\t\t\t\tconst expectedPath = path.isAbsolute(behavior.output)\n\t\t\t\t\t\t? behavior.output\n\t\t\t\t\t\t: path.join(chainDir, behavior.output);\n\t\t\t\t\tif (!fs.existsSync(expectedPath)) {\n\t\t\t\t\t\tconst dirFiles = fs.readdirSync(chainDir);\n\t\t\t\t\t\tconst mdFiles = dirFiles.filter((file) => file.endsWith(\".md\") && file !== \"progress.md\");\n\t\t\t\t\t\tconst warning = mdFiles.length > 0\n\t\t\t\t\t\t\t? `Agent wrote to different file(s): ${mdFiles.join(\", \")} instead of ${behavior.output}`\n\t\t\t\t\t\t\t: `Agent did not create expected output file: ${behavior.output}`;\n\t\t\t\t\t\tr.error = r.error ? `${r.error}\\n${warning}` : warning;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore validation errors; this diagnostic should not mask successful chain output.\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (seqStep.as) outputs[seqStep.as] = outputEntryFromResult(r, stepIndex);\n\t\t\tprev = getSingleResultOutput(r);\n\t\t}\n\t}\n\n\tconst summary = buildChainSummary(chainSteps, results, chainDir, \"completed\");\n\n\treturn {\n\t\tcontent: [{ type: \"text\", text: summary }],\n\t\tdetails: buildChainExecutionDetails(makeDetailsInput()),\n\t};\n}\n"]}
@@ -18,7 +18,7 @@ import { DEFAULT_GLOBAL_CONCURRENCY_LIMIT, Semaphore } from "../shared/parallel-
18
18
  import { recordRun } from "../shared/run-history.js";
19
19
  import { cleanupWorktrees, createWorktrees, diffWorktrees, findWorktreeTaskCwdConflict, formatWorktreeDiffSummary, formatWorktreeTaskCwdConflict, } from "../shared/worktree.js";
20
20
  import { MAX_CONCURRENCY, resolveChildMaxSubagentDepth, } from "../../shared/types.js";
21
- import { captureModelSelection, resolveEffectiveSubagentModel, resolveTierModelOverride } from "../shared/model-fallback.js";
21
+ import { captureModelSelection, resolveRequiredTierModel } from "../shared/model-fallback.js";
22
22
  import { injectSingleOutputInstruction, validateFileOnlyOutputMode } from "../shared/single-output.js";
23
23
  import { buildWorkflowGraphSnapshot } from "../shared/workflow-graph.js";
24
24
  import { ChainOutputValidationError, outputEntryFromResult, resolveOutputReferences, validateChainOutputBindings } from "../shared/chain-outputs.js";
@@ -93,9 +93,7 @@ async function runParallelChainTasks(input) {
93
93
  let aborted = false;
94
94
  const effectiveModels = input.step.parallel.map((task) => {
95
95
  const taskChildConfig = input.agents.find((child) => child.name === task.agent);
96
- return resolveEffectiveSubagentModel(
97
- // lunr: model tiers — explicit per-task model wins; otherwise resolve task.tier via the tier bridge.
98
- task.model ?? resolveTierModelOverride(task.tier), taskChildConfig?.model, input.ctx.model, input.availableModels, input.ctx.model?.provider, { scope: input.modelScope });
96
+ return resolveRequiredTierModel(task.tier, input.availableModels, input.ctx.model?.provider);
99
97
  });
100
98
  for (let taskIndex = 0; taskIndex < input.step.parallel.length; taskIndex++) {
101
99
  const task = input.step.parallel[taskIndex];
@@ -160,7 +158,7 @@ async function runParallelChainTasks(input) {
160
158
  permissions: task.permissions,
161
159
  model: effectiveModel ?? task.model,
162
160
  tier: task.tier,
163
- modelSelection: captureModelSelection({ model: task.model, tier: task.tier }),
161
+ modelSelection: captureModelSelection({ tier: task.tier }),
164
162
  skill: task.skill,
165
163
  cwd: taskCwd,
166
164
  output: task.output,
@@ -368,7 +366,6 @@ export async function executeChain(params) {
368
366
  return {
369
367
  ...step,
370
368
  task: result.templates[i],
371
- ...(override?.model !== undefined ? { model: override.model } : {}),
372
369
  ...(override?.output !== undefined ? { output: override.output } : {}),
373
370
  ...("outputMode" in step && step.outputMode !== undefined ? { outputMode: step.outputMode } : {}),
374
371
  ...(override?.reads !== undefined ? { reads: override.reads } : {}),
@@ -833,9 +830,7 @@ export async function executeChain(params) {
833
830
  stepTask = stepTask.replace(/\{chain_dir\}/g, chainDir);
834
831
  const cleanTask = stepTask;
835
832
  stepTask = prefix + stepTask + suffix;
836
- // lunr: model tiers — explicit step model wins; otherwise resolve seqStep.tier via the tier bridge.
837
- const explicitStepModel = tuiOverride?.model ?? seqStep.model ?? resolveTierModelOverride(seqStep.tier);
838
- const effectiveModel = resolveEffectiveSubagentModel(explicitStepModel, agentConfig.model, ctx.model, availableModels, ctx.model?.provider, { scope: modelScope });
833
+ const effectiveModel = resolveRequiredTierModel(seqStep.tier, availableModels, ctx.model?.provider);
839
834
  const outputPath = typeof behavior.output === "string"
840
835
  ? (path.isAbsolute(behavior.output) ? behavior.output : path.join(chainDir, behavior.output))
841
836
  : undefined;
@@ -889,9 +884,7 @@ export async function executeChain(params) {
889
884
  permissions: seqStep.permissions,
890
885
  model: effectiveModel ?? seqStep.model,
891
886
  tier: seqStep.tier,
892
- modelSelection: tuiOverride?.model !== undefined
893
- ? captureModelSelection({ model: tuiOverride.model })
894
- : captureModelSelection({ model: seqStep.model, tier: seqStep.tier }),
887
+ modelSelection: captureModelSelection({ tier: seqStep.tier }),
895
888
  skill: seqStep.skill,
896
889
  cwd: seqStep.cwd,
897
890
  output: seqStep.output,