@ashx-j/lunr 0.2.11 → 0.2.13

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 (342) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +211 -236
  3. package/dist/builtin-extensions/ashxj-tui.d.ts +3 -0
  4. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-tui.js +28 -11
  6. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  7. package/dist/builtin-extensions/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/index.js +0 -2
  9. package/dist/builtin-extensions/index.js.map +1 -1
  10. package/dist/builtin-extensions/lunr-cron.d.ts +1 -1
  11. package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
  12. package/dist/builtin-extensions/lunr-cron.js +1 -1
  13. package/dist/builtin-extensions/lunr-cron.js.map +1 -1
  14. package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.js +3 -3
  16. package/dist/builtin-extensions/pi-subagents/src/extension/chain-validation.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/doctor.d.ts +0 -2
  18. package/dist/builtin-extensions/pi-subagents/src/extension/doctor.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/doctor.js +1 -23
  20. package/dist/builtin-extensions/pi-subagents/src/extension/doctor.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +6 -7
  23. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +7 -14
  27. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +12 -9
  29. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +38 -34
  31. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  33. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +32 -47
  35. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts +2 -2
  37. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +7 -10
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +90 -109
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +3 -2
  44. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +37 -50
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.d.ts +4 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.d.ts.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.js +5 -5
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/scheduled-runs.js.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +31 -13
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts +2 -2
  58. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts +4 -3
  61. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +48 -20
  63. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts +2 -2
  65. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +90 -64
  67. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +6 -8
  69. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +262 -161
  71. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
  74. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +24 -33
  75. package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +25 -0
  77. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -0
  78. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +51 -0
  79. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -0
  80. package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.d.ts.map +1 -1
  81. package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.js +20 -3
  82. package/dist/builtin-extensions/pi-subagents/src/runs/shared/dynamic-fanout.js.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +4 -1
  84. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  85. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +5 -0
  87. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +9 -3
  89. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +2 -2
  92. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  93. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
  94. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
  95. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +20 -17
  96. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
  97. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +70 -0
  98. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -0
  99. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +153 -0
  100. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -0
  101. package/dist/builtin-extensions/pi-subagents/src/shared/settings.d.ts +13 -8
  102. package/dist/builtin-extensions/pi-subagents/src/shared/settings.d.ts.map +1 -1
  103. package/dist/builtin-extensions/pi-subagents/src/shared/settings.js +20 -51
  104. package/dist/builtin-extensions/pi-subagents/src/shared/settings.js.map +1 -1
  105. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +80 -20
  106. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  107. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +10 -2
  108. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  109. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +2 -2
  110. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  111. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +20 -32
  112. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  113. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +2 -1
  114. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  115. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +23 -449
  116. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  117. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
  118. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  119. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +13 -11
  120. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  121. package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.d.ts +2 -1
  122. package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.d.ts.map +1 -1
  123. package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.js +18 -17
  124. package/dist/builtin-extensions/pi-subagents/src/watchdog/runtime.js.map +1 -1
  125. package/dist/builtin-extensions/simple-pi-memory.d.ts +2 -2
  126. package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
  127. package/dist/builtin-extensions/simple-pi-memory.js +41 -17
  128. package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
  129. package/dist/catalog/models.json +1 -1
  130. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  131. package/dist/catalog/providers/azure-openai-responses.json +1 -1
  132. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  133. package/dist/catalog/providers/cloudflare-workers-ai.json +1 -1
  134. package/dist/catalog/providers/fireworks.json +1 -1
  135. package/dist/catalog/providers/github-copilot.json +1 -1
  136. package/dist/catalog/providers/huggingface.json +1 -1
  137. package/dist/catalog/providers/minimax-cn.json +1 -1
  138. package/dist/catalog/providers/minimax.json +1 -1
  139. package/dist/catalog/providers/mistral.json +1 -1
  140. package/dist/catalog/providers/nvidia.json +1 -1
  141. package/dist/catalog/providers/openai.json +1 -1
  142. package/dist/catalog/providers/opencode-go.json +1 -1
  143. package/dist/catalog/providers/opencode.json +1 -1
  144. package/dist/catalog/providers/openrouter.json +1 -1
  145. package/dist/catalog/providers/qwen-cloud-cn.json +1 -1
  146. package/dist/catalog/providers/qwen-cloud.json +1 -1
  147. package/dist/catalog/providers/qwen-token-plan-cn.json +1 -1
  148. package/dist/catalog/providers/qwen-token-plan.json +1 -1
  149. package/dist/catalog/providers/together.json +1 -1
  150. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  151. package/dist/catalog/providers/zai-coding-cn.json +1 -1
  152. package/dist/catalog/providers/zai.json +1 -1
  153. package/dist/catalog/publication.json +3 -3
  154. package/dist/core/agent-session.d.ts +7 -1
  155. package/dist/core/agent-session.d.ts.map +1 -1
  156. package/dist/core/agent-session.js +34 -4
  157. package/dist/core/agent-session.js.map +1 -1
  158. package/dist/core/context-breakdown.d.ts +3 -1
  159. package/dist/core/context-breakdown.d.ts.map +1 -1
  160. package/dist/core/context-breakdown.js +5 -2
  161. package/dist/core/context-breakdown.js.map +1 -1
  162. package/dist/core/customize.d.ts +2 -0
  163. package/dist/core/customize.d.ts.map +1 -1
  164. package/dist/core/customize.js +6 -0
  165. package/dist/core/customize.js.map +1 -1
  166. package/dist/core/memory-cap.d.ts +4 -8
  167. package/dist/core/memory-cap.d.ts.map +1 -1
  168. package/dist/core/memory-cap.js +8 -8
  169. package/dist/core/memory-cap.js.map +1 -1
  170. package/dist/core/permissions.d.ts +2 -0
  171. package/dist/core/permissions.d.ts.map +1 -1
  172. package/dist/core/permissions.js +30 -14
  173. package/dist/core/permissions.js.map +1 -1
  174. package/dist/core/plan-mode.d.ts.map +1 -1
  175. package/dist/core/plan-mode.js +1 -9
  176. package/dist/core/plan-mode.js.map +1 -1
  177. package/dist/core/rollback.d.ts.map +1 -1
  178. package/dist/core/rollback.js +1 -1
  179. package/dist/core/rollback.js.map +1 -1
  180. package/dist/core/settings-manager.d.ts +16 -5
  181. package/dist/core/settings-manager.d.ts.map +1 -1
  182. package/dist/core/settings-manager.js +37 -10
  183. package/dist/core/settings-manager.js.map +1 -1
  184. package/dist/core/slash-commands.d.ts.map +1 -1
  185. package/dist/core/slash-commands.js +1 -5
  186. package/dist/core/slash-commands.js.map +1 -1
  187. package/dist/core/subagent-permission-inherit.d.ts +34 -22
  188. package/dist/core/subagent-permission-inherit.d.ts.map +1 -1
  189. package/dist/core/subagent-permission-inherit.js +37 -80
  190. package/dist/core/subagent-permission-inherit.js.map +1 -1
  191. package/dist/core/swarm.d.ts.map +1 -1
  192. package/dist/core/swarm.js +13 -7
  193. package/dist/core/swarm.js.map +1 -1
  194. package/dist/core/system-prompt.d.ts +6 -4
  195. package/dist/core/system-prompt.d.ts.map +1 -1
  196. package/dist/core/system-prompt.js +38 -48
  197. package/dist/core/system-prompt.js.map +1 -1
  198. package/dist/core/usage-adapters/openai-codex.d.ts +1 -1
  199. package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
  200. package/dist/core/usage-adapters/openai-codex.js +22 -17
  201. package/dist/core/usage-adapters/openai-codex.js.map +1 -1
  202. package/dist/core/usage-service.d.ts +10 -1
  203. package/dist/core/usage-service.d.ts.map +1 -1
  204. package/dist/core/usage-service.js +17 -6
  205. package/dist/core/usage-service.js.map +1 -1
  206. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  207. package/dist/gateway/agent-bridge.js +1 -4
  208. package/dist/gateway/agent-bridge.js.map +1 -1
  209. package/dist/gateway/cron.d.ts.map +1 -1
  210. package/dist/gateway/cron.js +1 -4
  211. package/dist/gateway/cron.js.map +1 -1
  212. package/dist/index.d.ts +1 -1
  213. package/dist/index.d.ts.map +1 -1
  214. package/dist/index.js.map +1 -1
  215. package/dist/main.d.ts.map +1 -1
  216. package/dist/main.js +0 -5
  217. package/dist/main.js.map +1 -1
  218. package/dist/migrations.d.ts +2 -0
  219. package/dist/migrations.d.ts.map +1 -1
  220. package/dist/migrations.js +21 -0
  221. package/dist/migrations.js.map +1 -1
  222. package/dist/modes/interactive/components/settings-selector.d.ts +7 -4
  223. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  224. package/dist/modes/interactive/components/settings-selector.js +122 -162
  225. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  226. package/dist/modes/interactive/components/usage-view.d.ts +1 -1
  227. package/dist/modes/interactive/components/usage-view.d.ts.map +1 -1
  228. package/dist/modes/interactive/components/usage-view.js +7 -4
  229. package/dist/modes/interactive/components/usage-view.js.map +1 -1
  230. package/dist/modes/interactive/interactive-mode.d.ts +1 -2
  231. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  232. package/dist/modes/interactive/interactive-mode.js +55 -96
  233. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  234. package/dist/modes/interactive/skill-tag-autocomplete.d.ts +13 -0
  235. package/dist/modes/interactive/skill-tag-autocomplete.d.ts.map +1 -0
  236. package/dist/modes/interactive/skill-tag-autocomplete.js +72 -0
  237. package/dist/modes/interactive/skill-tag-autocomplete.js.map +1 -0
  238. package/docs/compaction.md +23 -23
  239. package/docs/containerization.md +24 -24
  240. package/docs/custom-provider.md +18 -18
  241. package/docs/development.md +16 -15
  242. package/docs/docs.json +6 -2
  243. package/docs/extensions.md +82 -80
  244. package/docs/features.md +102 -0
  245. package/docs/index.md +25 -19
  246. package/docs/json.md +7 -7
  247. package/docs/keybindings.md +4 -4
  248. package/docs/models.md +2 -2
  249. package/docs/packages.md +38 -42
  250. package/docs/prompt-templates.md +4 -4
  251. package/docs/providers.md +22 -10
  252. package/docs/quickstart.md +81 -46
  253. package/docs/rpc.md +7 -13
  254. package/docs/sdk.md +43 -41
  255. package/docs/security.md +18 -18
  256. package/docs/session-format.md +9 -9
  257. package/docs/sessions.md +13 -12
  258. package/docs/settings.md +63 -24
  259. package/docs/shell-aliases.md +2 -2
  260. package/docs/skills.md +21 -11
  261. package/docs/terminal-setup.md +5 -5
  262. package/docs/termux.md +7 -7
  263. package/docs/themes.md +12 -14
  264. package/docs/tmux.md +4 -4
  265. package/docs/tui.md +23 -23
  266. package/docs/usage.md +112 -87
  267. package/docs/windows.md +10 -2
  268. package/examples/README.md +3 -1
  269. package/examples/extensions/README.md +6 -6
  270. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  271. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  272. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  273. package/examples/extensions/doom-overlay/README.md +2 -2
  274. package/examples/extensions/gondolin/package-lock.json +2 -2
  275. package/examples/extensions/gondolin/package.json +1 -1
  276. package/examples/extensions/plan-mode/README.md +3 -1
  277. package/examples/extensions/sandbox/package-lock.json +2 -2
  278. package/examples/extensions/sandbox/package.json +1 -1
  279. package/examples/extensions/subagent/README.md +13 -11
  280. package/examples/extensions/todo.ts +2 -1
  281. package/examples/extensions/with-deps/package-lock.json +2 -2
  282. package/examples/extensions/with-deps/package.json +1 -1
  283. package/examples/sdk/README.md +9 -5
  284. package/package.json +6 -7
  285. package/dist/builtin-extensions/lunr-behavior.d.ts +0 -44
  286. package/dist/builtin-extensions/lunr-behavior.d.ts.map +0 -1
  287. package/dist/builtin-extensions/lunr-behavior.js +0 -213
  288. package/dist/builtin-extensions/lunr-behavior.js.map +0 -1
  289. package/dist/builtin-extensions/pi-subagents/agents/context-builder.md +0 -46
  290. package/dist/builtin-extensions/pi-subagents/agents/deep-researcher.md +0 -36
  291. package/dist/builtin-extensions/pi-subagents/agents/delegate.md +0 -12
  292. package/dist/builtin-extensions/pi-subagents/agents/oracle.md +0 -73
  293. package/dist/builtin-extensions/pi-subagents/agents/planner.md +0 -55
  294. package/dist/builtin-extensions/pi-subagents/agents/research-writer.md +0 -37
  295. package/dist/builtin-extensions/pi-subagents/agents/researcher.md +0 -52
  296. package/dist/builtin-extensions/pi-subagents/agents/reviewer.md +0 -79
  297. package/dist/builtin-extensions/pi-subagents/agents/scout.md +0 -50
  298. package/dist/builtin-extensions/pi-subagents/agents/worker.md +0 -55
  299. package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.d.ts +0 -20
  300. package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.d.ts.map +0 -1
  301. package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.js +0 -1273
  302. package/dist/builtin-extensions/pi-subagents/src/agents/agent-management.js.map +0 -1
  303. package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.d.ts +0 -49
  304. package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.d.ts.map +0 -1
  305. package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.js +0 -252
  306. package/dist/builtin-extensions/pi-subagents/src/agents/agent-memory.js.map +0 -1
  307. package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.d.ts +0 -3
  308. package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.d.ts.map +0 -1
  309. package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.js +0 -6
  310. package/dist/builtin-extensions/pi-subagents/src/agents/agent-scope.js.map +0 -1
  311. package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.d.ts +0 -3
  312. package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.d.ts.map +0 -1
  313. package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.js +0 -23
  314. package/dist/builtin-extensions/pi-subagents/src/agents/agent-selection.js.map +0 -1
  315. package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.d.ts +0 -8
  316. package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.d.ts.map +0 -1
  317. package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.js +0 -143
  318. package/dist/builtin-extensions/pi-subagents/src/agents/agent-serializer.js.map +0 -1
  319. package/dist/builtin-extensions/pi-subagents/src/agents/agents.d.ts +0 -176
  320. package/dist/builtin-extensions/pi-subagents/src/agents/agents.d.ts.map +0 -1
  321. package/dist/builtin-extensions/pi-subagents/src/agents/agents.js +0 -1326
  322. package/dist/builtin-extensions/pi-subagents/src/agents/agents.js.map +0 -1
  323. package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.d.ts +0 -7
  324. package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.d.ts.map +0 -1
  325. package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.js +0 -307
  326. package/dist/builtin-extensions/pi-subagents/src/agents/chain-serializer.js.map +0 -1
  327. package/dist/builtin-extensions/pi-subagents/src/agents/identity.d.ts +0 -8
  328. package/dist/builtin-extensions/pi-subagents/src/agents/identity.d.ts.map +0 -1
  329. package/dist/builtin-extensions/pi-subagents/src/agents/identity.js +0 -30
  330. package/dist/builtin-extensions/pi-subagents/src/agents/identity.js.map +0 -1
  331. package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.d.ts +0 -35
  332. package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.d.ts.map +0 -1
  333. package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.js +0 -151
  334. package/dist/builtin-extensions/pi-subagents/src/agents/proactive-skills.js.map +0 -1
  335. package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.d.ts +0 -131
  336. package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.d.ts.map +0 -1
  337. package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.js +0 -491
  338. package/dist/builtin-extensions/pi-subagents/src/profiles/profiles.js.map +0 -1
  339. package/dist/core/behavior-preset.d.ts +0 -60
  340. package/dist/core/behavior-preset.d.ts.map +0 -1
  341. package/dist/core/behavior-preset.js +0 -257
  342. package/dist/core/behavior-preset.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-runner.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.ts"],"names":[],"mappings":"","sourcesContent":["// @ts-nocheck\nimport { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { Message } from \"@ashx-j/lunr-ai\";\nimport { writeAtomicJson } from \"../../shared/atomic-json.ts\";\nimport { createChildTranscriptWriter, type ChildTranscriptWriter } from \"../../shared/child-transcript.ts\";\nimport { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, enqueueStepSteer, steerAcksDir, steerCapabilityPath, stepSteerInboxDir, watchAsyncControlInbox, type SteerAck, type SteerCapability, type SteerRequest } from \"./control-channel.ts\";\nimport { appendJsonl as appendRawJsonl, getArtifactPaths } from \"../../shared/artifacts.ts\";\nimport { PI_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from \"../shared/pi-spawn.ts\";\nimport { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, injectSingleOutputInstruction, resolveSingleOutput, type SingleOutputSnapshot } from \"../shared/single-output.ts\";\nimport {\n\ttype ActivityState,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype AsyncParallelGroupStatus,\n\ttype AsyncStatus,\n\ttype ChainOutputMap,\n\ttype CostSummary,\n\ttype ModelAttempt,\n\ttype NestedRouteInfo,\n\ttype NestedRunSummary,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SubagentRunMode,\n\ttype ToolBudgetState,\n\ttype TurnBudgetState,\n\ttype Usage,\n\ttype WorkflowGraphSnapshot,\n\ttype SteeringStatus,\n\ttype SteeringTargetState,\n\ttype SteeringTargetStatus,\n\tDEFAULT_MAX_OUTPUT,\n\ttype MaxOutputConfig,\n\tSUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\ttruncateOutput,\n\tgetSubagentDepthEnv,\n} from \"../../shared/types.ts\";\nimport {\n\tDEFAULT_CONTROL_CONFIG,\n\tbuildControlEvent,\n\tderiveActivityState,\n\tclaimControlNotification,\n\tformatControlIntercomMessage,\n\tformatControlNoticeMessage,\n} from \"../shared/subagent-control.ts\";\nimport {\n\ttype RunnerSubagentStep as SubagentStep,\n\ttype RunnerStep,\n\tisDynamicRunnerGroup,\n\tisParallelGroup,\n\tflattenSteps,\n\tmapConcurrent,\n\taggregateParallelOutputs,\n\tMAX_PARALLEL_CONCURRENCY,\n\tDEFAULT_GLOBAL_CONCURRENCY_LIMIT,\n\tSemaphore,\n} from \"../shared/parallel-utils.ts\";\nimport { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from \"../shared/pi-args.ts\";\nimport { filterToolsForInheritedChild, snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { outputEntryFromAsyncResult, resolveOutputReferences } from \"../shared/chain-outputs.ts\";\nimport { createStructuredOutputRuntime, readStructuredOutput } from \"../shared/structured-output.ts\";\nimport { readChildToolDiagnosticError } from \"../shared/tool-availability.ts\";\nimport { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from \"../shared/dynamic-fanout.ts\";\nimport { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from \"../shared/nested-events.ts\";\nimport { formatModelAttemptNote, isRetryableModelFailure } from \"../shared/model-fallback.ts\";\nimport { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from \"./steering.ts\";\nimport { attachPostExitStdioGuard, trySignalChild } from \"../../shared/post-exit-stdio-guard.ts\";\nimport { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput, readStatus } from \"../../shared/utils.ts\";\nimport { evaluateCompletionMutationGuard } from \"../shared/completion-guard.ts\";\nimport {\n\tcreateMutatingFailureState,\n\tdidMutatingToolFail,\n\tisMutatingTool,\n\tnextLongRunningTrigger,\n\trecordMutatingFailure,\n\tresetMutatingFailureState,\n\tresolveCurrentPath,\n\tshouldEscalateMutatingFailures,\n\tsummarizeRecentMutatingFailures,\n} from \"../shared/long-running-guard.ts\";\nimport { parseSessionTokens } from \"../../shared/session-tokens.ts\";\nimport type { TokenUsage } from \"../../shared/types.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport { resolveEffectiveThinking } from \"../../shared/model-info.ts\";\nimport { writeInitialProgressFile } from \"../../shared/settings.ts\";\nimport { resolveSubagentIntercomTarget } from \"../../intercom/intercom-bridge.ts\";\nimport { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from \"../shared/acceptance.ts\";\nimport { waitForImportedAsyncRoot } from \"./chain-root-attachment.ts\";\nimport { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from \"./chain-append.ts\";\nimport { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, shouldAbortForTurnBudget, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from \"../shared/turn-budget.ts\";\nimport { initialToolBudgetState, toolBudgetState } from \"../shared/tool-budget.ts\";\nimport { resolveWatchdogConfig } from \"../../watchdog/settings.ts\";\nimport { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from \"../shared/child-protocol.ts\";\nimport { acquireSessionLease, type SessionLeaseRequest } from \"../shared/session-lease.ts\";\nimport {\n\tCHILD_WATCHDOG_CONFIG_ENV,\n\tacceptChildWatchdogEvent,\n\tchildWatchdogIsActive,\n\tdecodeChildWatchdogConfig,\n\tisChildWatchdogStatusEvent,\n\tresolveChildWatchdogConfig,\n\ttype ChildWatchdogStateSnapshot,\n} from \"../../watchdog/child-status.ts\";\n\ninterface SubagentRunConfig {\n\tid: string;\n\tsteps: RunnerStep[];\n\tresultPath: string;\n\tcwd: string;\n\tplaceholder: string;\n\ttaskIndex?: number;\n\ttotalTasks?: number;\n\tmaxOutput?: MaxOutputConfig;\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\tshare?: boolean;\n\tsessionDir?: string;\n\tasyncDir: string;\n\tsessionId?: string | null;\n\tpiPackageRoot?: string;\n\tpiArgv1?: string;\n\tworktreeSetupHook?: string;\n\tworktreeSetupHookTimeoutMs?: number;\n\tworktreeBaseDir?: string;\n\tcontrolConfig?: ResolvedControlConfig;\n\tcontrolIntercomTarget?: string;\n\tchildIntercomTargets?: Array<string | undefined>;\n\tresultMode?: SubagentRunMode;\n\tdynamicFanoutMaxItems?: number;\n\tworkflowGraph?: WorkflowGraphSnapshot;\n\tnestedRoute?: NestedRouteInfo;\n\tnestedSelf?: { parentRunId: string; parentStepIndex?: number; depth: number; path?: Array<{ runId: string; stepIndex?: number; agent?: string }> };\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudget?: ResolvedToolBudget;\n\trevivalLease?: SessionLeaseRequest;\n\t/** Global cap on simultaneously-running subagent tasks within this run. */\n\tglobalConcurrencyLimit?: number;\n}\n\ninterface StepResult {\n\tagent: string;\n\toutput: string;\n\terror?: string;\n\tprotocolError?: ProtocolOutputLimit;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\tskipped?: boolean;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tsessionFile?: string;\n\tintercomTarget?: string;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\tmodelAttempts?: ModelAttempt[];\n\ttotalCost?: CostSummary;\n\tartifactPaths?: ArtifactPaths;\n\ttruncated?: boolean;\n\ttranscriptPath?: string;\n\ttranscriptError?: string;\n\tstructuredOutput?: unknown;\n\tstructuredOutputPath?: string;\n\tstructuredOutputSchemaPath?: string;\n\tacceptance?: import(\"../../shared/types.ts\").AcceptanceLedger;\n\twatchdog?: import(\"../../shared/types.ts\").ChildWatchdogProgress;\n}\n\nconst ASYNC_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === \"win32\" ? \"SIGBREAK\" : \"SIGUSR2\";\nconst DEFAULT_MAX_ASYNC_EVENTS_BYTES = 50 * 1024 * 1024;\nconst ASYNC_EVENTS_MAX_BYTES_ENV = \"PI_SUBAGENT_ASYNC_EVENTS_MAX_BYTES\";\nconst TRUNCATED_EVENT_TYPE = \"subagent.events.truncated\";\nconst TRUNCATION_MARKER_RESERVE_BYTES = 512;\n\ninterface AsyncEventLogState {\n\tbytes: number;\n\tdiagnosticsTruncated: boolean;\n}\n\nconst asyncEventLogStates = new Map<string, AsyncEventLogState>();\n\nfunction maxAsyncEventsBytes(): number {\n\tconst raw = process.env[ASYNC_EVENTS_MAX_BYTES_ENV];\n\tif (!raw) return DEFAULT_MAX_ASYNC_EVENTS_BYTES;\n\tconst parsed = Number(raw);\n\tif (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_MAX_ASYNC_EVENTS_BYTES;\n\treturn Math.floor(parsed);\n}\n\nfunction eventLogState(filePath: string): AsyncEventLogState {\n\tlet state = asyncEventLogStates.get(filePath);\n\tif (state) return state;\n\tlet bytes = 0;\n\ttry {\n\t\tbytes = fs.statSync(filePath).size;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\t// Diagnostic event accounting is best-effort; writes below are also safe.\n\t\t}\n\t}\n\tstate = { bytes, diagnosticsTruncated: false };\n\tasyncEventLogStates.set(filePath, state);\n\treturn state;\n}\n\nfunction appendJsonl(filePath: string, line: string): void {\n\ttry {\n\t\tappendRawJsonl(filePath, line);\n\t\tconst state = asyncEventLogStates.get(filePath);\n\t\tif (state) state.bytes += Buffer.byteLength(`${line}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Async event logging is diagnostic and must not fail the run.\n\t}\n}\n\nfunction appendDiagnosticJsonl(filePath: string, line: string, droppedEventType?: string): void {\n\tif (!line.trim()) return;\n\tconst state = eventLogState(filePath);\n\tif (state.diagnosticsTruncated) return;\n\tconst maxBytes = maxAsyncEventsBytes();\n\tconst chunkBytes = Buffer.byteLength(`${line}\\n`, \"utf-8\");\n\tconst diagnosticBudget = Math.max(0, maxBytes - TRUNCATION_MARKER_RESERVE_BYTES);\n\tif (state.bytes + chunkBytes <= diagnosticBudget) {\n\t\tappendJsonl(filePath, line);\n\t\treturn;\n\t}\n\n\tconst marker = JSON.stringify({\n\t\ttype: TRUNCATED_EVENT_TYPE,\n\t\tts: Date.now(),\n\t\tmaxBytes,\n\t\tdroppedEventType,\n\t});\n\tif (state.bytes + Buffer.byteLength(`${marker}\\n`, \"utf-8\") <= maxBytes) {\n\t\tappendJsonl(filePath, marker);\n\t}\n\tstate.diagnosticsTruncated = true;\n}\n\nfunction shouldPersistChildEvent(event: Record<string, unknown>): boolean {\n\treturn event.type !== \"message_update\";\n}\n\nfunction findLatestSessionFile(sessionDir: string): string | null {\n\ttry {\n\t\tconst files = fs\n\t\t\t.readdirSync(sessionDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => path.join(sessionDir, f));\n\t\tif (files.length === 0) return null;\n\t\tfiles.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);\n\t\treturn files[0] ?? null;\n\t} catch {\n\t\t// Session lookup is optional metadata.\n\t\treturn null;\n\t}\n}\n\nfunction emptyUsage(): Usage {\n\treturn { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };\n}\n\nfunction tokenUsageFromAttempts(attempts: ModelAttempt[] | undefined): TokenUsage | null {\n\tif (!attempts || attempts.length === 0) return null;\n\tlet input = 0;\n\tlet output = 0;\n\tfor (const attempt of attempts) {\n\t\tinput += attempt.usage?.input ?? 0;\n\t\toutput += attempt.usage?.output ?? 0;\n\t}\n\tconst total = input + output;\n\treturn total > 0 ? { input, output, total } : null;\n}\n\nfunction costSummaryFromAttempts(attempts: ModelAttempt[] | undefined): CostSummary | undefined {\n\tif (!attempts || attempts.length === 0) return undefined;\n\tlet inputTokens = 0;\n\tlet outputTokens = 0;\n\tlet costUsd = 0;\n\tfor (const attempt of attempts) {\n\t\tinputTokens += attempt.usage?.input ?? 0;\n\t\toutputTokens += attempt.usage?.output ?? 0;\n\t\tcostUsd += attempt.usage?.cost ?? 0;\n\t}\n\treturn inputTokens > 0 || outputTokens > 0 || costUsd > 0\n\t\t? { inputTokens, outputTokens, costUsd }\n\t\t: undefined;\n}\n\nfunction appendRecentStepOutput(step: RunnerStatusStep, lines: string[]): void {\n\tconst nonEmpty = lines.filter((line) => line.trim());\n\tif (nonEmpty.length === 0) return;\n\tstep.recentOutput ??= [];\n\tstep.recentOutput.push(...nonEmpty);\n\tif (step.recentOutput.length > 50) {\n\t\tstep.recentOutput.splice(0, step.recentOutput.length - 50);\n\t}\n}\n\nfunction isTerminalAssistantStop(message: Message): boolean {\n\tconst stopReason = (message as { stopReason?: string }).stopReason;\n\tconst hasToolCall = Array.isArray(message.content)\n\t\t&& message.content.some((part) => (part as { type?: string }).type === \"toolCall\");\n\treturn stopReason === \"stop\" && !hasToolCall;\n}\n\nfunction resetStepLiveDetail(step: RunnerStatusStep): void {\n\tstep.currentTool = undefined;\n\tstep.currentToolArgs = undefined;\n\tstep.currentToolStartedAt = undefined;\n\tstep.currentPath = undefined;\n\tstep.recentTools = [];\n\tstep.recentOutput = [];\n}\n\ninterface ChildEventContext {\n\teventsPath: string;\n\trunId: string;\n\tstepIndex: number;\n\tagent: string;\n}\n\ninterface ChildUsage {\n\tinput?: number;\n\tinputTokens?: number;\n\toutput?: number;\n\toutputTokens?: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\tcost?: { total?: number };\n}\n\ntype ChildMessage = Message & {\n\tmodel?: string;\n\terrorMessage?: string;\n\tusage?: ChildUsage;\n};\n\ninterface ChildEvent {\n\ttype?: string;\n\tmessage?: ChildMessage;\n\ttoolName?: string;\n\targs?: Record<string, unknown>;\n\twillRetry?: unknown;\n}\n\ninterface RunPiStreamingResult {\n\tstderr: string;\n\texitCode: number | null;\n\tmessages: Message[];\n\tusage: Usage;\n\tmodel?: string;\n\terror?: string;\n\tprotocolError?: ProtocolOutputLimit;\n\tfinalOutput: string;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tobservedMutationAttempt?: boolean;\n\twatchdog?: ChildWatchdogStateSnapshot;\n}\n\nfunction runPiStreaming(\n\targs: string[],\n\tcwd: string,\n\toutputFile: string,\n\tenv?: Record<string, string | undefined>,\n\tpiPackageRoot?: string,\n\tpiArgv1?: string,\n\tmaxSubagentDepth?: number,\n\tchildEventContext?: ChildEventContext,\n\tregisterInterrupt?: (interrupt: (() => void) | undefined) => void,\n\tonChildEvent?: (event: ChildEvent) => void,\n\ttranscriptWriter?: ChildTranscriptWriter,\n\tregisterTimeout?: (interrupt: (() => void) | undefined) => void,\n\ttimeoutMessage?: string,\n\tregisterStop?: (stop: (() => void) | undefined) => void,\n\tstopMessage?: string,\n\tregisterTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void,\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void,\n): Promise<RunPiStreamingResult> {\n\treturn new Promise((resolve) => {\n\t\tonWriterProcess?.({ state: \"spawning\" });\n\t\tconst outputStream = fs.createWriteStream(outputFile, { flags: \"w\" });\n\t\tconst spawnEnv = { ...process.env, ...(env ?? {}), ...getSubagentDepthEnv(maxSubagentDepth) };\n\t\tconst spawnSpec = getPiSpawnCommand(args, {\n\t\t\t...(piPackageRoot ? { piPackageRoot } : {}),\n\t\t\t...(piArgv1 ? { argv1: piArgv1 } : {}),\n\t\t});\n\t\tconst child = spawn(spawnSpec.command, spawnSpec.args, {\n\t\t\tcwd,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: spawnEnv,\n\t\t\twindowsHide: true,\n\t\t});\n\t\tconst stderrTail = createBoundedByteTail();\n\t\tconst rawStdoutTail = createBoundedByteTail();\n\t\tconst messages: Message[] = [];\n\t\tconst usage = emptyUsage();\n\t\tlet model: string | undefined;\n\t\tlet writerRegistrationError: string | undefined;\n\t\tif (typeof child.pid === \"number\") {\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"running\", pid: child.pid });\n\t\t\t} catch (writerError) {\n\t\t\t\twriterRegistrationError = `Failed to record revived Pi writer ownership: ${writerError instanceof Error ? writerError.message : String(writerError)}`;\n\t\t\t\ttrySignalChild(child, \"SIGKILL\");\n\t\t\t}\n\t\t}\n\t\tlet error: string | undefined = writerRegistrationError;\n\t\tlet assistantError: string | undefined;\n\t\tlet interrupted = false;\n\t\tlet timedOut = false;\n\t\tlet stopped = false;\n\t\tlet turnBudgetExceeded = false;\n\t\tlet turnBudgetMessage: string | undefined;\n\t\tlet turnBudget: TurnBudgetState | undefined;\n\t\tlet observedMutationAttempt = false;\n\t\tconst childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);\n\t\tlet childWatchdogState: ChildWatchdogStateSnapshot | undefined;\n\t\tlet applyChildLifecycle = (_action: ChildLifecycleAction): void => {};\n\t\tconst updateChildWatchdogState = (snapshot: ChildWatchdogStateSnapshot): void => {\n\t\t\tchildWatchdogState = snapshot;\n\t\t};\n\n\t\tconst writeOutputLine = (line: string) => {\n\t\t\tif (!line.trim()) return;\n\t\t\toutputStream.write(`${line}\\n`);\n\t\t};\n\n\t\tconst writeOutputText = (text: string) => {\n\t\t\tfor (const line of text.split(\"\\n\")) {\n\t\t\t\twriteOutputLine(line);\n\t\t\t}\n\t\t};\n\n\t\tconst appendChildEvent = (event: Record<string, unknown>) => {\n\t\t\tif (!childEventContext) return;\n\t\t\tif (!shouldPersistChildEvent(event)) return;\n\t\t\tappendDiagnosticJsonl(childEventContext.eventsPath, JSON.stringify({\n\t\t\t\t...event,\n\t\t\t\tsubagentSource: \"child\",\n\t\t\t\tsubagentRunId: childEventContext.runId,\n\t\t\t\tsubagentStepIndex: childEventContext.stepIndex,\n\t\t\t\tsubagentAgent: childEventContext.agent,\n\t\t\t\tobservedAt: Date.now(),\n\t\t\t}), typeof event.type === \"string\" ? event.type : undefined);\n\t\t};\n\n\t\tconst appendChildLine = (type: \"subagent.child.stdout\" | \"subagent.child.stderr\", line: string) => {\n\t\t\tappendChildEvent({ type, line });\n\t\t\tif (type === \"subagent.child.stdout\") transcriptWriter?.writeStdoutLine(line);\n\t\t\telse transcriptWriter?.writeStderrLine(line);\n\t\t};\n\n\t\tconst processStdoutLine = (line: string) => {\n\t\t\tif (!line.trim()) return;\n\t\t\tlet event: ChildEvent;\n\t\t\ttry {\n\t\t\t\tevent = JSON.parse(line) as ChildEvent;\n\t\t\t} catch {\n\t\t\t\trawStdoutTail.push(`${line}\\n`);\n\t\t\t\twriteOutputLine(line);\n\t\t\t\tappendChildLine(\"subagent.child.stdout\", line);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tappendChildEvent(event);\n\t\t\ttranscriptWriter?.writeChildEvent(event);\n\t\t\tif (event.type === \"agent_settled\") agentSettledReceived = true;\n\t\t\tapplyChildLifecycle(projectChildLifecycle(event));\n\n\t\t\tif (isChildWatchdogStatusEvent(event)) {\n\t\t\t\tif (!childWatchdogConfig) return;\n\t\t\t\tconst next = acceptChildWatchdogEvent({\n\t\t\t\t\tcurrent: childWatchdogState,\n\t\t\t\t\tevent,\n\t\t\t\t\trunId: childEventContext?.runId,\n\t\t\t\t\tagent: childEventContext?.agent,\n\t\t\t\t\tchildIndex: childEventContext?.stepIndex,\n\t\t\t\t});\n\t\t\t\tif (!next) return;\n\t\t\t\tupdateChildWatchdogState(next);\n\t\t\t\tonChildEvent?.(event);\n\t\t\t\tif (childWatchdogIsActive(next)) {\n\t\t\t\t\tif (finalDrainTimer) {\n\t\t\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tif (finalHardKillTimer) {\n\t\t\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tarmWatchdogTail();\n\t\t\t\t} else {\n\t\t\t\t\tclearWatchdogTailTimer();\n\t\t\t\t\tif (cleanTerminalAssistantStopReceived || agentSettledReceived) startFinalDrain();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tonChildEvent?.(event);\n\n\t\t\tif (event.type === \"tool_execution_start\" && event.toolName) {\n\t\t\t\tobservedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);\n\t\t\t\tconst toolArgs = extractToolArgsPreview(event.args ?? {});\n\t\t\t\twriteOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ((event.type === \"message_end\" || event.type === \"tool_result_end\") && event.message) {\n\t\t\t\tmessages.push(event.message);\n\t\t\t\tconst text = extractTextFromContent(event.message.content);\n\t\t\t\tif (text) writeOutputText(text);\n\n\t\t\t\tif (event.type !== \"message_end\" || event.message.role !== \"assistant\") return;\n\t\t\t\tif (event.message.model) model = event.message.model;\n\t\t\t\tif (event.message.errorMessage) assistantError = event.message.errorMessage;\n\t\t\t\tconst eventUsage = event.message.usage;\n\t\t\t\tif (eventUsage) {\n\t\t\t\t\tusage.turns++;\n\t\t\t\t\tusage.input += eventUsage.input ?? eventUsage.inputTokens ?? 0;\n\t\t\t\t\tusage.output += eventUsage.output ?? eventUsage.outputTokens ?? 0;\n\t\t\t\t\tusage.cacheRead += eventUsage.cacheRead ?? 0;\n\t\t\t\t\tusage.cacheWrite += eventUsage.cacheWrite ?? 0;\n\t\t\t\t\tusage.cost += eventUsage.cost?.total ?? 0;\n\t\t\t\t}\n\t\t\t\tif (isTerminalAssistantStop(event.message)) {\n\t\t\t\t\tif (!event.message.errorMessage && extractTextFromContent(event.message.content).trim()) assistantError = undefined;\n\t\t\t\t\tcleanTerminalAssistantStopReceived ||= !event.message.errorMessage;\n\t\t\t\t\tapplyChildLifecycle(projectChildLifecycle(event, true));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Guard both cases that can leave the parent waiting on `close` forever:\n\t\t// a lingering stdio holder after `exit`, or a child that never exits.\n\t\tconst FINAL_STOP_GRACE_MS = 1000;\n\t\tconst HARD_KILL_MS = 3000;\n\t\tconst TIMEOUT_HARD_KILL_MS = 3000;\n\t\tlet childExited = false;\n\t\tlet forcedTerminationSignal = false;\n\t\tlet cleanTerminalAssistantStopReceived = false;\n\t\tlet agentSettledReceived = false;\n\t\tlet finalDrainTimer: NodeJS.Timeout | undefined;\n\t\tlet finalHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet watchdogTailTimer: NodeJS.Timeout | undefined;\n\t\tlet timeoutHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet turnBudgetTerminationTimer: NodeJS.Timeout | undefined;\n\t\tlet turnBudgetHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet protocolHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet protocolError: ProtocolOutputLimit | undefined;\n\t\tlet settled = false;\n\t\tapplyChildLifecycle = (action: ChildLifecycleAction): void => {\n\t\t\tif (action === \"cancel-drain\") {\n\t\t\t\tif (finalDrainTimer) {\n\t\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t\t}\n\t\t\t\tif (finalHardKillTimer) {\n\t\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t\t}\n\t\t\t\tclearWatchdogTailTimer();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"start-drain\") startFinalDrain();\n\t\t};\n\t\tconst failProtocol = (limit: ProtocolOutputLimit): void => {\n\t\t\tif (protocolError) return;\n\t\t\tprotocolError = limit;\n\t\t\terror = formatProtocolOutputLimit(limit);\n\t\t\tif (!childExited) {\n\t\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\t\tprotocolHardKillTimer = setTimeout(() => {\n\t\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t\t}, 3000);\n\t\t\t\tprotocolHardKillTimer.unref?.();\n\t\t\t}\n\t\t};\n\t\tconst stdoutReader = createBoundedLineReader({ onLine: processStdoutLine, onLimit: failProtocol });\n\t\tconst stderrReader = createBoundedLineReader({\n\t\t\tstream: \"stderr\",\n\t\t\tmaxPendingLineBytes: MAX_CHILD_STDERR_BYTES,\n\t\t\tonLine: (line) => appendChildLine(\"subagent.child.stderr\", line),\n\t\t\tonLimit: (limit) => appendChildLine(\"subagent.child.stderr\", formatProtocolOutputLimit(limit)),\n\t\t});\n\t\tconst clearStdioGuard = attachPostExitStdioGuard(child, { idleMs: 2000, hardMs: 8000 });\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => stdoutReader.push(chunk));\n\t\tchild.stderr.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderrTail.push(chunk);\n\t\t\tstderrReader.push(chunk);\n\t\t\toutputStream.write(chunk);\n\t\t});\n\t\tregisterInterrupt?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\tinterrupted = true;\n\t\t\tif (!error) error = \"Interrupted. Waiting for explicit next action.\";\n\t\t\ttrySignalChild(child, \"SIGINT\");\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGTERM\");\n\t\t\t}, 1000).unref?.();\n\t\t});\n\t\tregisterTimeout?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\ttimedOut = true;\n\t\t\tinterrupted = false;\n\t\t\terror = timeoutMessage ?? \"Subagent timed out.\";\n\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\ttimeoutHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, TIMEOUT_HARD_KILL_MS);\n\t\t\ttimeoutHardKillTimer.unref?.();\n\t\t});\n\t\tregisterStop?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\tstopped = true;\n\t\t\tinterrupted = false;\n\t\t\terror = stopMessage ?? \"Subagent stopped by user.\";\n\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\ttimeoutHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, TIMEOUT_HARD_KILL_MS);\n\t\t\ttimeoutHardKillTimer.unref?.();\n\t\t});\n\t\tregisterTurnBudgetAbort?.((message, state) => {\n\t\t\tif (settled || timedOut || stopped || turnBudgetExceeded) return;\n\t\t\tturnBudgetExceeded = true;\n\t\t\tturnBudgetMessage = message;\n\t\t\tturnBudget = state;\n\t\t\tinterrupted = false;\n\t\t\terror = message;\n\t\t\ttrySignalChild(child, \"SIGINT\");\n\t\t\tturnBudgetTerminationTimer = setTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGTERM\");\n\t\t\t}, 1000);\n\t\t\tturnBudgetTerminationTimer.unref?.();\n\t\t\tturnBudgetHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, 4000);\n\t\t\tturnBudgetHardKillTimer.unref?.();\n\t\t});\n\t\tconst clearDrainTimers = () => {\n\t\t\tif (finalDrainTimer) {\n\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t}\n\t\t\tif (finalHardKillTimer) {\n\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t}\n\t\t\tclearWatchdogTailTimer();\n\t\t\tif (timeoutHardKillTimer) {\n\t\t\t\tclearTimeout(timeoutHardKillTimer);\n\t\t\t\ttimeoutHardKillTimer = undefined;\n\t\t\t}\n\t\t\tif (turnBudgetTerminationTimer) {\n\t\t\t\tclearTimeout(turnBudgetTerminationTimer);\n\t\t\t\tturnBudgetTerminationTimer = undefined;\n\t\t\t}\n\t\t\tif (turnBudgetHardKillTimer) {\n\t\t\t\tclearTimeout(turnBudgetHardKillTimer);\n\t\t\t\tturnBudgetHardKillTimer = undefined;\n\t\t\t}\n\t\t\tif (protocolHardKillTimer) {\n\t\t\t\tclearTimeout(protocolHardKillTimer);\n\t\t\t\tprotocolHardKillTimer = undefined;\n\t\t\t}\n\t\t};\n\t\tfunction startFinalDrain(): void {\n\t\t\tif (childWatchdogIsActive(childWatchdogState)) {\n\t\t\t\tarmWatchdogTail();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (childExited || finalDrainTimer || settled) return;\n\t\t\tfinalDrainTimer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tconst termSent = trySignalChild(child, \"SIGTERM\");\n\t\t\t\tif (!termSent) return;\n\t\t\t\tforcedTerminationSignal = true;\n\t\t\t\tif (!cleanTerminalAssistantStopReceived && !agentSettledReceived && !error && !assistantError) {\n\t\t\t\t\terror = `Subagent process did not exit within ${FINAL_STOP_GRACE_MS}ms after its terminal event. Forcing termination.`;\n\t\t\t\t}\n\t\t\t\tfinalHardKillTimer = setTimeout(() => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tforcedTerminationSignal = trySignalChild(child, \"SIGKILL\") || forcedTerminationSignal;\n\t\t\t\t}, HARD_KILL_MS);\n\t\t\t\tfinalHardKillTimer.unref?.();\n\t\t\t}, FINAL_STOP_GRACE_MS);\n\t\t\tfinalDrainTimer.unref?.();\n\t\t}\n\t\tfunction clearWatchdogTailTimer(): void {\n\t\t\tif (watchdogTailTimer) {\n\t\t\t\tclearTimeout(watchdogTailTimer);\n\t\t\t\twatchdogTailTimer = undefined;\n\t\t\t}\n\t\t}\n\t\tfunction armWatchdogTail(): void {\n\t\t\tif ((!cleanTerminalAssistantStopReceived && !agentSettledReceived) || watchdogTailTimer || settled) return;\n\t\t\twatchdogTailTimer = setTimeout(() => {\n\t\t\t\twatchdogTailTimer = undefined;\n\t\t\t\tupdateChildWatchdogState({\n\t\t\t\t\tphase: \"stale\",\n\t\t\t\t\tseq: (childWatchdogState?.seq ?? 0) + 1,\n\t\t\t\t\tlastUpdate: Date.now(),\n\t\t\t\t\tfollowUpPending: false,\n\t\t\t\t\treason: \"child watchdog tail timeout\",\n\t\t\t\t\ttimedOut: true,\n\t\t\t\t});\n\t\t\t\tstartFinalDrain();\n\t\t\t}, childWatchdogConfig?.watchdogTailTimeoutMs ?? 120_000);\n\t\t\twatchdogTailTimer.unref?.();\n\t\t}\n\t\tchild.on(\"exit\", () => {\n\t\t\tchildExited = true;\n\t\t\tclearDrainTimers();\n\t\t});\n\t\tchild.on(\"close\", (exitCode, signal) => {\n\t\t\tsettled = true;\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"none\" });\n\t\t\t} catch {\n\t\t\t\t// The runner still owns and releases the lease during finalization.\n\t\t\t}\n\t\t\tregisterInterrupt?.(undefined);\n\t\t\tregisterTimeout?.(undefined);\n\t\t\tregisterStop?.(undefined);\n\t\t\tregisterTurnBudgetAbort?.(undefined);\n\t\t\tclearDrainTimers();\n\t\t\tclearStdioGuard();\n\t\t\tstdoutReader.end();\n\t\t\tstderrReader.end();\n\t\t\toutputStream.end();\n\t\t\tconst stderr = stderrTail.text();\n\t\t\tconst finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();\n\t\t\tconst finalError = error ?? assistantError;\n\t\t\tconst forcedDrainAfterFinalSuccess = forcedTerminationSignal && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;\n\t\t\tresolve({\n\t\t\t\tstderr,\n\t\t\t\texitCode: timedOut || stopped ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,\n\t\t\t\tmessages,\n\t\t\t\tusage,\n\t\t\t\tmodel,\n\t\t\t\terror: stopped ? (stopMessage ?? \"Subagent stopped by user.\") : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,\n\t\t\t\tprotocolError,\n\t\t\t\tfinalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? \"Subagent stopped by user.\" : timeoutMessage ?? \"Subagent timed out.\") : finalOutput,\n\t\t\t\tinterrupted,\n\t\t\t\ttimedOut,\n\t\t\t\tstopped,\n\t\t\t\tturnBudget,\n\t\t\t\tturnBudgetExceeded,\n\t\t\t\twrapUpRequested: turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined,\n\t\t\t\tobservedMutationAttempt,\n\t\t\t\twatchdog: childWatchdogState,\n\t\t\t});\n\t\t});\n\n\t\tchild.on(\"error\", (spawnError) => {\n\t\t\tsettled = true;\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"none\" });\n\t\t\t} catch {\n\t\t\t\t// The runner still owns and releases the lease during finalization.\n\t\t\t}\n\t\t\tregisterInterrupt?.(undefined);\n\t\t\tregisterTimeout?.(undefined);\n\t\t\tregisterStop?.(undefined);\n\t\t\tregisterTurnBudgetAbort?.(undefined);\n\t\t\tclearDrainTimers();\n\t\t\tclearStdioGuard();\n\t\t\tstdoutReader.end();\n\t\t\tstderrReader.end();\n\t\t\toutputStream.end();\n\t\t\tconst stderr = stderrTail.text();\n\t\t\tconst finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();\n\t\t\tconst spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);\n\t\t\tresolve({ stderr, exitCode: 1, messages, usage, model, error: stopped ? (stopMessage ?? \"Subagent stopped by user.\") : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? \"Subagent stopped by user.\" : timeoutMessage ?? \"Subagent timed out.\") : finalOutput, timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState });\n\t\t});\n\t});\n}\n\nfunction resolvePiPackageRootFallback(): string {\n\tconst root = resolveInstalledPiPackageRoot();\n\tif (root) return root;\n\tthrow new Error(`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`);\n}\n\nasync function exportSessionHtml(sessionFile: string, outputDir: string, piPackageRoot?: string): Promise<string> {\n\tconst pkgRoot = piPackageRoot ?? resolvePiPackageRootFallback();\n\tconst exportModulePath = path.join(pkgRoot, \"dist\", \"core\", \"export-html\", \"index.js\");\n\tconst moduleUrl = pathToFileURL(exportModulePath).href;\n\tconst mod = await import(moduleUrl);\n\tconst exportFromFile = (mod as { exportFromFile?: (inputPath: string, options?: { outputPath?: string }) => string })\n\t\t.exportFromFile;\n\tif (typeof exportFromFile !== \"function\") {\n\t\tthrow new Error(\"exportFromFile not available\");\n\t}\n\tconst outputPath = path.join(outputDir, `${path.basename(sessionFile, \".jsonl\")}.html`);\n\treturn exportFromFile(sessionFile, { outputPath });\n}\n\nfunction createShareLink(htmlPath: string): { shareUrl: string; gistUrl: string } | { error: string } {\n\ttry {\n\t\tconst auth = spawnSync(\"gh\", [\"auth\", \"status\"], { encoding: \"utf-8\" });\n\t\tif (auth.status !== 0) {\n\t\t\treturn { error: \"GitHub CLI is not logged in. Run 'gh auth login' first.\" };\n\t\t}\n\t} catch {\n\t\treturn { error: \"GitHub CLI (gh) is not installed.\" };\n\t}\n\n\ttry {\n\t\tconst result = spawnSync(\"gh\", [\"gist\", \"create\", htmlPath], { encoding: \"utf-8\" });\n\t\tif (result.status !== 0) {\n\t\t\tconst err = (result.stderr || \"\").trim() || \"Failed to create gist.\";\n\t\t\treturn { error: err };\n\t\t}\n\t\tconst gistUrl = (result.stdout || \"\").trim();\n\t\tconst gistId = gistUrl.split(\"/\").pop();\n\t\tif (!gistId) return { error: \"Failed to parse gist ID.\" };\n\t\tconst shareUrl = `https://shittycodingagent.ai/session/?${gistId}`;\n\t\treturn { shareUrl, gistUrl };\n\t} catch (err) {\n\t\treturn { error: String(err) };\n\t}\n}\n\nfunction formatDuration(ms: number): string {\n\tif (ms < 1000) return `${ms}ms`;\n\tif (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n\tconst minutes = Math.floor(ms / 60000);\n\tconst seconds = Math.floor((ms % 60000) / 1000);\n\treturn `${minutes}m${seconds}s`;\n}\n\nfunction writeRunLog(\n\tlogPath: string,\n\tinput: {\n\t\tid: string;\n\t\tmode: SubagentRunMode;\n\t\tcwd: string;\n\t\tstartedAt: number;\n\t\tendedAt: number;\n\t\tsteps: Array<{\n\t\t\tagent: string;\n\t\t\tstatus: string;\n\t\t\tdurationMs?: number;\n\t\t}>;\n\t\tsummary: string;\n\t\ttruncated: boolean;\n\t\tartifactsDir?: string;\n\t\tsessionFile?: string;\n\t\tshareUrl?: string;\n\t\tshareError?: string;\n\t},\n): void {\n\tconst lines: string[] = [];\n\tlines.push(`# Subagent run ${input.id}`);\n\tlines.push(\"\");\n\tlines.push(`- **Mode:** ${input.mode}`);\n\tlines.push(`- **CWD:** ${input.cwd}`);\n\tlines.push(`- **Started:** ${new Date(input.startedAt).toISOString()}`);\n\tlines.push(`- **Ended:** ${new Date(input.endedAt).toISOString()}`);\n\tlines.push(`- **Duration:** ${formatDuration(input.endedAt - input.startedAt)}`);\n\tif (input.sessionFile) lines.push(`- **Session:** ${input.sessionFile}`);\n\tif (input.shareUrl) lines.push(`- **Share:** ${input.shareUrl}`);\n\tif (input.shareError) lines.push(`- **Share error:** ${input.shareError}`);\n\tif (input.artifactsDir) lines.push(`- **Artifacts:** ${input.artifactsDir}`);\n\tlines.push(\"\");\n\tlines.push(\"## Steps\");\n\tlines.push(\"| Step | Agent | Status | Duration |\");\n\tlines.push(\"| --- | --- | --- | --- |\");\n\tinput.steps.forEach((step, i) => {\n\t\tconst duration = step.durationMs !== undefined ? formatDuration(step.durationMs) : \"-\";\n\t\tlines.push(`| ${i + 1} | ${step.agent} | ${step.status} | ${duration} |`);\n\t});\n\tlines.push(\"\");\n\tlines.push(\"## Summary\");\n\tif (input.truncated) {\n\t\tlines.push(\"_Output truncated_\");\n\t\tlines.push(\"\");\n\t}\n\tlines.push(input.summary.trim() || \"(no output)\");\n\tlines.push(\"\");\n\tfs.writeFileSync(logPath, lines.join(\"\\n\"), \"utf-8\");\n}\n\n/** Context for running a single step */\ninterface SingleStepContext {\n\tpreviousOutput: string;\n\toutputs?: ChainOutputMap;\n\tplaceholder: string;\n\tcwd: string;\n\tsessionEnabled: boolean;\n\tsessionDir?: string;\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\tid: string;\n\tflatIndex: number;\n\tflatStepCount: number;\n\toutputFile: string;\n\tsteerInboxDir?: string;\n\tsteerCapabilityPath?: string;\n\tsteerAckDir?: string;\n\ttranscriptPath?: string;\n\tpiPackageRoot?: string;\n\tpiArgv1?: string;\n\tregisterInterrupt?: (interrupt: (() => void) | undefined) => void;\n\tregisterTimeout?: (interrupt: (() => void) | undefined) => void;\n\tregisterStop?: (stop: (() => void) | undefined) => void;\n\tregisterTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void;\n\ttimeoutSignal?: AbortSignal;\n\tstopSignal?: AbortSignal;\n\ttimeoutMessage?: string;\n\tstopMessage?: string;\n\tturnBudget?: ResolvedTurnBudget;\n\tchildIntercomTarget?: string;\n\torchestratorIntercomTarget?: string;\n\tnestedRoute?: NestedRouteInfo;\n\tonAttemptStart?: (attempt: { model?: string; thinking?: string }) => void;\n\tonChildEvent?: (event: ChildEvent) => void;\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void;\n\tskipAcceptance?: () => boolean;\n}\n\n/** Run a single pi agent step, returning output and metadata */\nasync function runSingleStep(\n\tstep: SubagentStep,\n\tctx: SingleStepContext,\n): Promise<{\n\tagent: string;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\tmodelAttempts?: ModelAttempt[];\n\tartifactPaths?: ArtifactPaths;\n\ttranscriptPath?: string;\n\ttranscriptError?: string;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tsessionFile?: string;\n\tintercomTarget?: string;\n\tcompletionGuardTriggered?: boolean;\n\tstructuredOutput?: unknown;\n\tstructuredOutputPath?: string;\n\tstructuredOutputSchemaPath?: string;\n\tacceptance?: import(\"../../shared/types.ts\").AcceptanceLedger;\n}> {\n\tif (step.importAsyncRoot) {\n\t\tlet importTimedOut = false;\n\t\tlet importStopped = false;\n\t\tctx.registerTimeout?.(() => {\n\t\t\timportTimedOut = true;\n\t\t\tlet pid: number | undefined;\n\t\t\ttry {\n\t\t\t\tpid = readStatus(step.importAsyncRoot!.asyncDir)?.pid;\n\t\t\t} catch {\n\t\t\t\tpid = undefined;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdeliverTimeoutRequest({ asyncDir: step.importAsyncRoot!.asyncDir, pid, source: \"ancestor-timeout\" });\n\t\t\t} catch {\n\t\t\t\t// The parent runner's own timeout result is authoritative for the attached step.\n\t\t\t}\n\t\t});\n\t\tctx.registerStop?.(() => {\n\t\t\timportStopped = true;\n\t\t\tlet pid: number | undefined;\n\t\t\ttry {\n\t\t\t\tpid = readStatus(step.importAsyncRoot!.asyncDir)?.pid;\n\t\t\t} catch {\n\t\t\t\tpid = undefined;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdeliverStopRequest({ asyncDir: step.importAsyncRoot!.asyncDir, pid, source: \"ancestor-stop\" });\n\t\t\t} catch {\n\t\t\t\t// The parent runner's own stopped result is authoritative for the attached step.\n\t\t\t}\n\t\t});\n\t\ttry {\n\t\t\tconst imported = await waitForImportedAsyncRoot(step.importAsyncRoot, {\n\t\t\t\tshouldAbort: () => importTimedOut || importStopped || ctx.timeoutSignal?.aborted === true || ctx.stopSignal?.aborted === true || ctx.skipAcceptance?.() === true,\n\t\t\t\ttimeoutMessage: importStopped || ctx.stopSignal?.aborted === true ? ctx.stopMessage : ctx.timeoutMessage,\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tfs.writeFileSync(ctx.outputFile, imported.output, \"utf-8\");\n\t\t\t} catch {\n\t\t\t\t// Output files are observability only for imported roots.\n\t\t\t}\n\t\t\tconst stopped = importStopped || imported.stopped === true || ctx.stopSignal?.aborted === true;\n\t\t\tconst timedOut = !stopped && (importTimedOut || imported.timedOut === true || ctx.timeoutSignal?.aborted === true || ctx.skipAcceptance?.() === true);\n\t\t\tconst message = stopped ? ctx.stopMessage ?? \"Subagent stopped by user.\" : ctx.timeoutMessage ?? \"Subagent timed out.\";\n\t\t\treturn {\n\t\t\t\tagent: imported.agent,\n\t\t\t\toutput: timedOut || stopped ? message : imported.output,\n\t\t\t\texitCode: timedOut || stopped ? 1 : imported.exitCode,\n\t\t\t\terror: timedOut || stopped ? message : imported.error,\n\t\t\t\ttimedOut: timedOut ? true : undefined,\n\t\t\t\tstopped: stopped ? true : undefined,\n\t\t\t\tsessionFile: imported.sessionFile,\n\t\t\t\tintercomTarget: imported.intercomTarget,\n\t\t\t\tmodel: imported.model,\n\t\t\t\tattemptedModels: imported.attemptedModels,\n\t\t\t\tmodelAttempts: imported.modelAttempts,\n\t\t\t\ttotalCost: imported.totalCost,\n\t\t\t\tstructuredOutput: timedOut || stopped ? undefined : imported.structuredOutput,\n\t\t\t\tstructuredOutputPath: timedOut || stopped ? undefined : imported.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: timedOut || stopped ? undefined : imported.structuredOutputSchemaPath,\n\t\t\t\tacceptance: timedOut || stopped ? undefined : imported.acceptance,\n\t\t\t};\n\t\t} finally {\n\t\t\tctx.registerTimeout?.(undefined);\n\t\t\tctx.registerStop?.(undefined);\n\t\t}\n\t}\n\n\tconst effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema\n\t\t? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), \"structured-output\"))\n\t\t: undefined);\n\tconst placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\");\n\tlet task = step.task.replace(placeholderRegex, () => ctx.previousOutput);\n\tif (ctx.outputs) task = resolveOutputReferences(task, ctx.outputs);\n\tconst taskForCompletionGuard = task;\n\tif (step.effectiveAcceptance) {\n\t\tconst acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance);\n\t\tif (acceptancePrompt) task = `${task}\\n${acceptancePrompt}`;\n\t}\n\tconst sessionEnabled = Boolean(step.sessionFile) || ctx.sessionEnabled;\n\tconst sessionDir = step.sessionFile ? undefined : ctx.sessionDir;\n\n\tlet artifactPaths: ArtifactPaths | undefined;\n\tlet transcriptWriter: ChildTranscriptWriter | undefined;\n\tif (ctx.artifactsDir && ctx.artifactConfig?.enabled !== false) {\n\t\tconst index = ctx.flatStepCount > 1 ? ctx.flatIndex : undefined;\n\t\tartifactPaths = getArtifactPaths(ctx.artifactsDir, ctx.id, step.agent, index);\n\t\tfs.mkdirSync(ctx.artifactsDir, { recursive: true });\n\t\tif (ctx.artifactConfig?.includeInput !== false) {\n\t\t\tfs.writeFileSync(artifactPaths.inputPath, `# Task for ${step.agent}\\n\\n${task}`, \"utf-8\");\n\t\t}\n\t\tif (ctx.artifactConfig?.includeTranscript !== false) {\n\t\t\ttranscriptWriter = createChildTranscriptWriter({\n\t\t\t\ttranscriptPath: artifactPaths.transcriptPath,\n\t\t\t\tsource: \"async\",\n\t\t\t\trunId: ctx.id,\n\t\t\t\tagent: step.agent,\n\t\t\t\tchildIndex: ctx.flatIndex,\n\t\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\t});\n\t\t}\n\t}\n\ttranscriptWriter?.writeInitialUserMessage(task);\n\n\tconst candidates = step.modelCandidates && step.modelCandidates.length > 0\n\t\t? step.modelCandidates\n\t\t: step.model\n\t\t\t? [step.model]\n\t\t\t: [undefined];\n\tconst attemptedModels: string[] = [];\n\tconst modelAttempts: ModelAttempt[] = [];\n\tconst attemptNotes: string[] = [];\n\tconst eventsPath = path.join(path.dirname(ctx.outputFile), \"events.jsonl\");\n\tlet finalResult: RunPiStreamingResult | undefined;\n\tlet finalOutputSnapshot: SingleOutputSnapshot | undefined;\n\tlet completionGuardTriggeredFinal = false;\n\tlet turnBudget = ctx.turnBudget ? initialTurnBudgetState(ctx.turnBudget) : undefined;\n\tlet toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;\n\tlet toolBudgetBlocked = false;\n\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tif (ctx.timeoutSignal?.aborted || ctx.skipAcceptance?.()) break;\n\t\tconst candidate = candidates[index];\n\t\tctx.onAttemptStart?.({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });\n\t\tconst outputSnapshot = captureSingleOutputSnapshot(step.outputPath);\n\t\tif (effectiveStructuredOutput) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(effectiveStructuredOutput.outputPath)) fs.unlinkSync(effectiveStructuredOutput.outputPath);\n\t\t\t} catch {\n\t\t\t\t// Missing/stale structured-output files are handled after the child exits.\n\t\t\t}\n\t\t}\n\t\tconst watchdogConfig = resolveWatchdogConfig(step.cwd ?? ctx.cwd);\n\t\tconst childWatchdog = watchdogConfig.ok\n\t\t\t? resolveChildWatchdogConfig({\n\t\t\t\tconfig: watchdogConfig.config,\n\t\t\t\tagent: step.agent,\n\t\t\t\trunId: ctx.id,\n\t\t\t\tchildIndex: ctx.flatIndex,\n\t\t\t})\n\t\t\t: undefined;\n\t\tconst parentPermissionMode = step.parentPermissionMode ?? snapshotParentPermissionMode(step.parentSessionId);\n\t\tconst { args, env, tempDir, toolDiagnosticPath } = buildPiArgs({\n\t\t\tparentSessionId: step.parentSessionId,\n\t\t\tbaseArgs: [\"--mode\", \"json\", \"-p\"],\n\t\t\ttask,\n\t\t\tsessionEnabled,\n\t\t\tsessionDir,\n\t\t\tsessionFile: step.sessionFile,\n\t\t\tmodel: candidate,\n\t\t\tinheritProjectContext: step.inheritProjectContext,\n\t\t\tinheritSkills: step.inheritSkills,\n\t\t\trequireReadTool: Boolean(step.skills?.length),\n\t\t\ttools: filterToolsForInheritedChild(step.tools, parentPermissionMode),\n\t\t\textensions: step.extensions,\n\t\t\tsubagentOnlyExtensions: step.subagentOnlyExtensions,\n\t\t\tsystemPrompt: appendTurnBudgetSystemPrompt(step.systemPrompt ?? \"\", ctx.turnBudget),\n\t\t\tsystemPromptMode: step.systemPromptMode,\n\t\t\tmcpDirectTools: step.mcpDirectTools,\n\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\tpromptFileStem: step.agent,\n\t\t\tintercomSessionName: ctx.childIntercomTarget,\n\t\t\torchestratorIntercomTarget: ctx.orchestratorIntercomTarget,\n\t\t\trunId: ctx.id,\n\t\t\tchildAgentName: step.agent,\n\t\t\tchildIndex: ctx.flatIndex,\n\t\t\tparentEventSink: ctx.nestedRoute?.eventSink,\n\t\t\tparentControlInbox: ctx.nestedRoute?.controlInbox,\n\t\t\tparentRootRunId: ctx.nestedRoute?.rootRunId,\n\t\t\tparentCapabilityToken: ctx.nestedRoute?.capabilityToken,\n\t\t\tsteerInboxDir: ctx.steerInboxDir,\n\t\t\tsteerCapabilityPath: ctx.steerCapabilityPath,\n\t\t\tsteerAckDir: ctx.steerAckDir,\n\t\t\tstructuredOutput: effectiveStructuredOutput,\n\t\t\ttoolBudget: step.toolBudget,\n\t\t\tchildWatchdog,\n\t\t\twaitToolEnabled: step.waitToolEnabled,\n\t\t\tparentPermissionMode,\n\t\t});\n\t\tconst run = await runPiStreaming(\n\t\t\targs,\n\t\t\tstep.cwd ?? ctx.cwd,\n\t\t\tctx.outputFile,\n\t\t\tenv,\n\t\t\tctx.piPackageRoot,\n\t\t\tctx.piArgv1,\n\t\t\tstep.maxSubagentDepth,\n\t\t\t{ eventsPath, runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },\n\t\t\tctx.registerInterrupt,\n\t\t\tctx.onChildEvent,\n\t\t\ttranscriptWriter,\n\t\t\tctx.registerTimeout,\n\t\t\tctx.timeoutMessage,\n\t\t\tctx.registerStop,\n\t\t\tctx.stopMessage,\n\t\t\tctx.registerTurnBudgetAbort,\n\t\t\tctx.onWriterProcess,\n\t\t);\n\t\tif (run.turnBudget) turnBudget = run.turnBudget;\n\t\telse if (ctx.turnBudget) {\n\t\t\tconst assistantMessages = run.messages.filter((message) => message.role === \"assistant\");\n\t\t\tconst turnCount = assistantMessages.length;\n\t\t\tconst lastAssistantMessage = assistantMessages.at(-1);\n\t\t\tif (turnCount > 0 && turnCount < ctx.turnBudget.maxTurns) {\n\t\t\t\tturnBudget = { ...ctx.turnBudget, outcome: \"within-budget\", turnCount };\n\t\t\t} else if (turnCount >= ctx.turnBudget.maxTurns) {\n\t\t\t\tturnBudget = turnBudgetState(\n\t\t\t\t\tctx.turnBudget,\n\t\t\t\t\tturnCount,\n\t\t\t\t\tshouldAbortForTurnBudget(ctx.turnBudget, turnCount, lastAssistantMessage ? isTerminalAssistantStop(lastAssistantMessage) : false),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst toolAvailabilityError = run.exitCode === 0 && !run.error\n\t\t\t? readChildToolDiagnosticError(toolDiagnosticPath)\n\t\t\t: undefined;\n\t\tcleanupTempDir(tempDir);\n\n\t\tconst hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError ? detectSubagentError(run.messages) : null;\n\t\tconst missingStructuredOutput = effectiveStructuredOutput\n\t\t\t? !fs.existsSync(effectiveStructuredOutput.outputPath)\n\t\t\t: false;\n\t\tconst emptyOutputError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !run.finalOutput.trim() && (!effectiveStructuredOutput || missingStructuredOutput)\n\t\t\t? \"Subagent produced no output (possible model cold-start or empty response).\"\n\t\t\t: undefined;\n\t\tlet structuredOutput: unknown;\n\t\tlet structuredError: string | undefined;\n\t\tif (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !emptyOutputError) {\n\t\t\tconst structured = readStructuredOutput({\n\t\t\t\tschema: effectiveStructuredOutput.schema,\n\t\t\t\tschemaPath: effectiveStructuredOutput.schemaPath,\n\t\t\t\toutputPath: effectiveStructuredOutput.outputPath,\n\t\t\t});\n\t\t\tif (structured.error) structuredError = structured.error;\n\t\t\telse structuredOutput = structured.value;\n\t\t}\n\t\tconst completionGuard = run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !emptyOutputError && step.completionGuard !== false\n\t\t\t? evaluateCompletionMutationGuard({\n\t\t\t\tagent: step.agent,\n\t\t\t\ttask: taskForCompletionGuard,\n\t\t\t\tmessages: run.messages,\n\t\t\t\ttools: step.tools,\n\t\t\t\tmcpDirectTools: step.mcpDirectTools,\n\t\t\t})\n\t\t\t: undefined;\n\t\tconst completionGuardTriggered = completionGuard?.triggered === true && !run.observedMutationAttempt;\n\t\tconst completionGuardError = completionGuardTriggered\n\t\t\t? \"Subagent completed without making edits for an implementation task.\\nIt appears to have returned planning or scratchpad output instead of applying changes.\"\n\t\t\t: undefined;\n\t\tconst effectiveExitCode = toolAvailabilityError || completionGuardTriggered || structuredError\n\t\t\t? 1\n\t\t\t: hiddenError?.hasError\n\t\t\t\t? (hiddenError.exitCode ?? 1)\n\t\t\t\t: emptyOutputError\n\t\t\t\t\t? 1\n\t\t\t\t\t: run.error && run.exitCode === 0\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: run.exitCode;\n\t\tconst error = toolAvailabilityError\n\t\t\t?? completionGuardError\n\t\t\t?? structuredError\n\t\t\t?? (hiddenError?.hasError\n\t\t\t\t? hiddenError.details\n\t\t\t\t\t? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`\n\t\t\t\t\t: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`\n\t\t\t\t: emptyOutputError ?? (run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined)));\n\t\tconst attempt: ModelAttempt = {\n\t\t\tmodel: candidate ?? run.model ?? step.model ?? \"default\",\n\t\t\tsuccess: effectiveExitCode === 0 && !error,\n\t\t\texitCode: effectiveExitCode,\n\t\t\terror,\n\t\t\tusage: run.usage,\n\t\t};\n\t\tmodelAttempts.push(attempt);\n\t\tif (candidate) attemptedModels.push(candidate);\n\t\tcompletionGuardTriggeredFinal = completionGuardTriggered;\n\t\tfinalOutputSnapshot = outputSnapshot;\n\t\tif (step.toolBudget) {\n\t\t\tconst toolMessages = run.messages.filter((message) => message.role === \"toolResult\");\n\t\t\tconst blockedMessage = toolMessages.find((message) => extractTextFromContent(message.content).includes(\"Tool budget hard limit reached\"));\n\t\t\ttoolBudgetBlocked = Boolean(blockedMessage);\n\t\t\ttoolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);\n\t\t}\n\t\tfinalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput } as RunPiStreamingResult & { structuredOutput?: unknown };\n\t\tif (run.turnBudgetExceeded) break;\n\t\tif (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;\n\t\tif (attempt.success || completionGuardTriggered) break;\n\t\tif (!isRetryableModelFailure(error) || index === candidates.length - 1) break;\n\t\tattemptNotes.push(formatModelAttemptNote(attempt, candidates[index + 1]));\n\t}\n\n\tconst rawOutput = finalResult?.finalOutput ?? \"\";\n\tconst outputForPersistence = stripAcceptanceReport(rawOutput);\n\tconst resolvedOutput = step.outputPath && finalResult?.exitCode === 0\n\t\t? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot)\n\t\t: { fullOutput: outputForPersistence };\n\tconst output = stripAcceptanceReport(resolvedOutput.fullOutput);\n\tconst outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;\n\tlet outputForSummary = output;\n\tif (attemptNotes.length > 0) {\n\t\toutputForSummary = `${attemptNotes.join(\"\\n\")}\\n\\n${outputForSummary}`.trim();\n\t}\n\tif (finalResult?.stopped && !outputForSummary.trim()) {\n\t\toutputForSummary = ctx.stopMessage ?? \"Subagent stopped by user.\";\n\t} else if (!finalResult?.timedOut && !finalResult?.stopped && finalResult?.turnBudgetExceeded && turnBudget) {\n\t\toutputForSummary = formatTurnBudgetOutput(turnBudgetExceededMessage(turnBudget, turnBudget.turnCount), outputForSummary);\n\t} else if (!finalResult?.timedOut && !finalResult?.stopped && turnBudget?.outcome === \"wrap-up-requested\") {\n\t\tconst note = turnBudgetSoftNote(turnBudget, turnBudget.wrapUpRequestedAtTurn ?? turnBudget.turnCount);\n\t\toutputForSummary = outputForSummary.trim() ? `${note}\\n\\n${outputForSummary}` : note;\n\t}\n\tconst outputForAcceptance = rawOutput;\n\tconst childWrittenOutput = step.outputPath\n\t\t? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)\n\t\t: undefined;\n\tconst finalizedOutput = finalizeSingleOutput({\n\t\tfullOutput: outputForSummary,\n\t\toutputPath: step.outputPath,\n\t\toutputMode: step.outputMode,\n\t\texitCode: finalResult?.exitCode ?? 1,\n\t\tsavedPath: resolvedOutput.savedPath,\n\t\toutputReference,\n\t\tsaveError: resolvedOutput.saveError,\n\t});\n\toutputForSummary = finalizedOutput.displayOutput;\n\tconst acceptance = step.effectiveAcceptance && !finalResult?.stopped && !finalResult?.turnBudgetExceeded && !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted && !ctx.skipAcceptance?.()\n\t\t? await evaluateAcceptance({\n\t\t\tacceptance: step.effectiveAcceptance,\n\t\t\toutput: outputForAcceptance,\n\t\t\tfileOutput: childWrittenOutput !== undefined && step.outputPath\n\t\t\t\t? { content: childWrittenOutput, path: step.outputPath, authoritative: step.outputMode === \"file-only\" }\n\t\t\t\t: undefined,\n\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\tsignal: combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]),\n\t\t\tabortMessage: ctx.stopSignal?.aborted ? ctx.stopMessage ?? \"Subagent stopped by user.\" : ctx.timeoutMessage ?? \"Subagent timed out.\",\n\t\t})\n\t\t: undefined;\n\tconst stoppedAfterAcceptance = finalResult?.stopped === true || ctx.stopSignal?.aborted === true;\n\tconst timedOutAfterAcceptance = !stoppedAfterAcceptance && (finalResult?.timedOut === true || ctx.timeoutSignal?.aborted === true);\n\tconst turnBudgetExceeded = finalResult?.turnBudgetExceeded === true;\n\tconst effectiveAcceptance = step.effectiveAcceptance\n\t\t? stoppedAfterAcceptance\n\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"stopped\", message: \"Acceptance was not evaluated because the subagent was stopped.\" })\n\t\t\t: timedOutAfterAcceptance\n\t\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"timeout\", message: \"Acceptance was not evaluated because the subagent timed out.\" })\n\t\t\t\t: turnBudgetExceeded\n\t\t\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"turn-budget\", message: \"Acceptance was not evaluated because the subagent exceeded its turn budget.\" })\n\t\t\t\t\t: acceptance\n\t\t: undefined;\n\tconst acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;\n\tconst acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !turnBudgetExceeded;\n\tconst effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;\n\tconst effectiveFinalError = stoppedAfterAcceptance\n\t\t? ctx.stopMessage ?? \"Subagent stopped by user.\"\n\t\t: timedOutAfterAcceptance\n\t\t\t? ctx.timeoutMessage ?? \"Subagent timed out.\"\n\t\t\t: turnBudgetExceeded\n\t\t\t\t? finalResult?.error ?? (turnBudget ? turnBudgetExceededMessage(turnBudget, turnBudget.turnCount) : \"Subagent exceeded turn budget.\")\n\t\t\t\t: acceptanceCanFailRun\n\t\t\t\t\t? (finalResult?.error ? `${finalResult.error}\\n${acceptanceFailure}` : acceptanceFailure)\n\t\t\t\t\t: finalResult?.error;\n\n\tif (artifactPaths && ctx.artifactConfig?.enabled !== false) {\n\t\tif (ctx.artifactConfig?.includeOutput !== false) {\n\t\t\tfs.writeFileSync(artifactPaths.outputPath, output, \"utf-8\");\n\t\t}\n\t\tif (ctx.artifactConfig?.includeMetadata !== false) {\n\t\t\tfs.writeFileSync(\n\t\t\t\tartifactPaths.metadataPath,\n\t\t\t\tJSON.stringify({\n\t\t\t\t\trunId: ctx.id,\n\t\t\t\t\tagent: step.agent,\n\t\t\t\t\ttask,\n\t\t\t\t\texitCode: effectiveFinalExitCode,\n\t\t\t\t\tmodel: finalResult?.model,\n\t\t\t\t\tattemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,\n\t\t\t\t\tmodelAttempts,\n\t\t\t\t\terror: effectiveFinalError,\n\t\t\t\t\tacceptance: effectiveAcceptance,\n\t\t\t\t\t...(transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {}),\n\t\t\t\t\ttranscriptError: transcriptWriter?.getError(),\n\t\t\t\t\tskills: step.skills,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t}, null, 2),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tagent: step.agent,\n\t\toutput: outputForSummary,\n\t\texitCode: effectiveFinalExitCode,\n\t\terror: effectiveFinalError,\n\t\tprotocolError: finalResult?.protocolError,\n\t\tsessionFile: step.sessionFile,\n\t\tintercomTarget: ctx.childIntercomTarget,\n\t\tmodel: finalResult?.model,\n\t\tattemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,\n\t\tmodelAttempts,\n\t\ttotalCost: costSummaryFromAttempts(modelAttempts),\n\t\tartifactPaths,\n\t\ttranscriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,\n\t\ttranscriptError: transcriptWriter?.getError(),\n\t\tinterrupted: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,\n\t\ttimedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,\n\t\tstopped: stoppedAfterAcceptance ? true : finalResult?.stopped,\n\t\tturnBudget,\n\t\tturnBudgetExceeded: turnBudgetExceeded || undefined,\n\t\twrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined,\n\t\ttoolBudget,\n\t\ttoolBudgetBlocked: toolBudgetBlocked || undefined,\n\t\tcompletionGuardTriggered: completionGuardTriggeredFinal,\n\t\tstructuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput,\n\t\tstructuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.outputPath,\n\t\tstructuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.schemaPath,\n\t\tacceptance: effectiveAcceptance,\n\t\twatchdog: finalResult?.watchdog,\n\t};\n}\n\ntype RunnerStatusStep = NonNullable<AsyncStatus[\"steps\"]>[number] & {\n\texitCode?: number | null;\n};\n\ntype RunnerStatusPayload = Omit<AsyncStatus, \"steps\" | \"parallelGroups\" | \"pid\" | \"cwd\" | \"currentStep\" | \"chainStepCount\" | \"lastUpdate\"> & {\n\tpid: number;\n\tcwd: string;\n\tcurrentStep: number;\n\tchainStepCount: number;\n\tparallelGroups: AsyncParallelGroupStatus[];\n\tsteps: RunnerStatusStep[];\n\tlastUpdate: number;\n\tartifactsDir?: string;\n\tshareUrl?: string;\n\tgistUrl?: string;\n\tshareError?: string;\n\terror?: string;\n};\n\nfunction markParallelGroupSetupFailure(input: {\n\tstatusPayload: RunnerStatusPayload;\n\tresults: StepResult[];\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>;\n\tgroupStartFlatIndex: number;\n\tsetupError: string;\n\tfailedAt: number;\n\tstatusPath: string;\n\teventsPath: string;\n\tasyncDir: string;\n\trunId: string;\n\tstepIndex: number;\n}): void {\n\tfor (let taskIndex = 0; taskIndex < input.group.parallel.length; taskIndex++) {\n\t\tconst flatTaskIndex = input.groupStartFlatIndex + taskIndex;\n\t\tinput.statusPayload.steps[flatTaskIndex].status = \"failed\";\n\t\tinput.statusPayload.steps[flatTaskIndex].startedAt = input.failedAt;\n\t\tinput.statusPayload.steps[flatTaskIndex].endedAt = input.failedAt;\n\t\tinput.statusPayload.steps[flatTaskIndex].durationMs = 0;\n\t\tinput.statusPayload.steps[flatTaskIndex].exitCode = 1;\n\t\tinput.results.push({ agent: input.group.parallel[taskIndex].agent, output: input.setupError, success: false, exitCode: 1, sessionFile: input.group.parallel[taskIndex].sessionFile });\n\t}\n\tinput.statusPayload.currentStep = input.groupStartFlatIndex;\n\tinput.statusPayload.lastUpdate = input.failedAt;\n\tinput.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);\n\twriteAtomicJson(input.statusPath, input.statusPayload);\n\tappendJsonl(input.eventsPath, JSON.stringify({\n\t\ttype: \"subagent.parallel.completed\",\n\t\tts: input.failedAt,\n\t\trunId: input.runId,\n\t\tstepIndex: input.stepIndex,\n\t\tsuccess: false,\n\t}));\n}\n\nfunction markParallelGroupRunning(input: {\n\tstatusPayload: RunnerStatusPayload;\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>;\n\tgroupStartFlatIndex: number;\n\tgroupStartTime: number;\n\tstatusPath: string;\n\teventsPath: string;\n\tasyncDir: string;\n\trunId: string;\n\tstepIndex: number;\n}): void {\n\tfor (let taskIndex = 0; taskIndex < input.group.parallel.length; taskIndex++) {\n\t\tconst flatTaskIndex = input.groupStartFlatIndex + taskIndex;\n\t\tinput.statusPayload.steps[flatTaskIndex].status = \"pending\";\n\t\tinput.statusPayload.steps[flatTaskIndex].startedAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].endedAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].durationMs = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].lastActivityAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].activityState = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].error = undefined;\n\t}\n\tinput.statusPayload.currentStep = input.groupStartFlatIndex;\n\tinput.statusPayload.activityState = undefined;\n\tinput.statusPayload.lastActivityAt = input.groupStartTime;\n\tinput.statusPayload.lastUpdate = input.groupStartTime;\n\tinput.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);\n\twriteAtomicJson(input.statusPath, input.statusPayload);\n\tappendJsonl(input.eventsPath, JSON.stringify({\n\t\ttype: \"subagent.parallel.started\",\n\t\tts: input.groupStartTime,\n\t\trunId: input.runId,\n\t\tstepIndex: input.stepIndex,\n\t\tagents: input.group.parallel.map((task) => task.agent),\n\t\tcount: input.group.parallel.length,\n\t}));\n}\n\nfunction prepareParallelTaskRun(\n\ttask: SubagentStep,\n\tcwd: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\ttaskIndex: number,\n): { taskForRun: SubagentStep; taskCwd: string } {\n\tif (!worktreeSetup) return { taskForRun: task, taskCwd: cwd };\n\treturn {\n\t\ttaskForRun: { ...task, cwd: undefined },\n\t\ttaskCwd: worktreeSetup.worktrees[taskIndex]!.agentCwd,\n\t};\n}\n\nfunction appendParallelWorktreeSummary(\n\tpreviousOutput: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tasyncDir: string,\n\tstepIndex: number,\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>,\n): string {\n\tif (!worktreeSetup) return previousOutput;\n\tconst diffsDir = path.join(asyncDir, \"worktree-diffs\", `step-${stepIndex}`);\n\tconst diffs = diffWorktrees(worktreeSetup, group.parallel.map((task) => task.agent), diffsDir);\n\tconst diffSummary = formatWorktreeDiffSummary(diffs);\n\tif (!diffSummary) return previousOutput;\n\treturn `${previousOutput}\\n\\n${diffSummary}`;\n}\n\nfunction ensureParallelProgressFile(cwd: string, group: Extract<RunnerStep, { parallel: SubagentStep[] }>): void {\n\tconst progressPath = path.join(cwd, \"progress.md\");\n\tif (!group.parallel.some((task) => task.task.includes(`Update progress at: ${progressPath}`))) return;\n\twriteInitialProgressFile(cwd);\n}\n\nfunction resolveAsyncStepTranscriptPath(input: {\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\trunId: string;\n\tagent: string;\n\tflatIndex: number;\n\tflatStepCount: number;\n}): string | undefined {\n\tif (!input.artifactsDir || input.artifactConfig?.enabled === false || input.artifactConfig?.includeTranscript === false) return undefined;\n\treturn getArtifactPaths(\n\t\tinput.artifactsDir,\n\t\tinput.runId,\n\t\tinput.agent,\n\t\tinput.flatStepCount > 1 ? input.flatIndex : undefined,\n\t).transcriptPath;\n}\n\ntype SingleStepResult = Awaited<ReturnType<typeof runSingleStep>>;\n\nfunction combinedAbortSignal(signals: Array<AbortSignal | undefined>): AbortSignal | undefined {\n\tconst activeSignals = signals.filter((signal): signal is AbortSignal => Boolean(signal));\n\tif (activeSignals.length === 0) return undefined;\n\tif (activeSignals.length === 1) return activeSignals[0];\n\tconst controller = new AbortController();\n\tconst abort = (): void => controller.abort();\n\tfor (const signal of activeSignals) {\n\t\tif (signal.aborted) {\n\t\t\tabort();\n\t\t\tbreak;\n\t\t}\n\t\tsignal.addEventListener(\"abort\", abort, { once: true });\n\t}\n\treturn controller.signal;\n}\n\nasync function runSubagent(\n\tconfig: SubagentRunConfig,\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void,\n): Promise<void> {\n\tconst { id, steps, resultPath, cwd, placeholder, taskIndex, totalTasks, maxOutput, artifactsDir, artifactConfig } =\n\t\tconfig;\n\tconst globalSemaphore = new Semaphore(config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);\n\tlet previousOutput = \"\";\n\tconst outputs: ChainOutputMap = {};\n\tconst results: StepResult[] = [];\n\tconst overallStartTime = Date.now();\n\tconst shareEnabled = config.share === true;\n\tconst asyncDir = config.asyncDir;\n\tconst statusPath = path.join(asyncDir, \"status.json\");\n\tconst eventsPath = path.join(asyncDir, \"events.jsonl\");\n\tconst logPath = path.join(asyncDir, `subagent-log-${id}.md`);\n\tconst controlConfig = config.controlConfig ?? DEFAULT_CONTROL_CONFIG;\n\tconst activeChildInterrupts = new Map<number, () => void>();\n\tconst activeChildTimeouts = new Map<number, () => void>();\n\tconst activeChildStops = new Map<number, () => void>();\n\tconst activeChildTurnBudgetAborts = new Map<number, (message: string, state?: TurnBudgetState) => void>();\n\tconst pendingStepSteers: SteerRequest[] = [];\n\tconst steeringCapabilities = new Map<number, SteerCapability>();\n\tlet interrupted = false;\n\tlet currentActivityState: ActivityState | undefined;\n\tlet activityTimer: NodeJS.Timeout | undefined;\n\tlet timeoutTimer: NodeJS.Timeout | undefined;\n\tlet timedOut = false;\n\tlet stopped = false;\n\tlet turnBudgetExceeded = false;\n\tconst timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;\n\tconst stopMessage = \"Subagent stopped by user.\";\n\tconst timeoutAbortController = new AbortController();\n\tconst stopAbortController = new AbortController();\n\tlet previousCumulativeTokens: TokenUsage = { input: 0, output: 0, total: 0 };\n\tlet latestSessionFile: string | undefined;\n\n\tconst flatSteps = flattenSteps(steps);\n\tconst initialFlatStepCount = flatSteps.length;\n\tconst parallelGroups: Array<{ start: number; count: number; stepIndex: number }> = [];\n\tconst initialStatusSteps: RunnerStatusStep[] = [];\n\tlet flatStepCount = 0;\n\tfor (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {\n\t\tconst step = steps[stepIndex]!;\n\t\tif (isParallelGroup(step)) {\n\t\t\tparallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tconst taskFlatIndex = flatStepCount;\n\t\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });\n\t\t\t\tinitialStatusSteps.push({\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\tphase: task.phase,\n\t\t\t\t\tlabel: task.label,\n\t\t\t\t\toutputName: task.outputName,\n\t\t\t\t\tstructured: task.structured,\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t...(task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {}),\n\t\t\t\t\t...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),\n\t\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\t\tskills: task.skills,\n\t\t\t\t\tmodel: task.model,\n\t\t\t\t\tthinking: task.thinking,\n\t\t\t\t\tattemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,\n\t\t\t\t\trecentTools: [],\n\t\t\t\t\trecentOutput: [],\n\t\t\t\t});\n\t\t\t\tflatStepCount++;\n\t\t\t}\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tparallelGroups.push({ start: flatStepCount, count: 1, stepIndex });\n\t\t\tinitialStatusSteps.push({\n\t\t\t\tagent: `expand:${step.parallel.agent}`,\n\t\t\t\tphase: step.phase ?? step.parallel.phase,\n\t\t\t\tlabel: step.label ?? step.parallel.label ?? `Dynamic fanout (${step.collect.as})`,\n\t\t\t\toutputName: step.collect.as,\n\t\t\t\tstructured: Boolean(step.collect.outputSchema),\n\t\t\t\tstatus: \"pending\",\n\t\t\t\t...(step.parallel.toolBudget ? { toolBudget: initialToolBudgetState(step.parallel.toolBudget) } : {}),\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t});\n\t\t\tflatStepCount++;\n\t\t} else {\n\t\t\tconst stepFlatIndex = flatStepCount;\n\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });\n\t\t\tinitialStatusSteps.push({\n\t\t\t\tagent: step.agent,\n\t\t\t\tphase: step.phase,\n\t\t\t\tlabel: step.label,\n\t\t\t\toutputName: step.outputName,\n\t\t\t\tstructured: step.structured,\n\t\t\t\tstatus: \"pending\",\n\t\t\t\t...(step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {}),\n\t\t\t\t...(step.sessionFile ? { sessionFile: step.sessionFile } : {}),\n\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\tskills: step.skills,\n\t\t\t\tmodel: step.model,\n\t\t\t\tthinking: step.thinking,\n\t\t\t\tattemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t});\n\t\t\tflatStepCount++;\n\t\t}\n\t}\n\tconst sessionEnabled = Boolean(config.sessionDir)\n\t\t|| shareEnabled\n\t\t|| flatSteps.some((step) => Boolean(step.sessionFile));\n\tconst statusPayload: RunnerStatusPayload = {\n\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\trunId: id,\n\t\t...(config.sessionId ? { sessionId: config.sessionId } : {}),\n\t\tmode: config.resultMode ?? (flatSteps.length > 1 ? \"chain\" : \"single\"),\n\t\t...(config.nestedRoute ? { isNested: true } : {}),\n\t\tstate: \"running\",\n\t\tsteering: createSteeringStatus(),\n\t\tlastActivityAt: overallStartTime,\n\t\tstartedAt: overallStartTime,\n\t\tlastUpdate: overallStartTime,\n\t\t...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),\n\t\t...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),\n\t\t...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),\n\t\t...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),\n\t\tpid: process.pid,\n\t\tcwd,\n\t\tcurrentStep: 0,\n\t\tchainStepCount: steps.length,\n\t\tparallelGroups,\n\t\tworkflowGraph: config.workflowGraph,\n\t\tsteps: initialStatusSteps,\n\t\tartifactsDir,\n\t\tsessionDir: config.sessionDir,\n\t\toutputFile: path.join(asyncDir, \"output-0.log\"),\n\t};\n\n\tfs.mkdirSync(asyncDir, { recursive: true });\n\twriteAtomicJson(statusPath, statusPayload);\n\tconst emitNestedSelfEvent = (type: \"subagent.nested.updated\" | \"subagent.nested.completed\"): void => {\n\t\tif (!config.nestedRoute || !config.nestedSelf) return;\n\t\ttry {\n\t\t\twriteNestedEvent(config.nestedRoute, {\n\t\t\t\ttype,\n\t\t\t\tts: Date.now(),\n\t\t\t\tparentRunId: config.nestedSelf.parentRunId,\n\t\t\t\tparentStepIndex: config.nestedSelf.parentStepIndex,\n\t\t\t\tchild: nestedSummaryFromAsyncStatus(statusPayload, asyncDir, {\n\t\t\t\t\tid,\n\t\t\t\t\tparentRunId: config.nestedSelf.parentRunId,\n\t\t\t\t\tparentStepIndex: config.nestedSelf.parentStepIndex,\n\t\t\t\t\tdepth: config.nestedSelf.depth,\n\t\t\t\t\tpath: config.nestedSelf.path,\n\t\t\t\t\tmode: statusPayload.mode,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to emit nested async status event:\", error);\n\t\t}\n\t};\n\tconst refreshWorkflowGraph = (): void => {\n\t\tif (!config.workflowGraph) return;\n\t\tconst graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);\n\t\tconst normalize = (status: RunnerStatusStep[\"status\"]): \"pending\" | \"running\" | \"completed\" | \"failed\" | \"paused\" | \"stopped\" | \"detached\" => {\n\t\t\tif (status === \"complete\" || status === \"completed\") return \"completed\";\n\t\t\tif (status === \"running\" || status === \"failed\" || status === \"paused\" || status === \"stopped\" || status === \"pending\") return status;\n\t\t\treturn \"pending\";\n\t\t};\n\t\tconst updateNode = (node: NonNullable<typeof graph.nodes>[number]): void => {\n\t\t\tif (node.flatIndex !== undefined) {\n\t\t\t\tconst step = statusPayload.steps[node.flatIndex];\n\t\t\t\tif (step) {\n\t\t\t\t\tnode.status = normalize(step.status);\n\t\t\t\t\tnode.error = step.error;\n\t\t\t\t\tnode.acceptanceStatus = step.acceptance?.status;\n\t\t\t\t}\n\t\t\t\tif (statusPayload.currentStep === node.flatIndex) graph.currentNodeId = node.id;\n\t\t\t}\n\t\t\tfor (const child of node.children ?? []) updateNode(child);\n\t\t\tif (node.children?.length) {\n\t\t\t\tif (node.children.every((child) => child.status === \"completed\")) node.status = \"completed\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"running\")) node.status = \"running\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"stopped\")) node.status = \"stopped\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"failed\")) node.status = \"failed\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"paused\")) node.status = \"paused\";\n\t\t\t}\n\t\t\tif (node.error && node.status !== \"stopped\") node.status = \"failed\";\n\t\t};\n\t\tfor (const node of graph.nodes) updateNode(node);\n\t\tstatusPayload.workflowGraph = graph;\n\t};\n\tconst writeStatusPayload = (): void => {\n\t\trefreshWorkflowGraph();\n\t\twriteAtomicJson(statusPath, statusPayload);\n\t\temitNestedSelfEvent(statusPayload.state === \"running\" || statusPayload.state === \"queued\" ? \"subagent.nested.updated\" : \"subagent.nested.completed\");\n\t};\n\tconst registerStepInterrupt = (flatIndex: number, interrupt: (() => void) | undefined): void => {\n\t\tif (!interrupt) {\n\t\t\tactiveChildInterrupts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildInterrupts.set(flatIndex, interrupt);\n\t\tif (interrupted) interrupt();\n\t};\n\tconst registerStepTimeout = (flatIndex: number, interrupt: (() => void) | undefined): void => {\n\t\tif (!interrupt) {\n\t\t\tactiveChildTimeouts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildTimeouts.set(flatIndex, interrupt);\n\t\tif (timedOut) interrupt();\n\t};\n\tconst registerStepStop = (flatIndex: number, stop: (() => void) | undefined): void => {\n\t\tif (!stop) {\n\t\t\tactiveChildStops.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildStops.set(flatIndex, stop);\n\t\tif (stopped) stop();\n\t};\n\tconst registerStepTurnBudgetAbort = (flatIndex: number, abort: ((message: string, state?: TurnBudgetState) => void) | undefined): void => {\n\t\tif (!abort) {\n\t\t\tactiveChildTurnBudgetAborts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildTurnBudgetAborts.set(flatIndex, abort);\n\t};\n\tconst interruptActiveChildren = (): void => {\n\t\tfor (const interrupt of [...activeChildInterrupts.values()]) interrupt();\n\t};\n\tconst timeoutActiveChildren = (): void => {\n\t\tfor (const interrupt of [...activeChildTimeouts.values()]) interrupt();\n\t};\n\tconst stopActiveChildren = (): void => {\n\t\tfor (const stop of [...activeChildStops.values()]) stop();\n\t};\n\tconst nestedRuns = function* (children: NestedRunSummary[] | undefined): Generator<NestedRunSummary> {\n\t\tfor (const child of children ?? []) {\n\t\t\tyield child;\n\t\t\tyield* nestedRuns(child.children);\n\t\t\tyield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));\n\t\t}\n\t};\n\tconst interruptNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.interrupt_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverInterruptRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-interrupt\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.interrupt_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst stopNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.stop_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverStopRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-stop\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.stop_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst timeoutNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.timeout_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverTimeoutRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-timeout\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.timeout_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst pausedStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: \"Paused after interrupt. Waiting for explicit next action.\",\n\t\texitCode: 0,\n\t\tinterrupted: true,\n\t});\n\tconst timedOutStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: timeoutMessage ?? \"Subagent timed out.\",\n\t\terror: timeoutMessage ?? \"Subagent timed out.\",\n\t\texitCode: 1,\n\t\ttimedOut: true,\n\t});\n\tconst stoppedStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: stopMessage,\n\t\terror: stopMessage,\n\t\texitCode: 1,\n\t\tstopped: true,\n\t});\n\tconst consumePendingAppendRequests = (): void => {\n\t\tif (statusPayload.mode !== \"chain\" || statusPayload.state !== \"running\") return;\n\t\tconst requests = consumeChainAppendRequests(asyncDir);\n\t\tif (requests.length === 0) {\n\t\t\tconst pendingAppends = countPendingChainAppendRequests(asyncDir);\n\t\t\tif ((statusPayload.pendingAppends ?? 0) !== pendingAppends) {\n\t\t\t\tstatusPayload.pendingAppends = pendingAppends;\n\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\twriteStatusPayload();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst appendedSteps = requests.flatMap((request) => request.steps);\n\t\tsteps.push(...appendedSteps);\n\t\tconst now = Date.now();\n\t\tconst pendingAppends = countPendingChainAppendRequests(asyncDir);\n\t\tconst added = appendRunnerStepsToStatus({\n\t\t\tstatus: statusPayload,\n\t\t\tsteps: appendedSteps,\n\t\t\tnow,\n\t\t\tpendingAppends,\n\t\t});\n\t\tmutatingFailureStates.push(...Array.from({ length: added.addedFlatSteps }, () => createMutatingFailureState()));\n\t\tpendingToolResults.push(...Array.from({ length: added.addedFlatSteps }, () => undefined));\n\t\tif (config.childIntercomTargets) {\n\t\t\tconfig.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.agent, index));\n\t\t}\n\t\twriteStatusPayload();\n\t\tfor (const request of requests) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.chain.append.accepted\",\n\t\t\t\tts: now,\n\t\t\t\trunId: id,\n\t\t\t\trequestId: request.id,\n\t\t\t\tstepCount: request.steps.length,\n\t\t\t\tpendingAppends,\n\t\t\t}));\n\t\t}\n\t};\n\tconst markDynamicGraphGroup = (stepIndex: number, status: \"completed\" | \"failed\" | \"running\" | \"stopped\", error?: string, acceptance?: import(\"../../shared/types.ts\").AcceptanceLedger): void => {\n\t\tconst groupNode = statusPayload.workflowGraph?.nodes.find((node) => node.id === `step-${stepIndex}`);\n\t\tif (!groupNode) return;\n\t\tgroupNode.status = status;\n\t\tgroupNode.error = error;\n\t\tgroupNode.acceptanceStatus = acceptance?.status ?? groupNode.acceptanceStatus;\n\t};\n\n\tconst stepOutputActivityAt = (index: number): number => {\n\t\tconst step = statusPayload.steps[index];\n\t\tlet lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;\n\t\tconst outputPath = path.join(asyncDir, `output-${index}.log`);\n\t\ttry {\n\t\t\tlastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\t\tconsole.error(`Failed to inspect async output file '${outputPath}':`, error);\n\t\t\t}\n\t\t}\n\t\treturn lastActivityAt;\n\t};\n\tconst emittedControlEventKeys = new Set<string>();\n\tconst activeLongRunningSteps = new Set<number>();\n\tconst mutatingFailureStates = initialStatusSteps.map(() => createMutatingFailureState());\n\tconst pendingToolResults: Array<{ tool: string; path?: string; mutates: boolean; startedAt?: number } | undefined> = initialStatusSteps.map(() => undefined);\n\tconst mutatingFailureWindowMs = 5 * 60_000;\n\tconst appendControlEvent = (event: ReturnType<typeof buildControlEvent>) => {\n\t\tif (!controlConfig.enabled) return;\n\t\tconst childIntercomTarget = config.childIntercomTargets?.[event.index ?? statusPayload.currentStep];\n\t\tconst channels = event.type === \"active_long_running\"\n\t\t\t? controlConfig.notifyChannels.filter((channel) => channel !== \"intercom\")\n\t\t\t: controlConfig.notifyChannels;\n\t\tif (channels.length === 0 || !claimControlNotification(controlConfig, event, emittedControlEventKeys, childIntercomTarget)) return;\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.control\",\n\t\t\tevent,\n\t\t\tchannels,\n\t\t\tchildIntercomTarget,\n\t\t\tnoticeText: formatControlNoticeMessage(event, childIntercomTarget),\n\t\t\t...(config.controlIntercomTarget && channels.includes(\"intercom\") ? {\n\t\t\t\tintercom: {\n\t\t\t\t\tto: config.controlIntercomTarget,\n\t\t\t\t\tmessage: formatControlIntercomMessage(event, childIntercomTarget),\n\t\t\t\t},\n\t\t\t} : {}),\n\t\t}));\n\t};\n\tconst syncTopLevelCurrentTool = (): void => {\n\t\tconst activeStep = statusPayload.steps\n\t\t\t.filter((step) => step.status === \"running\" && typeof step.currentTool === \"string\" && step.currentTool.length > 0)\n\t\t\t.sort((left, right) => (right.currentToolStartedAt ?? 0) - (left.currentToolStartedAt ?? 0))[0];\n\t\tstatusPayload.currentTool = activeStep?.currentTool;\n\t\tstatusPayload.currentToolStartedAt = activeStep?.currentToolStartedAt;\n\t\tstatusPayload.currentPath = activeStep?.currentPath;\n\t};\n\tconst maybeEmitActiveLongRunning = (flatIndex: number, now: number): boolean => {\n\t\tif (!controlConfig.enabled || activeLongRunningSteps.has(flatIndex)) return false;\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step || step.status !== \"running\" || step.activityState === \"needs_attention\") return false;\n\t\tconst reason = nextLongRunningTrigger(controlConfig, {\n\t\t\tstartedAt: step.startedAt ?? overallStartTime,\n\t\t\tnow,\n\t\t\tturns: step.turnCount ?? 0,\n\t\t\ttokens: step.tokens?.total ?? 0,\n\t\t});\n\t\tif (!reason) return false;\n\t\tactiveLongRunningSteps.add(flatIndex);\n\t\tconst previous = step.activityState;\n\t\tstep.activityState = \"active_long_running\";\n\t\tstatusPayload.activityState = statusPayload.activityState === \"needs_attention\" ? \"needs_attention\" : \"active_long_running\";\n\t\tconst event = buildControlEvent({\n\t\t\ttype: \"active_long_running\",\n\t\t\tfrom: previous,\n\t\t\tto: \"active_long_running\",\n\t\t\trunId: id,\n\t\t\tagent: step.agent,\n\t\t\tindex: flatIndex,\n\t\t\tts: now,\n\t\t\tmessage: `${step.agent} is still active but long-running`,\n\t\t\treason,\n\t\t\tturns: step.turnCount,\n\t\t\ttokens: step.tokens?.total,\n\t\t\ttoolCount: step.toolCount,\n\t\t\tcurrentTool: step.currentTool,\n\t\t\tcurrentToolDurationMs: step.currentToolStartedAt ? Math.max(0, now - step.currentToolStartedAt) : undefined,\n\t\t\tcurrentPath: step.currentPath,\n\t\t\telapsedMs: now - (step.startedAt ?? overallStartTime),\n\t\t});\n\t\tappendControlEvent(event);\n\t\treturn true;\n\t};\n\tconst steeringMarkerPath = (requestId: string): string => path.join(asyncDir, \"control\", \"steer-recovery\", `${Buffer.from(requestId).toString(\"base64url\")}.json`);\n\tconst markSteeringAttention = (index: number): void => {\n\t\tconst step = statusPayload.steps[index];\n\t\tif (step) step.activityState = \"needs_attention\";\n\t\tstatusPayload.activityState = \"needs_attention\";\n\t};\n\tconst emitSteeringEvent = (type: string, request: SteerRequest, index?: number, extra: Record<string, unknown> = {}): void => {\n\t\tappendJsonl(eventsPath, JSON.stringify({ type, ts: Date.now(), runId: id, requestId: request.id, ...(index !== undefined ? { index } : {}), ...extra }));\n\t};\n\tconst emitSteeringNotice = (requestId: string, state: \"failed\" | \"partial\" | \"recovered\", message: string): void => {\n\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.steering.notice\", ts: Date.now(), runId: id, requestId, state, message, ...(config.sessionId ? { currentSessionId: config.sessionId } : {}) }));\n\t};\n\tconst recordSteeringLifecycle = (request: SteerRequest, targets: Array<{ index: number; state: SteeringTargetState; reason?: string }>): void => {\n\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\trecordSteeringRequest(lifecycle, { id: request.id, requestedAt: request.ts, source: request.source, message: request.message, targets });\n\t\tfor (const target of targets) {\n\t\t\tconst step = statusPayload.steps[target.index];\n\t\t\tif (!step) continue;\n\t\t\tstep.steering ??= createSteeringStatus();\n\t\t\trecordSteeringRequest(step.steering, { id: request.id, requestedAt: request.ts, source: request.source, message: request.message, targets: [target] });\n\t\t}\n\t};\n\tconst updateSteeringLifecycleTarget = (\n\t\trequestId: string,\n\t\tindex: number,\n\t\tstate: SteeringTargetState,\n\t\tnow: number,\n\t\tfields: Pick<SteeringTargetStatus, \"reason\" | \"replacementRunId\"> = {},\n\t): SteeringTargetStatus | undefined => {\n\t\tconst updated = updateSteeringTarget(steeringStatus(statusPayload), requestId, index, state, now, fields);\n\t\tconst step = statusPayload.steps[index];\n\t\tif (step?.steering) updateSteeringTarget(step.steering, requestId, index, state, now, fields);\n\t\treturn updated;\n\t};\n\tconst emitTerminalSteeringNotice = (requestId: string, failureMessage: string): void => {\n\t\tconst state = terminalSteeringNoticeState(steeringStatus(statusPayload), requestId);\n\t\tif (state === \"partial\") emitSteeringNotice(requestId, \"partial\", `Steering partially delivered for run ${id}.`);\n\t\telse if (state === \"failed\") emitSteeringNotice(requestId, \"failed\", failureMessage);\n\t};\n\tconst deliverSteerRequest = (request: SteerRequest): void => {\n\t\tif (statusPayload.state !== \"running\") {\n\t\t\tconst reason = `run became ${statusPayload.state} before steering request was consumed`;\n\t\t\tconst indexes = request.targetIndex !== undefined\n\t\t\t\t? [request.targetIndex]\n\t\t\t\t: request.targetIndexes?.length\n\t\t\t\t\t? request.targetIndexes\n\t\t\t\t\t: statusPayload.steps.map((_, index) => index);\n\t\t\tconst targets = indexes.map((index) => ({ index, state: \"failed\" as const, reason }));\n\t\t\trecordSteeringLifecycle(request, targets);\n\t\t\temitSteeringEvent(\"subagent.steer.requested\", request, undefined, { targets });\n\t\t\tfor (const target of targets) emitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason });\n\t\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: ${reason}.`);\n\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\twriteStatusPayload();\n\t\t\treturn;\n\t\t}\n\t\tconst runningIndexes = statusPayload.steps\n\t\t\t.map((step, index) => ({ step, index }))\n\t\t\t.filter(({ step }) => step.status === \"running\")\n\t\t\t.map(({ index }) => index);\n\t\tconst targets = request.targetIndex !== undefined\n\t\t\t? [request.targetIndex]\n\t\t\t: request.targetIndexes?.length\n\t\t\t\t? request.targetIndexes\n\t\t\t\t: runningIndexes.length > 0\n\t\t\t\t\t? runningIndexes\n\t\t\t\t\t: statusPayload.mode === \"single\" && statusPayload.steps[0]?.status === \"pending\"\n\t\t\t\t\t\t? [0]\n\t\t\t\t\t\t: [];\n\t\tconst now = Date.now();\n\t\tconst targetStates = targets.map((index) => {\n\t\t\tconst step = statusPayload.steps[index];\n\t\t\tif (!step) return { index, state: \"failed\" as const, reason: \"child index out of range\" };\n\t\t\tif (step.status === \"pending\") return { index, state: \"scheduled\" as const };\n\t\t\tif (step.status !== \"running\") return { index, state: \"failed\" as const, reason: `child is ${step.status}` };\n\t\t\tif (steeringCapabilities.get(index)?.supported === false) return { index, state: \"failed\" as const, reason: \"child Pi session does not support steering\" };\n\t\t\treturn { index, state: \"routed\" as const };\n\t\t});\n\t\trecordSteeringLifecycle(request, targetStates);\n\t\temitSteeringEvent(\"subagent.steer.requested\", request, undefined, { targets: targetStates });\n\t\tfor (const target of targetStates) {\n\t\t\tif (target.state === \"routed\") {\n\t\t\t\ttry {\n\t\t\t\t\tenqueueStepSteer(asyncDir, target.index, request);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"routed\", now);\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.routed\", request, target.index);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tmarkSteeringAttention(target.index);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"failed\", now, { reason: error instanceof Error ? error.message : String(error) });\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason: error instanceof Error ? error.message : String(error) });\n\t\t\t\t}\n\t\t\t} else if (target.state === \"failed\") {\n\t\t\t\tmarkSteeringAttention(target.index);\n\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason: target.reason });\n\t\t\t} else {\n\t\t\t\temitSteeringEvent(\"subagent.steer.scheduled\", request, target.index);\n\t\t\t}\n\t\t}\n\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: no requested child remained steerable.`);\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst consumeSteerAck = (ack: SteerAck): void => {\n\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\tconst request = lifecycle.recent.find((candidate) => candidate.id === ack.requestId);\n\t\tif (!request || !request.targets.some((target) => target.index === ack.index)) return;\n\t\tconst late = fs.existsSync(steeringMarkerPath(ack.requestId));\n\t\tconst now = Date.now();\n\t\tif (ack.state === \"delivered\") {\n\t\t\tupdateSteeringLifecycleTarget(ack.requestId, ack.index, late ? \"late\" : \"delivered\", now, { reason: late ? \"acknowledged after recovery commit\" : undefined });\n\t\t\temitSteeringEvent(\"subagent.steer.delivered\", { type: \"steer\", id: ack.requestId, ts: now, message: ack.message }, ack.index, { late, message: ack.message });\n\t\t} else {\n\t\t\tmarkSteeringAttention(ack.index);\n\t\t\tupdateSteeringLifecycleTarget(ack.requestId, ack.index, \"failed\", now, { reason: ack.message });\n\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: ack.requestId, ts: now, message: ack.message }, ack.index, { reason: ack.message });\n\t\t}\n\t\temitTerminalSteeringNotice(ack.requestId, `Steering failed for run ${id}: ${ack.message}`);\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst flushPendingStepSteers = (flatIndex: number): void => {\n\t\tconst remaining: SteerRequest[] = [];\n\t\tfor (const request of pendingStepSteers.splice(0)) {\n\t\t\tif (request.targetIndex === undefined) deliverSteerRequest({ ...request, targetIndex: flatIndex });\n\t\t\telse if (request.targetIndex === flatIndex) deliverSteerRequest(request);\n\t\t\telse remaining.push(request);\n\t\t}\n\t\tpendingStepSteers.push(...remaining);\n\t};\n\tconst updateStepModel = (flatIndex: number, model: string | undefined, thinking: string | undefined, now = Date.now()): void => {\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step) return;\n\t\tstep.model = model;\n\t\tstep.thinking = thinking;\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst updateStepTurnBudget = (flatIndex: number, turnCount: number, now: number, terminalAssistantStop: boolean): void => {\n\t\tconst budget = config.turnBudget;\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!budget || !step || timedOut || stopped || turnBudgetExceeded || step.turnBudgetExceeded) return;\n\t\tif (turnCount < budget.maxTurns) {\n\t\t\tconst state: TurnBudgetState = { ...budget, outcome: \"within-budget\", turnCount };\n\t\t\tstep.turnBudget = state;\n\t\t\tstatusPayload.turnBudget = state;\n\t\t\treturn;\n\t\t}\n\t\tconst state = turnBudgetState(budget, turnCount, false);\n\t\tstep.turnBudget = state;\n\t\tstatusPayload.turnBudget = state;\n\t\tif (!step.wrapUpRequested) {\n\t\t\tstep.wrapUpRequested = true;\n\t\t\tstatusPayload.wrapUpRequested = true;\n\t\t\tappendRecentStepOutput(step, [turnBudgetSoftNote(budget, turnCount)]);\n\t\t}\n\t\tif (!shouldAbortForTurnBudget(budget, turnCount, terminalAssistantStop)) return;\n\t\tconst exceededState = turnBudgetState(budget, turnCount, true);\n\t\tconst message = turnBudgetExceededMessage(budget, turnCount);\n\t\tstep.turnBudget = exceededState;\n\t\tstep.turnBudgetExceeded = true;\n\t\tstep.wrapUpRequested = true;\n\t\tstep.error = message;\n\t\tturnBudgetExceeded = true;\n\t\tstatusPayload.turnBudget = exceededState;\n\t\tstatusPayload.turnBudgetExceeded = true;\n\t\tstatusPayload.wrapUpRequested = true;\n\t\tstatusPayload.error = message;\n\t\tstatusPayload.lastUpdate = now;\n\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.step.turn_budget_exceeded\", ts: now, runId: id, stepIndex: flatIndex, agent: step.agent, turnCount, maxTurns: budget.maxTurns, graceTurns: budget.graceTurns, message }));\n\t\tactiveChildTurnBudgetAborts.get(flatIndex)?.(message, exceededState);\n\t};\n\tconst updateStepFromChildEvent = (flatIndex: number, event: ChildEvent): void => {\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step) return;\n\t\tconst now = Date.now();\n\t\tstatusPayload.currentStep = flatIndex;\n\t\tif (isChildWatchdogStatusEvent(event)) {\n\t\t\tconst next = acceptChildWatchdogEvent({\n\t\t\t\tcurrent: step.watchdog,\n\t\t\t\tevent,\n\t\t\t\trunId: id,\n\t\t\t\tagent: step.agent,\n\t\t\t\tchildIndex: flatIndex,\n\t\t\t});\n\t\t\tif (!next) return;\n\t\t\tstep.watchdog = next;\n\t\t\tstep.lastActivityAt = now;\n\t\t\tstatusPayload.lastActivityAt = now;\n\t\t\tstatusPayload.lastUpdate = now;\n\t\t\twriteStatusPayload();\n\t\t\treturn;\n\t\t}\n\t\tif (event.type === \"tool_execution_start\" && event.toolName) {\n\t\t\tconst mutates = isMutatingTool(event.toolName, event.args);\n\t\t\tconst currentPath = resolveCurrentPath(event.toolName, event.args);\n\t\t\tstep.toolCount = (step.toolCount ?? 0) + 1;\n\t\t\tconst configuredToolBudget = flatSteps[flatIndex]?.toolBudget;\n\t\t\tif (configuredToolBudget) {\n\t\t\t\tstep.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount);\n\t\t\t\tstatusPayload.toolBudget = step.toolBudget;\n\t\t\t}\n\t\t\tstep.currentTool = event.toolName;\n\t\t\tstep.currentToolArgs = extractToolArgsPreview(event.args ?? {});\n\t\t\tstep.currentToolStartedAt = now;\n\t\t\tstep.currentPath = currentPath;\n\t\t\tpendingToolResults[flatIndex] = { tool: event.toolName, path: currentPath, mutates, startedAt: now };\n\t\t\tstatusPayload.toolCount = (statusPayload.toolCount ?? 0) + 1;\n\t\t\tsyncTopLevelCurrentTool();\n\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\tif (step.currentTool) {\n\t\t\t\tstep.recentTools ??= [];\n\t\t\t\tstep.recentTools.push({ tool: step.currentTool, args: step.currentToolArgs || \"\", endMs: now });\n\t\t\t}\n\t\t\tstep.currentTool = undefined;\n\t\t\tstep.currentToolArgs = undefined;\n\t\t\tstep.currentToolStartedAt = undefined;\n\t\t\tstep.currentPath = undefined;\n\t\t\tsyncTopLevelCurrentTool();\n\t\t} else if (event.type === \"tool_result_end\" && event.message) {\n\t\t\tconst toolSnapshot = pendingToolResults[flatIndex];\n\t\t\tpendingToolResults[flatIndex] = undefined;\n\t\t\tconst resultText = extractTextFromContent(event.message.content);\n\t\t\tif (toolSnapshot && resultText.includes(\"Tool budget hard limit reached\")) {\n\t\t\t\tconst configuredToolBudget = flatSteps[flatIndex]?.toolBudget;\n\t\t\t\tif (configuredToolBudget) {\n\t\t\t\t\tstep.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount ?? 0, toolSnapshot.tool);\n\t\t\t\t\tstep.toolBudgetBlocked = true;\n\t\t\t\t\tstatusPayload.toolBudget = step.toolBudget;\n\t\t\t\t\tstatusPayload.toolBudgetBlocked = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tappendRecentStepOutput(step, resultText.split(\"\\n\").slice(-10));\n\t\t\tif (toolSnapshot?.mutates && didMutatingToolFail(resultText)) {\n\t\t\t\tconst state = mutatingFailureStates[flatIndex]!;\n\t\t\t\trecordMutatingFailure(state, {\n\t\t\t\t\ttool: toolSnapshot.tool,\n\t\t\t\t\tpath: toolSnapshot.path,\n\t\t\t\t\terror: resultText.split(\"\\n\").find((line) => line.trim())?.trim().slice(0, 180) ?? \"mutating tool failed\",\n\t\t\t\t\tts: now,\n\t\t\t\t}, mutatingFailureWindowMs);\n\t\t\t\tif (controlConfig.enabled && shouldEscalateMutatingFailures(state, controlConfig.failedToolAttemptsBeforeAttention) && step.activityState !== \"needs_attention\") {\n\t\t\t\t\tconst previous = step.activityState;\n\t\t\t\t\tstep.activityState = \"needs_attention\";\n\t\t\t\t\tstatusPayload.activityState = \"needs_attention\";\n\t\t\t\t\tappendControlEvent(buildControlEvent({\n\t\t\t\t\t\ttype: \"needs_attention\",\n\t\t\t\t\t\tfrom: previous,\n\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tagent: step.agent,\n\t\t\t\t\t\tindex: flatIndex,\n\t\t\t\t\t\tts: now,\n\t\t\t\t\t\tmessage: `${step.agent} needs attention after repeated mutating tool failures`,\n\t\t\t\t\t\treason: \"tool_failures\",\n\t\t\t\t\t\tturns: step.turnCount,\n\t\t\t\t\t\ttokens: step.tokens?.total,\n\t\t\t\t\t\ttoolCount: step.toolCount,\n\t\t\t\t\t\tcurrentTool: toolSnapshot.tool,\n\t\t\t\t\t\tcurrentToolDurationMs: toolSnapshot.startedAt ? Math.max(0, now - toolSnapshot.startedAt) : undefined,\n\t\t\t\t\t\tcurrentPath: toolSnapshot.path,\n\t\t\t\t\t\trecentFailureSummary: summarizeRecentMutatingFailures(state),\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t} else if (toolSnapshot?.mutates) {\n\t\t\t\tresetMutatingFailureState(mutatingFailureStates[flatIndex]!);\n\t\t\t}\n\t\t} else if (event.type === \"message_end\" && event.message?.role === \"assistant\") {\n\t\t\tappendRecentStepOutput(step, stripAcceptanceReport(extractTextFromContent(event.message.content)).split(\"\\n\").slice(-10));\n\t\t\tstep.turnCount = (step.turnCount ?? 0) + 1;\n\t\t\tconst usage = event.message.usage;\n\t\t\tif (usage) {\n\t\t\t\tconst input = usage.input ?? usage.inputTokens ?? 0;\n\t\t\t\tconst output = usage.output ?? usage.outputTokens ?? 0;\n\t\t\t\tconst previousInput = step.tokens?.input ?? 0;\n\t\t\t\tconst previousOutput = step.tokens?.output ?? 0;\n\t\t\t\tstep.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output };\n\t\t\t\tconst totalInput = statusPayload.totalTokens?.input ?? 0;\n\t\t\t\tconst totalOutput = statusPayload.totalTokens?.output ?? 0;\n\t\t\t\tstatusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };\n\t\t\t}\n\t\t\tstatusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);\n\t\t\tupdateStepTurnBudget(flatIndex, step.turnCount, now, isTerminalAssistantStop(event.message));\n\t\t}\n\t\tsyncTopLevelCurrentTool();\n\t\tstep.lastActivityAt = now;\n\t\tstatusPayload.lastActivityAt = now;\n\t\tstatusPayload.lastUpdate = now;\n\t\tmaybeEmitActiveLongRunning(flatIndex, now);\n\t\twriteStatusPayload();\n\t};\n\tconst updateRunnerActivityState = (now: number): boolean => {\n\t\tif (!controlConfig.enabled) return false;\n\t\tlet changed = false;\n\t\tlet runLastActivityAt = statusPayload.lastActivityAt ?? overallStartTime;\n\t\tfor (let index = 0; index < statusPayload.steps.length; index++) {\n\t\t\tconst step = statusPayload.steps[index]!;\n\t\t\tif (step.status !== \"running\") continue;\n\t\t\tconst lastActivityAt = stepOutputActivityAt(index);\n\t\t\trunLastActivityAt = Math.max(runLastActivityAt, lastActivityAt);\n\t\t\tif (step.lastActivityAt !== lastActivityAt) {\n\t\t\t\tstep.lastActivityAt = lastActivityAt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tconst idleState = deriveActivityState({\n\t\t\t\tconfig: controlConfig,\n\t\t\t\tstartedAt: step.startedAt ?? overallStartTime,\n\t\t\t\tlastActivityAt,\n\t\t\t\tnow,\n\t\t\t});\n\t\t\tif (idleState === \"needs_attention\") {\n\t\t\t\tconst previous = step.activityState;\n\t\t\t\tstep.activityState = \"needs_attention\";\n\t\t\t\tif (previous !== \"needs_attention\") {\n\t\t\t\t\tappendControlEvent(buildControlEvent({\n\t\t\t\t\t\tfrom: previous,\n\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tagent: step.agent,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tts: now,\n\t\t\t\t\t\tlastActivityAt,\n\t\t\t\t\t}));\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t} else if (maybeEmitActiveLongRunning(index, now)) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t\tif (statusPayload.lastActivityAt !== runLastActivityAt) {\n\t\t\tstatusPayload.lastActivityAt = runLastActivityAt;\n\t\t\tchanged = true;\n\t\t}\n\t\tconst nextRunState = statusPayload.steps.some((step) => step.activityState === \"needs_attention\")\n\t\t\t? \"needs_attention\"\n\t\t\t: statusPayload.steps.some((step) => step.activityState === \"active_long_running\")\n\t\t\t\t? \"active_long_running\"\n\t\t\t\t: undefined;\n\t\tif (nextRunState !== currentActivityState) {\n\t\t\tcurrentActivityState = nextRunState;\n\t\t\tstatusPayload.activityState = nextRunState;\n\t\t\tchanged = true;\n\t\t}\n\t\tstatusPayload.lastUpdate = now;\n\t\tif (changed) writeStatusPayload();\n\t\treturn changed;\n\t};\n\tif (controlConfig.enabled) {\n\t\tactivityTimer = setInterval(() => {\n\t\t\tif (statusPayload.state !== \"running\") return;\n\t\t\tconst now = Date.now();\n\t\t\tupdateRunnerActivityState(now);\n\t\t}, 1000);\n\t\tactivityTimer.unref?.();\n\t}\n\n\tconst interruptRunner = () => {\n\t\tconsumeInterruptRequest(asyncDir);\n\t\tif (interrupted || statusPayload.state !== \"running\") return;\n\t\tinterrupted = true;\n\t\tconst now = Date.now();\n\t\tstatusPayload.state = \"paused\";\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status === \"running\") {\n\t\t\t\tstep.status = \"paused\";\n\t\t\t\tstep.activityState = undefined;\n\t\t\t\tstep.endedAt = now;\n\t\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : undefined;\n\t\t\t\tstep.lastActivityAt = now;\n\t\t\t}\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.paused\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t}));\n\t\tinterruptNestedAsyncDescendants();\n\t\tinterruptActiveChildren();\n\t};\n\tconst stopRunner = () => {\n\t\tif (stopped || timedOut || interrupted || statusPayload.state !== \"running\") return;\n\t\tstopped = true;\n\t\tconst now = Date.now();\n\t\tstatusPayload.state = \"stopped\";\n\t\tstatusPayload.stopped = true;\n\t\tstatusPayload.error = stopMessage;\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status !== \"running\" && step.status !== \"pending\") continue;\n\t\t\tstep.status = \"stopped\";\n\t\t\tstep.error = stopMessage;\n\t\t\tstep.exitCode = 1;\n\t\t\tstep.stopped = true;\n\t\t\tstep.activityState = undefined;\n\t\t\tstep.endedAt = now;\n\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : 0;\n\t\t\tstep.lastActivityAt = now;\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.stopped\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t\tmessage: stopMessage,\n\t\t}));\n\t\tstopAbortController.abort();\n\t\tstopNestedAsyncDescendants();\n\t\tstopActiveChildren();\n\t};\n\tconst timeoutRunner = () => {\n\t\tif (timedOut || stopped || interrupted || statusPayload.state !== \"running\") return;\n\t\ttimedOut = true;\n\t\tconst now = Date.now();\n\t\tconst message = timeoutMessage ?? \"Subagent timed out.\";\n\t\tstatusPayload.state = \"failed\";\n\t\tstatusPayload.timedOut = true;\n\t\tstatusPayload.error = message;\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status !== \"running\" && step.status !== \"pending\") continue;\n\t\t\tstep.status = \"failed\";\n\t\t\tstep.error = message;\n\t\t\tstep.exitCode = 1;\n\t\t\tstep.timedOut = true;\n\t\t\tstep.activityState = undefined;\n\t\t\tstep.endedAt = now;\n\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : 0;\n\t\t\tstep.lastActivityAt = now;\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.timed_out\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t\ttimeoutMs: config.timeoutMs,\n\t\t\tdeadlineAt: config.deadlineAt,\n\t\t\tmessage,\n\t\t}));\n\t\ttimeoutAbortController.abort();\n\t\ttimeoutNestedAsyncDescendants();\n\t\ttimeoutActiveChildren();\n\t};\n\tprocess.on(ASYNC_INTERRUPT_SIGNAL, interruptRunner);\n\t// Portable control inbox: the parent drops control request files here when\n\t// it cannot deliver OS signals (e.g. ENOSYS on Windows) or when steering a\n\t// live child. Interrupts still route into the same graceful interruptRunner().\n\tconst disposeControlInbox = watchAsyncControlInbox(asyncDir, {\n\t\tonInterrupt: interruptRunner,\n\t\tonTimeout: timeoutRunner,\n\t\tonStop: stopRunner,\n\t\tonSteer: (request) => {\n\t\t\tconst targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;\n\t\t\tif (targetStep?.status === \"pending\") {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t\tpendingStepSteers.push(request);\n\t\t\t} else if (request.targetIndexes !== undefined || request.targetIndex !== undefined || statusPayload.steps.some((step) => step.status === \"running\")) {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t} else {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t\tpendingStepSteers.push(request);\n\t\t\t}\n\t\t},\n\t\tonSteerCapability: (capability) => {\n\t\t\tsteeringCapabilities.set(capability.index, capability);\n\t\t\tif (!capability.supported) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\t\t\tfor (const request of lifecycle.recent) {\n\t\t\t\t\tif (!request.targets.some((target) => target.index === capability.index && (target.state === \"routed\" || target.state === \"scheduled\"))) continue;\n\t\t\t\t\tmarkSteeringAttention(capability.index);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, capability.index, \"failed\", now, { reason: \"child Pi session does not support steering\" });\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: request.id, ts: request.requestedAt, message: \"child Pi session does not support steering\" }, capability.index, { reason: \"child Pi session does not support steering\" });\n\t\t\t\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: child ${capability.index} does not support steering.`);\n\t\t\t\t}\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\twriteStatusPayload();\n\t\t\t}\n\t\t},\n\t\tonSteerAck: consumeSteerAck,\n\t});\n\tif (config.deadlineAt !== undefined) {\n\t\tconst remainingMs = Math.max(0, config.deadlineAt - Date.now());\n\t\ttimeoutTimer = setTimeout(timeoutRunner, remainingMs);\n\t\ttimeoutTimer.unref?.();\n\t}\n\tappendJsonl(\n\t\teventsPath,\n\t\tJSON.stringify({\n\t\t\ttype: \"subagent.run.started\",\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tts: overallStartTime,\n\t\t\trunId: id,\n\t\t\tmode: statusPayload.mode,\n\t\t\tcwd,\n\t\t\tpid: process.pid,\n\t\t}),\n\t);\n\n\tlet flatIndex = 0;\n\tlet stepCursor = 0;\n\n\twhile (true) {\n\t\tif (interrupted || timedOut || stopped || turnBudgetExceeded) break;\n\t\tconsumePendingAppendRequests();\n\t\tif (stepCursor >= steps.length) break;\n\t\tconst stepIndex = stepCursor++;\n\t\tconst step = steps[stepIndex]!;\n\n\t\tif (isDynamicRunnerGroup(step)) {\n\t\t\tconst groupStartFlatIndex = flatIndex;\n\t\t\tlet materialized: ReturnType<typeof materializeDynamicParallelStep>;\n\t\t\ttry {\n\t\t\t\tmaterialized = materializeDynamicParallelStep(step as Parameters<typeof materializeDynamicParallelStep>[0], outputs, stepIndex, { maxItems: config.dynamicFanoutMaxItems, allowRunnerFields: true });\n\t\t\t\tif (materialized.parallel.length > 1 && step.parallel.outputPath && !step.parallel.namespaceOutputPath) {\n\t\t\t\t\tthrow new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} materialized ${materialized.parallel.length} items that resolve output to the same path: ${step.parallel.outputPath}. Remove the explicit output path or use an inherited relative agent output so each item can be isolated.`);\n\t\t\t\t}\n\t\t\t\tif (materialized.collectedOnEmpty) validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);\n\t\t\t} catch (error) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tstatusPayload.state = \"failed\";\n\t\t\t\tstatusPayload.error = message;\n\t\t\t\tstatusPayload.currentStep = flatIndex;\n\t\t\t\tconst placeholder = statusPayload.steps[groupStartFlatIndex];\n\t\t\t\tif (placeholder) {\n\t\t\t\t\tplaceholder.status = \"failed\";\n\t\t\t\t\tplaceholder.error = message;\n\t\t\t\t\tplaceholder.startedAt = now;\n\t\t\t\t\tplaceholder.endedAt = now;\n\t\t\t\t\tplaceholder.durationMs = 0;\n\t\t\t\t\tplaceholder.exitCode = 1;\n\t\t\t\t}\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"failed\", message);\n\t\t\t\twriteStatusPayload();\n\t\t\t\tresults.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1 });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst effectiveDynamicGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\texplicit: step.acceptanceInput,\n\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\tacceptanceRole: step.acceptanceRole,\n\t\t\t\ttask: materialized.parallel.map((task) => task.task ?? step.parallel.task).join(\"\\n\") || step.parallel.task,\n\t\t\t\tmode: config.mode,\n\t\t\t\tasync: true,\n\t\t\t\tdynamicGroup: true,\n\t\t\t});\n\n\t\t\tif (materialized.parallel.length === 0) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst collection = materialized.collectedOnEmpty ?? [];\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\tstatusPayload.outputs = outputs;\n\t\t\t\tconst placeholder = statusPayload.steps[groupStartFlatIndex];\n\t\t\t\tif (placeholder) {\n\t\t\t\t\tplaceholder.status = \"complete\";\n\t\t\t\t\tplaceholder.startedAt = now;\n\t\t\t\t\tplaceholder.endedAt = now;\n\t\t\t\t\tplaceholder.durationMs = 0;\n\t\t\t\t}\n\t\t\t\tpreviousOutput = \"Dynamic fanout produced 0 results.\";\n\t\t\t\tconst groupAcceptance = effectiveDynamicGroupAcceptance.explicit && !timedOut && !stopped\n\t\t\t\t\t? await evaluateAcceptance({\n\t\t\t\t\t\tacceptance: effectiveDynamicGroupAcceptance,\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,\n\t\t\t\t\t\tsignal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),\n\t\t\t\t\t\tabortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? \"Subagent timed out.\",\n\t\t\t\t\t})\n\t\t\t\t\t: undefined;\n\t\t\t\tconst groupStopped = stopped || stopAbortController.signal.aborted;\n\t\t\t\tconst groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);\n\t\t\t\tconst effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;\n\t\t\t\tif (placeholder && effectiveGroupAcceptance) placeholder.acceptance = effectiveGroupAcceptance;\n\t\t\t\tconst groupAcceptanceFailure = effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;\n\t\t\t\tif (groupTimedOut || groupStopped || groupAcceptanceFailure) {\n\t\t\t\t\tconst errorMessage = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? \"Subagent timed out.\" : groupAcceptanceFailure!;\n\t\t\t\t\tstatusPayload.state = groupStopped ? \"stopped\" : \"failed\";\n\t\t\t\t\tstatusPayload.error = errorMessage;\n\t\t\t\t\tstatusPayload.stopped = groupStopped ? true : statusPayload.stopped;\n\t\t\t\t\tif (placeholder) {\n\t\t\t\t\t\tplaceholder.status = groupStopped ? \"stopped\" : \"failed\";\n\t\t\t\t\t\tplaceholder.error = errorMessage;\n\t\t\t\t\t\tplaceholder.exitCode = 1;\n\t\t\t\t\t\tplaceholder.timedOut = groupTimedOut ? true : undefined;\n\t\t\t\t\t\tplaceholder.stopped = groupStopped ? true : undefined;\n\t\t\t\t\t}\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, groupStopped ? \"stopped\" : \"failed\", errorMessage, effectiveGroupAcceptance);\n\t\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\tresults.push({ agent: step.parallel.agent, output: errorMessage, error: errorMessage, success: false, exitCode: 1, timedOut: groupTimedOut ? true : undefined, stopped: groupStopped ? true : undefined, acceptance: effectiveGroupAcceptance });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tflatIndex++;\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"completed\", undefined, effectiveGroupAcceptance);\n\t\t\t\twriteStatusPayload();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst dynamicSteps = materialized.parallel.map((task, itemIndex) => {\n\t\t\t\tconst thinkingOverride = step.thinkingOverrides?.[itemIndex];\n\t\t\t\tconst model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;\n\t\t\t\tconst thinking = thinkingOverride ? resolveEffectiveThinking(model, thinkingOverride) : undefined;\n\t\t\t\tconst outputPath = step.parallel.namespaceOutputPath && step.parallel.outputPath\n\t\t\t\t\t? path.join(path.dirname(step.parallel.outputPath), `dynamic-${stepIndex}`, `${itemIndex}-${step.parallel.agent}`, path.basename(step.parallel.outputPath))\n\t\t\t\t\t: step.parallel.outputPath;\n\t\t\t\tconst taskText = task.task ?? step.parallel.task;\n\t\t\t\tconst materializedTask = step.parallel.namespaceOutputPath ? injectSingleOutputInstruction(taskText, outputPath, step.parallel) : taskText;\n\t\t\t\treturn {\n\t\t\t\t\t...step.parallel,\n\t\t\t\t\ttask: materializedTask,\n\t\t\t\t\teffectiveAcceptance: resolveEffectiveAcceptance({\n\t\t\t\t\t\texplicit: step.parallel.acceptanceInput,\n\t\t\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\t\t\tacceptanceRole: step.parallel.acceptanceRole,\n\t\t\t\t\t\ttask: materializedTask,\n\t\t\t\t\t\tmode: config.mode,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tdynamic: step.parallel.acceptanceInput === undefined,\n\t\t\t\t\t}),\n\t\t\t\t\tsystemPrompt: step.parallel.namespaceOutputPath ? injectOutputPathSystemPrompt(step.parallel.systemPrompt ?? \"\", outputPath, step.parallel) : step.parallel.systemPrompt,\n\t\t\t\t\toutputPath,\n\t\t\t\t\tlabel: task.label ?? step.parallel.label,\n\t\t\t\t\t...(step.sessionFiles?.[itemIndex] ? { sessionFile: step.sessionFiles[itemIndex] } : {}),\n\t\t\t\t\t...(thinkingOverride ? {\n\t\t\t\t\t\t...(model ? { model } : {}),\n\t\t\t\t\t\t...(thinking ? { thinking } : {}),\n\t\t\t\t\t\t...(step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.map((candidate) => applyThinkingSuffix(candidate, thinkingOverride, true)) } : {}),\n\t\t\t\t\t} : {}),\n\t\t\t\t\tstructuredOutput: undefined,\n\t\t\t\t\tstructuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema,\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst dynamicFlatStepCount = Math.max(statusPayload.steps.length - 1 + dynamicSteps.length, 1);\n\t\t\tconst dynamicStatusSteps: RunnerStatusStep[] = dynamicSteps.map((task, itemIndex) => {\n\t\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });\n\t\t\t\treturn {\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\tphase: task.phase ?? step.phase,\n\t\t\t\t\tlabel: task.label,\n\t\t\t\t\toutputName: undefined,\n\t\t\t\t\tstructured: Boolean(task.structuredOutputSchema),\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),\n\t\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\t\tskills: task.skills,\n\t\t\t\t\tmodel: task.model,\n\t\t\t\t\tthinking: task.thinking,\n\t\t\t\t\tattemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,\n\t\t\t\t\trecentTools: [],\n\t\t\t\t\trecentOutput: [],\n\t\t\t\t};\n\t\t\t});\n\t\t\tstatusPayload.steps.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps);\n\t\t\tif (config.childIntercomTargets) {\n\t\t\t\tconfig.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.agent, index));\n\t\t\t}\n\t\t\tmutatingFailureStates.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => createMutatingFailureState()));\n\t\t\tpendingToolResults.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => undefined));\n\t\t\tconst materializedDelta = dynamicStatusSteps.length - 1;\n\t\t\tfor (const group of statusPayload.parallelGroups) {\n\t\t\t\tif (group.stepIndex === stepIndex) {\n\t\t\t\t\tgroup.start = groupStartFlatIndex;\n\t\t\t\t\tgroup.count = dynamicStatusSteps.length;\n\t\t\t\t} else if (group.start > groupStartFlatIndex) {\n\t\t\t\t\tgroup.start += materializedDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (statusPayload.workflowGraph) {\n\t\t\t\tconst shiftFlatIndexes = (nodes: NonNullable<typeof statusPayload.workflowGraph>[\"nodes\"]): void => {\n\t\t\t\t\tfor (const node of nodes) {\n\t\t\t\t\t\tif (node.stepIndex !== undefined && node.stepIndex > stepIndex && node.flatIndex !== undefined && node.flatIndex >= groupStartFlatIndex) {\n\t\t\t\t\t\t\tnode.flatIndex += dynamicStatusSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node.children) shiftFlatIndexes(node.children);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tshiftFlatIndexes(statusPayload.workflowGraph.nodes);\n\t\t\t\tconst groupNode = statusPayload.workflowGraph.nodes.find((node) => node.id === `step-${stepIndex}`);\n\t\t\t\tif (groupNode) {\n\t\t\t\t\tgroupNode.children = materialized.items.map((item, itemIndex) => ({\n\t\t\t\t\t\tid: `step-${stepIndex}-item-${item.idKey}`,\n\t\t\t\t\t\tkind: \"agent\",\n\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\tphase: dynamicSteps[itemIndex]?.phase ?? step.phase,\n\t\t\t\t\t\tlabel: dynamicSteps[itemIndex]?.label?.trim() || `${step.parallel.agent} ${item.key}`,\n\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\tflatIndex: groupStartFlatIndex + itemIndex,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t\titemKey: item.key,\n\t\t\t\t\t\tstructured: Boolean(dynamicSteps[itemIndex]?.structuredOutputSchema),\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteStatusPayload();\n\n\t\t\tconst concurrency = step.concurrency ?? MAX_PARALLEL_CONCURRENCY;\n\t\t\tconst failFast = step.failFast ?? false;\n\t\t\tlet aborted = false;\n\t\t\tconst parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {\n\t\t\t\tconst fi = groupStartFlatIndex + taskIdx;\n\t\t\t\tif (timedOut) return timedOutStepResult(task.agent);\n\t\t\t\tif (stopped) return stoppedStepResult(task.agent);\n\t\t\t\tif (interrupted) return pausedStepResult(task.agent);\n\t\t\t\tif (aborted && failFast) {\n\t\t\t\t\tconst skippedAt = Date.now();\n\t\t\t\t\tstatusPayload.steps[fi].status = \"failed\";\n\t\t\t\t\tstatusPayload.steps[fi].error = \"Skipped due to fail-fast\";\n\t\t\t\t\tstatusPayload.steps[fi].startedAt = skippedAt;\n\t\t\t\t\tstatusPayload.steps[fi].endedAt = skippedAt;\n\t\t\t\t\tstatusPayload.steps[fi].durationMs = 0;\n\t\t\t\t\tstatusPayload.steps[fi].exitCode = -1;\n\t\t\t\t\tstatusPayload.lastUpdate = skippedAt;\n\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\treturn { agent: task.agent, output: \"(skipped — fail-fast)\", exitCode: -1 as number | null, skipped: true };\n\t\t\t\t}\n\t\t\t\tconst taskStartTime = Date.now();\n\t\t\t\tstatusPayload.currentStep = fi;\n\t\t\t\tstatusPayload.steps[fi].status = \"running\";\n\t\t\t\tstatusPayload.steps[fi].error = undefined;\n\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\tresetStepLiveDetail(statusPayload.steps[fi]);\n\t\t\t\tstatusPayload.steps[fi].startedAt = taskStartTime;\n\t\t\t\tstatusPayload.steps[fi].lastActivityAt = taskStartTime;\n\t\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);\n\t\t\t\tstatusPayload.lastActivityAt = taskStartTime;\n\t\t\t\tstatusPayload.lastUpdate = taskStartTime;\n\t\t\t\twriteStatusPayload();\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.step.started\", ts: taskStartTime, runId: id, stepIndex: fi, agent: task.agent }));\n\t\t\t\tflushPendingStepSteers(fi);\n\t\t\t\tconst singleResult = await runSingleStep(task, {\n\t\t\t\t\tpreviousOutput, placeholder, cwd, sessionEnabled,\n\t\t\t\t\toutputs,\n\t\t\t\t\tsessionDir: config.sessionDir ? path.join(config.sessionDir, `dynamic-${stepIndex}-${taskIdx}`) : undefined,\n\t\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\t\tflatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\t\toutputFile: path.join(asyncDir, `output-${fi}.log`),\n\t\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, fi),\n\t\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, fi),\n\t\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, fi),\n\t\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[fi],\n\t\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),\n\t\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(fi, interrupt),\n\t\t\t\t\tregisterStop: (stop) => registerStepStop(fi, stop),\n\t\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),\n\t\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\t\ttimeoutMessage,\n\t\t\t\t\tstopMessage,\n\t\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\t\tonAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),\n\t\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(fi, event),\n\t\t\t\t\tonWriterProcess,\n\t\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t\t});\n\t\t\t\tconst taskEndTime = Date.now();\n\t\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\t\tconst childStopped = singleResult.stopped === true;\n\t\t\t\tstatusPayload.steps[fi].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\t\tstatusPayload.steps[fi].endedAt = taskEndTime;\n\t\t\t\tstatusPayload.steps[fi].durationMs = taskEndTime - taskStartTime;\n\t\t\t\tstatusPayload.steps[fi].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\t\tstatusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\t\tstatusPayload.steps[fi].stopped = stopped || childStopped ? true : undefined;\n\t\t\t\tstatusPayload.steps[fi].turnBudget = singleResult.turnBudget;\n\t\t\t\tstatusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\t\tstatusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\t\tstatusPayload.steps[fi].toolBudget = singleResult.toolBudget;\n\t\t\t\tstatusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\t\tstatusPayload.steps[fi].model = singleResult.model;\n\t\t\t\tstatusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);\n\t\t\t\tstatusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;\n\t\t\t\tstatusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;\n\t\t\t\tstatusPayload.steps[fi].totalCost = singleResult.totalCost;\n\t\t\t\tstatusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\t\tstatusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;\n\t\t\t\tstatusPayload.steps[fi].transcriptError = singleResult.transcriptError;\n\t\t\t\tstatusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;\n\t\t\t\tstatusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\t\tstatusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\t\tstatusPayload.steps[fi].acceptance = singleResult.acceptance;\n\t\t\t\tstatusPayload.steps[fi].watchdog = singleResult.watchdog;\n\t\t\t\tstatusPayload.lastUpdate = taskEndTime;\n\t\t\t\twriteStatusPayload();\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\t\tts: taskEndTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskEndTime - taskStartTime,\n\t\t\t\t}));\n\t\t\t\tif (singleResult.exitCode !== 0 && failFast) aborted = true;\n\t\t\t\treturn stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: timeoutMessage ?? \"Subagent timed out.\", error: timeoutMessage ?? \"Subagent timed out.\", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };\n\t\t\t}, globalSemaphore);\n\n\t\t\tflatIndex += dynamicSteps.length;\n\t\t\tfor (const pr of parallelResults) {\n\t\t\t\tresults.push({\n\t\t\t\t\tagent: pr.agent,\n\t\t\t\t\toutput: pr.output,\n\t\t\t\t\terror: pr.error,\n\t\t\t\t\tprotocolError: pr.protocolError,\n\t\t\t\t\tsuccess: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,\n\t\t\t\t\texitCode: pr.interrupted === true ? 0 : pr.exitCode,\n\t\t\t\t\tskipped: pr.skipped,\n\t\t\t\t\tinterrupted: pr.interrupted,\n\t\t\t\t\ttimedOut: pr.timedOut,\n\t\t\t\t\tstopped: pr.stopped,\n\t\t\t\t\tturnBudget: pr.turnBudget,\n\t\t\t\t\tturnBudgetExceeded: pr.turnBudgetExceeded,\n\t\t\t\t\twrapUpRequested: pr.wrapUpRequested,\n\t\t\t\t\ttoolBudget: pr.toolBudget,\n\t\t\t\t\ttoolBudgetBlocked: pr.toolBudgetBlocked,\n\t\t\t\t\tsessionFile: pr.sessionFile,\n\t\t\t\t\tintercomTarget: pr.intercomTarget,\n\t\t\t\t\tmodel: pr.model,\n\t\t\t\t\tattemptedModels: pr.attemptedModels,\n\t\t\t\t\tmodelAttempts: pr.modelAttempts,\n\t\t\t\t\ttotalCost: pr.totalCost,\n\t\t\t\t\tartifactPaths: pr.artifactPaths,\n\t\t\t\t\ttranscriptPath: pr.transcriptPath,\n\t\t\t\t\ttranscriptError: pr.transcriptError,\n\t\t\t\t\tstructuredOutput: pr.structuredOutput,\n\t\t\t\t\tstructuredOutputPath: pr.structuredOutputPath,\n\t\t\t\t\tstructuredOutputSchemaPath: pr.structuredOutputSchemaPath,\n\t\t\t\t\tacceptance: pr.acceptance,\n\t\t\t\t\twatchdog: pr.watchdog,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst collection = collectDynamicResults(step as Parameters<typeof collectDynamicResults>[0], materialized.items, parallelResults);\n\t\t\tconst failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\tif (failures.length === 0) {\n\t\t\t\ttry {\n\t\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collection);\n\t\t\t\t\toutputs[step.collect.as] = {\n\t\t\t\t\t\ttext: JSON.stringify(collection),\n\t\t\t\t\t\tstructured: collection,\n\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t};\n\t\t\t\t\tstatusPayload.outputs = outputs;\n\t\t\t\t\tconst groupAcceptance = !timedOut && !stopped\n\t\t\t\t\t\t? await evaluateAcceptance({\n\t\t\t\t\t\t\tacceptance: effectiveDynamicGroupAcceptance,\n\t\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\t\t\t\tnotes: `Dynamic fanout collected ${collection.length} result(s) into ${step.collect.as}.`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcwd,\n\t\t\t\t\t\t\tsignal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),\n\t\t\t\t\t\t\tabortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? \"Subagent timed out.\",\n\t\t\t\t\t\t})\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst groupStopped = stopped || stopAbortController.signal.aborted;\n\t\t\t\t\tconst groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);\n\t\t\t\t\tconst effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;\n\t\t\t\t\tconst groupAcceptanceFailure = effectiveDynamicGroupAcceptance.explicit && effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;\n\t\t\t\t\tconst groupError = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? \"Subagent timed out.\" : groupAcceptanceFailure;\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, groupError ? groupStopped ? \"stopped\" : \"failed\" : \"completed\", groupError, effectiveGroupAcceptance);\n\t\t\t\t\tif (groupError) {\n\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\t\toutput: groupError,\n\t\t\t\t\t\t\terror: groupError,\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\texitCode: 1,\n\t\t\t\t\t\t\ttimedOut: groupTimedOut ? true : undefined,\n\t\t\t\t\t\t\tstopped: groupStopped ? true : undefined,\n\t\t\t\t\t\t\tstructuredOutput: collection,\n\t\t\t\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tstatusPayload.error = groupError;\n\t\t\t\t\t\tstatusPayload.stopped = groupStopped ? true : statusPayload.stopped;\n\t\t\t\t\t}\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\tresults.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1, structuredOutput: collection });\n\t\t\t\t\tstatusPayload.error = message;\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"failed\", message);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousOutput = aggregateParallelOutputs(\n\t\t\t\tparallelResults.map((r, i) => ({\n\t\t\t\t\tagent: r.agent,\n\t\t\t\t\ttaskIndex: i,\n\t\t\t\t\toutput: r.output,\n\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\terror: r.error,\n\t\t\t\t})),\n\t\t\t\t(i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`,\n\t\t\t);\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.dynamic.completed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex,\n\t\t\t\tsuccess: failures.length === 0,\n\t\t\t}));\n\t\t\tif (failures.length > 0) markDynamicGraphGroup(stepIndex, \"failed\", failures[0]?.error ?? \"Dynamic fanout child failed.\");\n\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\twriteStatusPayload();\n\t\t\tif (failures.length > 0 || statusPayload.error) break;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isParallelGroup(step)) {\n\t\t\tconst group = step;\n\t\t\tconst concurrency = group.concurrency ?? MAX_PARALLEL_CONCURRENCY;\n\t\t\tconst failFast = group.failFast ?? false;\n\t\t\tconst groupStartFlatIndex = flatIndex;\n\t\t\tlet aborted = false;\n\t\t\tlet worktreeSetup: WorktreeSetup | undefined;\n\t\t\tif (group.worktree) {\n\t\t\t\tconst worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(group.parallel, cwd);\n\t\t\t\tif (worktreeTaskCwdConflict) {\n\t\t\t\t\tconst failedAt = Date.now();\n\t\t\t\t\tmarkParallelGroupSetupFailure({\n\t\t\t\t\t\tstatusPayload,\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\t\tsetupError: formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, cwd),\n\t\t\t\t\t\tfailedAt,\n\t\t\t\t\t\tstatusPath,\n\t\t\t\t\t\teventsPath,\n\t\t\t\t\t\tasyncDir,\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t});\n\t\t\t\t\tflatIndex += group.parallel.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tworktreeSetup = createWorktrees(cwd, `${id}-s${stepIndex}`, group.parallel.length, {\n\t\t\t\t\t\tagents: group.parallel.map((task) => task.agent),\n\t\t\t\t\t\tsetupHook: config.worktreeSetupHook\n\t\t\t\t\t\t\t? { hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tbaseDir: config.worktreeBaseDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst setupError = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst failedAt = Date.now();\n\t\t\t\t\tmarkParallelGroupSetupFailure({\n\t\t\t\t\t\tstatusPayload,\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\t\tsetupError,\n\t\t\t\t\t\tfailedAt,\n\t\t\t\t\t\tstatusPath,\n\t\t\t\t\t\teventsPath,\n\t\t\t\t\t\tasyncDir,\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t});\n\t\t\t\t\tflatIndex += group.parallel.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (group.worktree) ensureParallelProgressFile(cwd, group);\n\t\t\t\tconst groupStartTime = Date.now();\n\t\t\t\tmarkParallelGroupRunning({\n\t\t\t\t\tstatusPayload,\n\t\t\t\t\tgroup,\n\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\tgroupStartTime,\n\t\t\t\t\tstatusPath,\n\t\t\t\t\teventsPath,\n\t\t\t\t\tasyncDir,\n\t\t\t\t\trunId: id,\n\t\t\t\t\tstepIndex,\n\t\t\t\t});\n\t\t\t\tconst parallelResults = await mapConcurrent(\n\t\t\t\t\tgroup.parallel,\n\t\t\t\t\tconcurrency,\n\t\t\t\t\tasync (task, taskIdx) => {\n\t\t\t\t\t\tconst fi = groupStartFlatIndex + taskIdx;\n\t\t\t\t\t\tif (timedOut) return timedOutStepResult(task.agent);\n\t\t\t\t\t\tif (stopped) return stoppedStepResult(task.agent);\n\t\t\t\t\t\tif (interrupted) return pausedStepResult(task.agent);\n\t\t\t\t\t\tif (aborted && failFast) {\n\t\t\t\t\t\t\tconst skippedAt = Date.now();\n\t\t\t\t\t\t\tstatusPayload.steps[fi].status = \"failed\";\n\t\t\t\t\t\t\tstatusPayload.steps[fi].error = \"Skipped due to fail-fast\";\n\t\t\t\t\t\t\tstatusPayload.steps[fi].startedAt = skippedAt;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = skippedAt;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = 0;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].exitCode = -1;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\t\t\t\tstatusPayload.lastUpdate = skippedAt;\n\t\t\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\t\ttype: \"subagent.step.failed\", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: -1, durationMs: 0,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\treturn { agent: task.agent, output: \"(skipped — fail-fast)\", exitCode: -1 as number | null, skipped: true };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst taskStartTime = Date.now();\n\t\t\t\t\t\tstatusPayload.currentStep = fi;\n\t\t\t\t\t\tstatusPayload.steps[fi].status = \"running\";\n\t\t\t\t\t\tstatusPayload.steps[fi].error = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\t\t\tresetStepLiveDetail(statusPayload.steps[fi]);\n\t\t\t\t\t\tstatusPayload.steps[fi].startedAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].lastActivityAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);\n\t\t\t\t\t\tstatusPayload.lastActivityAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.lastUpdate = taskStartTime;\n\t\t\t\t\t\twriteStatusPayload();\n\n\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\ttype: \"subagent.step.started\", ts: taskStartTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\t\t}));\n\n\t\t\t\t\t\tconst taskSessionDir = config.sessionDir\n\t\t\t\t\t\t\t? path.join(config.sessionDir, `parallel-${taskIdx}`)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tconst { taskForRun, taskCwd } = prepareParallelTaskRun(task, cwd, worktreeSetup, taskIdx);\n\t\t\t\t\t\tflushPendingStepSteers(fi);\n\n\t\t\t\t\t\tconst singleResult = await runSingleStep(taskForRun, {\n\t\t\t\t\t\t\tpreviousOutput, placeholder, cwd: taskCwd, sessionEnabled,\n\t\t\t\t\t\t\toutputs,\n\t\t\t\t\t\t\tsessionDir: taskSessionDir,\n\t\t\t\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\t\t\t\tflatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\t\t\t\toutputFile: path.join(asyncDir, `output-${fi}.log`),\n\t\t\t\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, fi),\n\t\t\t\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, fi),\n\t\t\t\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, fi),\n\t\t\t\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[fi],\n\t\t\t\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),\n\t\t\t\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(fi, interrupt),\n\t\t\t\t\t\t\tregisterStop: (stop) => registerStepStop(fi, stop),\n\t\t\t\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),\n\t\t\t\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\t\t\t\ttimeoutMessage,\n\t\t\t\t\t\t\tstopMessage,\n\t\t\t\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\t\t\t\tonAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),\n\t\t\t\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(fi, event),\n\t\t\t\t\t\t\tonWriterProcess,\n\t\t\t\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (task.sessionFile) {\n\t\t\t\t\t\t\tlatestSessionFile = task.sessionFile;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst taskEndTime = Date.now();\n\t\t\t\t\t\tconst taskDuration = taskEndTime - taskStartTime;\n\t\t\t\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\t\t\t\tconst childStopped = singleResult.stopped === true;\n\n\t\t\t\t\t\tstatusPayload.steps[fi].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = taskEndTime;\n\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = taskDuration;\n\t\t\t\t\t\tstatusPayload.steps[fi].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\t\t\t\tstatusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].stopped = stopped || childStopped ? true : undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].turnBudget = singleResult.turnBudget;\n\t\t\t\t\t\tstatusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\t\t\t\tstatusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\t\t\t\tstatusPayload.steps[fi].toolBudget = singleResult.toolBudget;\n\t\t\t\t\t\tstatusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\t\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\t\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\t\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\t\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\t\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\t\t\t\tstatusPayload.steps[fi].model = singleResult.model;\n\t\t\t\t\t\tstatusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);\n\t\t\t\t\t\tstatusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;\n\t\t\t\t\t\tstatusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;\n\t\t\t\t\t\tstatusPayload.steps[fi].totalCost = singleResult.totalCost;\n\t\t\t\t\t\tstatusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\t\t\t\tstatusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].transcriptError = singleResult.transcriptError;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].acceptance = singleResult.acceptance;\n\t\t\t\t\t\tstatusPayload.steps[fi].watchdog = singleResult.watchdog;\n\t\t\t\t\t\tstatusPayload.lastUpdate = taskEndTime;\n\t\t\t\t\t\twriteStatusPayload();\n\n\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\t\t\t\tts: taskEndTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskDuration,\n\t\t\t\t\t\t}));\n\t\t\t\t\t\tif (singleResult.completionGuardTriggered) {\n\t\t\t\t\t\t\tconst event = buildControlEvent({\n\t\t\t\t\t\t\t\tfrom: statusPayload.steps[fi].activityState,\n\t\t\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\t\t\tagent: task.agent,\n\t\t\t\t\t\t\t\tindex: fi,\n\t\t\t\t\t\t\t\tts: taskEndTime,\n\t\t\t\t\t\t\t\tmessage: `${task.agent} completed without making edits for an implementation task`,\n\t\t\t\t\t\t\t\treason: \"completion_guard\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tappendControlEvent(event);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (singleResult.exitCode !== 0 && failFast) aborted = true;\n\t\t\t\t\t\treturn stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: timeoutMessage ?? \"Subagent timed out.\", error: timeoutMessage ?? \"Subagent timed out.\", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };\n\t\t\t\t\t},\n\t\t\t\t\tglobalSemaphore,\n\t\t\t\t);\n\n\t\t\t\tflatIndex += group.parallel.length;\n\n\t\t\t\tfor (let t = 0; t < group.parallel.length; t++) {\n\t\t\t\t\tconst fi = groupStartFlatIndex + t;\n\t\t\t\t\tconst sessionTokens = config.sessionDir\n\t\t\t\t\t\t? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`))\n\t\t\t\t\t\t: null;\n\t\t\t\t\tconst taskTokens = sessionTokens ?? tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);\n\t\t\t\t\tif (!taskTokens) continue;\n\t\t\t\t\tstatusPayload.steps[fi].tokens = taskTokens;\n\t\t\t\t\tpreviousCumulativeTokens = {\n\t\t\t\t\t\tinput: previousCumulativeTokens.input + taskTokens.input,\n\t\t\t\t\t\toutput: previousCumulativeTokens.output + taskTokens.output,\n\t\t\t\t\t\ttotal: previousCumulativeTokens.total + taskTokens.total,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatusPayload.totalTokens = { ...previousCumulativeTokens };\n\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\twriteStatusPayload();\n\n\t\t\t\tfor (const pr of parallelResults) {\n\t\t\t\t\tresults.push({\n\t\t\t\t\t\tagent: pr.agent,\n\t\t\t\t\t\toutput: pr.output,\n\t\t\t\t\t\terror: pr.error,\n\t\t\t\t\t\tprotocolError: pr.protocolError,\n\t\t\t\t\t\tsuccess: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,\n\t\t\t\t\t\texitCode: pr.interrupted === true ? 0 : pr.exitCode,\n\t\t\t\t\t\tskipped: pr.skipped,\n\t\t\t\t\t\tinterrupted: pr.interrupted,\n\t\t\t\t\t\ttimedOut: pr.timedOut,\n\t\t\t\t\t\tstopped: pr.stopped,\n\t\t\t\t\t\tturnBudget: pr.turnBudget,\n\t\t\t\t\t\tturnBudgetExceeded: pr.turnBudgetExceeded,\n\t\t\t\t\t\twrapUpRequested: pr.wrapUpRequested,\n\t\t\t\t\t\ttoolBudget: pr.toolBudget,\n\t\t\t\t\t\ttoolBudgetBlocked: pr.toolBudgetBlocked,\n\t\t\t\t\t\tsessionFile: pr.sessionFile,\n\t\t\t\t\t\tintercomTarget: pr.intercomTarget,\n\t\t\t\t\t\tmodel: pr.model,\n\t\t\t\t\t\tattemptedModels: pr.attemptedModels,\n\t\t\t\t\t\tmodelAttempts: pr.modelAttempts,\n\t\t\t\t\t\ttotalCost: pr.totalCost,\n\t\t\t\t\t\tartifactPaths: pr.artifactPaths,\n\t\t\t\t\t\ttranscriptPath: pr.transcriptPath,\n\t\t\t\t\t\ttranscriptError: pr.transcriptError,\n\t\t\t\t\t\tstructuredOutput: pr.structuredOutput,\n\t\t\t\t\t\tstructuredOutputPath: pr.structuredOutputPath,\n\t\t\t\t\t\tstructuredOutputSchemaPath: pr.structuredOutputSchemaPath,\n\t\t\t\t\t\tacceptance: pr.acceptance,\n\t\t\t\t\t\twatchdog: pr.watchdog,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (let t = 0; t < group.parallel.length; t++) {\n\t\t\t\t\tconst outputName = group.parallel[t]?.outputName;\n\t\t\t\t\tif (outputName) outputs[outputName] = outputEntryFromAsyncResult({\n\t\t\t\t\t\tagent: parallelResults[t]!.agent,\n\t\t\t\t\t\toutput: parallelResults[t]!.output,\n\t\t\t\t\t\tstructuredOutput: parallelResults[t]!.structuredOutput,\n\t\t\t\t\t}, stepIndex);\n\t\t\t\t}\n\t\t\t\tstatusPayload.outputs = outputs;\n\n\t\t\t\tpreviousOutput = aggregateParallelOutputs(\n\t\t\t\t\tparallelResults.map((r) => ({\n\t\t\t\t\t\tagent: r.agent,\n\t\t\t\t\t\toutput: r.output,\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\terror: r.error,\n\t\t\t\t\t\tmodel: r.model,\n\t\t\t\t\t\tattemptedModels: r.attemptedModels,\n\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tpreviousOutput = appendParallelWorktreeSummary(previousOutput, worktreeSetup, asyncDir, stepIndex, group);\n\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.parallel.completed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\tstepIndex,\n\t\t\t\t\tsuccess: parallelResults.every((r) => r.exitCode === 0 || r.exitCode === -1),\n\t\t\t\t}));\n\n\t\t\t\tif (parallelResults.some((r) => r.exitCode !== 0 && r.exitCode !== -1)) {\n\t\t\t\t\tbreak;\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 {\n\t\t\tconst seqStep = step as SubagentStep;\n\t\t\tconst stepStartTime = Date.now();\n\t\t\tstatusPayload.currentStep = flatIndex;\n\t\t\tstatusPayload.steps[flatIndex].status = \"running\";\n\t\t\tstatusPayload.steps[flatIndex].activityState = undefined;\n\t\t\tstatusPayload.activityState = undefined;\n\t\t\tresetStepLiveDetail(statusPayload.steps[flatIndex]);\n\t\t\tstatusPayload.steps[flatIndex].skills = seqStep.skills;\n\t\t\tstatusPayload.steps[flatIndex].startedAt = stepStartTime;\n\t\t\tstatusPayload.steps[flatIndex].lastActivityAt = stepStartTime;\n\t\t\tstatusPayload.lastActivityAt = stepStartTime;\n\t\t\tstatusPayload.lastUpdate = stepStartTime;\n\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${flatIndex}.log`);\n\t\t\twriteStatusPayload();\n\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.step.started\",\n\t\t\t\tts: stepStartTime,\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex: flatIndex,\n\t\t\t\tagent: seqStep.agent,\n\t\t\t}));\n\n\t\t\tflushPendingStepSteers(flatIndex);\n\t\t\tconst singleResult = await runSingleStep(seqStep, {\n\t\t\t\tpreviousOutput, placeholder, cwd, sessionEnabled,\n\t\t\t\toutputs: statusPayload.mode === \"single\" ? undefined : outputs,\n\t\t\t\tsessionDir: config.sessionDir,\n\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\tflatIndex, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\toutputFile: path.join(asyncDir, `output-${flatIndex}.log`),\n\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, flatIndex),\n\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, flatIndex),\n\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, flatIndex),\n\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[flatIndex],\n\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(flatIndex, interrupt),\n\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),\n\t\t\t\tregisterStop: (stop) => registerStepStop(flatIndex, stop),\n\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(flatIndex, abort),\n\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\ttimeoutMessage,\n\t\t\t\tstopMessage,\n\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\tonAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking),\n\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),\n\t\t\t\tonWriterProcess,\n\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t});\n\t\t\tif (seqStep.sessionFile) {\n\t\t\t\tlatestSessionFile = seqStep.sessionFile;\n\t\t\t}\n\n\t\t\tpreviousOutput = singleResult.output;\n\t\t\tconst childStopped = singleResult.stopped === true;\n\t\t\tresults.push({\n\t\t\t\tagent: singleResult.agent,\n\t\t\t\toutput: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.output,\n\t\t\t\terror: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error,\n\t\t\t\tprotocolError: singleResult.protocolError,\n\t\t\t\tsuccess: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,\n\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,\n\t\t\t\tsessionFile: singleResult.sessionFile,\n\t\t\t\tintercomTarget: singleResult.intercomTarget,\n\t\t\t\tmodel: singleResult.model,\n\t\t\t\tattemptedModels: singleResult.attemptedModels,\n\t\t\t\tmodelAttempts: singleResult.modelAttempts,\n\t\t\t\ttotalCost: singleResult.totalCost,\n\t\t\t\tartifactPaths: singleResult.artifactPaths,\n\t\t\t\ttranscriptPath: singleResult.transcriptPath,\n\t\t\t\ttranscriptError: singleResult.transcriptError,\n\t\t\t\tstructuredOutput: singleResult.structuredOutput,\n\t\t\t\tstructuredOutputPath: singleResult.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,\n\t\t\t\tacceptance: singleResult.acceptance,\n\t\t\t\twatchdog: singleResult.watchdog,\n\t\t\t\tinterrupted: singleResult.interrupted,\n\t\t\t\ttimedOut: timedOut || singleResult.timedOut ? true : undefined,\n\t\t\t\tstopped: stopped || childStopped ? true : undefined,\n\t\t\t\tturnBudget: singleResult.turnBudget,\n\t\t\t\tturnBudgetExceeded: singleResult.turnBudgetExceeded,\n\t\t\t\twrapUpRequested: singleResult.wrapUpRequested,\n\t\t\t\ttoolBudget: singleResult.toolBudget,\n\t\t\t\ttoolBudgetBlocked: singleResult.toolBudgetBlocked,\n\t\t\t});\n\t\t\tif (seqStep.outputName) {\n\t\t\t\toutputs[seqStep.outputName] = outputEntryFromAsyncResult({\n\t\t\t\t\tagent: singleResult.agent,\n\t\t\t\t\toutput: singleResult.output,\n\t\t\t\t\tstructuredOutput: singleResult.structuredOutput,\n\t\t\t\t}, stepIndex);\n\t\t\t}\n\t\t\tstatusPayload.outputs = outputs;\n\n\t\t\tconst cumulativeTokens = config.sessionDir ? parseSessionTokens(config.sessionDir) : null;\n\t\t\tlet stepTokens: TokenUsage | null = cumulativeTokens\n\t\t\t\t? {\n\t\t\t\t\t\tinput: cumulativeTokens.input - previousCumulativeTokens.input,\n\t\t\t\t\t\toutput: cumulativeTokens.output - previousCumulativeTokens.output,\n\t\t\t\t\t\ttotal: cumulativeTokens.total - previousCumulativeTokens.total,\n\t\t\t\t\t}\n\t\t\t\t: null;\n\t\t\tif (cumulativeTokens) {\n\t\t\t\tpreviousCumulativeTokens = cumulativeTokens;\n\t\t\t} else {\n\t\t\t\tstepTokens = tokenUsageFromAttempts(singleResult.modelAttempts);\n\t\t\t\tif (stepTokens) {\n\t\t\t\t\tpreviousCumulativeTokens = {\n\t\t\t\t\t\tinput: previousCumulativeTokens.input + stepTokens.input,\n\t\t\t\t\t\toutput: previousCumulativeTokens.output + stepTokens.output,\n\t\t\t\t\t\ttotal: previousCumulativeTokens.total + stepTokens.total,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst stepEndTime = Date.now();\n\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\tstatusPayload.steps[flatIndex].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\tstatusPayload.steps[flatIndex].endedAt = stepEndTime;\n\t\t\tstatusPayload.steps[flatIndex].durationMs = stepEndTime - stepStartTime;\n\t\t\tstatusPayload.steps[flatIndex].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\tstatusPayload.steps[flatIndex].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\tstatusPayload.steps[flatIndex].stopped = stopped || childStopped ? true : undefined;\n\t\t\tstatusPayload.steps[flatIndex].turnBudget = singleResult.turnBudget;\n\t\t\tstatusPayload.steps[flatIndex].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\tstatusPayload.steps[flatIndex].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\tstatusPayload.steps[flatIndex].toolBudget = singleResult.toolBudget;\n\t\t\tstatusPayload.steps[flatIndex].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\tstatusPayload.steps[flatIndex].model = singleResult.model;\n\t\t\tstatusPayload.steps[flatIndex].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[flatIndex].thinking);\n\t\t\tstatusPayload.steps[flatIndex].attemptedModels = singleResult.attemptedModels;\n\t\t\tstatusPayload.steps[flatIndex].modelAttempts = singleResult.modelAttempts;\n\t\t\tstatusPayload.steps[flatIndex].totalCost = singleResult.totalCost;\n\t\t\tstatusPayload.steps[flatIndex].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\tstatusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;\n\t\t\tstatusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutput = singleResult.structuredOutput;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\tstatusPayload.steps[flatIndex].acceptance = singleResult.acceptance;\n\t\t\tstatusPayload.steps[flatIndex].watchdog = singleResult.watchdog;\n\t\t\tif (stepTokens) {\n\t\t\t\tstatusPayload.steps[flatIndex].tokens = stepTokens;\n\t\t\t\tstatusPayload.totalTokens = { ...previousCumulativeTokens };\n\t\t\t}\n\t\t\tstatusPayload.lastUpdate = stepEndTime;\n\t\t\twriteStatusPayload();\n\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\tts: stepEndTime,\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex: flatIndex,\n\t\t\t\tagent: seqStep.agent,\n\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode,\n\t\t\t\tdurationMs: stepEndTime - stepStartTime,\n\t\t\t\ttokens: stepTokens,\n\t\t\t}));\n\t\t\tif (singleResult.completionGuardTriggered) {\n\t\t\t\tconst event = buildControlEvent({\n\t\t\t\t\tfrom: statusPayload.steps[flatIndex].activityState,\n\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\trunId: id,\n\t\t\t\t\tagent: seqStep.agent,\n\t\t\t\t\tindex: flatIndex,\n\t\t\t\t\tts: stepEndTime,\n\t\t\t\t\tmessage: `${seqStep.agent} completed without making edits for an implementation task`,\n\t\t\t\t\treason: \"completion_guard\",\n\t\t\t\t});\n\t\t\t\tappendControlEvent(event);\n\t\t\t}\n\n\t\t\tflatIndex++;\n\t\t\tif (singleResult.exitCode !== 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tlet summary = results.map((r) => `${r.agent}:\\n${r.output}`).join(\"\\n\\n\");\n\tlet truncated = false;\n\n\tif (maxOutput) {\n\t\tconst config = { ...DEFAULT_MAX_OUTPUT, ...maxOutput };\n\t\tconst lastArtifactPath = results[results.length - 1]?.artifactPaths?.outputPath;\n\t\tconst truncResult = truncateOutput(summary, config, lastArtifactPath);\n\t\tif (truncResult.truncated) {\n\t\t\tsummary = truncResult.text;\n\t\t\ttruncated = true;\n\t\t}\n\t}\n\n\tconst resultMode = config.resultMode ?? statusPayload.mode;\n\tconst totalCost = results.reduce<CostSummary>((sum, result) => ({\n\t\tinputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),\n\t\toutputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),\n\t\tcostUsd: sum.costUsd + (result.totalCost?.costUsd ?? 0),\n\t}), { inputTokens: 0, outputTokens: 0, costUsd: 0 });\n\tconst finalTotalCost = totalCost.inputTokens > 0 || totalCost.outputTokens > 0 || totalCost.costUsd > 0 ? totalCost : undefined;\n\tconst finalFlatAgents = statusPayload.steps.map((step) => step.agent);\n\tconst agentName = finalFlatAgents.length === 1\n\t\t? finalFlatAgents[0]!\n\t\t: resultMode === \"parallel\"\n\t\t\t? `parallel:${finalFlatAgents.join(\"+\")}`\n\t\t\t: `chain:${finalFlatAgents.join(\"->\")}`;\n\tlet sessionFile: string | undefined;\n\tlet shareUrl: string | undefined;\n\tlet gistUrl: string | undefined;\n\tlet shareError: string | undefined;\n\n\tif (shareEnabled) {\n\t\tsessionFile = config.sessionDir\n\t\t\t? (findLatestSessionFile(config.sessionDir) ?? undefined)\n\t\t\t: undefined;\n\t\tif (!sessionFile && latestSessionFile) {\n\t\t\tsessionFile = latestSessionFile;\n\t\t}\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tconst exportDir = config.sessionDir ?? path.dirname(sessionFile);\n\t\t\t\tconst htmlPath = await exportSessionHtml(sessionFile, exportDir, config.piPackageRoot);\n\t\t\t\tconst share = createShareLink(htmlPath);\n\t\t\t\tif (\"error\" in share) shareError = share.error;\n\t\t\t\telse {\n\t\t\t\t\tshareUrl = share.shareUrl;\n\t\t\t\t\tgistUrl = share.gistUrl;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tshareError = String(err);\n\t\t\t}\n\t\t} else {\n\t\t\tshareError = \"Session file not found.\";\n\t\t}\n\t}\n\n\tif (activityTimer) {\n\t\tclearInterval(activityTimer);\n\t\tactivityTimer = undefined;\n\t}\n\tif (timeoutTimer) {\n\t\tclearTimeout(timeoutTimer);\n\t\ttimeoutTimer = undefined;\n\t}\n\tstatusPayload.state = stopped ? \"stopped\" : timedOut || turnBudgetExceeded ? \"failed\" : interrupted ? \"paused\" : results.every((r) => r.success) ? \"complete\" : \"failed\";\n\tcloseSteerInbox(asyncDir, statusPayload.state);\n\tdisposeControlInbox();\n\tfor (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);\n\tconst effectiveSessionFile = sessionFile ?? latestSessionFile;\n\tconst steeringLifecycle = steeringStatus(statusPayload);\n\tfor (const request of steeringLifecycle.recent) {\n\t\tlet changed = false;\n\t\tfor (const target of request.targets) {\n\t\t\tif (target.state !== \"scheduled\" && target.state !== \"routed\") continue;\n\t\t\tchanged = true;\n\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"failed\", Date.now(), { reason: \"child terminated before steering delivery\" });\n\t\t\tmarkSteeringAttention(target.index);\n\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: request.id, ts: request.requestedAt, message: \"child terminated before steering delivery\" }, target.index, { reason: \"child terminated before steering delivery\" });\n\t\t}\n\t\tif (changed) emitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: child terminated before delivery.`);\n\t}\n\tconst runEndedAt = Date.now();\n\tstatusPayload.activityState = undefined;\n\tif (stopped) {\n\t\tstatusPayload.stopped = true;\n\t\tstatusPayload.error = stopMessage;\n\t}\n\tif (timedOut) {\n\t\tstatusPayload.timedOut = true;\n\t\tstatusPayload.error = timeoutMessage ?? \"Subagent timed out.\";\n\t}\n\tif (turnBudgetExceeded && !statusPayload.error) {\n\t\tconst budget = statusPayload.turnBudget;\n\t\tstatusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : \"Subagent exceeded turn budget.\";\n\t}\n\tstatusPayload.endedAt = runEndedAt;\n\tstatusPayload.lastUpdate = runEndedAt;\n\tstatusPayload.sessionFile = effectiveSessionFile;\n\tstatusPayload.totalCost = finalTotalCost;\n\tstatusPayload.shareUrl = shareUrl;\n\tstatusPayload.gistUrl = gistUrl;\n\tstatusPayload.shareError = shareError;\n\tif (statusPayload.state === \"failed\" && !statusPayload.error) {\n\t\tconst failedStep = statusPayload.steps.find((s) => s.status === \"failed\");\n\t\tif (failedStep?.agent) {\n\t\t\tstatusPayload.error = `Step failed: ${failedStep.agent}`;\n\t\t}\n\t}\n\twriteStatusPayload();\n\tappendJsonl(\n\t\teventsPath,\n\t\tJSON.stringify({\n\t\t\ttype: \"subagent.run.completed\",\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tts: runEndedAt,\n\t\t\trunId: id,\n\t\t\tstatus: statusPayload.state,\n\t\t\tdurationMs: runEndedAt - overallStartTime,\n\t\t\ttotalTokens: statusPayload.totalTokens,\n\t\t\ttotalCost: finalTotalCost,\n\t\t}),\n\t);\n\twriteRunLog(logPath, {\n\t\tid,\n\t\tmode: statusPayload.mode,\n\t\tcwd,\n\t\tstartedAt: overallStartTime,\n\t\tendedAt: runEndedAt,\n\t\tsteps: statusPayload.steps.map((step) => ({\n\t\t\tagent: step.agent,\n\t\t\tstatus: step.status,\n\t\t\tdurationMs: step.durationMs,\n\t\t})),\n\t\tsummary,\n\t\ttruncated,\n\t\tartifactsDir,\n\t\tsessionFile: effectiveSessionFile,\n\t\tshareUrl,\n\t\tshareError,\n\t});\n\n\ttry {\n\t\twriteAtomicJson(resultPath, {\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tid,\n\t\t\tagent: agentName,\n\t\t\tmode: resultMode,\n\t\t\tsuccess: !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),\n\t\t\tstate: stopped ? \"stopped\" : timedOut || turnBudgetExceeded ? \"failed\" : interrupted ? \"paused\" : results.every((r) => r.success) ? \"complete\" : \"failed\",\n\t\t\tsummary: stopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? (statusPayload.error ?? \"Subagent exceeded turn budget.\") : interrupted ? \"Paused after interrupt. Waiting for explicit next action.\" : summary,\n\t\t\t...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),\n\t\t\t...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),\n\t\t\t...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),\n\t\t\t...(statusPayload.turnBudgetExceeded ? { turnBudgetExceeded: true } : {}),\n\t\t\t...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),\n\t\t\t...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),\n\t\t\t...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),\n\t\t\t...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? \"Subagent timed out.\" } : turnBudgetExceeded ? { error: statusPayload.error ?? \"Subagent exceeded turn budget.\" } : {}),\n\t\t\tresults: results.map((r) => ({\n\t\t\t\tagent: r.agent,\n\t\t\t\toutput: r.output,\n\t\t\t\terror: r.error,\n\t\t\t\tprotocolError: r.protocolError,\n\t\t\t\tsuccess: r.success,\n\t\t\t\tskipped: r.skipped || undefined,\n\t\t\t\tinterrupted: r.interrupted || undefined,\n\t\t\t\ttimedOut: r.timedOut || undefined,\n\t\t\t\tstopped: r.stopped || undefined,\n\t\t\t\tturnBudget: r.turnBudget,\n\t\t\t\tturnBudgetExceeded: r.turnBudgetExceeded || undefined,\n\t\t\t\twrapUpRequested: r.wrapUpRequested || undefined,\n\t\t\t\ttoolBudget: r.toolBudget,\n\t\t\t\ttoolBudgetBlocked: r.toolBudgetBlocked || undefined,\n\t\t\t\tsessionFile: r.sessionFile,\n\t\t\t\tintercomTarget: r.intercomTarget,\n\t\t\t\tmodel: r.model,\n\t\t\t\tattemptedModels: r.attemptedModels,\n\t\t\t\tmodelAttempts: r.modelAttempts,\n\t\t\t\ttotalCost: r.totalCost,\n\t\t\t\tartifactPaths: r.artifactPaths,\n\t\t\t\ttruncated: r.truncated,\n\t\t\t\ttranscriptPath: r.transcriptPath,\n\t\t\t\ttranscriptError: r.transcriptError,\n\t\t\t\tstructuredOutput: r.structuredOutput,\n\t\t\t\tstructuredOutputPath: r.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: r.structuredOutputSchemaPath,\n\t\t\t\tacceptance: r.acceptance,\n\t\t\t\twatchdog: r.watchdog,\n\t\t\t})),\n\t\t\toutputs,\n\t\t\tworkflowGraph: statusPayload.workflowGraph,\n\t\t\texitCode: stopped || timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,\n\t\t\ttimestamp: runEndedAt,\n\t\t\tdurationMs: runEndedAt - overallStartTime,\n\t\t\ttotalTokens: statusPayload.totalTokens,\n\t\t\ttotalCost: finalTotalCost,\n\t\t\ttruncated,\n\t\t\tartifactsDir,\n\t\t\tcwd,\n\t\t\tasyncDir,\n\t\t\tsessionId: config.sessionId,\n\t\t\tsessionFile: effectiveSessionFile,\n\t\t\tintercomTarget: config.controlIntercomTarget,\n\t\t\tshareUrl,\n\t\t\tgistUrl,\n\t\t\tshareError,\n\t\t\t...(taskIndex !== undefined && { taskIndex }),\n\t\t\t...(totalTasks !== undefined && { totalTasks }),\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to write result file ${resultPath}:`, err);\n\t}\n}\n\nasync function waitForStartupControl(\n\tcontrolPath: string,\n\ttoken: string,\n\taction: \"ack\" | \"proceed\",\n\ttimeoutMs = 30_000,\n): Promise<void> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (fs.existsSync(controlPath)) {\n\t\t\tlet payload: { action?: unknown; token?: unknown };\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(fs.readFileSync(controlPath, \"utf-8\")) as { action?: unknown; token?: unknown };\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t\tif (payload.token !== token) throw new Error(\"Runner startup control token does not match the acquired session lease.\");\n\t\t\tif (payload.action === action) return;\n\t\t\tif (payload.action !== \"ack\" && payload.action !== \"proceed\") throw new Error(\"Runner startup control action is invalid.\");\n\t\t}\n\t\tawait new Promise((resolve) => setTimeout(resolve, 20));\n\t}\n\tthrow new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);\n}\n\nasync function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {\n\tlet lease: ReturnType<typeof acquireSessionLease> | undefined;\n\tlet startupCommitted = config.revivalLease === undefined;\n\tconst startupPath = path.join(config.asyncDir, \"runner-startup.json\");\n\tconst startupAckPath = path.join(config.asyncDir, \"runner-startup-ack.json\");\n\tconst startupProceedPath = path.join(config.asyncDir, \"runner-startup-proceed.json\");\n\tconst releaseOnExit = (): void => {\n\t\ttry {\n\t\t\tlease?.release();\n\t\t} catch {\n\t\t\t// Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.\n\t\t}\n\t};\n\tprocess.once(\"exit\", releaseOnExit);\n\ttry {\n\t\tif (config.revivalLease) {\n\t\t\tlease = acquireSessionLease(config.revivalLease);\n\t\t\twriteAtomicJson(startupPath, { state: \"ready\", token: lease.owner.token, pid: process.pid, owner: lease.owner });\n\t\t\tawait waitForStartupControl(startupAckPath, lease.owner.token, \"ack\");\n\t\t\twriteAtomicJson(startupPath, { state: \"acknowledged\", token: lease.owner.token, pid: process.pid });\n\t\t\tawait waitForStartupControl(startupProceedPath, lease.owner.token, \"proceed\");\n\t\t\tstartupCommitted = true;\n\t\t\tfor (const controlPath of [startupAckPath, startupProceedPath]) {\n\t\t\t\ttry {\n\t\t\t\t\tfs.rmSync(controlPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Startup control cleanup is best effort after the parent commits the run.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait runSubagent(config, lease ? (writer) => lease!.updateWriter(writer) : undefined);\n\t} catch (error) {\n\t\tif (config.revivalLease && !startupCommitted) {\n\t\t\ttry {\n\t\t\t\twriteAtomicJson(startupPath, { state: \"error\", pid: process.pid, error: error instanceof Error ? error.message : String(error) });\n\t\t\t} catch {\n\t\t\t\t// The parent will time out and terminate this runner if the handshake cannot be written.\n\t\t\t}\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tprocess.off(\"exit\", releaseOnExit);\n\t\tif (lease) {\n\t\t\ttry {\n\t\t\t\tlease.release();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to release session revival lease:\", error);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction startConfiguredSubagent(config: SubagentRunConfig): void {\n\trunConfiguredSubagent(config).catch((runErr) => {\n\t\tconsole.error(\"Subagent runner error:\", runErr);\n\t\tprocess.exit(1);\n\t});\n}\n\nconst configArg = process.argv[2];\nif (configArg) {\n\ttry {\n\t\tconst configJson = fs.readFileSync(configArg, \"utf-8\");\n\t\tconst config = JSON.parse(configJson) as SubagentRunConfig;\n\t\ttry {\n\t\t\tfs.unlinkSync(configArg);\n\t\t} catch {\n\t\t\t// Temp config cleanup is best effort.\n\t\t}\n\t\tstartConfiguredSubagent(config);\n\t} catch (err) {\n\t\tconsole.error(\"Subagent runner error:\", err);\n\t\tprocess.exit(1);\n\t}\n} else {\n\tlet input = \"\";\n\tprocess.stdin.setEncoding(\"utf-8\");\n\tprocess.stdin.on(\"data\", (chunk) => {\n\t\tinput += chunk;\n\t});\n\tprocess.stdin.on(\"end\", () => {\n\t\ttry {\n\t\t\tconst config = JSON.parse(input) as SubagentRunConfig;\n\t\t\tstartConfiguredSubagent(config);\n\t\t} catch (err) {\n\t\t\tconsole.error(\"Subagent runner error:\", err);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n}\n"]}
1
+ {"version":3,"file":"subagent-runner.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.ts"],"names":[],"mappings":"","sourcesContent":["// @ts-nocheck\nimport { spawn, spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { Message } from \"@ashx-j/lunr-ai\";\nimport { writeAtomicJson } from \"../../shared/atomic-json.ts\";\nimport { createChildTranscriptWriter, type ChildTranscriptWriter } from \"../../shared/child-transcript.ts\";\nimport { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, enqueueStepSteer, steerAcksDir, steerCapabilityPath, stepSteerInboxDir, watchAsyncControlInbox, type SteerAck, type SteerCapability, type SteerRequest } from \"./control-channel.ts\";\nimport { appendJsonl as appendRawJsonl, getArtifactPaths } from \"../../shared/artifacts.ts\";\nimport { PI_CODING_AGENT_PACKAGE, getPiSpawnCommand, resolveInstalledPiPackageRoot } from \"../shared/pi-spawn.ts\";\nimport { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, injectSingleOutputInstruction, resolveSingleOutput, type SingleOutputSnapshot } from \"../shared/single-output.ts\";\nimport {\n\ttype ActivityState,\n\ttype ArtifactConfig,\n\ttype ArtifactPaths,\n\ttype AsyncParallelGroupStatus,\n\ttype AsyncStatus,\n\ttype ChainOutputMap,\n\ttype CostSummary,\n\ttype ModelAttempt,\n\ttype NestedRouteInfo,\n\ttype NestedRunSummary,\n\ttype ResolvedControlConfig,\n\ttype ResolvedTurnBudget,\n\ttype ResolvedToolBudget,\n\ttype SubagentRunMode,\n\ttype ToolBudgetState,\n\ttype TurnBudgetState,\n\ttype Usage,\n\ttype WorkflowGraphSnapshot,\n\ttype SteeringStatus,\n\ttype SteeringTargetState,\n\ttype SteeringTargetStatus,\n\tDEFAULT_MAX_OUTPUT,\n\ttype MaxOutputConfig,\n\tSUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\ttruncateOutput,\n\tgetSubagentDepthEnv,\n} from \"../../shared/types.ts\";\nimport {\n\tDEFAULT_CONTROL_CONFIG,\n\tbuildControlEvent,\n\tderiveActivityState,\n\tclaimControlNotification,\n\tformatControlIntercomMessage,\n\tformatControlNoticeMessage,\n} from \"../shared/subagent-control.ts\";\nimport {\n\ttype RunnerSubagentStep as SubagentStep,\n\ttype RunnerStep,\n\tisDynamicRunnerGroup,\n\tisParallelGroup,\n\tflattenSteps,\n\tmapConcurrent,\n\taggregateParallelOutputs,\n\tMAX_PARALLEL_CONCURRENCY,\n\tDEFAULT_GLOBAL_CONCURRENCY_LIMIT,\n\tSemaphore,\n} from \"../shared/parallel-utils.ts\";\nimport { applyThinkingSuffix, buildPiArgs, cleanupTempDir } from \"../shared/pi-args.ts\";\nimport { snapshotParentPermissionMode } from \"../../../../../core/subagent-permission-inherit.ts\";\nimport { resolveChildExcludeTools } from \"../shared/child-tools.ts\";\nimport { outputEntryFromAsyncResult, resolveOutputReferences } from \"../shared/chain-outputs.ts\";\nimport { createStructuredOutputRuntime, readStructuredOutput } from \"../shared/structured-output.ts\";\nimport { readChildToolDiagnosticError } from \"../shared/tool-availability.ts\";\nimport { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from \"../shared/dynamic-fanout.ts\";\nimport { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from \"../shared/nested-events.ts\";\nimport { formatModelAttemptNote, isRetryableModelFailure } from \"../shared/model-fallback.ts\";\nimport { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from \"./steering.ts\";\nimport { attachPostExitStdioGuard, trySignalChild } from \"../../shared/post-exit-stdio-guard.ts\";\nimport { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput, readStatus } from \"../../shared/utils.ts\";\nimport { evaluateCompletionMutationGuard } from \"../shared/completion-guard.ts\";\nimport {\n\tcreateMutatingFailureState,\n\tdidMutatingToolFail,\n\tisMutatingTool,\n\tnextLongRunningTrigger,\n\trecordMutatingFailure,\n\tresetMutatingFailureState,\n\tresolveCurrentPath,\n\tshouldEscalateMutatingFailures,\n\tsummarizeRecentMutatingFailures,\n} from \"../shared/long-running-guard.ts\";\nimport { parseSessionTokens } from \"../../shared/session-tokens.ts\";\nimport type { TokenUsage } from \"../../shared/types.ts\";\nimport {\n\tcleanupWorktrees,\n\tcreateWorktrees,\n\tdiffWorktrees,\n\tfindWorktreeTaskCwdConflict,\n\tformatWorktreeDiffSummary,\n\tformatWorktreeTaskCwdConflict,\n\ttype WorktreeSetup,\n} from \"../shared/worktree.ts\";\nimport { resolveEffectiveThinking } from \"../../shared/model-info.ts\";\nimport { writeInitialProgressFile } from \"../../shared/settings.ts\";\nimport { resolveSubagentIntercomTarget } from \"../../intercom/intercom-bridge.ts\";\nimport { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from \"../shared/acceptance.ts\";\nimport { waitForImportedAsyncRoot } from \"./chain-root-attachment.ts\";\nimport { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from \"./chain-append.ts\";\nimport { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, shouldAbortForTurnBudget, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from \"../shared/turn-budget.ts\";\nimport { initialToolBudgetState, toolBudgetState } from \"../shared/tool-budget.ts\";\nimport { resolveWatchdogConfig } from \"../../watchdog/settings.ts\";\nimport { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from \"../shared/child-protocol.ts\";\nimport { acquireSessionLease, type SessionLeaseRequest } from \"../shared/session-lease.ts\";\nimport {\n\tCHILD_WATCHDOG_CONFIG_ENV,\n\tacceptChildWatchdogEvent,\n\tchildWatchdogIsActive,\n\tdecodeChildWatchdogConfig,\n\tisChildWatchdogStatusEvent,\n\tresolveChildWatchdogConfig,\n\ttype ChildWatchdogStateSnapshot,\n} from \"../../watchdog/child-status.ts\";\n\ninterface SubagentRunConfig {\n\tid: string;\n\tsteps: RunnerStep[];\n\tresultPath: string;\n\tcwd: string;\n\tplaceholder: string;\n\ttaskIndex?: number;\n\ttotalTasks?: number;\n\tmaxOutput?: MaxOutputConfig;\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\tshare?: boolean;\n\tsessionDir?: string;\n\tasyncDir: string;\n\tsessionId?: string | null;\n\tpiPackageRoot?: string;\n\tpiArgv1?: string;\n\tworktreeSetupHook?: string;\n\tworktreeSetupHookTimeoutMs?: number;\n\tworktreeBaseDir?: string;\n\tcontrolConfig?: ResolvedControlConfig;\n\tcontrolIntercomTarget?: string;\n\tchildIntercomTargets?: Array<string | undefined>;\n\tresultMode?: SubagentRunMode;\n\tdynamicFanoutMaxItems?: number;\n\tworkflowGraph?: WorkflowGraphSnapshot;\n\tnestedRoute?: NestedRouteInfo;\n\tnestedSelf?: { parentRunId: string; parentStepIndex?: number; depth: number; path?: Array<{ runId: string; stepIndex?: number; agent?: string }> };\n\ttimeoutMs?: number;\n\tdeadlineAt?: number;\n\tturnBudget?: ResolvedTurnBudget;\n\ttoolBudget?: ResolvedToolBudget;\n\trevivalLease?: SessionLeaseRequest;\n\t/** Global cap on simultaneously-running subagent tasks within this run. */\n\tglobalConcurrencyLimit?: number;\n}\n\ninterface StepResult {\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\tagent: string;\n\toutput: string;\n\terror?: string;\n\tprotocolError?: ProtocolOutputLimit;\n\tsuccess: boolean;\n\texitCode?: number | null;\n\tskipped?: boolean;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tsessionFile?: string;\n\tintercomTarget?: string;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\tmodelAttempts?: ModelAttempt[];\n\ttotalCost?: CostSummary;\n\tartifactPaths?: ArtifactPaths;\n\ttruncated?: boolean;\n\ttranscriptPath?: string;\n\ttranscriptError?: string;\n\tstructuredOutput?: unknown;\n\tstructuredOutputPath?: string;\n\tstructuredOutputSchemaPath?: string;\n\tacceptance?: import(\"../../shared/types.ts\").AcceptanceLedger;\n\twatchdog?: import(\"../../shared/types.ts\").ChildWatchdogProgress;\n}\n\nconst ASYNC_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === \"win32\" ? \"SIGBREAK\" : \"SIGUSR2\";\nconst DEFAULT_MAX_ASYNC_EVENTS_BYTES = 50 * 1024 * 1024;\nconst ASYNC_EVENTS_MAX_BYTES_ENV = \"PI_SUBAGENT_ASYNC_EVENTS_MAX_BYTES\";\nconst TRUNCATED_EVENT_TYPE = \"subagent.events.truncated\";\nconst TRUNCATION_MARKER_RESERVE_BYTES = 512;\n\ninterface AsyncEventLogState {\n\tbytes: number;\n\tdiagnosticsTruncated: boolean;\n}\n\nconst asyncEventLogStates = new Map<string, AsyncEventLogState>();\n\nfunction maxAsyncEventsBytes(): number {\n\tconst raw = process.env[ASYNC_EVENTS_MAX_BYTES_ENV];\n\tif (!raw) return DEFAULT_MAX_ASYNC_EVENTS_BYTES;\n\tconst parsed = Number(raw);\n\tif (!Number.isFinite(parsed) || parsed < 0) return DEFAULT_MAX_ASYNC_EVENTS_BYTES;\n\treturn Math.floor(parsed);\n}\n\nfunction eventLogState(filePath: string): AsyncEventLogState {\n\tlet state = asyncEventLogStates.get(filePath);\n\tif (state) return state;\n\tlet bytes = 0;\n\ttry {\n\t\tbytes = fs.statSync(filePath).size;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\t// Diagnostic event accounting is best-effort; writes below are also safe.\n\t\t}\n\t}\n\tstate = { bytes, diagnosticsTruncated: false };\n\tasyncEventLogStates.set(filePath, state);\n\treturn state;\n}\n\nfunction appendJsonl(filePath: string, line: string): void {\n\ttry {\n\t\tappendRawJsonl(filePath, line);\n\t\tconst state = asyncEventLogStates.get(filePath);\n\t\tif (state) state.bytes += Buffer.byteLength(`${line}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Async event logging is diagnostic and must not fail the run.\n\t}\n}\n\nfunction appendDiagnosticJsonl(filePath: string, line: string, droppedEventType?: string): void {\n\tif (!line.trim()) return;\n\tconst state = eventLogState(filePath);\n\tif (state.diagnosticsTruncated) return;\n\tconst maxBytes = maxAsyncEventsBytes();\n\tconst chunkBytes = Buffer.byteLength(`${line}\\n`, \"utf-8\");\n\tconst diagnosticBudget = Math.max(0, maxBytes - TRUNCATION_MARKER_RESERVE_BYTES);\n\tif (state.bytes + chunkBytes <= diagnosticBudget) {\n\t\tappendJsonl(filePath, line);\n\t\treturn;\n\t}\n\n\tconst marker = JSON.stringify({\n\t\ttype: TRUNCATED_EVENT_TYPE,\n\t\tts: Date.now(),\n\t\tmaxBytes,\n\t\tdroppedEventType,\n\t});\n\tif (state.bytes + Buffer.byteLength(`${marker}\\n`, \"utf-8\") <= maxBytes) {\n\t\tappendJsonl(filePath, marker);\n\t}\n\tstate.diagnosticsTruncated = true;\n}\n\nfunction shouldPersistChildEvent(event: Record<string, unknown>): boolean {\n\treturn event.type !== \"message_update\";\n}\n\nfunction findLatestSessionFile(sessionDir: string): string | null {\n\ttry {\n\t\tconst files = fs\n\t\t\t.readdirSync(sessionDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => path.join(sessionDir, f));\n\t\tif (files.length === 0) return null;\n\t\tfiles.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);\n\t\treturn files[0] ?? null;\n\t} catch {\n\t\t// Session lookup is optional metadata.\n\t\treturn null;\n\t}\n}\n\nfunction emptyUsage(): Usage {\n\treturn { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };\n}\n\nfunction tokenUsageFromAttempts(attempts: ModelAttempt[] | undefined): TokenUsage | null {\n\tif (!attempts || attempts.length === 0) return null;\n\tlet input = 0;\n\tlet output = 0;\n\tfor (const attempt of attempts) {\n\t\tinput += attempt.usage?.input ?? 0;\n\t\toutput += attempt.usage?.output ?? 0;\n\t}\n\tconst total = input + output;\n\treturn total > 0 ? { input, output, total } : null;\n}\n\nfunction costSummaryFromAttempts(attempts: ModelAttempt[] | undefined): CostSummary | undefined {\n\tif (!attempts || attempts.length === 0) return undefined;\n\tlet inputTokens = 0;\n\tlet outputTokens = 0;\n\tlet costUsd = 0;\n\tfor (const attempt of attempts) {\n\t\tinputTokens += attempt.usage?.input ?? 0;\n\t\toutputTokens += attempt.usage?.output ?? 0;\n\t\tcostUsd += attempt.usage?.cost ?? 0;\n\t}\n\treturn inputTokens > 0 || outputTokens > 0 || costUsd > 0\n\t\t? { inputTokens, outputTokens, costUsd }\n\t\t: undefined;\n}\n\nfunction appendRecentStepOutput(step: RunnerStatusStep, lines: string[]): void {\n\tconst nonEmpty = lines.filter((line) => line.trim());\n\tif (nonEmpty.length === 0) return;\n\tstep.recentOutput ??= [];\n\tstep.recentOutput.push(...nonEmpty);\n\tif (step.recentOutput.length > 50) {\n\t\tstep.recentOutput.splice(0, step.recentOutput.length - 50);\n\t}\n}\n\nfunction isTerminalAssistantStop(message: Message): boolean {\n\tconst stopReason = (message as { stopReason?: string }).stopReason;\n\tconst hasToolCall = Array.isArray(message.content)\n\t\t&& message.content.some((part) => (part as { type?: string }).type === \"toolCall\");\n\treturn stopReason === \"stop\" && !hasToolCall;\n}\n\nfunction resetStepLiveDetail(step: RunnerStatusStep): void {\n\tstep.currentTool = undefined;\n\tstep.currentToolArgs = undefined;\n\tstep.currentToolStartedAt = undefined;\n\tstep.currentPath = undefined;\n\tstep.recentTools = [];\n\tstep.recentOutput = [];\n}\n\ninterface ChildEventContext {\n\teventsPath: string;\n\trunId: string;\n\tstepIndex: number;\n\tagent: string;\n}\n\ninterface ChildUsage {\n\tinput?: number;\n\tinputTokens?: number;\n\toutput?: number;\n\toutputTokens?: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\tcost?: { total?: number };\n}\n\ntype ChildMessage = Message & {\n\tmodel?: string;\n\terrorMessage?: string;\n\tusage?: ChildUsage;\n};\n\ninterface ChildEvent {\n\ttype?: string;\n\tmessage?: ChildMessage;\n\ttoolName?: string;\n\targs?: Record<string, unknown>;\n\twillRetry?: unknown;\n}\n\ninterface RunPiStreamingResult {\n\tstderr: string;\n\texitCode: number | null;\n\tmessages: Message[];\n\tusage: Usage;\n\tmodel?: string;\n\terror?: string;\n\tprotocolError?: ProtocolOutputLimit;\n\tfinalOutput: string;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tobservedMutationAttempt?: boolean;\n\twatchdog?: ChildWatchdogStateSnapshot;\n}\n\nfunction runPiStreaming(\n\targs: string[],\n\tcwd: string,\n\toutputFile: string,\n\tenv?: Record<string, string | undefined>,\n\tpiPackageRoot?: string,\n\tpiArgv1?: string,\n\tmaxSubagentDepth?: number,\n\tchildEventContext?: ChildEventContext,\n\tregisterInterrupt?: (interrupt: (() => void) | undefined) => void,\n\tonChildEvent?: (event: ChildEvent) => void,\n\ttranscriptWriter?: ChildTranscriptWriter,\n\tregisterTimeout?: (interrupt: (() => void) | undefined) => void,\n\ttimeoutMessage?: string,\n\tregisterStop?: (stop: (() => void) | undefined) => void,\n\tstopMessage?: string,\n\tregisterTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void,\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void,\n): Promise<RunPiStreamingResult> {\n\treturn new Promise((resolve) => {\n\t\tonWriterProcess?.({ state: \"spawning\" });\n\t\tconst outputStream = fs.createWriteStream(outputFile, { flags: \"w\" });\n\t\tconst spawnEnv = { ...process.env, ...(env ?? {}), ...getSubagentDepthEnv(maxSubagentDepth) };\n\t\tconst spawnSpec = getPiSpawnCommand(args, {\n\t\t\t...(piPackageRoot ? { piPackageRoot } : {}),\n\t\t\t...(piArgv1 ? { argv1: piArgv1 } : {}),\n\t\t});\n\t\tconst child = spawn(spawnSpec.command, spawnSpec.args, {\n\t\t\tcwd,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: spawnEnv,\n\t\t\twindowsHide: true,\n\t\t});\n\t\tconst stderrTail = createBoundedByteTail();\n\t\tconst rawStdoutTail = createBoundedByteTail();\n\t\tconst messages: Message[] = [];\n\t\tconst usage = emptyUsage();\n\t\tlet model: string | undefined;\n\t\tlet writerRegistrationError: string | undefined;\n\t\tif (typeof child.pid === \"number\") {\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"running\", pid: child.pid });\n\t\t\t} catch (writerError) {\n\t\t\t\twriterRegistrationError = `Failed to record revived Pi writer ownership: ${writerError instanceof Error ? writerError.message : String(writerError)}`;\n\t\t\t\ttrySignalChild(child, \"SIGKILL\");\n\t\t\t}\n\t\t}\n\t\tlet error: string | undefined = writerRegistrationError;\n\t\tlet assistantError: string | undefined;\n\t\tlet interrupted = false;\n\t\tlet timedOut = false;\n\t\tlet stopped = false;\n\t\tlet turnBudgetExceeded = false;\n\t\tlet turnBudgetMessage: string | undefined;\n\t\tlet turnBudget: TurnBudgetState | undefined;\n\t\tlet observedMutationAttempt = false;\n\t\tconst childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);\n\t\tlet childWatchdogState: ChildWatchdogStateSnapshot | undefined;\n\t\tlet applyChildLifecycle = (_action: ChildLifecycleAction): void => {};\n\t\tconst updateChildWatchdogState = (snapshot: ChildWatchdogStateSnapshot): void => {\n\t\t\tchildWatchdogState = snapshot;\n\t\t};\n\n\t\tconst writeOutputLine = (line: string) => {\n\t\t\tif (!line.trim()) return;\n\t\t\toutputStream.write(`${line}\\n`);\n\t\t};\n\n\t\tconst writeOutputText = (text: string) => {\n\t\t\tfor (const line of text.split(\"\\n\")) {\n\t\t\t\twriteOutputLine(line);\n\t\t\t}\n\t\t};\n\n\t\tconst appendChildEvent = (event: Record<string, unknown>) => {\n\t\t\tif (!childEventContext) return;\n\t\t\tif (!shouldPersistChildEvent(event)) return;\n\t\t\tappendDiagnosticJsonl(childEventContext.eventsPath, JSON.stringify({\n\t\t\t\t...event,\n\t\t\t\tsubagentSource: \"child\",\n\t\t\t\tsubagentRunId: childEventContext.runId,\n\t\t\t\tsubagentStepIndex: childEventContext.stepIndex,\n\t\t\t\tsubagentAgent: childEventContext.agent,\n\t\t\t\tobservedAt: Date.now(),\n\t\t\t}), typeof event.type === \"string\" ? event.type : undefined);\n\t\t};\n\n\t\tconst appendChildLine = (type: \"subagent.child.stdout\" | \"subagent.child.stderr\", line: string) => {\n\t\t\tappendChildEvent({ type, line });\n\t\t\tif (type === \"subagent.child.stdout\") transcriptWriter?.writeStdoutLine(line);\n\t\t\telse transcriptWriter?.writeStderrLine(line);\n\t\t};\n\n\t\tconst processStdoutLine = (line: string) => {\n\t\t\tif (!line.trim()) return;\n\t\t\tlet event: ChildEvent;\n\t\t\ttry {\n\t\t\t\tevent = JSON.parse(line) as ChildEvent;\n\t\t\t} catch {\n\t\t\t\trawStdoutTail.push(`${line}\\n`);\n\t\t\t\twriteOutputLine(line);\n\t\t\t\tappendChildLine(\"subagent.child.stdout\", line);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tappendChildEvent(event);\n\t\t\ttranscriptWriter?.writeChildEvent(event);\n\t\t\tif (event.type === \"agent_settled\") agentSettledReceived = true;\n\t\t\tapplyChildLifecycle(projectChildLifecycle(event));\n\n\t\t\tif (isChildWatchdogStatusEvent(event)) {\n\t\t\t\tif (!childWatchdogConfig) return;\n\t\t\t\tconst next = acceptChildWatchdogEvent({\n\t\t\t\t\tcurrent: childWatchdogState,\n\t\t\t\t\tevent,\n\t\t\t\t\trunId: childEventContext?.runId,\n\t\t\t\t\tagent: childEventContext?.agent,\n\t\t\t\t\tchildIndex: childEventContext?.stepIndex,\n\t\t\t\t});\n\t\t\t\tif (!next) return;\n\t\t\t\tupdateChildWatchdogState(next);\n\t\t\t\tonChildEvent?.(event);\n\t\t\t\tif (childWatchdogIsActive(next)) {\n\t\t\t\t\tif (finalDrainTimer) {\n\t\t\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tif (finalHardKillTimer) {\n\t\t\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t\t\t}\n\t\t\t\t\tarmWatchdogTail();\n\t\t\t\t} else {\n\t\t\t\t\tclearWatchdogTailTimer();\n\t\t\t\t\tif (cleanTerminalAssistantStopReceived || agentSettledReceived) startFinalDrain();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tonChildEvent?.(event);\n\n\t\t\tif (event.type === \"tool_execution_start\" && event.toolName) {\n\t\t\t\tobservedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);\n\t\t\t\tconst toolArgs = extractToolArgsPreview(event.args ?? {});\n\t\t\t\twriteOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ((event.type === \"message_end\" || event.type === \"tool_result_end\") && event.message) {\n\t\t\t\tmessages.push(event.message);\n\t\t\t\tconst text = extractTextFromContent(event.message.content);\n\t\t\t\tif (text) writeOutputText(text);\n\n\t\t\t\tif (event.type !== \"message_end\" || event.message.role !== \"assistant\") return;\n\t\t\t\tif (event.message.model) model = event.message.model;\n\t\t\t\tif (event.message.errorMessage) assistantError = event.message.errorMessage;\n\t\t\t\tconst eventUsage = event.message.usage;\n\t\t\t\tif (eventUsage) {\n\t\t\t\t\tusage.turns++;\n\t\t\t\t\tusage.input += eventUsage.input ?? eventUsage.inputTokens ?? 0;\n\t\t\t\t\tusage.output += eventUsage.output ?? eventUsage.outputTokens ?? 0;\n\t\t\t\t\tusage.cacheRead += eventUsage.cacheRead ?? 0;\n\t\t\t\t\tusage.cacheWrite += eventUsage.cacheWrite ?? 0;\n\t\t\t\t\tusage.cost += eventUsage.cost?.total ?? 0;\n\t\t\t\t}\n\t\t\t\tif (isTerminalAssistantStop(event.message)) {\n\t\t\t\t\tif (!event.message.errorMessage && extractTextFromContent(event.message.content).trim()) assistantError = undefined;\n\t\t\t\t\tcleanTerminalAssistantStopReceived ||= !event.message.errorMessage;\n\t\t\t\t\tapplyChildLifecycle(projectChildLifecycle(event, true));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Guard both cases that can leave the parent waiting on `close` forever:\n\t\t// a lingering stdio holder after `exit`, or a child that never exits.\n\t\tconst FINAL_STOP_GRACE_MS = 1000;\n\t\tconst HARD_KILL_MS = 3000;\n\t\tconst TIMEOUT_HARD_KILL_MS = 3000;\n\t\tlet childExited = false;\n\t\tlet forcedTerminationSignal = false;\n\t\tlet cleanTerminalAssistantStopReceived = false;\n\t\tlet agentSettledReceived = false;\n\t\tlet finalDrainTimer: NodeJS.Timeout | undefined;\n\t\tlet finalHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet watchdogTailTimer: NodeJS.Timeout | undefined;\n\t\tlet timeoutHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet turnBudgetTerminationTimer: NodeJS.Timeout | undefined;\n\t\tlet turnBudgetHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet protocolHardKillTimer: NodeJS.Timeout | undefined;\n\t\tlet protocolError: ProtocolOutputLimit | undefined;\n\t\tlet settled = false;\n\t\tapplyChildLifecycle = (action: ChildLifecycleAction): void => {\n\t\t\tif (action === \"cancel-drain\") {\n\t\t\t\tif (finalDrainTimer) {\n\t\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t\t}\n\t\t\t\tif (finalHardKillTimer) {\n\t\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t\t}\n\t\t\t\tclearWatchdogTailTimer();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === \"start-drain\") startFinalDrain();\n\t\t};\n\t\tconst failProtocol = (limit: ProtocolOutputLimit): void => {\n\t\t\tif (protocolError) return;\n\t\t\tprotocolError = limit;\n\t\t\terror = formatProtocolOutputLimit(limit);\n\t\t\tif (!childExited) {\n\t\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\t\tprotocolHardKillTimer = setTimeout(() => {\n\t\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t\t}, 3000);\n\t\t\t\tprotocolHardKillTimer.unref?.();\n\t\t\t}\n\t\t};\n\t\tconst stdoutReader = createBoundedLineReader({ onLine: processStdoutLine, onLimit: failProtocol });\n\t\tconst stderrReader = createBoundedLineReader({\n\t\t\tstream: \"stderr\",\n\t\t\tmaxPendingLineBytes: MAX_CHILD_STDERR_BYTES,\n\t\t\tonLine: (line) => appendChildLine(\"subagent.child.stderr\", line),\n\t\t\tonLimit: (limit) => appendChildLine(\"subagent.child.stderr\", formatProtocolOutputLimit(limit)),\n\t\t});\n\t\tconst clearStdioGuard = attachPostExitStdioGuard(child, { idleMs: 2000, hardMs: 8000 });\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => stdoutReader.push(chunk));\n\t\tchild.stderr.on(\"data\", (chunk: Buffer) => {\n\t\t\tstderrTail.push(chunk);\n\t\t\tstderrReader.push(chunk);\n\t\t\toutputStream.write(chunk);\n\t\t});\n\t\tregisterInterrupt?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\tinterrupted = true;\n\t\t\tif (!error) error = \"Interrupted. Waiting for explicit next action.\";\n\t\t\ttrySignalChild(child, \"SIGINT\");\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGTERM\");\n\t\t\t}, 1000).unref?.();\n\t\t});\n\t\tregisterTimeout?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\ttimedOut = true;\n\t\t\tinterrupted = false;\n\t\t\terror = timeoutMessage ?? \"Subagent timed out.\";\n\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\ttimeoutHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, TIMEOUT_HARD_KILL_MS);\n\t\t\ttimeoutHardKillTimer.unref?.();\n\t\t});\n\t\tregisterStop?.(() => {\n\t\t\tif (settled || timedOut || stopped) return;\n\t\t\tstopped = true;\n\t\t\tinterrupted = false;\n\t\t\terror = stopMessage ?? \"Subagent stopped by user.\";\n\t\t\ttrySignalChild(child, \"SIGTERM\");\n\t\t\ttimeoutHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, TIMEOUT_HARD_KILL_MS);\n\t\t\ttimeoutHardKillTimer.unref?.();\n\t\t});\n\t\tregisterTurnBudgetAbort?.((message, state) => {\n\t\t\tif (settled || timedOut || stopped || turnBudgetExceeded) return;\n\t\t\tturnBudgetExceeded = true;\n\t\t\tturnBudgetMessage = message;\n\t\t\tturnBudget = state;\n\t\t\tinterrupted = false;\n\t\t\terror = message;\n\t\t\ttrySignalChild(child, \"SIGINT\");\n\t\t\tturnBudgetTerminationTimer = setTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGTERM\");\n\t\t\t}, 1000);\n\t\t\tturnBudgetTerminationTimer.unref?.();\n\t\t\tturnBudgetHardKillTimer = setTimeout(() => {\n\t\t\t\tif (!settled && !timedOut && !stopped) trySignalChild(child, \"SIGKILL\");\n\t\t\t}, 4000);\n\t\t\tturnBudgetHardKillTimer.unref?.();\n\t\t});\n\t\tconst clearDrainTimers = () => {\n\t\t\tif (finalDrainTimer) {\n\t\t\t\tclearTimeout(finalDrainTimer);\n\t\t\t\tfinalDrainTimer = undefined;\n\t\t\t}\n\t\t\tif (finalHardKillTimer) {\n\t\t\t\tclearTimeout(finalHardKillTimer);\n\t\t\t\tfinalHardKillTimer = undefined;\n\t\t\t}\n\t\t\tclearWatchdogTailTimer();\n\t\t\tif (timeoutHardKillTimer) {\n\t\t\t\tclearTimeout(timeoutHardKillTimer);\n\t\t\t\ttimeoutHardKillTimer = undefined;\n\t\t\t}\n\t\t\tif (turnBudgetTerminationTimer) {\n\t\t\t\tclearTimeout(turnBudgetTerminationTimer);\n\t\t\t\tturnBudgetTerminationTimer = undefined;\n\t\t\t}\n\t\t\tif (turnBudgetHardKillTimer) {\n\t\t\t\tclearTimeout(turnBudgetHardKillTimer);\n\t\t\t\tturnBudgetHardKillTimer = undefined;\n\t\t\t}\n\t\t\tif (protocolHardKillTimer) {\n\t\t\t\tclearTimeout(protocolHardKillTimer);\n\t\t\t\tprotocolHardKillTimer = undefined;\n\t\t\t}\n\t\t};\n\t\tfunction startFinalDrain(): void {\n\t\t\tif (childWatchdogIsActive(childWatchdogState)) {\n\t\t\t\tarmWatchdogTail();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (childExited || finalDrainTimer || settled) return;\n\t\t\tfinalDrainTimer = setTimeout(() => {\n\t\t\t\tif (settled) return;\n\t\t\t\tconst termSent = trySignalChild(child, \"SIGTERM\");\n\t\t\t\tif (!termSent) return;\n\t\t\t\tforcedTerminationSignal = true;\n\t\t\t\tif (!cleanTerminalAssistantStopReceived && !agentSettledReceived && !error && !assistantError) {\n\t\t\t\t\terror = `Subagent process did not exit within ${FINAL_STOP_GRACE_MS}ms after its terminal event. Forcing termination.`;\n\t\t\t\t}\n\t\t\t\tfinalHardKillTimer = setTimeout(() => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tforcedTerminationSignal = trySignalChild(child, \"SIGKILL\") || forcedTerminationSignal;\n\t\t\t\t}, HARD_KILL_MS);\n\t\t\t\tfinalHardKillTimer.unref?.();\n\t\t\t}, FINAL_STOP_GRACE_MS);\n\t\t\tfinalDrainTimer.unref?.();\n\t\t}\n\t\tfunction clearWatchdogTailTimer(): void {\n\t\t\tif (watchdogTailTimer) {\n\t\t\t\tclearTimeout(watchdogTailTimer);\n\t\t\t\twatchdogTailTimer = undefined;\n\t\t\t}\n\t\t}\n\t\tfunction armWatchdogTail(): void {\n\t\t\tif ((!cleanTerminalAssistantStopReceived && !agentSettledReceived) || watchdogTailTimer || settled) return;\n\t\t\twatchdogTailTimer = setTimeout(() => {\n\t\t\t\twatchdogTailTimer = undefined;\n\t\t\t\tupdateChildWatchdogState({\n\t\t\t\t\tphase: \"stale\",\n\t\t\t\t\tseq: (childWatchdogState?.seq ?? 0) + 1,\n\t\t\t\t\tlastUpdate: Date.now(),\n\t\t\t\t\tfollowUpPending: false,\n\t\t\t\t\treason: \"child watchdog tail timeout\",\n\t\t\t\t\ttimedOut: true,\n\t\t\t\t});\n\t\t\t\tstartFinalDrain();\n\t\t\t}, childWatchdogConfig?.watchdogTailTimeoutMs ?? 120_000);\n\t\t\twatchdogTailTimer.unref?.();\n\t\t}\n\t\tchild.on(\"exit\", () => {\n\t\t\tchildExited = true;\n\t\t\tclearDrainTimers();\n\t\t});\n\t\tchild.on(\"close\", (exitCode, signal) => {\n\t\t\tsettled = true;\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"none\" });\n\t\t\t} catch {\n\t\t\t\t// The runner still owns and releases the lease during finalization.\n\t\t\t}\n\t\t\tregisterInterrupt?.(undefined);\n\t\t\tregisterTimeout?.(undefined);\n\t\t\tregisterStop?.(undefined);\n\t\t\tregisterTurnBudgetAbort?.(undefined);\n\t\t\tclearDrainTimers();\n\t\t\tclearStdioGuard();\n\t\t\tstdoutReader.end();\n\t\t\tstderrReader.end();\n\t\t\toutputStream.end();\n\t\t\tconst stderr = stderrTail.text();\n\t\t\tconst finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();\n\t\t\tconst finalError = error ?? assistantError;\n\t\t\tconst forcedDrainAfterFinalSuccess = forcedTerminationSignal && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;\n\t\t\tresolve({\n\t\t\t\tstderr,\n\t\t\t\texitCode: timedOut || stopped ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,\n\t\t\t\tmessages,\n\t\t\t\tusage,\n\t\t\t\tmodel,\n\t\t\t\terror: stopped ? (stopMessage ?? \"Subagent stopped by user.\") : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,\n\t\t\t\tprotocolError,\n\t\t\t\tfinalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? \"Subagent stopped by user.\" : timeoutMessage ?? \"Subagent timed out.\") : finalOutput,\n\t\t\t\tinterrupted,\n\t\t\t\ttimedOut,\n\t\t\t\tstopped,\n\t\t\t\tturnBudget,\n\t\t\t\tturnBudgetExceeded,\n\t\t\t\twrapUpRequested: turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined,\n\t\t\t\tobservedMutationAttempt,\n\t\t\t\twatchdog: childWatchdogState,\n\t\t\t});\n\t\t});\n\n\t\tchild.on(\"error\", (spawnError) => {\n\t\t\tsettled = true;\n\t\t\ttry {\n\t\t\t\tonWriterProcess?.({ state: \"none\" });\n\t\t\t} catch {\n\t\t\t\t// The runner still owns and releases the lease during finalization.\n\t\t\t}\n\t\t\tregisterInterrupt?.(undefined);\n\t\t\tregisterTimeout?.(undefined);\n\t\t\tregisterStop?.(undefined);\n\t\t\tregisterTurnBudgetAbort?.(undefined);\n\t\t\tclearDrainTimers();\n\t\t\tclearStdioGuard();\n\t\t\tstdoutReader.end();\n\t\t\tstderrReader.end();\n\t\t\toutputStream.end();\n\t\t\tconst stderr = stderrTail.text();\n\t\t\tconst finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();\n\t\t\tconst spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);\n\t\t\tresolve({ stderr, exitCode: 1, messages, usage, model, error: stopped ? (stopMessage ?? \"Subagent stopped by user.\") : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? \"Subagent stopped by user.\" : timeoutMessage ?? \"Subagent timed out.\") : finalOutput, timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState });\n\t\t});\n\t});\n}\n\nfunction resolvePiPackageRootFallback(): string {\n\tconst root = resolveInstalledPiPackageRoot();\n\tif (root) return root;\n\tthrow new Error(`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`);\n}\n\nasync function exportSessionHtml(sessionFile: string, outputDir: string, piPackageRoot?: string): Promise<string> {\n\tconst pkgRoot = piPackageRoot ?? resolvePiPackageRootFallback();\n\tconst exportModulePath = path.join(pkgRoot, \"dist\", \"core\", \"export-html\", \"index.js\");\n\tconst moduleUrl = pathToFileURL(exportModulePath).href;\n\tconst mod = await import(moduleUrl);\n\tconst exportFromFile = (mod as { exportFromFile?: (inputPath: string, options?: { outputPath?: string }) => string })\n\t\t.exportFromFile;\n\tif (typeof exportFromFile !== \"function\") {\n\t\tthrow new Error(\"exportFromFile not available\");\n\t}\n\tconst outputPath = path.join(outputDir, `${path.basename(sessionFile, \".jsonl\")}.html`);\n\treturn exportFromFile(sessionFile, { outputPath });\n}\n\nfunction createShareLink(htmlPath: string): { shareUrl: string; gistUrl: string } | { error: string } {\n\ttry {\n\t\tconst auth = spawnSync(\"gh\", [\"auth\", \"status\"], { encoding: \"utf-8\" });\n\t\tif (auth.status !== 0) {\n\t\t\treturn { error: \"GitHub CLI is not logged in. Run 'gh auth login' first.\" };\n\t\t}\n\t} catch {\n\t\treturn { error: \"GitHub CLI (gh) is not installed.\" };\n\t}\n\n\ttry {\n\t\tconst result = spawnSync(\"gh\", [\"gist\", \"create\", htmlPath], { encoding: \"utf-8\" });\n\t\tif (result.status !== 0) {\n\t\t\tconst err = (result.stderr || \"\").trim() || \"Failed to create gist.\";\n\t\t\treturn { error: err };\n\t\t}\n\t\tconst gistUrl = (result.stdout || \"\").trim();\n\t\tconst gistId = gistUrl.split(\"/\").pop();\n\t\tif (!gistId) return { error: \"Failed to parse gist ID.\" };\n\t\tconst shareUrl = `https://shittycodingagent.ai/session/?${gistId}`;\n\t\treturn { shareUrl, gistUrl };\n\t} catch (err) {\n\t\treturn { error: String(err) };\n\t}\n}\n\nfunction formatDuration(ms: number): string {\n\tif (ms < 1000) return `${ms}ms`;\n\tif (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n\tconst minutes = Math.floor(ms / 60000);\n\tconst seconds = Math.floor((ms % 60000) / 1000);\n\treturn `${minutes}m${seconds}s`;\n}\n\nfunction writeRunLog(\n\tlogPath: string,\n\tinput: {\n\t\tid: string;\n\t\tmode: SubagentRunMode;\n\t\tcwd: string;\n\t\tstartedAt: number;\n\t\tendedAt: number;\n\t\tsteps: Array<{\n\t\t\tagent: string;\n\t\t\tstatus: string;\n\t\t\tdurationMs?: number;\n\t\t}>;\n\t\tsummary: string;\n\t\ttruncated: boolean;\n\t\tartifactsDir?: string;\n\t\tsessionFile?: string;\n\t\tshareUrl?: string;\n\t\tshareError?: string;\n\t},\n): void {\n\tconst lines: string[] = [];\n\tlines.push(`# Subagent run ${input.id}`);\n\tlines.push(\"\");\n\tlines.push(`- **Mode:** ${input.mode}`);\n\tlines.push(`- **CWD:** ${input.cwd}`);\n\tlines.push(`- **Started:** ${new Date(input.startedAt).toISOString()}`);\n\tlines.push(`- **Ended:** ${new Date(input.endedAt).toISOString()}`);\n\tlines.push(`- **Duration:** ${formatDuration(input.endedAt - input.startedAt)}`);\n\tif (input.sessionFile) lines.push(`- **Session:** ${input.sessionFile}`);\n\tif (input.shareUrl) lines.push(`- **Share:** ${input.shareUrl}`);\n\tif (input.shareError) lines.push(`- **Share error:** ${input.shareError}`);\n\tif (input.artifactsDir) lines.push(`- **Artifacts:** ${input.artifactsDir}`);\n\tlines.push(\"\");\n\tlines.push(\"## Steps\");\n\tlines.push(\"| Step | Agent | Status | Duration |\");\n\tlines.push(\"| --- | --- | --- | --- |\");\n\tinput.steps.forEach((step, i) => {\n\t\tconst duration = step.durationMs !== undefined ? formatDuration(step.durationMs) : \"-\";\n\t\tlines.push(`| ${i + 1} | ${step.agent} | ${step.status} | ${duration} |`);\n\t});\n\tlines.push(\"\");\n\tlines.push(\"## Summary\");\n\tif (input.truncated) {\n\t\tlines.push(\"_Output truncated_\");\n\t\tlines.push(\"\");\n\t}\n\tlines.push(input.summary.trim() || \"(no output)\");\n\tlines.push(\"\");\n\tfs.writeFileSync(logPath, lines.join(\"\\n\"), \"utf-8\");\n}\n\n/** Context for running a single step */\ninterface SingleStepContext {\n\tpreviousOutput: string;\n\toutputs?: ChainOutputMap;\n\tplaceholder: string;\n\tcwd: string;\n\tsessionEnabled: boolean;\n\tsessionDir?: string;\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\tid: string;\n\tflatIndex: number;\n\tflatStepCount: number;\n\toutputFile: string;\n\tsteerInboxDir?: string;\n\tsteerCapabilityPath?: string;\n\tsteerAckDir?: string;\n\ttranscriptPath?: string;\n\tpiPackageRoot?: string;\n\tpiArgv1?: string;\n\tregisterInterrupt?: (interrupt: (() => void) | undefined) => void;\n\tregisterTimeout?: (interrupt: (() => void) | undefined) => void;\n\tregisterStop?: (stop: (() => void) | undefined) => void;\n\tregisterTurnBudgetAbort?: (abort: ((message: string, state?: TurnBudgetState) => void) | undefined) => void;\n\ttimeoutSignal?: AbortSignal;\n\tstopSignal?: AbortSignal;\n\ttimeoutMessage?: string;\n\tstopMessage?: string;\n\tturnBudget?: ResolvedTurnBudget;\n\tchildIntercomTarget?: string;\n\torchestratorIntercomTarget?: string;\n\tnestedRoute?: NestedRouteInfo;\n\tonAttemptStart?: (attempt: { model?: string; thinking?: string }) => void;\n\tonChildEvent?: (event: ChildEvent) => void;\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void;\n\tskipAcceptance?: () => boolean;\n}\n\n/** Run a single pi agent step, returning output and metadata */\nasync function runSingleStep(\n\tstep: SubagentStep,\n\tctx: SingleStepContext,\n): Promise<{\n\tagent: string;\n\toutput: string;\n\texitCode: number | null;\n\terror?: string;\n\tmodel?: string;\n\tattemptedModels?: string[];\n\tmodelAttempts?: ModelAttempt[];\n\tartifactPaths?: ArtifactPaths;\n\ttranscriptPath?: string;\n\ttranscriptError?: string;\n\tinterrupted?: boolean;\n\ttimedOut?: boolean;\n\tstopped?: boolean;\n\tturnBudget?: TurnBudgetState;\n\tturnBudgetExceeded?: boolean;\n\twrapUpRequested?: boolean;\n\ttoolBudget?: ToolBudgetState;\n\ttoolBudgetBlocked?: boolean;\n\tsessionFile?: string;\n\tintercomTarget?: string;\n\tcompletionGuardTriggered?: boolean;\n\tstructuredOutput?: unknown;\n\tstructuredOutputPath?: string;\n\tstructuredOutputSchemaPath?: string;\n\tacceptance?: import(\"../../shared/types.ts\").AcceptanceLedger;\n}> {\n\tif (step.importAsyncRoot) {\n\t\tlet importTimedOut = false;\n\t\tlet importStopped = false;\n\t\tctx.registerTimeout?.(() => {\n\t\t\timportTimedOut = true;\n\t\t\tlet pid: number | undefined;\n\t\t\ttry {\n\t\t\t\tpid = readStatus(step.importAsyncRoot!.asyncDir)?.pid;\n\t\t\t} catch {\n\t\t\t\tpid = undefined;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdeliverTimeoutRequest({ asyncDir: step.importAsyncRoot!.asyncDir, pid, source: \"ancestor-timeout\" });\n\t\t\t} catch {\n\t\t\t\t// The parent runner's own timeout result is authoritative for the attached step.\n\t\t\t}\n\t\t});\n\t\tctx.registerStop?.(() => {\n\t\t\timportStopped = true;\n\t\t\tlet pid: number | undefined;\n\t\t\ttry {\n\t\t\t\tpid = readStatus(step.importAsyncRoot!.asyncDir)?.pid;\n\t\t\t} catch {\n\t\t\t\tpid = undefined;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tdeliverStopRequest({ asyncDir: step.importAsyncRoot!.asyncDir, pid, source: \"ancestor-stop\" });\n\t\t\t} catch {\n\t\t\t\t// The parent runner's own stopped result is authoritative for the attached step.\n\t\t\t}\n\t\t});\n\t\ttry {\n\t\t\tconst imported = await waitForImportedAsyncRoot(step.importAsyncRoot, {\n\t\t\t\tshouldAbort: () => importTimedOut || importStopped || ctx.timeoutSignal?.aborted === true || ctx.stopSignal?.aborted === true || ctx.skipAcceptance?.() === true,\n\t\t\t\ttimeoutMessage: importStopped || ctx.stopSignal?.aborted === true ? ctx.stopMessage : ctx.timeoutMessage,\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tfs.writeFileSync(ctx.outputFile, imported.output, \"utf-8\");\n\t\t\t} catch {\n\t\t\t\t// Output files are observability only for imported roots.\n\t\t\t}\n\t\t\tconst stopped = importStopped || imported.stopped === true || ctx.stopSignal?.aborted === true;\n\t\t\tconst timedOut = !stopped && (importTimedOut || imported.timedOut === true || ctx.timeoutSignal?.aborted === true || ctx.skipAcceptance?.() === true);\n\t\t\tconst message = stopped ? ctx.stopMessage ?? \"Subagent stopped by user.\" : ctx.timeoutMessage ?? \"Subagent timed out.\";\n\t\t\treturn {\n\t\t\t\tagent: imported.agent,\n\t\t\t\toutput: timedOut || stopped ? message : imported.output,\n\t\t\t\texitCode: timedOut || stopped ? 1 : imported.exitCode,\n\t\t\t\terror: timedOut || stopped ? message : imported.error,\n\t\t\t\ttimedOut: timedOut ? true : undefined,\n\t\t\t\tstopped: stopped ? true : undefined,\n\t\t\t\tsessionFile: imported.sessionFile,\n\t\t\t\tintercomTarget: imported.intercomTarget,\n\t\t\t\tmodel: imported.model,\n\t\t\t\tattemptedModels: imported.attemptedModels,\n\t\t\t\tmodelAttempts: imported.modelAttempts,\n\t\t\t\ttotalCost: imported.totalCost,\n\t\t\t\tstructuredOutput: timedOut || stopped ? undefined : imported.structuredOutput,\n\t\t\t\tstructuredOutputPath: timedOut || stopped ? undefined : imported.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: timedOut || stopped ? undefined : imported.structuredOutputSchemaPath,\n\t\t\t\tacceptance: timedOut || stopped ? undefined : imported.acceptance,\n\t\t\t};\n\t\t} finally {\n\t\t\tctx.registerTimeout?.(undefined);\n\t\t\tctx.registerStop?.(undefined);\n\t\t}\n\t}\n\n\tconst effectiveStructuredOutput = step.structuredOutput ?? (step.structuredOutputSchema\n\t\t? createStructuredOutputRuntime(step.structuredOutputSchema, path.join(path.dirname(ctx.outputFile), \"structured-output\"))\n\t\t: undefined);\n\tconst placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\");\n\tlet task = step.task.replace(placeholderRegex, () => ctx.previousOutput);\n\tif (ctx.outputs) task = resolveOutputReferences(task, ctx.outputs);\n\tconst taskForCompletionGuard = task;\n\tif (step.effectiveAcceptance) {\n\t\tconst acceptancePrompt = formatAcceptancePrompt(step.effectiveAcceptance);\n\t\tif (acceptancePrompt) task = `${task}\\n${acceptancePrompt}`;\n\t}\n\tconst sessionEnabled = Boolean(step.sessionFile) || ctx.sessionEnabled;\n\tconst sessionDir = step.sessionFile ? undefined : ctx.sessionDir;\n\n\tlet artifactPaths: ArtifactPaths | undefined;\n\tlet transcriptWriter: ChildTranscriptWriter | undefined;\n\tif (ctx.artifactsDir && ctx.artifactConfig?.enabled !== false) {\n\t\tconst index = ctx.flatStepCount > 1 ? ctx.flatIndex : undefined;\n\t\tartifactPaths = getArtifactPaths(ctx.artifactsDir, ctx.id, step.agent, index);\n\t\tfs.mkdirSync(ctx.artifactsDir, { recursive: true });\n\t\tif (ctx.artifactConfig?.includeInput !== false) {\n\t\t\tfs.writeFileSync(artifactPaths.inputPath, `# Task for ${step.agent}\\n\\n${task}`, \"utf-8\");\n\t\t}\n\t\tif (ctx.artifactConfig?.includeTranscript !== false) {\n\t\t\ttranscriptWriter = createChildTranscriptWriter({\n\t\t\t\ttranscriptPath: artifactPaths.transcriptPath,\n\t\t\t\tsource: \"async\",\n\t\t\t\trunId: ctx.id,\n\t\t\t\tagent: step.agent,\n\t\t\t\tchildIndex: ctx.flatIndex,\n\t\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\t});\n\t\t}\n\t}\n\ttranscriptWriter?.writeInitialUserMessage(task);\n\n\tconst candidates = step.modelCandidates && step.modelCandidates.length > 0\n\t\t? step.modelCandidates\n\t\t: step.model\n\t\t\t? [step.model]\n\t\t\t: [undefined];\n\tconst attemptedModels: string[] = [];\n\tconst modelAttempts: ModelAttempt[] = [];\n\tconst attemptNotes: string[] = [];\n\tconst eventsPath = path.join(path.dirname(ctx.outputFile), \"events.jsonl\");\n\tlet finalResult: RunPiStreamingResult | undefined;\n\tlet finalOutputSnapshot: SingleOutputSnapshot | undefined;\n\tlet completionGuardTriggeredFinal = false;\n\tlet turnBudget = ctx.turnBudget ? initialTurnBudgetState(ctx.turnBudget) : undefined;\n\tlet toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;\n\tlet toolBudgetBlocked = false;\n\n\tfor (let index = 0; index < candidates.length; index++) {\n\t\tif (ctx.timeoutSignal?.aborted || ctx.skipAcceptance?.()) break;\n\t\tconst candidate = candidates[index];\n\t\tctx.onAttemptStart?.({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });\n\t\tconst outputSnapshot = captureSingleOutputSnapshot(step.outputPath);\n\t\tif (effectiveStructuredOutput) {\n\t\t\ttry {\n\t\t\t\tif (fs.existsSync(effectiveStructuredOutput.outputPath)) fs.unlinkSync(effectiveStructuredOutput.outputPath);\n\t\t\t} catch {\n\t\t\t\t// Missing/stale structured-output files are handled after the child exits.\n\t\t\t}\n\t\t}\n\t\tconst watchdogConfig = resolveWatchdogConfig(step.cwd ?? ctx.cwd);\n\t\tconst childWatchdog = watchdogConfig.ok\n\t\t\t? resolveChildWatchdogConfig({\n\t\t\t\tconfig: watchdogConfig.config,\n\t\t\t\tagent: step.agent,\n\t\t\t\trunId: ctx.id,\n\t\t\t\tchildIndex: ctx.flatIndex,\n\t\t\t})\n\t\t\t: undefined;\n\t\tconst parentPermissionMode = step.parentPermissionMode ?? snapshotParentPermissionMode(step.parentSessionId);\n\t\tconst childPermission = step.permissions === \"read-only\" || parentPermissionMode === \"plan\" ? \"read-only\" : \"full\";\n\t\tconst excludeTools = resolveChildExcludeTools({\n\t\t\tpermissions: childPermission,\n\t\t\tfanoutAuthorized: Array.isArray(step.tools) && step.tools.includes(\"subagent\"),\n\t\t});\n\t\tconst { args, env, tempDir, toolDiagnosticPath } = buildPiArgs({\n\t\t\tparentSessionId: step.parentSessionId,\n\t\t\tbaseArgs: [\"--mode\", \"json\", \"-p\"],\n\t\t\ttask,\n\t\t\tsessionEnabled,\n\t\t\tsessionDir,\n\t\t\tsessionFile: step.sessionFile,\n\t\t\tmodel: candidate,\n\t\t\tinheritProjectContext: true,\n\t\t\tinheritSkills: false,\n\t\t\trequireReadTool: Boolean(step.skills?.length),\n\t\t\texcludeTools,\n\t\t\tchildPermission,\n\t\t\tchildId: step.childId ?? step.agent,\n\t\t\tchildDescription: step.description ?? step.agent,\n\t\t\tsystemPrompt: appendTurnBudgetSystemPrompt(step.systemPrompt && !step.systemPrompt.includes(\"You are `\") ? step.systemPrompt : \"\", ctx.turnBudget) || undefined,\n\t\t\tsystemPromptMode: \"append\",\n\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\tpromptFileStem: step.childId ?? step.agent,\n\t\t\tintercomSessionName: ctx.childIntercomTarget,\n\t\t\torchestratorIntercomTarget: ctx.orchestratorIntercomTarget,\n\t\t\trunId: ctx.id,\n\t\t\tchildAgentName: step.childId ?? step.agent,\n\t\t\tchildIndex: ctx.flatIndex,\n\t\t\tparentEventSink: ctx.nestedRoute?.eventSink,\n\t\t\tparentControlInbox: ctx.nestedRoute?.controlInbox,\n\t\t\tparentRootRunId: ctx.nestedRoute?.rootRunId,\n\t\t\tparentCapabilityToken: ctx.nestedRoute?.capabilityToken,\n\t\t\tsteerInboxDir: ctx.steerInboxDir,\n\t\t\tsteerCapabilityPath: ctx.steerCapabilityPath,\n\t\t\tsteerAckDir: ctx.steerAckDir,\n\t\t\tstructuredOutput: effectiveStructuredOutput,\n\t\t\ttoolBudget: step.toolBudget,\n\t\t\tchildWatchdog,\n\t\t\twaitToolEnabled: step.waitToolEnabled,\n\t\t\tparentPermissionMode,\n\t\t});\n\t\tconst run = await runPiStreaming(\n\t\t\targs,\n\t\t\tstep.cwd ?? ctx.cwd,\n\t\t\tctx.outputFile,\n\t\t\tenv,\n\t\t\tctx.piPackageRoot,\n\t\t\tctx.piArgv1,\n\t\t\tstep.maxSubagentDepth,\n\t\t\t{ eventsPath, runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },\n\t\t\tctx.registerInterrupt,\n\t\t\tctx.onChildEvent,\n\t\t\ttranscriptWriter,\n\t\t\tctx.registerTimeout,\n\t\t\tctx.timeoutMessage,\n\t\t\tctx.registerStop,\n\t\t\tctx.stopMessage,\n\t\t\tctx.registerTurnBudgetAbort,\n\t\t\tctx.onWriterProcess,\n\t\t);\n\t\tif (run.turnBudget) turnBudget = run.turnBudget;\n\t\telse if (ctx.turnBudget) {\n\t\t\tconst assistantMessages = run.messages.filter((message) => message.role === \"assistant\");\n\t\t\tconst turnCount = assistantMessages.length;\n\t\t\tconst lastAssistantMessage = assistantMessages.at(-1);\n\t\t\tif (turnCount > 0 && turnCount < ctx.turnBudget.maxTurns) {\n\t\t\t\tturnBudget = { ...ctx.turnBudget, outcome: \"within-budget\", turnCount };\n\t\t\t} else if (turnCount >= ctx.turnBudget.maxTurns) {\n\t\t\t\tturnBudget = turnBudgetState(\n\t\t\t\t\tctx.turnBudget,\n\t\t\t\t\tturnCount,\n\t\t\t\t\tshouldAbortForTurnBudget(ctx.turnBudget, turnCount, lastAssistantMessage ? isTerminalAssistantStop(lastAssistantMessage) : false),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tconst toolAvailabilityError = run.exitCode === 0 && !run.error\n\t\t\t? readChildToolDiagnosticError(toolDiagnosticPath)\n\t\t\t: undefined;\n\t\tcleanupTempDir(tempDir);\n\n\t\tconst hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError ? detectSubagentError(run.messages) : null;\n\t\tconst missingStructuredOutput = effectiveStructuredOutput\n\t\t\t? !fs.existsSync(effectiveStructuredOutput.outputPath)\n\t\t\t: false;\n\t\tconst emptyOutputError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !run.finalOutput.trim() && (!effectiveStructuredOutput || missingStructuredOutput)\n\t\t\t? \"Subagent produced no output (possible model cold-start or empty response).\"\n\t\t\t: undefined;\n\t\tlet structuredOutput: unknown;\n\t\tlet structuredError: string | undefined;\n\t\tif (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !emptyOutputError) {\n\t\t\tconst structured = readStructuredOutput({\n\t\t\t\tschema: effectiveStructuredOutput.schema,\n\t\t\t\tschemaPath: effectiveStructuredOutput.schemaPath,\n\t\t\t\toutputPath: effectiveStructuredOutput.outputPath,\n\t\t\t});\n\t\t\tif (structured.error) structuredError = structured.error;\n\t\t\telse structuredOutput = structured.value;\n\t\t}\n\t\tconst completionGuard = run.exitCode === 0 && !run.error && !toolAvailabilityError && !hiddenError?.hasError && !emptyOutputError && step.completionGuard !== false\n\t\t\t? evaluateCompletionMutationGuard({\n\t\t\t\tagent: step.agent,\n\t\t\t\ttask: taskForCompletionGuard,\n\t\t\t\tmessages: run.messages,\n\t\t\t\ttools: step.tools,\n\t\t\t\tmcpDirectTools: step.mcpDirectTools,\n\t\t\t})\n\t\t\t: undefined;\n\t\tconst completionGuardTriggered = completionGuard?.triggered === true && !run.observedMutationAttempt;\n\t\tconst completionGuardError = completionGuardTriggered\n\t\t\t? \"Subagent completed without making edits for an implementation task.\\nIt appears to have returned planning or scratchpad output instead of applying changes.\"\n\t\t\t: undefined;\n\t\tconst effectiveExitCode = toolAvailabilityError || completionGuardTriggered || structuredError\n\t\t\t? 1\n\t\t\t: hiddenError?.hasError\n\t\t\t\t? (hiddenError.exitCode ?? 1)\n\t\t\t\t: emptyOutputError\n\t\t\t\t\t? 1\n\t\t\t\t\t: run.error && run.exitCode === 0\n\t\t\t\t\t\t? 1\n\t\t\t\t\t\t: run.exitCode;\n\t\tconst error = toolAvailabilityError\n\t\t\t?? completionGuardError\n\t\t\t?? structuredError\n\t\t\t?? (hiddenError?.hasError\n\t\t\t\t? hiddenError.details\n\t\t\t\t\t? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`\n\t\t\t\t\t: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`\n\t\t\t\t: emptyOutputError ?? (run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined)));\n\t\tconst attempt: ModelAttempt = {\n\t\t\tmodel: candidate ?? run.model ?? step.model ?? \"default\",\n\t\t\tsuccess: effectiveExitCode === 0 && !error,\n\t\t\texitCode: effectiveExitCode,\n\t\t\terror,\n\t\t\tusage: run.usage,\n\t\t};\n\t\tmodelAttempts.push(attempt);\n\t\tif (candidate) attemptedModels.push(candidate);\n\t\tcompletionGuardTriggeredFinal = completionGuardTriggered;\n\t\tfinalOutputSnapshot = outputSnapshot;\n\t\tif (step.toolBudget) {\n\t\t\tconst toolMessages = run.messages.filter((message) => message.role === \"toolResult\");\n\t\t\tconst blockedMessage = toolMessages.find((message) => extractTextFromContent(message.content).includes(\"Tool budget hard limit reached\"));\n\t\t\ttoolBudgetBlocked = Boolean(blockedMessage);\n\t\t\ttoolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);\n\t\t}\n\t\tfinalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput } as RunPiStreamingResult & { structuredOutput?: unknown };\n\t\tif (run.turnBudgetExceeded) break;\n\t\tif (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;\n\t\tif (attempt.success || completionGuardTriggered) break;\n\t\tif (!isRetryableModelFailure(error) || index === candidates.length - 1) break;\n\t\tattemptNotes.push(formatModelAttemptNote(attempt, candidates[index + 1]));\n\t}\n\n\tconst rawOutput = finalResult?.finalOutput ?? \"\";\n\tconst outputForPersistence = stripAcceptanceReport(rawOutput);\n\tconst resolvedOutput = step.outputPath && finalResult?.exitCode === 0\n\t\t? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot)\n\t\t: { fullOutput: outputForPersistence };\n\tconst output = stripAcceptanceReport(resolvedOutput.fullOutput);\n\tconst outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;\n\tlet outputForSummary = output;\n\tif (attemptNotes.length > 0) {\n\t\toutputForSummary = `${attemptNotes.join(\"\\n\")}\\n\\n${outputForSummary}`.trim();\n\t}\n\tif (finalResult?.stopped && !outputForSummary.trim()) {\n\t\toutputForSummary = ctx.stopMessage ?? \"Subagent stopped by user.\";\n\t} else if (!finalResult?.timedOut && !finalResult?.stopped && finalResult?.turnBudgetExceeded && turnBudget) {\n\t\toutputForSummary = formatTurnBudgetOutput(turnBudgetExceededMessage(turnBudget, turnBudget.turnCount), outputForSummary);\n\t} else if (!finalResult?.timedOut && !finalResult?.stopped && turnBudget?.outcome === \"wrap-up-requested\") {\n\t\tconst note = turnBudgetSoftNote(turnBudget, turnBudget.wrapUpRequestedAtTurn ?? turnBudget.turnCount);\n\t\toutputForSummary = outputForSummary.trim() ? `${note}\\n\\n${outputForSummary}` : note;\n\t}\n\tconst outputForAcceptance = rawOutput;\n\tconst childWrittenOutput = step.outputPath\n\t\t? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)\n\t\t: undefined;\n\tconst finalizedOutput = finalizeSingleOutput({\n\t\tfullOutput: outputForSummary,\n\t\toutputPath: step.outputPath,\n\t\toutputMode: step.outputMode,\n\t\texitCode: finalResult?.exitCode ?? 1,\n\t\tsavedPath: resolvedOutput.savedPath,\n\t\toutputReference,\n\t\tsaveError: resolvedOutput.saveError,\n\t});\n\toutputForSummary = finalizedOutput.displayOutput;\n\tconst acceptance = step.effectiveAcceptance && !finalResult?.stopped && !finalResult?.turnBudgetExceeded && !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted && !ctx.skipAcceptance?.()\n\t\t? await evaluateAcceptance({\n\t\t\tacceptance: step.effectiveAcceptance,\n\t\t\toutput: outputForAcceptance,\n\t\t\tfileOutput: childWrittenOutput !== undefined && step.outputPath\n\t\t\t\t? { content: childWrittenOutput, path: step.outputPath, authoritative: step.outputMode === \"file-only\" }\n\t\t\t\t: undefined,\n\t\t\tcwd: step.cwd ?? ctx.cwd,\n\t\t\tsignal: combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]),\n\t\t\tabortMessage: ctx.stopSignal?.aborted ? ctx.stopMessage ?? \"Subagent stopped by user.\" : ctx.timeoutMessage ?? \"Subagent timed out.\",\n\t\t})\n\t\t: undefined;\n\tconst stoppedAfterAcceptance = finalResult?.stopped === true || ctx.stopSignal?.aborted === true;\n\tconst timedOutAfterAcceptance = !stoppedAfterAcceptance && (finalResult?.timedOut === true || ctx.timeoutSignal?.aborted === true);\n\tconst turnBudgetExceeded = finalResult?.turnBudgetExceeded === true;\n\tconst effectiveAcceptance = step.effectiveAcceptance\n\t\t? stoppedAfterAcceptance\n\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"stopped\", message: \"Acceptance was not evaluated because the subagent was stopped.\" })\n\t\t\t: timedOutAfterAcceptance\n\t\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"timeout\", message: \"Acceptance was not evaluated because the subagent timed out.\" })\n\t\t\t\t: turnBudgetExceeded\n\t\t\t\t\t? buildSkippedAcceptanceLedger(step.effectiveAcceptance, { id: \"turn-budget\", message: \"Acceptance was not evaluated because the subagent exceeded its turn budget.\" })\n\t\t\t\t\t: acceptance\n\t\t: undefined;\n\tconst acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;\n\tconst acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !turnBudgetExceeded;\n\tconst effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;\n\tconst effectiveFinalError = stoppedAfterAcceptance\n\t\t? ctx.stopMessage ?? \"Subagent stopped by user.\"\n\t\t: timedOutAfterAcceptance\n\t\t\t? ctx.timeoutMessage ?? \"Subagent timed out.\"\n\t\t\t: turnBudgetExceeded\n\t\t\t\t? finalResult?.error ?? (turnBudget ? turnBudgetExceededMessage(turnBudget, turnBudget.turnCount) : \"Subagent exceeded turn budget.\")\n\t\t\t\t: acceptanceCanFailRun\n\t\t\t\t\t? (finalResult?.error ? `${finalResult.error}\\n${acceptanceFailure}` : acceptanceFailure)\n\t\t\t\t\t: finalResult?.error;\n\n\tif (artifactPaths && ctx.artifactConfig?.enabled !== false) {\n\t\tif (ctx.artifactConfig?.includeOutput !== false) {\n\t\t\tfs.writeFileSync(artifactPaths.outputPath, output, \"utf-8\");\n\t\t}\n\t\tif (ctx.artifactConfig?.includeMetadata !== false) {\n\t\t\tfs.writeFileSync(\n\t\t\t\tartifactPaths.metadataPath,\n\t\t\t\tJSON.stringify({\n\t\t\t\t\trunId: ctx.id,\n\t\t\t\t\tagent: step.agent,\n\t\t\t\t\ttask,\n\t\t\t\t\texitCode: effectiveFinalExitCode,\n\t\t\t\t\tmodel: finalResult?.model,\n\t\t\t\t\tattemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,\n\t\t\t\t\tmodelAttempts,\n\t\t\t\t\terror: effectiveFinalError,\n\t\t\t\t\tacceptance: effectiveAcceptance,\n\t\t\t\t\t...(transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {}),\n\t\t\t\t\ttranscriptError: transcriptWriter?.getError(),\n\t\t\t\t\tskills: step.skills,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t}, null, 2),\n\t\t\t\t\"utf-8\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tchildId: step.childId,\n\t\tdescription: step.description,\n\t\tpermissions: step.permissions,\n\t\tagent: step.agent,\n\t\toutput: outputForSummary,\n\t\texitCode: effectiveFinalExitCode,\n\t\terror: effectiveFinalError,\n\t\tprotocolError: finalResult?.protocolError,\n\t\tsessionFile: step.sessionFile,\n\t\tintercomTarget: ctx.childIntercomTarget,\n\t\tmodel: finalResult?.model,\n\t\tattemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,\n\t\tmodelAttempts,\n\t\ttotalCost: costSummaryFromAttempts(modelAttempts),\n\t\tartifactPaths,\n\t\ttranscriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,\n\t\ttranscriptError: transcriptWriter?.getError(),\n\t\tinterrupted: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,\n\t\ttimedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,\n\t\tstopped: stoppedAfterAcceptance ? true : finalResult?.stopped,\n\t\tturnBudget,\n\t\tturnBudgetExceeded: turnBudgetExceeded || undefined,\n\t\twrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === \"wrap-up-requested\" || turnBudgetExceeded || undefined,\n\t\ttoolBudget,\n\t\ttoolBudgetBlocked: toolBudgetBlocked || undefined,\n\t\tcompletionGuardTriggered: completionGuardTriggeredFinal,\n\t\tstructuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput,\n\t\tstructuredOutputPath: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.outputPath,\n\t\tstructuredOutputSchemaPath: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? undefined : effectiveStructuredOutput?.schemaPath,\n\t\tacceptance: effectiveAcceptance,\n\t\twatchdog: finalResult?.watchdog,\n\t};\n}\n\ntype RunnerStatusStep = NonNullable<AsyncStatus[\"steps\"]>[number] & {\n\texitCode?: number | null;\n};\n\ntype RunnerStatusPayload = Omit<AsyncStatus, \"steps\" | \"parallelGroups\" | \"pid\" | \"cwd\" | \"currentStep\" | \"chainStepCount\" | \"lastUpdate\"> & {\n\tpid: number;\n\tcwd: string;\n\tcurrentStep: number;\n\tchainStepCount: number;\n\tparallelGroups: AsyncParallelGroupStatus[];\n\tsteps: RunnerStatusStep[];\n\tlastUpdate: number;\n\tartifactsDir?: string;\n\tshareUrl?: string;\n\tgistUrl?: string;\n\tshareError?: string;\n\terror?: string;\n};\n\nfunction markParallelGroupSetupFailure(input: {\n\tstatusPayload: RunnerStatusPayload;\n\tresults: StepResult[];\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>;\n\tgroupStartFlatIndex: number;\n\tsetupError: string;\n\tfailedAt: number;\n\tstatusPath: string;\n\teventsPath: string;\n\tasyncDir: string;\n\trunId: string;\n\tstepIndex: number;\n}): void {\n\tfor (let taskIndex = 0; taskIndex < input.group.parallel.length; taskIndex++) {\n\t\tconst flatTaskIndex = input.groupStartFlatIndex + taskIndex;\n\t\tinput.statusPayload.steps[flatTaskIndex].status = \"failed\";\n\t\tinput.statusPayload.steps[flatTaskIndex].startedAt = input.failedAt;\n\t\tinput.statusPayload.steps[flatTaskIndex].endedAt = input.failedAt;\n\t\tinput.statusPayload.steps[flatTaskIndex].durationMs = 0;\n\t\tinput.statusPayload.steps[flatTaskIndex].exitCode = 1;\n\t\tinput.results.push({ agent: input.group.parallel[taskIndex].agent, output: input.setupError, success: false, exitCode: 1, sessionFile: input.group.parallel[taskIndex].sessionFile });\n\t}\n\tinput.statusPayload.currentStep = input.groupStartFlatIndex;\n\tinput.statusPayload.lastUpdate = input.failedAt;\n\tinput.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);\n\twriteAtomicJson(input.statusPath, input.statusPayload);\n\tappendJsonl(input.eventsPath, JSON.stringify({\n\t\ttype: \"subagent.parallel.completed\",\n\t\tts: input.failedAt,\n\t\trunId: input.runId,\n\t\tstepIndex: input.stepIndex,\n\t\tsuccess: false,\n\t}));\n}\n\nfunction markParallelGroupRunning(input: {\n\tstatusPayload: RunnerStatusPayload;\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>;\n\tgroupStartFlatIndex: number;\n\tgroupStartTime: number;\n\tstatusPath: string;\n\teventsPath: string;\n\tasyncDir: string;\n\trunId: string;\n\tstepIndex: number;\n}): void {\n\tfor (let taskIndex = 0; taskIndex < input.group.parallel.length; taskIndex++) {\n\t\tconst flatTaskIndex = input.groupStartFlatIndex + taskIndex;\n\t\tinput.statusPayload.steps[flatTaskIndex].status = \"pending\";\n\t\tinput.statusPayload.steps[flatTaskIndex].startedAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].endedAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].durationMs = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].lastActivityAt = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].activityState = undefined;\n\t\tinput.statusPayload.steps[flatTaskIndex].error = undefined;\n\t}\n\tinput.statusPayload.currentStep = input.groupStartFlatIndex;\n\tinput.statusPayload.activityState = undefined;\n\tinput.statusPayload.lastActivityAt = input.groupStartTime;\n\tinput.statusPayload.lastUpdate = input.groupStartTime;\n\tinput.statusPayload.outputFile = path.join(input.asyncDir, `output-${input.groupStartFlatIndex}.log`);\n\twriteAtomicJson(input.statusPath, input.statusPayload);\n\tappendJsonl(input.eventsPath, JSON.stringify({\n\t\ttype: \"subagent.parallel.started\",\n\t\tts: input.groupStartTime,\n\t\trunId: input.runId,\n\t\tstepIndex: input.stepIndex,\n\t\tagents: input.group.parallel.map((task) => task.agent),\n\t\tcount: input.group.parallel.length,\n\t}));\n}\n\nfunction prepareParallelTaskRun(\n\ttask: SubagentStep,\n\tcwd: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\ttaskIndex: number,\n): { taskForRun: SubagentStep; taskCwd: string } {\n\tif (!worktreeSetup) return { taskForRun: task, taskCwd: cwd };\n\treturn {\n\t\ttaskForRun: { ...task, cwd: undefined },\n\t\ttaskCwd: worktreeSetup.worktrees[taskIndex]!.agentCwd,\n\t};\n}\n\nfunction appendParallelWorktreeSummary(\n\tpreviousOutput: string,\n\tworktreeSetup: WorktreeSetup | undefined,\n\tasyncDir: string,\n\tstepIndex: number,\n\tgroup: Extract<RunnerStep, { parallel: SubagentStep[] }>,\n): string {\n\tif (!worktreeSetup) return previousOutput;\n\tconst diffsDir = path.join(asyncDir, \"worktree-diffs\", `step-${stepIndex}`);\n\tconst diffs = diffWorktrees(worktreeSetup, group.parallel.map((task) => task.agent), diffsDir);\n\tconst diffSummary = formatWorktreeDiffSummary(diffs);\n\tif (!diffSummary) return previousOutput;\n\treturn `${previousOutput}\\n\\n${diffSummary}`;\n}\n\nfunction ensureParallelProgressFile(cwd: string, group: Extract<RunnerStep, { parallel: SubagentStep[] }>): void {\n\tconst progressPath = path.join(cwd, \"progress.md\");\n\tif (!group.parallel.some((task) => task.task.includes(`Update progress at: ${progressPath}`))) return;\n\twriteInitialProgressFile(cwd);\n}\n\nfunction resolveAsyncStepTranscriptPath(input: {\n\tartifactsDir?: string;\n\tartifactConfig?: Partial<ArtifactConfig>;\n\trunId: string;\n\tagent: string;\n\tflatIndex: number;\n\tflatStepCount: number;\n}): string | undefined {\n\tif (!input.artifactsDir || input.artifactConfig?.enabled === false || input.artifactConfig?.includeTranscript === false) return undefined;\n\treturn getArtifactPaths(\n\t\tinput.artifactsDir,\n\t\tinput.runId,\n\t\tinput.agent,\n\t\tinput.flatStepCount > 1 ? input.flatIndex : undefined,\n\t).transcriptPath;\n}\n\ntype SingleStepResult = Awaited<ReturnType<typeof runSingleStep>>;\n\nfunction combinedAbortSignal(signals: Array<AbortSignal | undefined>): AbortSignal | undefined {\n\tconst activeSignals = signals.filter((signal): signal is AbortSignal => Boolean(signal));\n\tif (activeSignals.length === 0) return undefined;\n\tif (activeSignals.length === 1) return activeSignals[0];\n\tconst controller = new AbortController();\n\tconst abort = (): void => controller.abort();\n\tfor (const signal of activeSignals) {\n\t\tif (signal.aborted) {\n\t\t\tabort();\n\t\t\tbreak;\n\t\t}\n\t\tsignal.addEventListener(\"abort\", abort, { once: true });\n\t}\n\treturn controller.signal;\n}\n\nasync function runSubagent(\n\tconfig: SubagentRunConfig,\n\tonWriterProcess?: (writer: { state: \"none\" | \"spawning\" } | { state: \"running\"; pid: number }) => void,\n): Promise<void> {\n\tconst { id, steps, resultPath, cwd, placeholder, taskIndex, totalTasks, maxOutput, artifactsDir, artifactConfig } =\n\t\tconfig;\n\tconst globalSemaphore = new Semaphore(config.globalConcurrencyLimit ?? DEFAULT_GLOBAL_CONCURRENCY_LIMIT);\n\tlet previousOutput = \"\";\n\tconst outputs: ChainOutputMap = {};\n\tconst results: StepResult[] = [];\n\tconst overallStartTime = Date.now();\n\tconst shareEnabled = config.share === true;\n\tconst asyncDir = config.asyncDir;\n\tconst statusPath = path.join(asyncDir, \"status.json\");\n\tconst eventsPath = path.join(asyncDir, \"events.jsonl\");\n\tconst logPath = path.join(asyncDir, `subagent-log-${id}.md`);\n\tconst controlConfig = config.controlConfig ?? DEFAULT_CONTROL_CONFIG;\n\tconst activeChildInterrupts = new Map<number, () => void>();\n\tconst activeChildTimeouts = new Map<number, () => void>();\n\tconst activeChildStops = new Map<number, () => void>();\n\tconst activeChildTurnBudgetAborts = new Map<number, (message: string, state?: TurnBudgetState) => void>();\n\tconst pendingStepSteers: SteerRequest[] = [];\n\tconst steeringCapabilities = new Map<number, SteerCapability>();\n\tlet interrupted = false;\n\tlet currentActivityState: ActivityState | undefined;\n\tlet activityTimer: NodeJS.Timeout | undefined;\n\tlet timeoutTimer: NodeJS.Timeout | undefined;\n\tlet timedOut = false;\n\tlet stopped = false;\n\tlet turnBudgetExceeded = false;\n\tconst timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;\n\tconst stopMessage = \"Subagent stopped by user.\";\n\tconst timeoutAbortController = new AbortController();\n\tconst stopAbortController = new AbortController();\n\tlet previousCumulativeTokens: TokenUsage = { input: 0, output: 0, total: 0 };\n\tlet latestSessionFile: string | undefined;\n\n\tconst flatSteps = flattenSteps(steps);\n\tconst initialFlatStepCount = flatSteps.length;\n\tconst parallelGroups: Array<{ start: number; count: number; stepIndex: number }> = [];\n\tconst initialStatusSteps: RunnerStatusStep[] = [];\n\tlet flatStepCount = 0;\n\tfor (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {\n\t\tconst step = steps[stepIndex]!;\n\t\tif (isParallelGroup(step)) {\n\t\t\tparallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });\n\t\t\tfor (const task of step.parallel) {\n\t\t\t\tconst taskFlatIndex = flatStepCount;\n\t\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });\n\t\t\t\tinitialStatusSteps.push({\n\t\t\t\t\tchildId: task.childId,\n\t\t\t\t\tdescription: task.description,\n\t\t\t\t\tpermissions: task.permissions,\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\tphase: task.phase,\n\t\t\t\t\tlabel: task.label,\n\t\t\t\t\toutputName: task.outputName,\n\t\t\t\t\tstructured: task.structured,\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t...(task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {}),\n\t\t\t\t\t...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),\n\t\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\t\tskills: task.skills,\n\t\t\t\t\tmodel: task.model,\n\t\t\t\t\tthinking: task.thinking,\n\t\t\t\t\tattemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,\n\t\t\t\t\trecentTools: [],\n\t\t\t\t\trecentOutput: [],\n\t\t\t\t});\n\t\t\t\tflatStepCount++;\n\t\t\t}\n\t\t} else if (isDynamicRunnerGroup(step)) {\n\t\t\tparallelGroups.push({ start: flatStepCount, count: 1, stepIndex });\n\t\t\tinitialStatusSteps.push({\n\t\t\t\tagent: `expand:${step.parallel.agent}`,\n\t\t\t\tphase: step.phase ?? step.parallel.phase,\n\t\t\t\tlabel: step.label ?? step.parallel.label ?? `Dynamic fanout (${step.collect.as})`,\n\t\t\t\toutputName: step.collect.as,\n\t\t\t\tstructured: Boolean(step.collect.outputSchema),\n\t\t\t\tstatus: \"pending\",\n\t\t\t\t...(step.parallel.toolBudget ? { toolBudget: initialToolBudgetState(step.parallel.toolBudget) } : {}),\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t});\n\t\t\tflatStepCount++;\n\t\t} else {\n\t\t\tconst stepFlatIndex = flatStepCount;\n\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });\n\t\t\tinitialStatusSteps.push({\n\t\t\t\tchildId: step.childId,\n\t\t\t\tdescription: step.description,\n\t\t\t\tpermissions: step.permissions,\n\t\t\t\tagent: step.agent,\n\t\t\t\tphase: step.phase,\n\t\t\t\tlabel: step.label,\n\t\t\t\toutputName: step.outputName,\n\t\t\t\tstructured: step.structured,\n\t\t\t\tstatus: \"pending\",\n\t\t\t\t...(step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {}),\n\t\t\t\t...(step.sessionFile ? { sessionFile: step.sessionFile } : {}),\n\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\tskills: step.skills,\n\t\t\t\tmodel: step.model,\n\t\t\t\tthinking: step.thinking,\n\t\t\t\tattemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,\n\t\t\t\trecentTools: [],\n\t\t\t\trecentOutput: [],\n\t\t\t});\n\t\t\tflatStepCount++;\n\t\t}\n\t}\n\tconst sessionEnabled = Boolean(config.sessionDir)\n\t\t|| shareEnabled\n\t\t|| flatSteps.some((step) => Boolean(step.sessionFile));\n\tconst statusPayload: RunnerStatusPayload = {\n\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\trunId: id,\n\t\t...(config.sessionId ? { sessionId: config.sessionId } : {}),\n\t\tmode: config.resultMode ?? (flatSteps.length > 1 ? \"chain\" : \"single\"),\n\t\t...(config.nestedRoute ? { isNested: true } : {}),\n\t\tstate: \"running\",\n\t\tsteering: createSteeringStatus(),\n\t\tlastActivityAt: overallStartTime,\n\t\tstartedAt: overallStartTime,\n\t\tlastUpdate: overallStartTime,\n\t\t...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),\n\t\t...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),\n\t\t...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),\n\t\t...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),\n\t\tpid: process.pid,\n\t\tcwd,\n\t\tcurrentStep: 0,\n\t\tchainStepCount: steps.length,\n\t\tparallelGroups,\n\t\tworkflowGraph: config.workflowGraph,\n\t\tsteps: initialStatusSteps,\n\t\tartifactsDir,\n\t\tsessionDir: config.sessionDir,\n\t\toutputFile: path.join(asyncDir, \"output-0.log\"),\n\t};\n\n\tfs.mkdirSync(asyncDir, { recursive: true });\n\twriteAtomicJson(statusPath, statusPayload);\n\tconst emitNestedSelfEvent = (type: \"subagent.nested.updated\" | \"subagent.nested.completed\"): void => {\n\t\tif (!config.nestedRoute || !config.nestedSelf) return;\n\t\ttry {\n\t\t\twriteNestedEvent(config.nestedRoute, {\n\t\t\t\ttype,\n\t\t\t\tts: Date.now(),\n\t\t\t\tparentRunId: config.nestedSelf.parentRunId,\n\t\t\t\tparentStepIndex: config.nestedSelf.parentStepIndex,\n\t\t\t\tchild: nestedSummaryFromAsyncStatus(statusPayload, asyncDir, {\n\t\t\t\t\tid,\n\t\t\t\t\tparentRunId: config.nestedSelf.parentRunId,\n\t\t\t\t\tparentStepIndex: config.nestedSelf.parentStepIndex,\n\t\t\t\t\tdepth: config.nestedSelf.depth,\n\t\t\t\t\tpath: config.nestedSelf.path,\n\t\t\t\t\tmode: statusPayload.mode,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t}),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to emit nested async status event:\", error);\n\t\t}\n\t};\n\tconst refreshWorkflowGraph = (): void => {\n\t\tif (!config.workflowGraph) return;\n\t\tconst graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);\n\t\tconst normalize = (status: RunnerStatusStep[\"status\"]): \"pending\" | \"running\" | \"completed\" | \"failed\" | \"paused\" | \"stopped\" | \"detached\" => {\n\t\t\tif (status === \"complete\" || status === \"completed\") return \"completed\";\n\t\t\tif (status === \"running\" || status === \"failed\" || status === \"paused\" || status === \"stopped\" || status === \"pending\") return status;\n\t\t\treturn \"pending\";\n\t\t};\n\t\tconst updateNode = (node: NonNullable<typeof graph.nodes>[number]): void => {\n\t\t\tif (node.flatIndex !== undefined) {\n\t\t\t\tconst step = statusPayload.steps[node.flatIndex];\n\t\t\t\tif (step) {\n\t\t\t\t\tnode.status = normalize(step.status);\n\t\t\t\t\tnode.error = step.error;\n\t\t\t\t\tnode.acceptanceStatus = step.acceptance?.status;\n\t\t\t\t}\n\t\t\t\tif (statusPayload.currentStep === node.flatIndex) graph.currentNodeId = node.id;\n\t\t\t}\n\t\t\tfor (const child of node.children ?? []) updateNode(child);\n\t\t\tif (node.children?.length) {\n\t\t\t\tif (node.children.every((child) => child.status === \"completed\")) node.status = \"completed\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"running\")) node.status = \"running\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"stopped\")) node.status = \"stopped\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"failed\")) node.status = \"failed\";\n\t\t\t\telse if (node.children.some((child) => child.status === \"paused\")) node.status = \"paused\";\n\t\t\t}\n\t\t\tif (node.error && node.status !== \"stopped\") node.status = \"failed\";\n\t\t};\n\t\tfor (const node of graph.nodes) updateNode(node);\n\t\tstatusPayload.workflowGraph = graph;\n\t};\n\tconst writeStatusPayload = (): void => {\n\t\trefreshWorkflowGraph();\n\t\twriteAtomicJson(statusPath, statusPayload);\n\t\temitNestedSelfEvent(statusPayload.state === \"running\" || statusPayload.state === \"queued\" ? \"subagent.nested.updated\" : \"subagent.nested.completed\");\n\t};\n\tconst registerStepInterrupt = (flatIndex: number, interrupt: (() => void) | undefined): void => {\n\t\tif (!interrupt) {\n\t\t\tactiveChildInterrupts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildInterrupts.set(flatIndex, interrupt);\n\t\tif (interrupted) interrupt();\n\t};\n\tconst registerStepTimeout = (flatIndex: number, interrupt: (() => void) | undefined): void => {\n\t\tif (!interrupt) {\n\t\t\tactiveChildTimeouts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildTimeouts.set(flatIndex, interrupt);\n\t\tif (timedOut) interrupt();\n\t};\n\tconst registerStepStop = (flatIndex: number, stop: (() => void) | undefined): void => {\n\t\tif (!stop) {\n\t\t\tactiveChildStops.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildStops.set(flatIndex, stop);\n\t\tif (stopped) stop();\n\t};\n\tconst registerStepTurnBudgetAbort = (flatIndex: number, abort: ((message: string, state?: TurnBudgetState) => void) | undefined): void => {\n\t\tif (!abort) {\n\t\t\tactiveChildTurnBudgetAborts.delete(flatIndex);\n\t\t\treturn;\n\t\t}\n\t\tactiveChildTurnBudgetAborts.set(flatIndex, abort);\n\t};\n\tconst interruptActiveChildren = (): void => {\n\t\tfor (const interrupt of [...activeChildInterrupts.values()]) interrupt();\n\t};\n\tconst timeoutActiveChildren = (): void => {\n\t\tfor (const interrupt of [...activeChildTimeouts.values()]) interrupt();\n\t};\n\tconst stopActiveChildren = (): void => {\n\t\tfor (const stop of [...activeChildStops.values()]) stop();\n\t};\n\tconst nestedRuns = function* (children: NestedRunSummary[] | undefined): Generator<NestedRunSummary> {\n\t\tfor (const child of children ?? []) {\n\t\t\tyield child;\n\t\t\tyield* nestedRuns(child.children);\n\t\t\tyield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));\n\t\t}\n\t};\n\tconst interruptNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.interrupt_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverInterruptRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-interrupt\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.interrupt_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst stopNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.stop_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverStopRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-stop\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.stop_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst timeoutNestedAsyncDescendants = (): void => {\n\t\tif (!config.nestedRoute) return;\n\t\tlet registry: ReturnType<typeof projectNestedEvents>;\n\t\ttry {\n\t\t\tregistry = projectNestedEvents(config.nestedRoute);\n\t\t} catch (error) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.nested.timeout_failed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t}));\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of nestedRuns(registry.children)) {\n\t\t\tif (run.state !== \"running\" && run.state !== \"queued\") continue;\n\t\t\tconst nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);\n\t\t\tif (!nestedAsyncDir) continue;\n\t\t\ttry {\n\t\t\t\tdeliverTimeoutRequest({ asyncDir: nestedAsyncDir, pid: run.pid, source: \"ancestor-timeout\" });\n\t\t\t} catch (error) {\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.nested.timeout_failed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\ttargetRunId: run.id,\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t};\n\tconst pausedStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: \"Paused after interrupt. Waiting for explicit next action.\",\n\t\texitCode: 0,\n\t\tinterrupted: true,\n\t});\n\tconst timedOutStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: timeoutMessage ?? \"Subagent timed out.\",\n\t\terror: timeoutMessage ?? \"Subagent timed out.\",\n\t\texitCode: 1,\n\t\ttimedOut: true,\n\t});\n\tconst stoppedStepResult = (agent: string): SingleStepResult => ({\n\t\tagent,\n\t\toutput: stopMessage,\n\t\terror: stopMessage,\n\t\texitCode: 1,\n\t\tstopped: true,\n\t});\n\tconst consumePendingAppendRequests = (): void => {\n\t\tif (statusPayload.mode !== \"chain\" || statusPayload.state !== \"running\") return;\n\t\tconst requests = consumeChainAppendRequests(asyncDir);\n\t\tif (requests.length === 0) {\n\t\t\tconst pendingAppends = countPendingChainAppendRequests(asyncDir);\n\t\t\tif ((statusPayload.pendingAppends ?? 0) !== pendingAppends) {\n\t\t\t\tstatusPayload.pendingAppends = pendingAppends;\n\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\twriteStatusPayload();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst appendedSteps = requests.flatMap((request) => request.steps);\n\t\tsteps.push(...appendedSteps);\n\t\tconst now = Date.now();\n\t\tconst pendingAppends = countPendingChainAppendRequests(asyncDir);\n\t\tconst added = appendRunnerStepsToStatus({\n\t\t\tstatus: statusPayload,\n\t\t\tsteps: appendedSteps,\n\t\t\tnow,\n\t\t\tpendingAppends,\n\t\t});\n\t\tmutatingFailureStates.push(...Array.from({ length: added.addedFlatSteps }, () => createMutatingFailureState()));\n\t\tpendingToolResults.push(...Array.from({ length: added.addedFlatSteps }, () => undefined));\n\t\tif (config.childIntercomTargets) {\n\t\t\tconfig.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.childId ?? statusStep.agent, index));\n\t\t}\n\t\twriteStatusPayload();\n\t\tfor (const request of requests) {\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.chain.append.accepted\",\n\t\t\t\tts: now,\n\t\t\t\trunId: id,\n\t\t\t\trequestId: request.id,\n\t\t\t\tstepCount: request.steps.length,\n\t\t\t\tpendingAppends,\n\t\t\t}));\n\t\t}\n\t};\n\tconst markDynamicGraphGroup = (stepIndex: number, status: \"completed\" | \"failed\" | \"running\" | \"stopped\", error?: string, acceptance?: import(\"../../shared/types.ts\").AcceptanceLedger): void => {\n\t\tconst groupNode = statusPayload.workflowGraph?.nodes.find((node) => node.id === `step-${stepIndex}`);\n\t\tif (!groupNode) return;\n\t\tgroupNode.status = status;\n\t\tgroupNode.error = error;\n\t\tgroupNode.acceptanceStatus = acceptance?.status ?? groupNode.acceptanceStatus;\n\t};\n\n\tconst stepOutputActivityAt = (index: number): number => {\n\t\tconst step = statusPayload.steps[index];\n\t\tlet lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;\n\t\tconst outputPath = path.join(asyncDir, `output-${index}.log`);\n\t\ttry {\n\t\t\tlastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n\t\t\t\tconsole.error(`Failed to inspect async output file '${outputPath}':`, error);\n\t\t\t}\n\t\t}\n\t\treturn lastActivityAt;\n\t};\n\tconst emittedControlEventKeys = new Set<string>();\n\tconst activeLongRunningSteps = new Set<number>();\n\tconst mutatingFailureStates = initialStatusSteps.map(() => createMutatingFailureState());\n\tconst pendingToolResults: Array<{ tool: string; path?: string; mutates: boolean; startedAt?: number } | undefined> = initialStatusSteps.map(() => undefined);\n\tconst mutatingFailureWindowMs = 5 * 60_000;\n\tconst appendControlEvent = (event: ReturnType<typeof buildControlEvent>) => {\n\t\tif (!controlConfig.enabled) return;\n\t\tconst childIntercomTarget = config.childIntercomTargets?.[event.index ?? statusPayload.currentStep];\n\t\tconst channels = event.type === \"active_long_running\"\n\t\t\t? controlConfig.notifyChannels.filter((channel) => channel !== \"intercom\")\n\t\t\t: controlConfig.notifyChannels;\n\t\tif (channels.length === 0 || !claimControlNotification(controlConfig, event, emittedControlEventKeys, childIntercomTarget)) return;\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.control\",\n\t\t\tevent,\n\t\t\tchannels,\n\t\t\tchildIntercomTarget,\n\t\t\tnoticeText: formatControlNoticeMessage(event, childIntercomTarget),\n\t\t\t...(config.controlIntercomTarget && channels.includes(\"intercom\") ? {\n\t\t\t\tintercom: {\n\t\t\t\t\tto: config.controlIntercomTarget,\n\t\t\t\t\tmessage: formatControlIntercomMessage(event, childIntercomTarget),\n\t\t\t\t},\n\t\t\t} : {}),\n\t\t}));\n\t};\n\tconst syncTopLevelCurrentTool = (): void => {\n\t\tconst activeStep = statusPayload.steps\n\t\t\t.filter((step) => step.status === \"running\" && typeof step.currentTool === \"string\" && step.currentTool.length > 0)\n\t\t\t.sort((left, right) => (right.currentToolStartedAt ?? 0) - (left.currentToolStartedAt ?? 0))[0];\n\t\tstatusPayload.currentTool = activeStep?.currentTool;\n\t\tstatusPayload.currentToolStartedAt = activeStep?.currentToolStartedAt;\n\t\tstatusPayload.currentPath = activeStep?.currentPath;\n\t};\n\tconst maybeEmitActiveLongRunning = (flatIndex: number, now: number): boolean => {\n\t\tif (!controlConfig.enabled || activeLongRunningSteps.has(flatIndex)) return false;\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step || step.status !== \"running\" || step.activityState === \"needs_attention\") return false;\n\t\tconst reason = nextLongRunningTrigger(controlConfig, {\n\t\t\tstartedAt: step.startedAt ?? overallStartTime,\n\t\t\tnow,\n\t\t\tturns: step.turnCount ?? 0,\n\t\t\ttokens: step.tokens?.total ?? 0,\n\t\t});\n\t\tif (!reason) return false;\n\t\tactiveLongRunningSteps.add(flatIndex);\n\t\tconst previous = step.activityState;\n\t\tstep.activityState = \"active_long_running\";\n\t\tstatusPayload.activityState = statusPayload.activityState === \"needs_attention\" ? \"needs_attention\" : \"active_long_running\";\n\t\tconst event = buildControlEvent({\n\t\t\ttype: \"active_long_running\",\n\t\t\tfrom: previous,\n\t\t\tto: \"active_long_running\",\n\t\t\trunId: id,\n\t\t\tagent: step.agent,\n\t\t\tindex: flatIndex,\n\t\t\tts: now,\n\t\t\tmessage: `${step.agent} is still active but long-running`,\n\t\t\treason,\n\t\t\tturns: step.turnCount,\n\t\t\ttokens: step.tokens?.total,\n\t\t\ttoolCount: step.toolCount,\n\t\t\tcurrentTool: step.currentTool,\n\t\t\tcurrentToolDurationMs: step.currentToolStartedAt ? Math.max(0, now - step.currentToolStartedAt) : undefined,\n\t\t\tcurrentPath: step.currentPath,\n\t\t\telapsedMs: now - (step.startedAt ?? overallStartTime),\n\t\t});\n\t\tappendControlEvent(event);\n\t\treturn true;\n\t};\n\tconst steeringMarkerPath = (requestId: string): string => path.join(asyncDir, \"control\", \"steer-recovery\", `${Buffer.from(requestId).toString(\"base64url\")}.json`);\n\tconst markSteeringAttention = (index: number): void => {\n\t\tconst step = statusPayload.steps[index];\n\t\tif (step) step.activityState = \"needs_attention\";\n\t\tstatusPayload.activityState = \"needs_attention\";\n\t};\n\tconst emitSteeringEvent = (type: string, request: SteerRequest, index?: number, extra: Record<string, unknown> = {}): void => {\n\t\tappendJsonl(eventsPath, JSON.stringify({ type, ts: Date.now(), runId: id, requestId: request.id, ...(index !== undefined ? { index } : {}), ...extra }));\n\t};\n\tconst emitSteeringNotice = (requestId: string, state: \"failed\" | \"partial\" | \"recovered\", message: string): void => {\n\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.steering.notice\", ts: Date.now(), runId: id, requestId, state, message, ...(config.sessionId ? { currentSessionId: config.sessionId } : {}) }));\n\t};\n\tconst recordSteeringLifecycle = (request: SteerRequest, targets: Array<{ index: number; state: SteeringTargetState; reason?: string }>): void => {\n\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\trecordSteeringRequest(lifecycle, { id: request.id, requestedAt: request.ts, source: request.source, message: request.message, targets });\n\t\tfor (const target of targets) {\n\t\t\tconst step = statusPayload.steps[target.index];\n\t\t\tif (!step) continue;\n\t\t\tstep.steering ??= createSteeringStatus();\n\t\t\trecordSteeringRequest(step.steering, { id: request.id, requestedAt: request.ts, source: request.source, message: request.message, targets: [target] });\n\t\t}\n\t};\n\tconst updateSteeringLifecycleTarget = (\n\t\trequestId: string,\n\t\tindex: number,\n\t\tstate: SteeringTargetState,\n\t\tnow: number,\n\t\tfields: Pick<SteeringTargetStatus, \"reason\" | \"replacementRunId\"> = {},\n\t): SteeringTargetStatus | undefined => {\n\t\tconst updated = updateSteeringTarget(steeringStatus(statusPayload), requestId, index, state, now, fields);\n\t\tconst step = statusPayload.steps[index];\n\t\tif (step?.steering) updateSteeringTarget(step.steering, requestId, index, state, now, fields);\n\t\treturn updated;\n\t};\n\tconst emitTerminalSteeringNotice = (requestId: string, failureMessage: string): void => {\n\t\tconst state = terminalSteeringNoticeState(steeringStatus(statusPayload), requestId);\n\t\tif (state === \"partial\") emitSteeringNotice(requestId, \"partial\", `Steering partially delivered for run ${id}.`);\n\t\telse if (state === \"failed\") emitSteeringNotice(requestId, \"failed\", failureMessage);\n\t};\n\tconst deliverSteerRequest = (request: SteerRequest): void => {\n\t\tif (statusPayload.state !== \"running\") {\n\t\t\tconst reason = `run became ${statusPayload.state} before steering request was consumed`;\n\t\t\tconst indexes = request.targetIndex !== undefined\n\t\t\t\t? [request.targetIndex]\n\t\t\t\t: request.targetIndexes?.length\n\t\t\t\t\t? request.targetIndexes\n\t\t\t\t\t: statusPayload.steps.map((_, index) => index);\n\t\t\tconst targets = indexes.map((index) => ({ index, state: \"failed\" as const, reason }));\n\t\t\trecordSteeringLifecycle(request, targets);\n\t\t\temitSteeringEvent(\"subagent.steer.requested\", request, undefined, { targets });\n\t\t\tfor (const target of targets) emitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason });\n\t\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: ${reason}.`);\n\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\twriteStatusPayload();\n\t\t\treturn;\n\t\t}\n\t\tconst runningIndexes = statusPayload.steps\n\t\t\t.map((step, index) => ({ step, index }))\n\t\t\t.filter(({ step }) => step.status === \"running\")\n\t\t\t.map(({ index }) => index);\n\t\tconst targets = request.targetIndex !== undefined\n\t\t\t? [request.targetIndex]\n\t\t\t: request.targetIndexes?.length\n\t\t\t\t? request.targetIndexes\n\t\t\t\t: runningIndexes.length > 0\n\t\t\t\t\t? runningIndexes\n\t\t\t\t\t: statusPayload.mode === \"single\" && statusPayload.steps[0]?.status === \"pending\"\n\t\t\t\t\t\t? [0]\n\t\t\t\t\t\t: [];\n\t\tconst now = Date.now();\n\t\tconst targetStates = targets.map((index) => {\n\t\t\tconst step = statusPayload.steps[index];\n\t\t\tif (!step) return { index, state: \"failed\" as const, reason: \"child index out of range\" };\n\t\t\tif (step.status === \"pending\") return { index, state: \"scheduled\" as const };\n\t\t\tif (step.status !== \"running\") return { index, state: \"failed\" as const, reason: `child is ${step.status}` };\n\t\t\tif (steeringCapabilities.get(index)?.supported === false) return { index, state: \"failed\" as const, reason: \"child Pi session does not support steering\" };\n\t\t\treturn { index, state: \"routed\" as const };\n\t\t});\n\t\trecordSteeringLifecycle(request, targetStates);\n\t\temitSteeringEvent(\"subagent.steer.requested\", request, undefined, { targets: targetStates });\n\t\tfor (const target of targetStates) {\n\t\t\tif (target.state === \"routed\") {\n\t\t\t\ttry {\n\t\t\t\t\tenqueueStepSteer(asyncDir, target.index, request);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"routed\", now);\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.routed\", request, target.index);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tmarkSteeringAttention(target.index);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"failed\", now, { reason: error instanceof Error ? error.message : String(error) });\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason: error instanceof Error ? error.message : String(error) });\n\t\t\t\t}\n\t\t\t} else if (target.state === \"failed\") {\n\t\t\t\tmarkSteeringAttention(target.index);\n\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", request, target.index, { reason: target.reason });\n\t\t\t} else {\n\t\t\t\temitSteeringEvent(\"subagent.steer.scheduled\", request, target.index);\n\t\t\t}\n\t\t}\n\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: no requested child remained steerable.`);\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst consumeSteerAck = (ack: SteerAck): void => {\n\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\tconst request = lifecycle.recent.find((candidate) => candidate.id === ack.requestId);\n\t\tif (!request || !request.targets.some((target) => target.index === ack.index)) return;\n\t\tconst late = fs.existsSync(steeringMarkerPath(ack.requestId));\n\t\tconst now = Date.now();\n\t\tif (ack.state === \"delivered\") {\n\t\t\tupdateSteeringLifecycleTarget(ack.requestId, ack.index, late ? \"late\" : \"delivered\", now, { reason: late ? \"acknowledged after recovery commit\" : undefined });\n\t\t\temitSteeringEvent(\"subagent.steer.delivered\", { type: \"steer\", id: ack.requestId, ts: now, message: ack.message }, ack.index, { late, message: ack.message });\n\t\t} else {\n\t\t\tmarkSteeringAttention(ack.index);\n\t\t\tupdateSteeringLifecycleTarget(ack.requestId, ack.index, \"failed\", now, { reason: ack.message });\n\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: ack.requestId, ts: now, message: ack.message }, ack.index, { reason: ack.message });\n\t\t}\n\t\temitTerminalSteeringNotice(ack.requestId, `Steering failed for run ${id}: ${ack.message}`);\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst flushPendingStepSteers = (flatIndex: number): void => {\n\t\tconst remaining: SteerRequest[] = [];\n\t\tfor (const request of pendingStepSteers.splice(0)) {\n\t\t\tif (request.targetIndex === undefined) deliverSteerRequest({ ...request, targetIndex: flatIndex });\n\t\t\telse if (request.targetIndex === flatIndex) deliverSteerRequest(request);\n\t\t\telse remaining.push(request);\n\t\t}\n\t\tpendingStepSteers.push(...remaining);\n\t};\n\tconst updateStepModel = (flatIndex: number, model: string | undefined, thinking: string | undefined, now = Date.now()): void => {\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step) return;\n\t\tstep.model = model;\n\t\tstep.thinking = thinking;\n\t\tstatusPayload.lastUpdate = now;\n\t\twriteStatusPayload();\n\t};\n\tconst updateStepTurnBudget = (flatIndex: number, turnCount: number, now: number, terminalAssistantStop: boolean): void => {\n\t\tconst budget = config.turnBudget;\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!budget || !step || timedOut || stopped || turnBudgetExceeded || step.turnBudgetExceeded) return;\n\t\tif (turnCount < budget.maxTurns) {\n\t\t\tconst state: TurnBudgetState = { ...budget, outcome: \"within-budget\", turnCount };\n\t\t\tstep.turnBudget = state;\n\t\t\tstatusPayload.turnBudget = state;\n\t\t\treturn;\n\t\t}\n\t\tconst state = turnBudgetState(budget, turnCount, false);\n\t\tstep.turnBudget = state;\n\t\tstatusPayload.turnBudget = state;\n\t\tif (!step.wrapUpRequested) {\n\t\t\tstep.wrapUpRequested = true;\n\t\t\tstatusPayload.wrapUpRequested = true;\n\t\t\tappendRecentStepOutput(step, [turnBudgetSoftNote(budget, turnCount)]);\n\t\t}\n\t\tif (!shouldAbortForTurnBudget(budget, turnCount, terminalAssistantStop)) return;\n\t\tconst exceededState = turnBudgetState(budget, turnCount, true);\n\t\tconst message = turnBudgetExceededMessage(budget, turnCount);\n\t\tstep.turnBudget = exceededState;\n\t\tstep.turnBudgetExceeded = true;\n\t\tstep.wrapUpRequested = true;\n\t\tstep.error = message;\n\t\tturnBudgetExceeded = true;\n\t\tstatusPayload.turnBudget = exceededState;\n\t\tstatusPayload.turnBudgetExceeded = true;\n\t\tstatusPayload.wrapUpRequested = true;\n\t\tstatusPayload.error = message;\n\t\tstatusPayload.lastUpdate = now;\n\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.step.turn_budget_exceeded\", ts: now, runId: id, stepIndex: flatIndex, agent: step.agent, turnCount, maxTurns: budget.maxTurns, graceTurns: budget.graceTurns, message }));\n\t\tactiveChildTurnBudgetAborts.get(flatIndex)?.(message, exceededState);\n\t};\n\tconst updateStepFromChildEvent = (flatIndex: number, event: ChildEvent): void => {\n\t\tconst step = statusPayload.steps[flatIndex];\n\t\tif (!step) return;\n\t\tconst now = Date.now();\n\t\tstatusPayload.currentStep = flatIndex;\n\t\tif (isChildWatchdogStatusEvent(event)) {\n\t\t\tconst next = acceptChildWatchdogEvent({\n\t\t\t\tcurrent: step.watchdog,\n\t\t\t\tevent,\n\t\t\t\trunId: id,\n\t\t\t\tagent: step.agent,\n\t\t\t\tchildIndex: flatIndex,\n\t\t\t});\n\t\t\tif (!next) return;\n\t\t\tstep.watchdog = next;\n\t\t\tstep.lastActivityAt = now;\n\t\t\tstatusPayload.lastActivityAt = now;\n\t\t\tstatusPayload.lastUpdate = now;\n\t\t\twriteStatusPayload();\n\t\t\treturn;\n\t\t}\n\t\tif (event.type === \"tool_execution_start\" && event.toolName) {\n\t\t\tconst mutates = isMutatingTool(event.toolName, event.args);\n\t\t\tconst currentPath = resolveCurrentPath(event.toolName, event.args);\n\t\t\tstep.toolCount = (step.toolCount ?? 0) + 1;\n\t\t\tconst configuredToolBudget = flatSteps[flatIndex]?.toolBudget;\n\t\t\tif (configuredToolBudget) {\n\t\t\t\tstep.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount);\n\t\t\t\tstatusPayload.toolBudget = step.toolBudget;\n\t\t\t}\n\t\t\tstep.currentTool = event.toolName;\n\t\t\tstep.currentToolArgs = extractToolArgsPreview(event.args ?? {});\n\t\t\tstep.currentToolStartedAt = now;\n\t\t\tstep.currentPath = currentPath;\n\t\t\tpendingToolResults[flatIndex] = { tool: event.toolName, path: currentPath, mutates, startedAt: now };\n\t\t\tstatusPayload.toolCount = (statusPayload.toolCount ?? 0) + 1;\n\t\t\tsyncTopLevelCurrentTool();\n\t\t} else if (event.type === \"tool_execution_end\") {\n\t\t\tif (step.currentTool) {\n\t\t\t\tstep.recentTools ??= [];\n\t\t\t\tstep.recentTools.push({ tool: step.currentTool, args: step.currentToolArgs || \"\", endMs: now });\n\t\t\t}\n\t\t\tstep.currentTool = undefined;\n\t\t\tstep.currentToolArgs = undefined;\n\t\t\tstep.currentToolStartedAt = undefined;\n\t\t\tstep.currentPath = undefined;\n\t\t\tsyncTopLevelCurrentTool();\n\t\t} else if (event.type === \"tool_result_end\" && event.message) {\n\t\t\tconst toolSnapshot = pendingToolResults[flatIndex];\n\t\t\tpendingToolResults[flatIndex] = undefined;\n\t\t\tconst resultText = extractTextFromContent(event.message.content);\n\t\t\tif (toolSnapshot && resultText.includes(\"Tool budget hard limit reached\")) {\n\t\t\t\tconst configuredToolBudget = flatSteps[flatIndex]?.toolBudget;\n\t\t\t\tif (configuredToolBudget) {\n\t\t\t\t\tstep.toolBudget = toolBudgetState(configuredToolBudget, step.toolCount ?? 0, toolSnapshot.tool);\n\t\t\t\t\tstep.toolBudgetBlocked = true;\n\t\t\t\t\tstatusPayload.toolBudget = step.toolBudget;\n\t\t\t\t\tstatusPayload.toolBudgetBlocked = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tappendRecentStepOutput(step, resultText.split(\"\\n\").slice(-10));\n\t\t\tif (toolSnapshot?.mutates && didMutatingToolFail(resultText)) {\n\t\t\t\tconst state = mutatingFailureStates[flatIndex]!;\n\t\t\t\trecordMutatingFailure(state, {\n\t\t\t\t\ttool: toolSnapshot.tool,\n\t\t\t\t\tpath: toolSnapshot.path,\n\t\t\t\t\terror: resultText.split(\"\\n\").find((line) => line.trim())?.trim().slice(0, 180) ?? \"mutating tool failed\",\n\t\t\t\t\tts: now,\n\t\t\t\t}, mutatingFailureWindowMs);\n\t\t\t\tif (controlConfig.enabled && shouldEscalateMutatingFailures(state, controlConfig.failedToolAttemptsBeforeAttention) && step.activityState !== \"needs_attention\") {\n\t\t\t\t\tconst previous = step.activityState;\n\t\t\t\t\tstep.activityState = \"needs_attention\";\n\t\t\t\t\tstatusPayload.activityState = \"needs_attention\";\n\t\t\t\t\tappendControlEvent(buildControlEvent({\n\t\t\t\t\t\ttype: \"needs_attention\",\n\t\t\t\t\t\tfrom: previous,\n\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tagent: step.agent,\n\t\t\t\t\t\tindex: flatIndex,\n\t\t\t\t\t\tts: now,\n\t\t\t\t\t\tmessage: `${step.agent} needs attention after repeated mutating tool failures`,\n\t\t\t\t\t\treason: \"tool_failures\",\n\t\t\t\t\t\tturns: step.turnCount,\n\t\t\t\t\t\ttokens: step.tokens?.total,\n\t\t\t\t\t\ttoolCount: step.toolCount,\n\t\t\t\t\t\tcurrentTool: toolSnapshot.tool,\n\t\t\t\t\t\tcurrentToolDurationMs: toolSnapshot.startedAt ? Math.max(0, now - toolSnapshot.startedAt) : undefined,\n\t\t\t\t\t\tcurrentPath: toolSnapshot.path,\n\t\t\t\t\t\trecentFailureSummary: summarizeRecentMutatingFailures(state),\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t} else if (toolSnapshot?.mutates) {\n\t\t\t\tresetMutatingFailureState(mutatingFailureStates[flatIndex]!);\n\t\t\t}\n\t\t} else if (event.type === \"message_end\" && event.message?.role === \"assistant\") {\n\t\t\tappendRecentStepOutput(step, stripAcceptanceReport(extractTextFromContent(event.message.content)).split(\"\\n\").slice(-10));\n\t\t\tstep.turnCount = (step.turnCount ?? 0) + 1;\n\t\t\tconst usage = event.message.usage;\n\t\t\tif (usage) {\n\t\t\t\tconst input = usage.input ?? usage.inputTokens ?? 0;\n\t\t\t\tconst output = usage.output ?? usage.outputTokens ?? 0;\n\t\t\t\tconst previousInput = step.tokens?.input ?? 0;\n\t\t\t\tconst previousOutput = step.tokens?.output ?? 0;\n\t\t\t\tstep.tokens = { input: previousInput + input, output: previousOutput + output, total: previousInput + previousOutput + input + output };\n\t\t\t\tconst totalInput = statusPayload.totalTokens?.input ?? 0;\n\t\t\t\tconst totalOutput = statusPayload.totalTokens?.output ?? 0;\n\t\t\t\tstatusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };\n\t\t\t}\n\t\t\tstatusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);\n\t\t\tupdateStepTurnBudget(flatIndex, step.turnCount, now, isTerminalAssistantStop(event.message));\n\t\t}\n\t\tsyncTopLevelCurrentTool();\n\t\tstep.lastActivityAt = now;\n\t\tstatusPayload.lastActivityAt = now;\n\t\tstatusPayload.lastUpdate = now;\n\t\tmaybeEmitActiveLongRunning(flatIndex, now);\n\t\twriteStatusPayload();\n\t};\n\tconst updateRunnerActivityState = (now: number): boolean => {\n\t\tif (!controlConfig.enabled) return false;\n\t\tlet changed = false;\n\t\tlet runLastActivityAt = statusPayload.lastActivityAt ?? overallStartTime;\n\t\tfor (let index = 0; index < statusPayload.steps.length; index++) {\n\t\t\tconst step = statusPayload.steps[index]!;\n\t\t\tif (step.status !== \"running\") continue;\n\t\t\tconst lastActivityAt = stepOutputActivityAt(index);\n\t\t\trunLastActivityAt = Math.max(runLastActivityAt, lastActivityAt);\n\t\t\tif (step.lastActivityAt !== lastActivityAt) {\n\t\t\t\tstep.lastActivityAt = lastActivityAt;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tconst idleState = deriveActivityState({\n\t\t\t\tconfig: controlConfig,\n\t\t\t\tstartedAt: step.startedAt ?? overallStartTime,\n\t\t\t\tlastActivityAt,\n\t\t\t\tnow,\n\t\t\t});\n\t\t\tif (idleState === \"needs_attention\") {\n\t\t\t\tconst previous = step.activityState;\n\t\t\t\tstep.activityState = \"needs_attention\";\n\t\t\t\tif (previous !== \"needs_attention\") {\n\t\t\t\t\tappendControlEvent(buildControlEvent({\n\t\t\t\t\t\tfrom: previous,\n\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tagent: step.agent,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tts: now,\n\t\t\t\t\t\tlastActivityAt,\n\t\t\t\t\t}));\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t} else if (maybeEmitActiveLongRunning(index, now)) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\t\tif (statusPayload.lastActivityAt !== runLastActivityAt) {\n\t\t\tstatusPayload.lastActivityAt = runLastActivityAt;\n\t\t\tchanged = true;\n\t\t}\n\t\tconst nextRunState = statusPayload.steps.some((step) => step.activityState === \"needs_attention\")\n\t\t\t? \"needs_attention\"\n\t\t\t: statusPayload.steps.some((step) => step.activityState === \"active_long_running\")\n\t\t\t\t? \"active_long_running\"\n\t\t\t\t: undefined;\n\t\tif (nextRunState !== currentActivityState) {\n\t\t\tcurrentActivityState = nextRunState;\n\t\t\tstatusPayload.activityState = nextRunState;\n\t\t\tchanged = true;\n\t\t}\n\t\tstatusPayload.lastUpdate = now;\n\t\tif (changed) writeStatusPayload();\n\t\treturn changed;\n\t};\n\tif (controlConfig.enabled) {\n\t\tactivityTimer = setInterval(() => {\n\t\t\tif (statusPayload.state !== \"running\") return;\n\t\t\tconst now = Date.now();\n\t\t\tupdateRunnerActivityState(now);\n\t\t}, 1000);\n\t\tactivityTimer.unref?.();\n\t}\n\n\tconst interruptRunner = () => {\n\t\tconsumeInterruptRequest(asyncDir);\n\t\tif (interrupted || statusPayload.state !== \"running\") return;\n\t\tinterrupted = true;\n\t\tconst now = Date.now();\n\t\tstatusPayload.state = \"paused\";\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status === \"running\") {\n\t\t\t\tstep.status = \"paused\";\n\t\t\t\tstep.activityState = undefined;\n\t\t\t\tstep.endedAt = now;\n\t\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : undefined;\n\t\t\t\tstep.lastActivityAt = now;\n\t\t\t}\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.paused\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t}));\n\t\tinterruptNestedAsyncDescendants();\n\t\tinterruptActiveChildren();\n\t};\n\tconst stopRunner = () => {\n\t\tif (stopped || timedOut || interrupted || statusPayload.state !== \"running\") return;\n\t\tstopped = true;\n\t\tconst now = Date.now();\n\t\tstatusPayload.state = \"stopped\";\n\t\tstatusPayload.stopped = true;\n\t\tstatusPayload.error = stopMessage;\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status !== \"running\" && step.status !== \"pending\") continue;\n\t\t\tstep.status = \"stopped\";\n\t\t\tstep.error = stopMessage;\n\t\t\tstep.exitCode = 1;\n\t\t\tstep.stopped = true;\n\t\t\tstep.activityState = undefined;\n\t\t\tstep.endedAt = now;\n\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : 0;\n\t\t\tstep.lastActivityAt = now;\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.stopped\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t\tmessage: stopMessage,\n\t\t}));\n\t\tstopAbortController.abort();\n\t\tstopNestedAsyncDescendants();\n\t\tstopActiveChildren();\n\t};\n\tconst timeoutRunner = () => {\n\t\tif (timedOut || stopped || interrupted || statusPayload.state !== \"running\") return;\n\t\ttimedOut = true;\n\t\tconst now = Date.now();\n\t\tconst message = timeoutMessage ?? \"Subagent timed out.\";\n\t\tstatusPayload.state = \"failed\";\n\t\tstatusPayload.timedOut = true;\n\t\tstatusPayload.error = message;\n\t\tcurrentActivityState = undefined;\n\t\tstatusPayload.activityState = undefined;\n\t\tstatusPayload.lastUpdate = now;\n\t\tfor (const step of statusPayload.steps) {\n\t\t\tif (step.status !== \"running\" && step.status !== \"pending\") continue;\n\t\t\tstep.status = \"failed\";\n\t\t\tstep.error = message;\n\t\t\tstep.exitCode = 1;\n\t\t\tstep.timedOut = true;\n\t\t\tstep.activityState = undefined;\n\t\t\tstep.endedAt = now;\n\t\t\tstep.durationMs = step.startedAt ? now - step.startedAt : 0;\n\t\t\tstep.lastActivityAt = now;\n\t\t}\n\t\twriteStatusPayload();\n\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\ttype: \"subagent.run.timed_out\",\n\t\t\tts: now,\n\t\t\trunId: id,\n\t\t\ttimeoutMs: config.timeoutMs,\n\t\t\tdeadlineAt: config.deadlineAt,\n\t\t\tmessage,\n\t\t}));\n\t\ttimeoutAbortController.abort();\n\t\ttimeoutNestedAsyncDescendants();\n\t\ttimeoutActiveChildren();\n\t};\n\tprocess.on(ASYNC_INTERRUPT_SIGNAL, interruptRunner);\n\t// Portable control inbox: the parent drops control request files here when\n\t// it cannot deliver OS signals (e.g. ENOSYS on Windows) or when steering a\n\t// live child. Interrupts still route into the same graceful interruptRunner().\n\tconst disposeControlInbox = watchAsyncControlInbox(asyncDir, {\n\t\tonInterrupt: interruptRunner,\n\t\tonTimeout: timeoutRunner,\n\t\tonStop: stopRunner,\n\t\tonSteer: (request) => {\n\t\t\tconst targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;\n\t\t\tif (targetStep?.status === \"pending\") {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t\tpendingStepSteers.push(request);\n\t\t\t} else if (request.targetIndexes !== undefined || request.targetIndex !== undefined || statusPayload.steps.some((step) => step.status === \"running\")) {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t} else {\n\t\t\t\tdeliverSteerRequest(request);\n\t\t\t\tpendingStepSteers.push(request);\n\t\t\t}\n\t\t},\n\t\tonSteerCapability: (capability) => {\n\t\t\tsteeringCapabilities.set(capability.index, capability);\n\t\t\tif (!capability.supported) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst lifecycle = steeringStatus(statusPayload);\n\t\t\t\tfor (const request of lifecycle.recent) {\n\t\t\t\t\tif (!request.targets.some((target) => target.index === capability.index && (target.state === \"routed\" || target.state === \"scheduled\"))) continue;\n\t\t\t\t\tmarkSteeringAttention(capability.index);\n\t\t\t\t\tupdateSteeringLifecycleTarget(request.id, capability.index, \"failed\", now, { reason: \"child Pi session does not support steering\" });\n\t\t\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: request.id, ts: request.requestedAt, message: \"child Pi session does not support steering\" }, capability.index, { reason: \"child Pi session does not support steering\" });\n\t\t\t\t\temitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: child ${capability.index} does not support steering.`);\n\t\t\t\t}\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\twriteStatusPayload();\n\t\t\t}\n\t\t},\n\t\tonSteerAck: consumeSteerAck,\n\t});\n\tif (config.deadlineAt !== undefined) {\n\t\tconst remainingMs = Math.max(0, config.deadlineAt - Date.now());\n\t\ttimeoutTimer = setTimeout(timeoutRunner, remainingMs);\n\t\ttimeoutTimer.unref?.();\n\t}\n\tappendJsonl(\n\t\teventsPath,\n\t\tJSON.stringify({\n\t\t\ttype: \"subagent.run.started\",\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tts: overallStartTime,\n\t\t\trunId: id,\n\t\t\tmode: statusPayload.mode,\n\t\t\tcwd,\n\t\t\tpid: process.pid,\n\t\t}),\n\t);\n\n\tlet flatIndex = 0;\n\tlet stepCursor = 0;\n\n\twhile (true) {\n\t\tif (interrupted || timedOut || stopped || turnBudgetExceeded) break;\n\t\tconsumePendingAppendRequests();\n\t\tif (stepCursor >= steps.length) break;\n\t\tconst stepIndex = stepCursor++;\n\t\tconst step = steps[stepIndex]!;\n\n\t\tif (isDynamicRunnerGroup(step)) {\n\t\t\tconst groupStartFlatIndex = flatIndex;\n\t\t\tlet materialized: ReturnType<typeof materializeDynamicParallelStep>;\n\t\t\ttry {\n\t\t\t\tmaterialized = materializeDynamicParallelStep(step as Parameters<typeof materializeDynamicParallelStep>[0], outputs, stepIndex, { maxItems: config.dynamicFanoutMaxItems, allowRunnerFields: true });\n\t\t\t\tif (materialized.parallel.length > 1 && step.parallel.outputPath && !step.parallel.namespaceOutputPath) {\n\t\t\t\t\tthrow new DynamicFanoutError(`Dynamic chain step ${stepIndex + 1} materialized ${materialized.parallel.length} items that resolve output to the same path: ${step.parallel.outputPath}. Remove the explicit output path or use an inherited relative agent output so each item can be isolated.`);\n\t\t\t\t}\n\t\t\t\tif (materialized.collectedOnEmpty) validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);\n\t\t\t} catch (error) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst message = error instanceof DynamicFanoutError ? error.message : error instanceof Error ? error.message : String(error);\n\t\t\t\tstatusPayload.state = \"failed\";\n\t\t\t\tstatusPayload.error = message;\n\t\t\t\tstatusPayload.currentStep = flatIndex;\n\t\t\t\tconst placeholder = statusPayload.steps[groupStartFlatIndex];\n\t\t\t\tif (placeholder) {\n\t\t\t\t\tplaceholder.status = \"failed\";\n\t\t\t\t\tplaceholder.error = message;\n\t\t\t\t\tplaceholder.startedAt = now;\n\t\t\t\t\tplaceholder.endedAt = now;\n\t\t\t\t\tplaceholder.durationMs = 0;\n\t\t\t\t\tplaceholder.exitCode = 1;\n\t\t\t\t}\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"failed\", message);\n\t\t\t\twriteStatusPayload();\n\t\t\t\tresults.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1 });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst effectiveDynamicGroupAcceptance = resolveEffectiveAcceptance({\n\t\t\t\texplicit: step.acceptanceInput,\n\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\tacceptanceRole: step.acceptanceRole,\n\t\t\t\ttask: materialized.parallel.map((task) => task.task ?? step.parallel.task).join(\"\\n\") || step.parallel.task,\n\t\t\t\tmode: config.mode,\n\t\t\t\tasync: true,\n\t\t\t\tdynamicGroup: true,\n\t\t\t});\n\n\t\t\tif (materialized.parallel.length === 0) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tconst collection = materialized.collectedOnEmpty ?? [];\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\tstatusPayload.outputs = outputs;\n\t\t\t\tconst placeholder = statusPayload.steps[groupStartFlatIndex];\n\t\t\t\tif (placeholder) {\n\t\t\t\t\tplaceholder.status = \"complete\";\n\t\t\t\t\tplaceholder.startedAt = now;\n\t\t\t\t\tplaceholder.endedAt = now;\n\t\t\t\t\tplaceholder.durationMs = 0;\n\t\t\t\t}\n\t\t\t\tpreviousOutput = \"Dynamic fanout produced 0 results.\";\n\t\t\t\tconst groupAcceptance = effectiveDynamicGroupAcceptance.explicit && !timedOut && !stopped\n\t\t\t\t\t? await evaluateAcceptance({\n\t\t\t\t\t\tacceptance: effectiveDynamicGroupAcceptance,\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,\n\t\t\t\t\t\tsignal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),\n\t\t\t\t\t\tabortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? \"Subagent timed out.\",\n\t\t\t\t\t})\n\t\t\t\t\t: undefined;\n\t\t\t\tconst groupStopped = stopped || stopAbortController.signal.aborted;\n\t\t\t\tconst groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);\n\t\t\t\tconst effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;\n\t\t\t\tif (placeholder && effectiveGroupAcceptance) placeholder.acceptance = effectiveGroupAcceptance;\n\t\t\t\tconst groupAcceptanceFailure = effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;\n\t\t\t\tif (groupTimedOut || groupStopped || groupAcceptanceFailure) {\n\t\t\t\t\tconst errorMessage = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? \"Subagent timed out.\" : groupAcceptanceFailure!;\n\t\t\t\t\tstatusPayload.state = groupStopped ? \"stopped\" : \"failed\";\n\t\t\t\t\tstatusPayload.error = errorMessage;\n\t\t\t\t\tstatusPayload.stopped = groupStopped ? true : statusPayload.stopped;\n\t\t\t\t\tif (placeholder) {\n\t\t\t\t\t\tplaceholder.status = groupStopped ? \"stopped\" : \"failed\";\n\t\t\t\t\t\tplaceholder.error = errorMessage;\n\t\t\t\t\t\tplaceholder.exitCode = 1;\n\t\t\t\t\t\tplaceholder.timedOut = groupTimedOut ? true : undefined;\n\t\t\t\t\t\tplaceholder.stopped = groupStopped ? true : undefined;\n\t\t\t\t\t}\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, groupStopped ? \"stopped\" : \"failed\", errorMessage, effectiveGroupAcceptance);\n\t\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\tresults.push({ agent: step.parallel.agent, output: errorMessage, error: errorMessage, success: false, exitCode: 1, timedOut: groupTimedOut ? true : undefined, stopped: groupStopped ? true : undefined, acceptance: effectiveGroupAcceptance });\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tflatIndex++;\n\t\t\t\tstatusPayload.lastUpdate = now;\n\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"completed\", undefined, effectiveGroupAcceptance);\n\t\t\t\twriteStatusPayload();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst dynamicSteps = materialized.parallel.map((task, itemIndex) => {\n\t\t\t\tconst thinkingOverride = step.thinkingOverrides?.[itemIndex];\n\t\t\t\tconst model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;\n\t\t\t\tconst thinking = thinkingOverride ? resolveEffectiveThinking(model, thinkingOverride) : undefined;\n\t\t\t\tconst outputPath = step.parallel.namespaceOutputPath && step.parallel.outputPath\n\t\t\t\t\t? path.join(path.dirname(step.parallel.outputPath), `dynamic-${stepIndex}`, `${itemIndex}-${step.parallel.agent}`, path.basename(step.parallel.outputPath))\n\t\t\t\t\t: step.parallel.outputPath;\n\t\t\t\tconst taskText = task.task ?? step.parallel.task;\n\t\t\t\tconst materializedTask = step.parallel.namespaceOutputPath ? injectSingleOutputInstruction(taskText, outputPath, step.parallel) : taskText;\n\t\t\t\treturn {\n\t\t\t\t\t...step.parallel,\n\t\t\t\t\ttask: materializedTask,\n\t\t\t\t\teffectiveAcceptance: resolveEffectiveAcceptance({\n\t\t\t\t\t\texplicit: step.parallel.acceptanceInput,\n\t\t\t\t\t\tagentName: step.parallel.agent,\n\t\t\t\t\t\tacceptanceRole: step.parallel.acceptanceRole,\n\t\t\t\t\t\ttask: materializedTask,\n\t\t\t\t\t\tmode: config.mode,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tdynamic: step.parallel.acceptanceInput === undefined,\n\t\t\t\t\t}),\n\t\t\t\t\tsystemPrompt: step.parallel.namespaceOutputPath ? injectOutputPathSystemPrompt(step.parallel.systemPrompt ?? \"\", outputPath, step.parallel) : step.parallel.systemPrompt,\n\t\t\t\t\toutputPath,\n\t\t\t\t\tlabel: task.label ?? step.parallel.label,\n\t\t\t\t\t...(step.sessionFiles?.[itemIndex] ? { sessionFile: step.sessionFiles[itemIndex] } : {}),\n\t\t\t\t\t...(thinkingOverride ? {\n\t\t\t\t\t\t...(model ? { model } : {}),\n\t\t\t\t\t\t...(thinking ? { thinking } : {}),\n\t\t\t\t\t\t...(step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.map((candidate) => applyThinkingSuffix(candidate, thinkingOverride, true)) } : {}),\n\t\t\t\t\t} : {}),\n\t\t\t\t\tstructuredOutput: undefined,\n\t\t\t\t\tstructuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema,\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst dynamicFlatStepCount = Math.max(statusPayload.steps.length - 1 + dynamicSteps.length, 1);\n\t\t\tconst dynamicStatusSteps: RunnerStatusStep[] = dynamicSteps.map((task, itemIndex) => {\n\t\t\t\tconst transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });\n\t\t\t\treturn {\n\t\t\t\t\tagent: task.agent,\n\t\t\t\t\tphase: task.phase ?? step.phase,\n\t\t\t\t\tlabel: task.label,\n\t\t\t\t\toutputName: undefined,\n\t\t\t\t\tstructured: Boolean(task.structuredOutputSchema),\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),\n\t\t\t\t\t...(transcriptPath ? { transcriptPath } : {}),\n\t\t\t\t\tskills: task.skills,\n\t\t\t\t\tmodel: task.model,\n\t\t\t\t\tthinking: task.thinking,\n\t\t\t\t\tattemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,\n\t\t\t\t\trecentTools: [],\n\t\t\t\t\trecentOutput: [],\n\t\t\t\t};\n\t\t\t});\n\t\t\tstatusPayload.steps.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps);\n\t\t\tif (config.childIntercomTargets) {\n\t\t\t\tconfig.childIntercomTargets = statusPayload.steps.map((statusStep, index) => resolveSubagentIntercomTarget(id, statusStep.childId ?? statusStep.agent, index));\n\t\t\t}\n\t\t\tmutatingFailureStates.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => createMutatingFailureState()));\n\t\t\tpendingToolResults.splice(groupStartFlatIndex, 1, ...dynamicStatusSteps.map(() => undefined));\n\t\t\tconst materializedDelta = dynamicStatusSteps.length - 1;\n\t\t\tfor (const group of statusPayload.parallelGroups) {\n\t\t\t\tif (group.stepIndex === stepIndex) {\n\t\t\t\t\tgroup.start = groupStartFlatIndex;\n\t\t\t\t\tgroup.count = dynamicStatusSteps.length;\n\t\t\t\t} else if (group.start > groupStartFlatIndex) {\n\t\t\t\t\tgroup.start += materializedDelta;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (statusPayload.workflowGraph) {\n\t\t\t\tconst shiftFlatIndexes = (nodes: NonNullable<typeof statusPayload.workflowGraph>[\"nodes\"]): void => {\n\t\t\t\t\tfor (const node of nodes) {\n\t\t\t\t\t\tif (node.stepIndex !== undefined && node.stepIndex > stepIndex && node.flatIndex !== undefined && node.flatIndex >= groupStartFlatIndex) {\n\t\t\t\t\t\t\tnode.flatIndex += dynamicStatusSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (node.children) shiftFlatIndexes(node.children);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tshiftFlatIndexes(statusPayload.workflowGraph.nodes);\n\t\t\t\tconst groupNode = statusPayload.workflowGraph.nodes.find((node) => node.id === `step-${stepIndex}`);\n\t\t\t\tif (groupNode) {\n\t\t\t\t\tgroupNode.children = materialized.items.map((item, itemIndex) => ({\n\t\t\t\t\t\tid: `step-${stepIndex}-item-${item.idKey}`,\n\t\t\t\t\t\tkind: \"agent\",\n\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\tphase: dynamicSteps[itemIndex]?.phase ?? step.phase,\n\t\t\t\t\t\tlabel: dynamicSteps[itemIndex]?.label?.trim() || `${step.parallel.agent} ${item.key}`,\n\t\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\t\tflatIndex: groupStartFlatIndex + itemIndex,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t\titemKey: item.key,\n\t\t\t\t\t\tstructured: Boolean(dynamicSteps[itemIndex]?.structuredOutputSchema),\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t}\n\t\t\twriteStatusPayload();\n\n\t\t\tconst concurrency = step.concurrency ?? MAX_PARALLEL_CONCURRENCY;\n\t\t\tconst failFast = step.failFast ?? false;\n\t\t\tlet aborted = false;\n\t\t\tconst parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {\n\t\t\t\tconst fi = groupStartFlatIndex + taskIdx;\n\t\t\t\tif (timedOut) return timedOutStepResult(task.agent);\n\t\t\t\tif (stopped) return stoppedStepResult(task.agent);\n\t\t\t\tif (interrupted) return pausedStepResult(task.agent);\n\t\t\t\tif (aborted && failFast) {\n\t\t\t\t\tconst skippedAt = Date.now();\n\t\t\t\t\tstatusPayload.steps[fi].status = \"failed\";\n\t\t\t\t\tstatusPayload.steps[fi].error = \"Skipped due to fail-fast\";\n\t\t\t\t\tstatusPayload.steps[fi].startedAt = skippedAt;\n\t\t\t\t\tstatusPayload.steps[fi].endedAt = skippedAt;\n\t\t\t\t\tstatusPayload.steps[fi].durationMs = 0;\n\t\t\t\t\tstatusPayload.steps[fi].exitCode = -1;\n\t\t\t\t\tstatusPayload.lastUpdate = skippedAt;\n\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\treturn { agent: task.agent, output: \"(skipped — fail-fast)\", exitCode: -1 as number | null, skipped: true };\n\t\t\t\t}\n\t\t\t\tconst taskStartTime = Date.now();\n\t\t\t\tstatusPayload.currentStep = fi;\n\t\t\t\tstatusPayload.steps[fi].status = \"running\";\n\t\t\t\tstatusPayload.steps[fi].error = undefined;\n\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\tresetStepLiveDetail(statusPayload.steps[fi]);\n\t\t\t\tstatusPayload.steps[fi].startedAt = taskStartTime;\n\t\t\t\tstatusPayload.steps[fi].lastActivityAt = taskStartTime;\n\t\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);\n\t\t\t\tstatusPayload.lastActivityAt = taskStartTime;\n\t\t\t\tstatusPayload.lastUpdate = taskStartTime;\n\t\t\t\twriteStatusPayload();\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({ type: \"subagent.step.started\", ts: taskStartTime, runId: id, stepIndex: fi, agent: task.agent }));\n\t\t\t\tflushPendingStepSteers(fi);\n\t\t\t\tconst singleResult = await runSingleStep(task, {\n\t\t\t\t\tpreviousOutput, placeholder, cwd, sessionEnabled,\n\t\t\t\t\toutputs,\n\t\t\t\t\tsessionDir: config.sessionDir ? path.join(config.sessionDir, `dynamic-${stepIndex}-${taskIdx}`) : undefined,\n\t\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\t\tflatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\t\toutputFile: path.join(asyncDir, `output-${fi}.log`),\n\t\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, fi),\n\t\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, fi),\n\t\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, fi),\n\t\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[fi],\n\t\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),\n\t\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(fi, interrupt),\n\t\t\t\t\tregisterStop: (stop) => registerStepStop(fi, stop),\n\t\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),\n\t\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\t\ttimeoutMessage,\n\t\t\t\t\tstopMessage,\n\t\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\t\tonAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),\n\t\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(fi, event),\n\t\t\t\t\tonWriterProcess,\n\t\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t\t});\n\t\t\t\tconst taskEndTime = Date.now();\n\t\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\t\tconst childStopped = singleResult.stopped === true;\n\t\t\t\tstatusPayload.steps[fi].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\t\tstatusPayload.steps[fi].endedAt = taskEndTime;\n\t\t\t\tstatusPayload.steps[fi].durationMs = taskEndTime - taskStartTime;\n\t\t\t\tstatusPayload.steps[fi].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\t\tstatusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\t\tstatusPayload.steps[fi].stopped = stopped || childStopped ? true : undefined;\n\t\t\t\tstatusPayload.steps[fi].turnBudget = singleResult.turnBudget;\n\t\t\t\tstatusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\t\tstatusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\t\tstatusPayload.steps[fi].toolBudget = singleResult.toolBudget;\n\t\t\t\tstatusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\t\tstatusPayload.steps[fi].model = singleResult.model;\n\t\t\t\tstatusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);\n\t\t\t\tstatusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;\n\t\t\t\tstatusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;\n\t\t\t\tstatusPayload.steps[fi].totalCost = singleResult.totalCost;\n\t\t\t\tstatusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\t\tstatusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;\n\t\t\t\tstatusPayload.steps[fi].transcriptError = singleResult.transcriptError;\n\t\t\t\tstatusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;\n\t\t\t\tstatusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\t\tstatusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\t\tstatusPayload.steps[fi].acceptance = singleResult.acceptance;\n\t\t\t\tstatusPayload.steps[fi].watchdog = singleResult.watchdog;\n\t\t\t\tstatusPayload.lastUpdate = taskEndTime;\n\t\t\t\twriteStatusPayload();\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\t\tts: taskEndTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskEndTime - taskStartTime,\n\t\t\t\t}));\n\t\t\t\tif (singleResult.exitCode !== 0 && failFast) aborted = true;\n\t\t\t\treturn stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: timeoutMessage ?? \"Subagent timed out.\", error: timeoutMessage ?? \"Subagent timed out.\", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };\n\t\t\t}, globalSemaphore);\n\n\t\t\tflatIndex += dynamicSteps.length;\n\t\t\tfor (const pr of parallelResults) {\n\t\t\t\tresults.push({\n\t\t\t\t\tagent: pr.agent,\n\t\t\t\t\toutput: pr.output,\n\t\t\t\t\terror: pr.error,\n\t\t\t\t\tprotocolError: pr.protocolError,\n\t\t\t\t\tsuccess: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,\n\t\t\t\t\texitCode: pr.interrupted === true ? 0 : pr.exitCode,\n\t\t\t\t\tskipped: pr.skipped,\n\t\t\t\t\tinterrupted: pr.interrupted,\n\t\t\t\t\ttimedOut: pr.timedOut,\n\t\t\t\t\tstopped: pr.stopped,\n\t\t\t\t\tturnBudget: pr.turnBudget,\n\t\t\t\t\tturnBudgetExceeded: pr.turnBudgetExceeded,\n\t\t\t\t\twrapUpRequested: pr.wrapUpRequested,\n\t\t\t\t\ttoolBudget: pr.toolBudget,\n\t\t\t\t\ttoolBudgetBlocked: pr.toolBudgetBlocked,\n\t\t\t\t\tsessionFile: pr.sessionFile,\n\t\t\t\t\tintercomTarget: pr.intercomTarget,\n\t\t\t\t\tmodel: pr.model,\n\t\t\t\t\tattemptedModels: pr.attemptedModels,\n\t\t\t\t\tmodelAttempts: pr.modelAttempts,\n\t\t\t\t\ttotalCost: pr.totalCost,\n\t\t\t\t\tartifactPaths: pr.artifactPaths,\n\t\t\t\t\ttranscriptPath: pr.transcriptPath,\n\t\t\t\t\ttranscriptError: pr.transcriptError,\n\t\t\t\t\tstructuredOutput: pr.structuredOutput,\n\t\t\t\t\tstructuredOutputPath: pr.structuredOutputPath,\n\t\t\t\t\tstructuredOutputSchemaPath: pr.structuredOutputSchemaPath,\n\t\t\t\t\tacceptance: pr.acceptance,\n\t\t\t\t\twatchdog: pr.watchdog,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst collection = collectDynamicResults(step as Parameters<typeof collectDynamicResults>[0], materialized.items, parallelResults);\n\t\t\tconst failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);\n\t\t\tif (failures.length === 0) {\n\t\t\t\ttry {\n\t\t\t\t\tvalidateDynamicCollection(step.collect.outputSchema, collection);\n\t\t\t\t\toutputs[step.collect.as] = {\n\t\t\t\t\t\ttext: JSON.stringify(collection),\n\t\t\t\t\t\tstructured: collection,\n\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t};\n\t\t\t\t\tstatusPayload.outputs = outputs;\n\t\t\t\t\tconst groupAcceptance = !timedOut && !stopped\n\t\t\t\t\t\t? await evaluateAcceptance({\n\t\t\t\t\t\t\tacceptance: effectiveDynamicGroupAcceptance,\n\t\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\t\treport: aggregateAcceptanceReport({\n\t\t\t\t\t\t\t\tresults: parallelResults,\n\t\t\t\t\t\t\t\tnotes: `Dynamic fanout collected ${collection.length} result(s) into ${step.collect.as}.`,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tcwd,\n\t\t\t\t\t\t\tsignal: combinedAbortSignal([timeoutAbortController.signal, stopAbortController.signal]),\n\t\t\t\t\t\t\tabortMessage: stopAbortController.signal.aborted ? stopMessage : timeoutMessage ?? \"Subagent timed out.\",\n\t\t\t\t\t\t})\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst groupStopped = stopped || stopAbortController.signal.aborted;\n\t\t\t\t\tconst groupTimedOut = !groupStopped && (timedOut || timeoutAbortController.signal.aborted);\n\t\t\t\t\tconst effectiveGroupAcceptance = groupTimedOut || groupStopped ? undefined : groupAcceptance;\n\t\t\t\t\tconst groupAcceptanceFailure = effectiveDynamicGroupAcceptance.explicit && effectiveGroupAcceptance ? acceptanceFailureMessage(effectiveGroupAcceptance) : undefined;\n\t\t\t\t\tconst groupError = groupStopped ? stopMessage : groupTimedOut ? timeoutMessage ?? \"Subagent timed out.\" : groupAcceptanceFailure;\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, groupError ? groupStopped ? \"stopped\" : \"failed\" : \"completed\", groupError, effectiveGroupAcceptance);\n\t\t\t\t\tif (groupError) {\n\t\t\t\t\t\tresults.push({\n\t\t\t\t\t\t\tagent: step.parallel.agent,\n\t\t\t\t\t\t\toutput: groupError,\n\t\t\t\t\t\t\terror: groupError,\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\texitCode: 1,\n\t\t\t\t\t\t\ttimedOut: groupTimedOut ? true : undefined,\n\t\t\t\t\t\t\tstopped: groupStopped ? true : undefined,\n\t\t\t\t\t\t\tstructuredOutput: collection,\n\t\t\t\t\t\t\tacceptance: effectiveGroupAcceptance,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tstatusPayload.error = groupError;\n\t\t\t\t\t\tstatusPayload.stopped = groupStopped ? true : statusPayload.stopped;\n\t\t\t\t\t}\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\tresults.push({ agent: step.parallel.agent, output: message, error: message, success: false, exitCode: 1, structuredOutput: collection });\n\t\t\t\t\tstatusPayload.error = message;\n\t\t\t\t\tmarkDynamicGraphGroup(stepIndex, \"failed\", message);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpreviousOutput = aggregateParallelOutputs(\n\t\t\t\tparallelResults.map((r, i) => ({\n\t\t\t\t\tagent: r.agent,\n\t\t\t\t\ttaskIndex: i,\n\t\t\t\t\toutput: r.output,\n\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\terror: r.error,\n\t\t\t\t})),\n\t\t\t\t(i, agent) => `=== Dynamic Item ${i + 1} (${agent}, key ${materialized.items[i]?.key ?? i}) ===`,\n\t\t\t);\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.dynamic.completed\",\n\t\t\t\tts: Date.now(),\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex,\n\t\t\t\tsuccess: failures.length === 0,\n\t\t\t}));\n\t\t\tif (failures.length > 0) markDynamicGraphGroup(stepIndex, \"failed\", failures[0]?.error ?? \"Dynamic fanout child failed.\");\n\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\twriteStatusPayload();\n\t\t\tif (failures.length > 0 || statusPayload.error) break;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isParallelGroup(step)) {\n\t\t\tconst group = step;\n\t\t\tconst concurrency = group.concurrency ?? MAX_PARALLEL_CONCURRENCY;\n\t\t\tconst failFast = group.failFast ?? false;\n\t\t\tconst groupStartFlatIndex = flatIndex;\n\t\t\tlet aborted = false;\n\t\t\tlet worktreeSetup: WorktreeSetup | undefined;\n\t\t\tif (group.worktree) {\n\t\t\t\tconst worktreeTaskCwdConflict = findWorktreeTaskCwdConflict(group.parallel, cwd);\n\t\t\t\tif (worktreeTaskCwdConflict) {\n\t\t\t\t\tconst failedAt = Date.now();\n\t\t\t\t\tmarkParallelGroupSetupFailure({\n\t\t\t\t\t\tstatusPayload,\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\t\tsetupError: formatWorktreeTaskCwdConflict(worktreeTaskCwdConflict, cwd),\n\t\t\t\t\t\tfailedAt,\n\t\t\t\t\t\tstatusPath,\n\t\t\t\t\t\teventsPath,\n\t\t\t\t\t\tasyncDir,\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t});\n\t\t\t\t\tflatIndex += group.parallel.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tworktreeSetup = createWorktrees(cwd, `${id}-s${stepIndex}`, group.parallel.length, {\n\t\t\t\t\t\tagents: group.parallel.map((task) => task.agent),\n\t\t\t\t\t\tsetupHook: config.worktreeSetupHook\n\t\t\t\t\t\t\t? { hookPath: config.worktreeSetupHook, timeoutMs: config.worktreeSetupHookTimeoutMs }\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tbaseDir: config.worktreeBaseDir,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst setupError = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst failedAt = Date.now();\n\t\t\t\t\tmarkParallelGroupSetupFailure({\n\t\t\t\t\t\tstatusPayload,\n\t\t\t\t\t\tresults,\n\t\t\t\t\t\tgroup,\n\t\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\t\tsetupError,\n\t\t\t\t\t\tfailedAt,\n\t\t\t\t\t\tstatusPath,\n\t\t\t\t\t\teventsPath,\n\t\t\t\t\t\tasyncDir,\n\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\tstepIndex,\n\t\t\t\t\t});\n\t\t\t\t\tflatIndex += group.parallel.length;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (group.worktree) ensureParallelProgressFile(cwd, group);\n\t\t\t\tconst groupStartTime = Date.now();\n\t\t\t\tmarkParallelGroupRunning({\n\t\t\t\t\tstatusPayload,\n\t\t\t\t\tgroup,\n\t\t\t\t\tgroupStartFlatIndex,\n\t\t\t\t\tgroupStartTime,\n\t\t\t\t\tstatusPath,\n\t\t\t\t\teventsPath,\n\t\t\t\t\tasyncDir,\n\t\t\t\t\trunId: id,\n\t\t\t\t\tstepIndex,\n\t\t\t\t});\n\t\t\t\tconst parallelResults = await mapConcurrent(\n\t\t\t\t\tgroup.parallel,\n\t\t\t\t\tconcurrency,\n\t\t\t\t\tasync (task, taskIdx) => {\n\t\t\t\t\t\tconst fi = groupStartFlatIndex + taskIdx;\n\t\t\t\t\t\tif (timedOut) return timedOutStepResult(task.agent);\n\t\t\t\t\t\tif (stopped) return stoppedStepResult(task.agent);\n\t\t\t\t\t\tif (interrupted) return pausedStepResult(task.agent);\n\t\t\t\t\t\tif (aborted && failFast) {\n\t\t\t\t\t\t\tconst skippedAt = Date.now();\n\t\t\t\t\t\t\tstatusPayload.steps[fi].status = \"failed\";\n\t\t\t\t\t\t\tstatusPayload.steps[fi].error = \"Skipped due to fail-fast\";\n\t\t\t\t\t\t\tstatusPayload.steps[fi].startedAt = skippedAt;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = skippedAt;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = 0;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].exitCode = -1;\n\t\t\t\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\t\t\t\tstatusPayload.lastUpdate = skippedAt;\n\t\t\t\t\t\t\twriteStatusPayload();\n\t\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\t\ttype: \"subagent.step.failed\", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: -1, durationMs: 0,\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\treturn { agent: task.agent, output: \"(skipped — fail-fast)\", exitCode: -1 as number | null, skipped: true };\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst taskStartTime = Date.now();\n\t\t\t\t\t\tstatusPayload.currentStep = fi;\n\t\t\t\t\t\tstatusPayload.steps[fi].status = \"running\";\n\t\t\t\t\t\tstatusPayload.steps[fi].error = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].activityState = undefined;\n\t\t\t\t\t\tresetStepLiveDetail(statusPayload.steps[fi]);\n\t\t\t\t\t\tstatusPayload.steps[fi].startedAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].lastActivityAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${fi}.log`);\n\t\t\t\t\t\tstatusPayload.lastActivityAt = taskStartTime;\n\t\t\t\t\t\tstatusPayload.lastUpdate = taskStartTime;\n\t\t\t\t\t\twriteStatusPayload();\n\n\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\ttype: \"subagent.step.started\", ts: taskStartTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\t\t}));\n\n\t\t\t\t\t\tconst taskSessionDir = config.sessionDir\n\t\t\t\t\t\t\t? path.join(config.sessionDir, `parallel-${taskIdx}`)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tconst { taskForRun, taskCwd } = prepareParallelTaskRun(task, cwd, worktreeSetup, taskIdx);\n\t\t\t\t\t\tflushPendingStepSteers(fi);\n\n\t\t\t\t\t\tconst singleResult = await runSingleStep(taskForRun, {\n\t\t\t\t\t\t\tpreviousOutput, placeholder, cwd: taskCwd, sessionEnabled,\n\t\t\t\t\t\t\toutputs,\n\t\t\t\t\t\t\tsessionDir: taskSessionDir,\n\t\t\t\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\t\t\t\tflatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\t\t\t\toutputFile: path.join(asyncDir, `output-${fi}.log`),\n\t\t\t\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, fi),\n\t\t\t\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, fi),\n\t\t\t\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, fi),\n\t\t\t\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[fi],\n\t\t\t\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(fi, interrupt),\n\t\t\t\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(fi, interrupt),\n\t\t\t\t\t\t\tregisterStop: (stop) => registerStepStop(fi, stop),\n\t\t\t\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(fi, abort),\n\t\t\t\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\t\t\t\ttimeoutMessage,\n\t\t\t\t\t\t\tstopMessage,\n\t\t\t\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\t\t\t\tonAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking),\n\t\t\t\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(fi, event),\n\t\t\t\t\t\t\tonWriterProcess,\n\t\t\t\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (task.sessionFile) {\n\t\t\t\t\t\t\tlatestSessionFile = task.sessionFile;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst taskEndTime = Date.now();\n\t\t\t\t\t\tconst taskDuration = taskEndTime - taskStartTime;\n\t\t\t\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\t\t\t\tconst childStopped = singleResult.stopped === true;\n\n\t\t\t\t\t\tstatusPayload.steps[fi].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\t\t\t\tstatusPayload.steps[fi].endedAt = taskEndTime;\n\t\t\t\t\t\tstatusPayload.steps[fi].durationMs = taskDuration;\n\t\t\t\t\t\tstatusPayload.steps[fi].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\t\t\t\tstatusPayload.steps[fi].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].stopped = stopped || childStopped ? true : undefined;\n\t\t\t\t\t\tstatusPayload.steps[fi].turnBudget = singleResult.turnBudget;\n\t\t\t\t\t\tstatusPayload.steps[fi].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\t\t\t\tstatusPayload.steps[fi].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\t\t\t\tstatusPayload.steps[fi].toolBudget = singleResult.toolBudget;\n\t\t\t\t\t\tstatusPayload.steps[fi].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\t\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\t\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\t\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\t\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\t\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\t\t\t\tstatusPayload.steps[fi].model = singleResult.model;\n\t\t\t\t\t\tstatusPayload.steps[fi].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[fi].thinking);\n\t\t\t\t\t\tstatusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;\n\t\t\t\t\t\tstatusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;\n\t\t\t\t\t\tstatusPayload.steps[fi].totalCost = singleResult.totalCost;\n\t\t\t\t\t\tstatusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\t\t\t\tstatusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].transcriptError = singleResult.transcriptError;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutput = singleResult.structuredOutput;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\t\t\t\tstatusPayload.steps[fi].acceptance = singleResult.acceptance;\n\t\t\t\t\t\tstatusPayload.steps[fi].watchdog = singleResult.watchdog;\n\t\t\t\t\t\tstatusPayload.lastUpdate = taskEndTime;\n\t\t\t\t\t\twriteStatusPayload();\n\n\t\t\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\t\t\t\tts: taskEndTime, runId: id, stepIndex: fi, agent: task.agent,\n\t\t\t\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskDuration,\n\t\t\t\t\t\t}));\n\t\t\t\t\t\tif (singleResult.completionGuardTriggered) {\n\t\t\t\t\t\t\tconst event = buildControlEvent({\n\t\t\t\t\t\t\t\tfrom: statusPayload.steps[fi].activityState,\n\t\t\t\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\t\t\t\trunId: id,\n\t\t\t\t\t\t\t\tagent: task.agent,\n\t\t\t\t\t\t\t\tindex: fi,\n\t\t\t\t\t\t\t\tts: taskEndTime,\n\t\t\t\t\t\t\t\tmessage: `${task.agent} completed without making edits for an implementation task`,\n\t\t\t\t\t\t\t\treason: \"completion_guard\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tappendControlEvent(event);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (singleResult.exitCode !== 0 && failFast) aborted = true;\n\t\t\t\t\t\treturn stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: timeoutMessage ?? \"Subagent timed out.\", error: timeoutMessage ?? \"Subagent timed out.\", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };\n\t\t\t\t\t},\n\t\t\t\t\tglobalSemaphore,\n\t\t\t\t);\n\n\t\t\t\tflatIndex += group.parallel.length;\n\n\t\t\t\tfor (let t = 0; t < group.parallel.length; t++) {\n\t\t\t\t\tconst fi = groupStartFlatIndex + t;\n\t\t\t\t\tconst sessionTokens = config.sessionDir\n\t\t\t\t\t\t? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`))\n\t\t\t\t\t\t: null;\n\t\t\t\t\tconst taskTokens = sessionTokens ?? tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);\n\t\t\t\t\tif (!taskTokens) continue;\n\t\t\t\t\tstatusPayload.steps[fi].tokens = taskTokens;\n\t\t\t\t\tpreviousCumulativeTokens = {\n\t\t\t\t\t\tinput: previousCumulativeTokens.input + taskTokens.input,\n\t\t\t\t\t\toutput: previousCumulativeTokens.output + taskTokens.output,\n\t\t\t\t\t\ttotal: previousCumulativeTokens.total + taskTokens.total,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatusPayload.totalTokens = { ...previousCumulativeTokens };\n\t\t\t\tstatusPayload.lastUpdate = Date.now();\n\t\t\t\twriteStatusPayload();\n\n\t\t\t\tfor (const pr of parallelResults) {\n\t\t\t\t\tresults.push({\n\t\t\t\t\t\tagent: pr.agent,\n\t\t\t\t\t\toutput: pr.output,\n\t\t\t\t\t\terror: pr.error,\n\t\t\t\t\t\tprotocolError: pr.protocolError,\n\t\t\t\t\t\tsuccess: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,\n\t\t\t\t\t\texitCode: pr.interrupted === true ? 0 : pr.exitCode,\n\t\t\t\t\t\tskipped: pr.skipped,\n\t\t\t\t\t\tinterrupted: pr.interrupted,\n\t\t\t\t\t\ttimedOut: pr.timedOut,\n\t\t\t\t\t\tstopped: pr.stopped,\n\t\t\t\t\t\tturnBudget: pr.turnBudget,\n\t\t\t\t\t\tturnBudgetExceeded: pr.turnBudgetExceeded,\n\t\t\t\t\t\twrapUpRequested: pr.wrapUpRequested,\n\t\t\t\t\t\ttoolBudget: pr.toolBudget,\n\t\t\t\t\t\ttoolBudgetBlocked: pr.toolBudgetBlocked,\n\t\t\t\t\t\tsessionFile: pr.sessionFile,\n\t\t\t\t\t\tintercomTarget: pr.intercomTarget,\n\t\t\t\t\t\tmodel: pr.model,\n\t\t\t\t\t\tattemptedModels: pr.attemptedModels,\n\t\t\t\t\t\tmodelAttempts: pr.modelAttempts,\n\t\t\t\t\t\ttotalCost: pr.totalCost,\n\t\t\t\t\t\tartifactPaths: pr.artifactPaths,\n\t\t\t\t\t\ttranscriptPath: pr.transcriptPath,\n\t\t\t\t\t\ttranscriptError: pr.transcriptError,\n\t\t\t\t\t\tstructuredOutput: pr.structuredOutput,\n\t\t\t\t\t\tstructuredOutputPath: pr.structuredOutputPath,\n\t\t\t\t\t\tstructuredOutputSchemaPath: pr.structuredOutputSchemaPath,\n\t\t\t\t\t\tacceptance: pr.acceptance,\n\t\t\t\t\t\twatchdog: pr.watchdog,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (let t = 0; t < group.parallel.length; t++) {\n\t\t\t\t\tconst outputName = group.parallel[t]?.outputName;\n\t\t\t\t\tif (outputName) outputs[outputName] = outputEntryFromAsyncResult({\n\t\t\t\t\t\tagent: parallelResults[t]!.agent,\n\t\t\t\t\t\toutput: parallelResults[t]!.output,\n\t\t\t\t\t\tstructuredOutput: parallelResults[t]!.structuredOutput,\n\t\t\t\t\t}, stepIndex);\n\t\t\t\t}\n\t\t\t\tstatusPayload.outputs = outputs;\n\n\t\t\t\tpreviousOutput = aggregateParallelOutputs(\n\t\t\t\t\tparallelResults.map((r) => ({\n\t\t\t\t\t\tagent: r.agent,\n\t\t\t\t\t\toutput: r.output,\n\t\t\t\t\t\texitCode: r.exitCode,\n\t\t\t\t\t\terror: r.error,\n\t\t\t\t\t\tmodel: r.model,\n\t\t\t\t\t\tattemptedModels: r.attemptedModels,\n\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tpreviousOutput = appendParallelWorktreeSummary(previousOutput, worktreeSetup, asyncDir, stepIndex, group);\n\n\t\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\t\ttype: \"subagent.parallel.completed\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\trunId: id,\n\t\t\t\t\tstepIndex,\n\t\t\t\t\tsuccess: parallelResults.every((r) => r.exitCode === 0 || r.exitCode === -1),\n\t\t\t\t}));\n\n\t\t\t\tif (parallelResults.some((r) => r.exitCode !== 0 && r.exitCode !== -1)) {\n\t\t\t\t\tbreak;\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 {\n\t\t\tconst seqStep = step as SubagentStep;\n\t\t\tconst stepStartTime = Date.now();\n\t\t\tstatusPayload.currentStep = flatIndex;\n\t\t\tstatusPayload.steps[flatIndex].status = \"running\";\n\t\t\tstatusPayload.steps[flatIndex].activityState = undefined;\n\t\t\tstatusPayload.activityState = undefined;\n\t\t\tresetStepLiveDetail(statusPayload.steps[flatIndex]);\n\t\t\tstatusPayload.steps[flatIndex].skills = seqStep.skills;\n\t\t\tstatusPayload.steps[flatIndex].startedAt = stepStartTime;\n\t\t\tstatusPayload.steps[flatIndex].lastActivityAt = stepStartTime;\n\t\t\tstatusPayload.lastActivityAt = stepStartTime;\n\t\t\tstatusPayload.lastUpdate = stepStartTime;\n\t\t\tstatusPayload.outputFile = path.join(asyncDir, `output-${flatIndex}.log`);\n\t\t\twriteStatusPayload();\n\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: \"subagent.step.started\",\n\t\t\t\tts: stepStartTime,\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex: flatIndex,\n\t\t\t\tagent: seqStep.agent,\n\t\t\t}));\n\n\t\t\tflushPendingStepSteers(flatIndex);\n\t\t\tconst singleResult = await runSingleStep(seqStep, {\n\t\t\t\tpreviousOutput, placeholder, cwd, sessionEnabled,\n\t\t\t\toutputs: statusPayload.mode === \"single\" ? undefined : outputs,\n\t\t\t\tsessionDir: config.sessionDir,\n\t\t\t\tartifactsDir, artifactConfig, id,\n\t\t\t\tflatIndex, flatStepCount: Math.max(statusPayload.steps.length, 1),\n\t\t\t\toutputFile: path.join(asyncDir, `output-${flatIndex}.log`),\n\t\t\t\tsteerInboxDir: stepSteerInboxDir(asyncDir, flatIndex),\n\t\t\t\tsteerCapabilityPath: steerCapabilityPath(asyncDir, flatIndex),\n\t\t\t\tsteerAckDir: steerAcksDir(asyncDir, flatIndex),\n\t\t\t\tpiPackageRoot: config.piPackageRoot,\n\t\t\t\tpiArgv1: config.piArgv1,\n\t\t\t\tchildIntercomTarget: config.childIntercomTargets?.[flatIndex],\n\t\t\t\torchestratorIntercomTarget: config.controlIntercomTarget,\n\t\t\t\tnestedRoute: config.nestedRoute,\n\t\t\t\tregisterInterrupt: (interrupt) => registerStepInterrupt(flatIndex, interrupt),\n\t\t\t\tregisterTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),\n\t\t\t\tregisterStop: (stop) => registerStepStop(flatIndex, stop),\n\t\t\t\tregisterTurnBudgetAbort: (abort) => registerStepTurnBudgetAbort(flatIndex, abort),\n\t\t\t\ttimeoutSignal: timeoutAbortController.signal,\n\t\t\t\tstopSignal: stopAbortController.signal,\n\t\t\t\ttimeoutMessage,\n\t\t\t\tstopMessage,\n\t\t\t\tturnBudget: config.turnBudget,\n\t\t\t\tonAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking),\n\t\t\t\tonChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),\n\t\t\t\tonWriterProcess,\n\t\t\t\tskipAcceptance: () => timedOut || stopped,\n\t\t\t});\n\t\t\tif (seqStep.sessionFile) {\n\t\t\t\tlatestSessionFile = seqStep.sessionFile;\n\t\t\t}\n\n\t\t\tpreviousOutput = singleResult.output;\n\t\t\tconst childStopped = singleResult.stopped === true;\n\t\t\tresults.push({\n\t\t\t\tagent: singleResult.agent,\n\t\t\t\toutput: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.output,\n\t\t\t\terror: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error,\n\t\t\t\tprotocolError: singleResult.protocolError,\n\t\t\t\tsuccess: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,\n\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,\n\t\t\t\tsessionFile: singleResult.sessionFile,\n\t\t\t\tintercomTarget: singleResult.intercomTarget,\n\t\t\t\tmodel: singleResult.model,\n\t\t\t\tattemptedModels: singleResult.attemptedModels,\n\t\t\t\tmodelAttempts: singleResult.modelAttempts,\n\t\t\t\ttotalCost: singleResult.totalCost,\n\t\t\t\tartifactPaths: singleResult.artifactPaths,\n\t\t\t\ttranscriptPath: singleResult.transcriptPath,\n\t\t\t\ttranscriptError: singleResult.transcriptError,\n\t\t\t\tstructuredOutput: singleResult.structuredOutput,\n\t\t\t\tstructuredOutputPath: singleResult.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: singleResult.structuredOutputSchemaPath,\n\t\t\t\tacceptance: singleResult.acceptance,\n\t\t\t\twatchdog: singleResult.watchdog,\n\t\t\t\tinterrupted: singleResult.interrupted,\n\t\t\t\ttimedOut: timedOut || singleResult.timedOut ? true : undefined,\n\t\t\t\tstopped: stopped || childStopped ? true : undefined,\n\t\t\t\tturnBudget: singleResult.turnBudget,\n\t\t\t\tturnBudgetExceeded: singleResult.turnBudgetExceeded,\n\t\t\t\twrapUpRequested: singleResult.wrapUpRequested,\n\t\t\t\ttoolBudget: singleResult.toolBudget,\n\t\t\t\ttoolBudgetBlocked: singleResult.toolBudgetBlocked,\n\t\t\t});\n\t\t\tif (seqStep.outputName) {\n\t\t\t\toutputs[seqStep.outputName] = outputEntryFromAsyncResult({\n\t\t\t\t\tagent: singleResult.agent,\n\t\t\t\t\toutput: singleResult.output,\n\t\t\t\t\tstructuredOutput: singleResult.structuredOutput,\n\t\t\t\t}, stepIndex);\n\t\t\t}\n\t\t\tstatusPayload.outputs = outputs;\n\n\t\t\tconst cumulativeTokens = config.sessionDir ? parseSessionTokens(config.sessionDir) : null;\n\t\t\tlet stepTokens: TokenUsage | null = cumulativeTokens\n\t\t\t\t? {\n\t\t\t\t\t\tinput: cumulativeTokens.input - previousCumulativeTokens.input,\n\t\t\t\t\t\toutput: cumulativeTokens.output - previousCumulativeTokens.output,\n\t\t\t\t\t\ttotal: cumulativeTokens.total - previousCumulativeTokens.total,\n\t\t\t\t\t}\n\t\t\t\t: null;\n\t\t\tif (cumulativeTokens) {\n\t\t\t\tpreviousCumulativeTokens = cumulativeTokens;\n\t\t\t} else {\n\t\t\t\tstepTokens = tokenUsageFromAttempts(singleResult.modelAttempts);\n\t\t\t\tif (stepTokens) {\n\t\t\t\t\tpreviousCumulativeTokens = {\n\t\t\t\t\t\tinput: previousCumulativeTokens.input + stepTokens.input,\n\t\t\t\t\t\toutput: previousCumulativeTokens.output + stepTokens.output,\n\t\t\t\t\t\ttotal: previousCumulativeTokens.total + stepTokens.total,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst stepEndTime = Date.now();\n\t\t\tconst childInterrupted = singleResult.interrupted === true;\n\t\t\tstatusPayload.steps[flatIndex].status = stopped || childStopped ? \"stopped\" : timedOut ? \"failed\" : childInterrupted ? \"paused\" : singleResult.exitCode === 0 ? \"complete\" : \"failed\";\n\t\t\tstatusPayload.steps[flatIndex].endedAt = stepEndTime;\n\t\t\tstatusPayload.steps[flatIndex].durationMs = stepEndTime - stepStartTime;\n\t\t\tstatusPayload.steps[flatIndex].exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;\n\t\t\tstatusPayload.steps[flatIndex].timedOut = timedOut || singleResult.timedOut ? true : undefined;\n\t\t\tstatusPayload.steps[flatIndex].stopped = stopped || childStopped ? true : undefined;\n\t\t\tstatusPayload.steps[flatIndex].turnBudget = singleResult.turnBudget;\n\t\t\tstatusPayload.steps[flatIndex].turnBudgetExceeded = singleResult.turnBudgetExceeded;\n\t\t\tstatusPayload.steps[flatIndex].wrapUpRequested = singleResult.wrapUpRequested;\n\t\t\tstatusPayload.steps[flatIndex].toolBudget = singleResult.toolBudget;\n\t\t\tstatusPayload.steps[flatIndex].toolBudgetBlocked = singleResult.toolBudgetBlocked;\n\t\t\tif (singleResult.toolBudget) statusPayload.toolBudget = singleResult.toolBudget;\n\t\t\tif (singleResult.toolBudgetBlocked) statusPayload.toolBudgetBlocked = true;\n\t\t\tif (singleResult.turnBudget) statusPayload.turnBudget = singleResult.turnBudget;\n\t\t\tif (singleResult.turnBudgetExceeded) statusPayload.turnBudgetExceeded = true;\n\t\t\tif (singleResult.wrapUpRequested) statusPayload.wrapUpRequested = true;\n\t\t\tstatusPayload.steps[flatIndex].model = singleResult.model;\n\t\t\tstatusPayload.steps[flatIndex].thinking = resolveEffectiveThinking(singleResult.model, statusPayload.steps[flatIndex].thinking);\n\t\t\tstatusPayload.steps[flatIndex].attemptedModels = singleResult.attemptedModels;\n\t\t\tstatusPayload.steps[flatIndex].modelAttempts = singleResult.modelAttempts;\n\t\t\tstatusPayload.steps[flatIndex].totalCost = singleResult.totalCost;\n\t\t\tstatusPayload.steps[flatIndex].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : singleResult.error;\n\t\t\tstatusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;\n\t\t\tstatusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutput = singleResult.structuredOutput;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutputPath = singleResult.structuredOutputPath;\n\t\t\tstatusPayload.steps[flatIndex].structuredOutputSchemaPath = singleResult.structuredOutputSchemaPath;\n\t\t\tstatusPayload.steps[flatIndex].acceptance = singleResult.acceptance;\n\t\t\tstatusPayload.steps[flatIndex].watchdog = singleResult.watchdog;\n\t\t\tif (stepTokens) {\n\t\t\t\tstatusPayload.steps[flatIndex].tokens = stepTokens;\n\t\t\t\tstatusPayload.totalTokens = { ...previousCumulativeTokens };\n\t\t\t}\n\t\t\tstatusPayload.lastUpdate = stepEndTime;\n\t\t\twriteStatusPayload();\n\n\t\t\tappendJsonl(eventsPath, JSON.stringify({\n\t\t\t\ttype: stopped || childStopped ? \"subagent.step.stopped\" : timedOut ? \"subagent.step.failed\" : childInterrupted ? \"subagent.step.paused\" : singleResult.exitCode === 0 ? \"subagent.step.completed\" : \"subagent.step.failed\",\n\t\t\t\tts: stepEndTime,\n\t\t\t\trunId: id,\n\t\t\t\tstepIndex: flatIndex,\n\t\t\t\tagent: seqStep.agent,\n\t\t\t\texitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode,\n\t\t\t\tdurationMs: stepEndTime - stepStartTime,\n\t\t\t\ttokens: stepTokens,\n\t\t\t}));\n\t\t\tif (singleResult.completionGuardTriggered) {\n\t\t\t\tconst event = buildControlEvent({\n\t\t\t\t\tfrom: statusPayload.steps[flatIndex].activityState,\n\t\t\t\t\tto: \"needs_attention\",\n\t\t\t\t\trunId: id,\n\t\t\t\t\tagent: seqStep.agent,\n\t\t\t\t\tindex: flatIndex,\n\t\t\t\t\tts: stepEndTime,\n\t\t\t\t\tmessage: `${seqStep.agent} completed without making edits for an implementation task`,\n\t\t\t\t\treason: \"completion_guard\",\n\t\t\t\t});\n\t\t\t\tappendControlEvent(event);\n\t\t\t}\n\n\t\t\tflatIndex++;\n\t\t\tif (singleResult.exitCode !== 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tlet summary = results.map((r) => `${r.agent}:\\n${r.output}`).join(\"\\n\\n\");\n\tlet truncated = false;\n\n\tif (maxOutput) {\n\t\tconst config = { ...DEFAULT_MAX_OUTPUT, ...maxOutput };\n\t\tconst lastArtifactPath = results[results.length - 1]?.artifactPaths?.outputPath;\n\t\tconst truncResult = truncateOutput(summary, config, lastArtifactPath);\n\t\tif (truncResult.truncated) {\n\t\t\tsummary = truncResult.text;\n\t\t\ttruncated = true;\n\t\t}\n\t}\n\n\tconst resultMode = config.resultMode ?? statusPayload.mode;\n\tconst totalCost = results.reduce<CostSummary>((sum, result) => ({\n\t\tinputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),\n\t\toutputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),\n\t\tcostUsd: sum.costUsd + (result.totalCost?.costUsd ?? 0),\n\t}), { inputTokens: 0, outputTokens: 0, costUsd: 0 });\n\tconst finalTotalCost = totalCost.inputTokens > 0 || totalCost.outputTokens > 0 || totalCost.costUsd > 0 ? totalCost : undefined;\n\tconst finalFlatAgents = statusPayload.steps.map((step) => step.agent);\n\tconst agentName = finalFlatAgents.length === 1\n\t\t? finalFlatAgents[0]!\n\t\t: resultMode === \"parallel\"\n\t\t\t? `parallel:${finalFlatAgents.join(\"+\")}`\n\t\t\t: `chain:${finalFlatAgents.join(\"->\")}`;\n\tlet sessionFile: string | undefined;\n\tlet shareUrl: string | undefined;\n\tlet gistUrl: string | undefined;\n\tlet shareError: string | undefined;\n\n\tif (shareEnabled) {\n\t\tsessionFile = config.sessionDir\n\t\t\t? (findLatestSessionFile(config.sessionDir) ?? undefined)\n\t\t\t: undefined;\n\t\tif (!sessionFile && latestSessionFile) {\n\t\t\tsessionFile = latestSessionFile;\n\t\t}\n\t\tif (sessionFile) {\n\t\t\ttry {\n\t\t\t\tconst exportDir = config.sessionDir ?? path.dirname(sessionFile);\n\t\t\t\tconst htmlPath = await exportSessionHtml(sessionFile, exportDir, config.piPackageRoot);\n\t\t\t\tconst share = createShareLink(htmlPath);\n\t\t\t\tif (\"error\" in share) shareError = share.error;\n\t\t\t\telse {\n\t\t\t\t\tshareUrl = share.shareUrl;\n\t\t\t\t\tgistUrl = share.gistUrl;\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tshareError = String(err);\n\t\t\t}\n\t\t} else {\n\t\t\tshareError = \"Session file not found.\";\n\t\t}\n\t}\n\n\tif (activityTimer) {\n\t\tclearInterval(activityTimer);\n\t\tactivityTimer = undefined;\n\t}\n\tif (timeoutTimer) {\n\t\tclearTimeout(timeoutTimer);\n\t\ttimeoutTimer = undefined;\n\t}\n\tstatusPayload.state = stopped ? \"stopped\" : timedOut || turnBudgetExceeded ? \"failed\" : interrupted ? \"paused\" : results.every((r) => r.success) ? \"complete\" : \"failed\";\n\tcloseSteerInbox(asyncDir, statusPayload.state);\n\tdisposeControlInbox();\n\tfor (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);\n\tconst effectiveSessionFile = sessionFile ?? latestSessionFile;\n\tconst steeringLifecycle = steeringStatus(statusPayload);\n\tfor (const request of steeringLifecycle.recent) {\n\t\tlet changed = false;\n\t\tfor (const target of request.targets) {\n\t\t\tif (target.state !== \"scheduled\" && target.state !== \"routed\") continue;\n\t\t\tchanged = true;\n\t\t\tupdateSteeringLifecycleTarget(request.id, target.index, \"failed\", Date.now(), { reason: \"child terminated before steering delivery\" });\n\t\t\tmarkSteeringAttention(target.index);\n\t\t\temitSteeringEvent(\"subagent.steer.failed\", { type: \"steer\", id: request.id, ts: request.requestedAt, message: \"child terminated before steering delivery\" }, target.index, { reason: \"child terminated before steering delivery\" });\n\t\t}\n\t\tif (changed) emitTerminalSteeringNotice(request.id, `Steering failed for run ${id}: child terminated before delivery.`);\n\t}\n\tconst runEndedAt = Date.now();\n\tstatusPayload.activityState = undefined;\n\tif (stopped) {\n\t\tstatusPayload.stopped = true;\n\t\tstatusPayload.error = stopMessage;\n\t}\n\tif (timedOut) {\n\t\tstatusPayload.timedOut = true;\n\t\tstatusPayload.error = timeoutMessage ?? \"Subagent timed out.\";\n\t}\n\tif (turnBudgetExceeded && !statusPayload.error) {\n\t\tconst budget = statusPayload.turnBudget;\n\t\tstatusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : \"Subagent exceeded turn budget.\";\n\t}\n\tstatusPayload.endedAt = runEndedAt;\n\tstatusPayload.lastUpdate = runEndedAt;\n\tstatusPayload.sessionFile = effectiveSessionFile;\n\tstatusPayload.totalCost = finalTotalCost;\n\tstatusPayload.shareUrl = shareUrl;\n\tstatusPayload.gistUrl = gistUrl;\n\tstatusPayload.shareError = shareError;\n\tif (statusPayload.state === \"failed\" && !statusPayload.error) {\n\t\tconst failedStep = statusPayload.steps.find((s) => s.status === \"failed\");\n\t\tif (failedStep?.agent) {\n\t\t\tstatusPayload.error = `Step failed: ${failedStep.agent}`;\n\t\t}\n\t}\n\twriteStatusPayload();\n\tappendJsonl(\n\t\teventsPath,\n\t\tJSON.stringify({\n\t\t\ttype: \"subagent.run.completed\",\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tts: runEndedAt,\n\t\t\trunId: id,\n\t\t\tstatus: statusPayload.state,\n\t\t\tdurationMs: runEndedAt - overallStartTime,\n\t\t\ttotalTokens: statusPayload.totalTokens,\n\t\t\ttotalCost: finalTotalCost,\n\t\t}),\n\t);\n\twriteRunLog(logPath, {\n\t\tid,\n\t\tmode: statusPayload.mode,\n\t\tcwd,\n\t\tstartedAt: overallStartTime,\n\t\tendedAt: runEndedAt,\n\t\tsteps: statusPayload.steps.map((step) => ({\n\t\t\tagent: step.agent,\n\t\t\tstatus: step.status,\n\t\t\tdurationMs: step.durationMs,\n\t\t})),\n\t\tsummary,\n\t\ttruncated,\n\t\tartifactsDir,\n\t\tsessionFile: effectiveSessionFile,\n\t\tshareUrl,\n\t\tshareError,\n\t});\n\n\ttry {\n\t\twriteAtomicJson(resultPath, {\n\t\t\tlifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n\t\t\tid,\n\t\t\tagent: agentName,\n\t\t\tmode: resultMode,\n\t\t\tsuccess: !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),\n\t\t\tstate: stopped ? \"stopped\" : timedOut || turnBudgetExceeded ? \"failed\" : interrupted ? \"paused\" : results.every((r) => r.success) ? \"complete\" : \"failed\",\n\t\t\tsummary: stopped ? stopMessage : timedOut ? (timeoutMessage ?? \"Subagent timed out.\") : turnBudgetExceeded ? (statusPayload.error ?? \"Subagent exceeded turn budget.\") : interrupted ? \"Paused after interrupt. Waiting for explicit next action.\" : summary,\n\t\t\t...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),\n\t\t\t...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),\n\t\t\t...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),\n\t\t\t...(statusPayload.turnBudgetExceeded ? { turnBudgetExceeded: true } : {}),\n\t\t\t...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),\n\t\t\t...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),\n\t\t\t...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),\n\t\t\t...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? \"Subagent timed out.\" } : turnBudgetExceeded ? { error: statusPayload.error ?? \"Subagent exceeded turn budget.\" } : {}),\n\t\t\tresults: results.map((r) => ({\n\t\t\t\tchildId: r.childId,\n\t\t\t\tdescription: r.description,\n\t\t\t\tpermissions: r.permissions,\n\t\t\t\tagent: r.agent,\n\t\t\t\toutput: r.output,\n\t\t\t\terror: r.error,\n\t\t\t\tprotocolError: r.protocolError,\n\t\t\t\tsuccess: r.success,\n\t\t\t\tskipped: r.skipped || undefined,\n\t\t\t\tinterrupted: r.interrupted || undefined,\n\t\t\t\ttimedOut: r.timedOut || undefined,\n\t\t\t\tstopped: r.stopped || undefined,\n\t\t\t\tturnBudget: r.turnBudget,\n\t\t\t\tturnBudgetExceeded: r.turnBudgetExceeded || undefined,\n\t\t\t\twrapUpRequested: r.wrapUpRequested || undefined,\n\t\t\t\ttoolBudget: r.toolBudget,\n\t\t\t\ttoolBudgetBlocked: r.toolBudgetBlocked || undefined,\n\t\t\t\tsessionFile: r.sessionFile,\n\t\t\t\tintercomTarget: r.intercomTarget,\n\t\t\t\tmodel: r.model,\n\t\t\t\tattemptedModels: r.attemptedModels,\n\t\t\t\tmodelAttempts: r.modelAttempts,\n\t\t\t\ttotalCost: r.totalCost,\n\t\t\t\tartifactPaths: r.artifactPaths,\n\t\t\t\ttruncated: r.truncated,\n\t\t\t\ttranscriptPath: r.transcriptPath,\n\t\t\t\ttranscriptError: r.transcriptError,\n\t\t\t\tstructuredOutput: r.structuredOutput,\n\t\t\t\tstructuredOutputPath: r.structuredOutputPath,\n\t\t\t\tstructuredOutputSchemaPath: r.structuredOutputSchemaPath,\n\t\t\t\tacceptance: r.acceptance,\n\t\t\t\twatchdog: r.watchdog,\n\t\t\t})),\n\t\t\toutputs,\n\t\t\tworkflowGraph: statusPayload.workflowGraph,\n\t\t\texitCode: stopped || timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,\n\t\t\ttimestamp: runEndedAt,\n\t\t\tdurationMs: runEndedAt - overallStartTime,\n\t\t\ttotalTokens: statusPayload.totalTokens,\n\t\t\ttotalCost: finalTotalCost,\n\t\t\ttruncated,\n\t\t\tartifactsDir,\n\t\t\tcwd,\n\t\t\tasyncDir,\n\t\t\tsessionId: config.sessionId,\n\t\t\tsessionFile: effectiveSessionFile,\n\t\t\tintercomTarget: config.controlIntercomTarget,\n\t\t\tshareUrl,\n\t\t\tgistUrl,\n\t\t\tshareError,\n\t\t\t...(taskIndex !== undefined && { taskIndex }),\n\t\t\t...(totalTasks !== undefined && { totalTasks }),\n\t\t});\n\t} catch (err) {\n\t\tconsole.error(`Failed to write result file ${resultPath}:`, err);\n\t}\n}\n\nasync function waitForStartupControl(\n\tcontrolPath: string,\n\ttoken: string,\n\taction: \"ack\" | \"proceed\",\n\ttimeoutMs = 30_000,\n): Promise<void> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (fs.existsSync(controlPath)) {\n\t\t\tlet payload: { action?: unknown; token?: unknown };\n\t\t\ttry {\n\t\t\t\tpayload = JSON.parse(fs.readFileSync(controlPath, \"utf-8\")) as { action?: unknown; token?: unknown };\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t\tif (payload.token !== token) throw new Error(\"Runner startup control token does not match the acquired session lease.\");\n\t\t\tif (payload.action === action) return;\n\t\t\tif (payload.action !== \"ack\" && payload.action !== \"proceed\") throw new Error(\"Runner startup control action is invalid.\");\n\t\t}\n\t\tawait new Promise((resolve) => setTimeout(resolve, 20));\n\t}\n\tthrow new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);\n}\n\nasync function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {\n\tlet lease: ReturnType<typeof acquireSessionLease> | undefined;\n\tlet startupCommitted = config.revivalLease === undefined;\n\tconst startupPath = path.join(config.asyncDir, \"runner-startup.json\");\n\tconst startupAckPath = path.join(config.asyncDir, \"runner-startup-ack.json\");\n\tconst startupProceedPath = path.join(config.asyncDir, \"runner-startup-proceed.json\");\n\tconst releaseOnExit = (): void => {\n\t\ttry {\n\t\t\tlease?.release();\n\t\t} catch {\n\t\t\t// Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.\n\t\t}\n\t};\n\tprocess.once(\"exit\", releaseOnExit);\n\ttry {\n\t\tif (config.revivalLease) {\n\t\t\tlease = acquireSessionLease(config.revivalLease);\n\t\t\twriteAtomicJson(startupPath, { state: \"ready\", token: lease.owner.token, pid: process.pid, owner: lease.owner });\n\t\t\tawait waitForStartupControl(startupAckPath, lease.owner.token, \"ack\");\n\t\t\twriteAtomicJson(startupPath, { state: \"acknowledged\", token: lease.owner.token, pid: process.pid });\n\t\t\tawait waitForStartupControl(startupProceedPath, lease.owner.token, \"proceed\");\n\t\t\tstartupCommitted = true;\n\t\t\tfor (const controlPath of [startupAckPath, startupProceedPath]) {\n\t\t\t\ttry {\n\t\t\t\t\tfs.rmSync(controlPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Startup control cleanup is best effort after the parent commits the run.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tawait runSubagent(config, lease ? (writer) => lease!.updateWriter(writer) : undefined);\n\t} catch (error) {\n\t\tif (config.revivalLease && !startupCommitted) {\n\t\t\ttry {\n\t\t\t\twriteAtomicJson(startupPath, { state: \"error\", pid: process.pid, error: error instanceof Error ? error.message : String(error) });\n\t\t\t} catch {\n\t\t\t\t// The parent will time out and terminate this runner if the handshake cannot be written.\n\t\t\t}\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\tprocess.off(\"exit\", releaseOnExit);\n\t\tif (lease) {\n\t\t\ttry {\n\t\t\t\tlease.release();\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to release session revival lease:\", error);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction startConfiguredSubagent(config: SubagentRunConfig): void {\n\trunConfiguredSubagent(config).catch((runErr) => {\n\t\tconsole.error(\"Subagent runner error:\", runErr);\n\t\tprocess.exit(1);\n\t});\n}\n\nconst configArg = process.argv[2];\nif (configArg) {\n\ttry {\n\t\tconst configJson = fs.readFileSync(configArg, \"utf-8\");\n\t\tconst config = JSON.parse(configJson) as SubagentRunConfig;\n\t\ttry {\n\t\t\tfs.unlinkSync(configArg);\n\t\t} catch {\n\t\t\t// Temp config cleanup is best effort.\n\t\t}\n\t\tstartConfiguredSubagent(config);\n\t} catch (err) {\n\t\tconsole.error(\"Subagent runner error:\", err);\n\t\tprocess.exit(1);\n\t}\n} else {\n\tlet input = \"\";\n\tprocess.stdin.setEncoding(\"utf-8\");\n\tprocess.stdin.on(\"data\", (chunk) => {\n\t\tinput += chunk;\n\t});\n\tprocess.stdin.on(\"end\", () => {\n\t\ttry {\n\t\t\tconst config = JSON.parse(input) as SubagentRunConfig;\n\t\t\tstartConfiguredSubagent(config);\n\t\t} catch (err) {\n\t\t\tconsole.error(\"Subagent runner error:\", err);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n}\n"]}