@selesai/code 0.5.28 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -1
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts.map +1 -1
  7. package/dist/cli/config-selector.js +1 -1
  8. package/dist/cli/config-selector.js.map +1 -1
  9. package/dist/cli/credential-print.d.ts +23 -0
  10. package/dist/cli/credential-print.d.ts.map +1 -0
  11. package/dist/cli/credential-print.js +117 -0
  12. package/dist/cli/credential-print.js.map +1 -0
  13. package/dist/cli/startup-ui.d.ts.map +1 -1
  14. package/dist/cli/startup-ui.js +1 -1
  15. package/dist/cli/startup-ui.js.map +1 -1
  16. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  17. package/dist/core/agent-session-runtime.js +3 -0
  18. package/dist/core/agent-session-runtime.js.map +1 -1
  19. package/dist/core/agent-session.d.ts +12 -1
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +20 -14
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/compaction/compaction.d.ts.map +1 -1
  24. package/dist/core/compaction/compaction.js +11 -3
  25. package/dist/core/compaction/compaction.js.map +1 -1
  26. package/dist/core/extensions/runner.d.ts +1 -0
  27. package/dist/core/extensions/runner.d.ts.map +1 -1
  28. package/dist/core/extensions/runner.js +11 -0
  29. package/dist/core/extensions/runner.js.map +1 -1
  30. package/dist/core/extensions/types.d.ts +14 -1
  31. package/dist/core/extensions/types.d.ts.map +1 -1
  32. package/dist/core/extensions/types.js.map +1 -1
  33. package/dist/core/footer-data-provider.d.ts +10 -0
  34. package/dist/core/footer-data-provider.d.ts.map +1 -1
  35. package/dist/core/footer-data-provider.js +1 -1
  36. package/dist/core/footer-data-provider.js.map +1 -1
  37. package/dist/core/llama/provider.d.ts.map +1 -1
  38. package/dist/core/llama/provider.js +8 -3
  39. package/dist/core/llama/provider.js.map +1 -1
  40. package/dist/core/model-config.d.ts +30 -0
  41. package/dist/core/model-config.d.ts.map +1 -1
  42. package/dist/core/model-config.js +6 -0
  43. package/dist/core/model-config.js.map +1 -1
  44. package/dist/core/model-registry.d.ts.map +1 -1
  45. package/dist/core/model-registry.js +2 -2
  46. package/dist/core/model-registry.js.map +1 -1
  47. package/dist/core/model-resolver.d.ts +1 -0
  48. package/dist/core/model-resolver.d.ts.map +1 -1
  49. package/dist/core/model-resolver.js +20 -3
  50. package/dist/core/model-resolver.js.map +1 -1
  51. package/dist/core/model-runtime.d.ts +2 -0
  52. package/dist/core/model-runtime.d.ts.map +1 -1
  53. package/dist/core/model-runtime.js +5 -4
  54. package/dist/core/model-runtime.js.map +1 -1
  55. package/dist/core/package-manager.d.ts.map +1 -1
  56. package/dist/core/package-manager.js +13 -6
  57. package/dist/core/package-manager.js.map +1 -1
  58. package/dist/core/remote-catalog-provider.d.ts +1 -1
  59. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  60. package/dist/core/remote-catalog-provider.js +24 -11
  61. package/dist/core/remote-catalog-provider.js.map +1 -1
  62. package/dist/core/resource-loader.d.ts +15 -0
  63. package/dist/core/resource-loader.d.ts.map +1 -1
  64. package/dist/core/resource-loader.js +66 -9
  65. package/dist/core/resource-loader.js.map +1 -1
  66. package/dist/core/settings-manager.d.ts +1 -1
  67. package/dist/core/settings-manager.d.ts.map +1 -1
  68. package/dist/core/settings-manager.js.map +1 -1
  69. package/dist/core/system-prompt.d.ts.map +1 -1
  70. package/dist/core/system-prompt.js +19 -1
  71. package/dist/core/system-prompt.js.map +1 -1
  72. package/dist/core/system-prompt.test.d.ts +2 -0
  73. package/dist/core/system-prompt.test.d.ts.map +1 -0
  74. package/dist/core/system-prompt.test.js +89 -0
  75. package/dist/core/system-prompt.test.js.map +1 -0
  76. package/dist/core/tools/bash.d.ts +2 -0
  77. package/dist/core/tools/bash.d.ts.map +1 -1
  78. package/dist/core/tools/bash.js +34 -5
  79. package/dist/core/tools/bash.js.map +1 -1
  80. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  81. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  82. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  83. package/dist/defaults/models.json +13 -45
  84. package/dist/defaults/settings.json +1 -2
  85. package/dist/extensions/copy-turn.test.ts +131 -0
  86. package/dist/extensions/copy-turn.ts +6 -1
  87. package/dist/extensions/package.json +0 -1
  88. package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
  89. package/dist/extensions/pi-intercom/README.md +102 -39
  90. package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
  91. package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
  92. package/dist/extensions/pi-intercom/broker/client.ts +315 -12
  93. package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
  94. package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
  95. package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
  96. package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
  97. package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
  98. package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
  99. package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
  100. package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
  101. package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
  102. package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
  103. package/dist/extensions/pi-intercom/config.test.ts +93 -0
  104. package/dist/extensions/pi-intercom/config.ts +55 -6
  105. package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
  106. package/dist/extensions/pi-intercom/cwd.ts +31 -0
  107. package/dist/extensions/pi-intercom/extension-api.ts +44 -0
  108. package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
  109. package/dist/extensions/pi-intercom/format-context.ts +32 -0
  110. package/dist/extensions/pi-intercom/index.ts +742 -145
  111. package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
  112. package/dist/extensions/pi-intercom/package.json +15 -5
  113. package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
  114. package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
  115. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
  116. package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
  117. package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
  118. package/dist/extensions/pi-intercom/types.ts +94 -4
  119. package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
  120. package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
  121. package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
  122. package/dist/extensions/pi-subagents/CHANGELOG.md +88 -0
  123. package/dist/extensions/pi-subagents/LICENSE +21 -0
  124. package/dist/extensions/pi-subagents/README.md +158 -69
  125. package/dist/extensions/pi-subagents/agents/architect.md +5 -4
  126. package/dist/extensions/pi-subagents/agents/builder.md +6 -4
  127. package/dist/extensions/pi-subagents/agents/commentator.md +3 -2
  128. package/dist/extensions/pi-subagents/agents/explorer.md +3 -2
  129. package/dist/extensions/pi-subagents/agents/recapper.md +3 -2
  130. package/dist/extensions/pi-subagents/agents/researcher.md +4 -3
  131. package/dist/extensions/pi-subagents/package-lock.json +2 -2
  132. package/dist/extensions/pi-subagents/package.json +3 -3
  133. package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
  134. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -988
  135. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +257 -0
  136. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +431 -0
  137. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
  138. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +281 -0
  139. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +125 -37
  140. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
  141. package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
  142. package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
  143. package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +125 -0
  144. package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
  145. package/dist/extensions/pi-subagents/src/api/preflight.ts +17 -13
  146. package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
  147. package/dist/extensions/pi-subagents/src/extension/index.ts +22 -8
  148. package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
  149. package/dist/extensions/pi-subagents/src/extension/schemas.ts +33 -8
  150. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +32 -14
  151. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
  152. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
  153. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +86 -21
  154. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
  155. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
  156. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
  157. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
  158. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
  159. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +56 -5
  160. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +92 -11
  161. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
  162. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +388 -29
  163. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
  164. package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
  165. package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +214 -60
  166. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +546 -252
  167. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
  168. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +553 -154
  169. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +19 -13
  170. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
  171. package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
  172. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
  173. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
  174. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
  175. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
  176. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
  177. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
  178. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
  179. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
  180. package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
  181. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +63 -9
  182. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
  183. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
  184. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +22 -1
  185. package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
  186. package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
  187. package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
  188. package/dist/extensions/pi-subagents/src/shared/types.ts +196 -12
  189. package/dist/extensions/pi-subagents/src/shared/utils.ts +102 -5
  190. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +10 -1
  191. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
  192. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
  193. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
  194. package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
  195. package/dist/extensions/pi-subagents/src/tui/render.ts +55 -34
  196. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
  197. package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
  198. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
  199. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
  200. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
  201. package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
  202. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +113 -8
  203. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +419 -47
  204. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
  205. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
  206. package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
  207. package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +62 -22
  208. package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
  209. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +8 -6
  210. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +231 -19
  211. package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +48 -7
  212. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
  213. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +199 -17
  214. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +898 -16
  215. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
  216. package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
  217. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
  218. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +18 -2
  219. package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
  220. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
  221. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
  222. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +198 -6
  223. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +161 -1
  224. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
  225. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
  226. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
  227. package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +63 -0
  228. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +136 -0
  229. package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
  230. package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
  231. package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
  232. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
  233. package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
  234. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
  235. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +28 -2
  236. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
  237. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
  238. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
  239. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
  240. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +17 -12
  241. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
  242. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
  243. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
  244. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +39 -2
  245. package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
  246. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
  247. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
  248. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +48 -0
  249. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
  250. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
  251. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
  252. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
  253. package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
  254. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +46 -2
  255. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +91 -1
  256. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  257. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
  258. package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
  259. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
  260. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
  261. package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +213 -0
  262. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -1
  263. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +61 -10
  264. package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
  265. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
  266. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
  267. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
  268. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
  269. package/dist/main.d.ts.map +1 -1
  270. package/dist/main.js +43 -0
  271. package/dist/main.js.map +1 -1
  272. package/dist/modes/interactive/components/custom-message.d.ts +3 -1
  273. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  274. package/dist/modes/interactive/components/custom-message.js +10 -2
  275. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  276. package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
  277. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  278. package/dist/modes/interactive/components/extension-editor.js +16 -46
  279. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  280. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  281. package/dist/modes/interactive/components/model-selector.js +4 -1
  282. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  283. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
  285. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  286. package/dist/modes/interactive/external-editor.d.ts +12 -0
  287. package/dist/modes/interactive/external-editor.d.ts.map +1 -0
  288. package/dist/modes/interactive/external-editor.js +37 -0
  289. package/dist/modes/interactive/external-editor.js.map +1 -0
  290. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  291. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  292. package/dist/modes/interactive/interactive-mode.js +72 -64
  293. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  294. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  295. package/dist/modes/rpc/rpc-mode.js +14 -0
  296. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  297. package/dist/skills/ponytail/SKILL.md +1 -3
  298. package/dist/utils/clipboard.d.ts.map +1 -1
  299. package/dist/utils/clipboard.js +19 -8
  300. package/dist/utils/clipboard.js.map +1 -1
  301. package/dist/utils/version-check.d.ts.map +1 -1
  302. package/dist/utils/version-check.js +1 -1
  303. package/dist/utils/version-check.js.map +1 -1
  304. package/docs/compaction.md +1 -1
  305. package/docs/custom-provider.md +14 -5
  306. package/docs/environment-variables.md +86 -0
  307. package/docs/extensions.md +15 -5
  308. package/docs/index.md +1 -0
  309. package/docs/models.md +9 -2
  310. package/docs/plans/subagent-delegation/phase-0-correctness.md +265 -0
  311. package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +486 -0
  312. package/docs/plans/subagent-delegation/phase-2-context-controls.md +282 -0
  313. package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +362 -0
  314. package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +381 -0
  315. package/docs/providers.md +21 -2
  316. package/docs/rpc.md +23 -6
  317. package/docs/session-format.md +2 -0
  318. package/docs/settings.md +1 -1
  319. package/docs/usage.md +0 -13
  320. package/examples/extensions/custom-compaction.ts +5 -2
  321. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  322. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  323. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  324. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  325. package/examples/extensions/gondolin/package-lock.json +2 -2
  326. package/examples/extensions/gondolin/package.json +1 -1
  327. package/examples/extensions/handoff.ts +11 -3
  328. package/examples/extensions/message-renderer.ts +3 -3
  329. package/examples/extensions/sandbox/package-lock.json +2 -2
  330. package/examples/extensions/sandbox/package.json +1 -1
  331. package/examples/extensions/summarize.ts +5 -2
  332. package/examples/extensions/with-deps/package-lock.json +2 -2
  333. package/examples/extensions/with-deps/package.json +1 -1
  334. package/examples/sdk/12-full-control.ts +3 -1
  335. package/package.json +16 -7
  336. package/dist/extensions/caveman/caveman-instructions.cjs +0 -11
  337. package/dist/extensions/caveman/index.js +0 -118
  338. package/dist/extensions/caveman/package.json +0 -8
  339. package/dist/extensions/caveman/test/extension.test.js +0 -203
  340. package/dist/extensions/caveman/test/helpers.test.js +0 -58
  341. package/dist/skills/caveman/SKILL.md +0 -50
@@ -18,6 +18,8 @@ import {
18
18
  type AsyncStatus,
19
19
  type ChainOutputMap,
20
20
  type CostSummary,
21
+ type LaunchResolvedChildExtensionsV1,
22
+ type RuntimeAcknowledgedChildExtensionsV1,
21
23
  type ModelAttempt,
22
24
  type NestedRouteInfo,
23
25
  type NestedRunSummary,
@@ -25,6 +27,8 @@ import {
25
27
  type ResolvedTurnBudget,
26
28
  type ResolvedToolBudget,
27
29
  type SubagentRunMode,
30
+ type SubagentOutputState,
31
+ type UsageBudgetConfig,
28
32
  type ToolBudgetState,
29
33
  type TurnBudgetState,
30
34
  type Usage,
@@ -35,6 +39,7 @@ import {
35
39
  DEFAULT_MAX_OUTPUT,
36
40
  type MaxOutputConfig,
37
41
  SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
42
+ POLL_INTERVAL_MS,
38
43
  truncateOutput,
39
44
  getSubagentDepthEnv,
40
45
  } from "../../shared/types.ts";
@@ -49,6 +54,7 @@ import {
49
54
  import {
50
55
  type RunnerSubagentStep as SubagentStep,
51
56
  type RunnerStep,
57
+ isCheckpointRunnerStep,
52
58
  isDynamicRunnerGroup,
53
59
  isParallelGroup,
54
60
  flattenSteps,
@@ -58,13 +64,22 @@ import {
58
64
  DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
59
65
  Semaphore,
60
66
  } from "../shared/parallel-utils.ts";
61
- import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
67
+ import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
68
+ import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
62
69
  import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
63
70
  import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.ts";
71
+ import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
64
72
  import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
65
73
  import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
66
74
  import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
67
75
  import { formatModelAttemptNote, isRetryableModelFailure } from "../shared/model-fallback.ts";
76
+ import {
77
+ SUBAGENT_STARTUP_RETRY_DELAYS_MS,
78
+ formatSubagentStartupRetryExhaustedError,
79
+ formatSubagentStartupRetryNote,
80
+ isRetryableSubagentStartupFailure,
81
+ waitForSubagentStartupRetry,
82
+ } from "../shared/subagent-startup-retry.ts";
68
83
  import { markProcessTerminalCandidateLeaseRelease, writeProcessTerminalCandidate, type ProcessTerminalCandidate } from "./process-terminal.ts";
69
84
  import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.ts";
70
85
  import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
@@ -99,9 +114,10 @@ import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts
99
114
  import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.ts";
100
115
  import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
101
116
  import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
102
- import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from "./chain-append.ts";
117
+ import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
103
118
  import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
104
119
  import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
120
+ import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
105
121
  import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup } from "../shared/parallel-handoff.ts";
106
122
  import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
107
123
  import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
@@ -149,12 +165,15 @@ interface SubagentRunConfig {
149
165
  deadlineAt?: number;
150
166
  turnBudget?: ResolvedTurnBudget;
151
167
  toolBudget?: ResolvedToolBudget;
168
+ usageBudget?: UsageBudgetConfig;
152
169
  revivalLease?: SessionLeaseRequest;
153
170
  revivalLeaseToken?: string;
154
171
  /** Global cap on simultaneously-running subagent tasks within this run. */
155
172
  globalConcurrencyLimit?: number;
156
173
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
157
174
  launchContractDigest?: string;
175
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
176
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
158
177
  runnerProcessInstanceId?: string;
159
178
  }
160
179
 
@@ -163,7 +182,10 @@ interface StepResult {
163
182
  context?: "fresh" | "fork";
164
183
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
165
184
  capabilityAudit?: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit;
185
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
186
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
166
187
  output: string;
188
+ outputState?: SubagentOutputState;
167
189
  error?: string;
168
190
  protocolError?: ProtocolOutputLimit;
169
191
  success: boolean;
@@ -172,6 +194,7 @@ interface StepResult {
172
194
  interrupted?: boolean;
173
195
  timedOut?: boolean;
174
196
  stopped?: boolean;
197
+ processSignal?: string | null;
175
198
  turnBudget?: TurnBudgetState;
176
199
  turnBudgetExceeded?: boolean;
177
200
  wrapUpRequested?: boolean;
@@ -395,10 +418,13 @@ interface RunPiStreamingResult {
395
418
  exitCode: number | null;
396
419
  messages: Message[];
397
420
  usage: Usage;
421
+ toolCount: number;
422
+ durationMs: number;
398
423
  model?: string;
399
424
  error?: string;
400
425
  protocolError?: ProtocolOutputLimit;
401
426
  finalOutput: string;
427
+ outputState: SubagentOutputState;
402
428
  interrupted?: boolean;
403
429
  timedOut?: boolean;
404
430
  stopped?: boolean;
@@ -409,6 +435,7 @@ interface RunPiStreamingResult {
409
435
  toolBudgetBlocked?: boolean;
410
436
  observedMutationAttempt?: boolean;
411
437
  watchdog?: ChildWatchdogStateSnapshot;
438
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
412
439
  processInstanceId: string;
413
440
  processCloseObservedAt?: number;
414
441
  processSignal?: string | null;
@@ -434,6 +461,7 @@ function runPiStreaming(
434
461
  onWriterProcess?: (writer: { state: "none" | "spawning" } | { state: "running"; pid: number }) => void,
435
462
  ): Promise<RunPiStreamingResult> {
436
463
  return new Promise((resolve) => {
464
+ const startedAt = Date.now();
437
465
  const processInstanceId = randomUUID();
438
466
  onWriterProcess?.({ state: "spawning" });
439
467
  const outputStream = fs.createWriteStream(outputFile, { flags: "w" });
@@ -471,6 +499,7 @@ function runPiStreaming(
471
499
  let turnBudgetMessage: string | undefined;
472
500
  let turnBudget: TurnBudgetState | undefined;
473
501
  let observedMutationAttempt = false;
502
+ let toolCount = 0;
474
503
  const childWatchdogConfig = decodeChildWatchdogConfig(env?.[CHILD_WATCHDOG_CONFIG_ENV]);
475
504
  let childWatchdogState: ChildWatchdogStateSnapshot | undefined;
476
505
  let applyChildLifecycle = (_action: ChildLifecycleAction): void => {};
@@ -557,6 +586,7 @@ function runPiStreaming(
557
586
  onChildEvent?.(event);
558
587
 
559
588
  if (event.type === "tool_execution_start" && event.toolName) {
589
+ toolCount += 1;
560
590
  observedMutationAttempt = observedMutationAttempt || isMutatingTool(event.toolName, event.args);
561
591
  const toolArgs = extractToolArgsPreview(event.args ?? {});
562
592
  writeOutputLine(toolArgs ? `${event.toolName}: ${toolArgs}` : event.toolName);
@@ -790,16 +820,27 @@ function runPiStreaming(
790
820
  const stderr = stderrTail.text();
791
821
  const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
792
822
  const finalError = error ?? assistantError;
793
- const forcedDrainAfterFinalSuccess = forcedTerminationSignal && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
823
+ const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
824
+ const signalError = isUnexplainedProcessSignal({
825
+ processSignal: signal,
826
+ interrupted,
827
+ timedOut,
828
+ stopped,
829
+ turnBudgetExceeded,
830
+ forcedDrainAfterFinalSuccess,
831
+ }) ? formatProcessSignalError(signal!) : undefined;
794
832
  resolve({
795
833
  stderr,
796
834
  exitCode: timedOut || stopped ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,
797
835
  messages,
798
836
  usage,
837
+ toolCount,
838
+ durationMs: Date.now() - startedAt,
799
839
  model,
800
- error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,
840
+ error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError ?? signalError,
801
841
  protocolError,
802
842
  finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput,
843
+ outputState: finalOutput.trim() ? "present" : "absent",
803
844
  interrupted,
804
845
  timedOut,
805
846
  stopped,
@@ -833,7 +874,7 @@ function runPiStreaming(
833
874
  const stderr = stderrTail.text();
834
875
  const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
835
876
  const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
836
- resolve({ 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" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
877
+ resolve({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, 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, outputState: finalOutput.trim() ? "present" : "absent", timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
837
878
  });
838
879
  });
839
880
  }
@@ -992,6 +1033,8 @@ async function runSingleStep(
992
1033
  context?: "fresh" | "fork";
993
1034
  agentContract?: import("../../shared/types.ts").AgentContract;
994
1035
  launchContractDigest?: string;
1036
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
1037
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
995
1038
  output: string;
996
1039
  exitCode: number | null;
997
1040
  error?: string;
@@ -1132,6 +1175,7 @@ async function runSingleStep(
1132
1175
  : [undefined];
1133
1176
  const attemptedModels: string[] = [];
1134
1177
  let capabilityAudit: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit | undefined;
1178
+ let launchResolvedExtensions = step.launchResolvedExtensions;
1135
1179
  const modelAttempts: ModelAttempt[] = [];
1136
1180
  const writerProcesses: Array<{ processInstanceId: string; kind: "pi-writer"; attempt: number; closeObservedAt: number; exitCode: number | null; signal: string | null }> = [];
1137
1181
  let writerAttemptCount = 0;
@@ -1145,9 +1189,11 @@ async function runSingleStep(
1145
1189
  let toolBudgetBlocked = false;
1146
1190
  let actualLaunchContractDigest = step.launchContractDigest;
1147
1191
 
1148
- for (let index = 0; index < candidates.length; index++) {
1149
- if (ctx.timeoutSignal?.aborted || ctx.skipAcceptance?.()) break;
1150
- const candidate = candidates[index];
1192
+ let modelIndex = 0;
1193
+ let startupAttemptIndex = 0;
1194
+ modelAttemptsLoop: while (modelIndex < candidates.length) {
1195
+ if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
1196
+ const candidate = candidates[modelIndex];
1151
1197
  ctx.onAttemptStart?.({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
1152
1198
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
1153
1199
  if (effectiveStructuredOutput) {
@@ -1166,7 +1212,7 @@ async function runSingleStep(
1166
1212
  childIndex: ctx.flatIndex,
1167
1213
  })
1168
1214
  : undefined;
1169
- const { args, env, tempDir, toolDiagnosticPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
1215
+ const { args, env, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
1170
1216
  parentSessionId: step.parentSessionId,
1171
1217
  baseArgs: ["--offline", "--mode", "json", "-p"],
1172
1218
  task,
@@ -1215,6 +1261,7 @@ async function runSingleStep(
1215
1261
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1216
1262
  inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
1217
1263
  });
1264
+ launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1218
1265
  actualLaunchContractDigest = launchBindingDigest({
1219
1266
  definitionDigest: step.definitionDigest,
1220
1267
  task: step.launchBindingTask ?? task,
@@ -1259,7 +1306,7 @@ async function runSingleStep(
1259
1306
  writerProcesses.push({
1260
1307
  processInstanceId: run.processInstanceId,
1261
1308
  kind: "pi-writer",
1262
- attempt: index,
1309
+ attempt: writerAttemptCount - 1,
1263
1310
  closeObservedAt: run.processCloseObservedAt,
1264
1311
  exitCode: run.exitCode,
1265
1312
  signal: run.processSignal ?? null,
@@ -1287,6 +1334,7 @@ async function runSingleStep(
1287
1334
  const toolAvailabilityError = run.exitCode === 0 && !run.error
1288
1335
  ? readChildToolDiagnosticError(toolDiagnosticPath)
1289
1336
  : undefined;
1337
+ const runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
1290
1338
  cleanupTempDir(tempDir);
1291
1339
 
1292
1340
  const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError ? detectSubagentError(run.messages) : null;
@@ -1341,6 +1389,13 @@ async function runSingleStep(
1341
1389
  : run.error && run.exitCode === 0
1342
1390
  ? 1
1343
1391
  : run.exitCode;
1392
+ const signalError = run.exitCode !== 0 && isUnexplainedProcessSignal({
1393
+ processSignal: run.processSignal,
1394
+ interrupted: run.interrupted,
1395
+ timedOut: run.timedOut,
1396
+ stopped: run.stopped,
1397
+ turnBudgetExceeded: run.turnBudgetExceeded,
1398
+ }) ? formatProcessSignalError(run.processSignal!) : undefined;
1344
1399
  const error = toolAvailabilityError
1345
1400
  ?? completionGuardError
1346
1401
  ?? structuredError
@@ -1349,7 +1404,7 @@ async function runSingleStep(
1349
1404
  ? hiddenError.details
1350
1405
  ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
1351
1406
  : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
1352
- : run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
1407
+ : run.error || signalError || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
1353
1408
  const attempt: ModelAttempt = {
1354
1409
  model: candidate ?? run.model ?? step.model ?? "default",
1355
1410
  success: effectiveExitCode === 0 && !error,
@@ -1358,7 +1413,7 @@ async function runSingleStep(
1358
1413
  usage: run.usage,
1359
1414
  };
1360
1415
  modelAttempts.push(attempt);
1361
- if (candidate) attemptedModels.push(candidate);
1416
+ if (candidate && startupAttemptIndex === 0) attemptedModels.push(candidate);
1362
1417
  completionGuardTriggeredFinal = completionGuardTriggered;
1363
1418
  finalOutputSnapshot = outputSnapshot;
1364
1419
  if (step.toolBudget) {
@@ -1367,17 +1422,65 @@ async function runSingleStep(
1367
1422
  toolBudgetBlocked = Boolean(blockedMessage);
1368
1423
  toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
1369
1424
  }
1370
- finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
1371
- if (run.turnBudgetExceeded) break;
1372
- if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
1373
- if (attempt.success || completionGuardTriggered) break;
1374
- if (!isRetryableModelFailure(error) || index === candidates.length - 1) break;
1375
- attemptNotes.push(formatModelAttemptNote(attempt, candidates[index + 1]));
1425
+ finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
1426
+ if (run.turnBudgetExceeded) break modelAttemptsLoop;
1427
+ if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
1428
+ if (attempt.success || completionGuardTriggered) break modelAttemptsLoop;
1429
+
1430
+ const startupFailure = isRetryableSubagentStartupFailure({
1431
+ exitCode: effectiveExitCode,
1432
+ error,
1433
+ finalOutput: run.finalOutput,
1434
+ messageCount: run.messages.length,
1435
+ toolCount: run.toolCount,
1436
+ usage: run.usage,
1437
+ durationMs: run.durationMs,
1438
+ protocolError: run.protocolError,
1439
+ processSignal: run.processSignal,
1440
+ observedMutationAttempt: run.observedMutationAttempt,
1441
+ interrupted: run.interrupted,
1442
+ timedOut: run.timedOut,
1443
+ stopped: run.stopped,
1444
+ turnBudgetExceeded: run.turnBudgetExceeded,
1445
+ });
1446
+ const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
1447
+ if (startupFailure && retryDelayMs !== undefined) {
1448
+ const retryNote = formatSubagentStartupRetryNote({
1449
+ model: attempt.model,
1450
+ attempt: startupAttemptIndex + 1,
1451
+ maxAttempts: SUBAGENT_STARTUP_RETRY_DELAYS_MS.length + 1,
1452
+ delayMs: retryDelayMs,
1453
+ });
1454
+ const shouldRetry = await waitForSubagentStartupRetry(retryDelayMs, [ctx.timeoutSignal, ctx.stopSignal]);
1455
+ if (!shouldRetry || ctx.skipAcceptance?.()) break modelAttemptsLoop;
1456
+ attempt.error = retryNote;
1457
+ attemptNotes.push(retryNote);
1458
+ startupAttemptIndex += 1;
1459
+ continue;
1460
+ }
1461
+ if (startupFailure) {
1462
+ const startupError = formatSubagentStartupRetryExhaustedError({
1463
+ model: attempt.model,
1464
+ attempts: startupAttemptIndex + 1,
1465
+ });
1466
+ attempt.error = startupError;
1467
+ finalResult.error = startupError;
1468
+ finalResult.finalOutput = startupError;
1469
+ break modelAttemptsLoop;
1470
+ }
1471
+ if (!isRetryableModelFailure(error) || modelIndex === candidates.length - 1) break modelAttemptsLoop;
1472
+ attemptNotes.push(formatModelAttemptNote(attempt, candidates[modelIndex + 1]));
1473
+ modelIndex += 1;
1474
+ startupAttemptIndex = 0;
1376
1475
  }
1377
1476
 
1378
1477
  const rawOutput = finalResult?.finalOutput ?? "";
1379
1478
  const outputForPersistence = stripAcceptanceReport(rawOutput);
1380
- const resolvedOutput = step.outputPath && finalResult?.exitCode === 0
1479
+ // Persist whenever an output path is configured and meaningful output exists,
1480
+ // not only for successful runs: failed children keep a readable result file
1481
+ // and a saved-output reference instead of raw inline output. Synthetic
1482
+ // failures without output stay "absent" and are not promoted to a reference.
1483
+ const resolvedOutput = step.outputPath && (outputForPersistence.trim() || (finalResult?.exitCode ?? 1) === 0)
1381
1484
  ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot)
1382
1485
  : { fullOutput: outputForPersistence };
1383
1486
  const output = stripAcceptanceReport(resolvedOutput.fullOutput);
@@ -1401,6 +1504,13 @@ async function runSingleStep(
1401
1504
  const childWrittenOutput = step.outputPath
1402
1505
  ? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
1403
1506
  : undefined;
1507
+ const outputState: SubagentOutputState = finalResult?.outputState === "present"
1508
+ || (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput !== undefined
1509
+ || Boolean(childWrittenOutput?.trim())
1510
+ ? "present"
1511
+ : resolvedOutput.savedPath
1512
+ ? "unknown"
1513
+ : finalResult?.outputState ?? "unknown";
1404
1514
  const finalizedOutput = finalizeSingleOutput({
1405
1515
  fullOutput: outputForSummary,
1406
1516
  outputPath: step.outputPath,
@@ -1409,6 +1519,9 @@ async function runSingleStep(
1409
1519
  savedPath: resolvedOutput.savedPath,
1410
1520
  outputReference,
1411
1521
  saveError: resolvedOutput.saveError,
1522
+ error: finalResult?.error
1523
+ ?? (finalResult?.stopped ? ctx.stopMessage ?? "Subagent stopped by user." : undefined)
1524
+ ?? (finalResult?.timedOut ? ctx.timeoutMessage ?? "Subagent timed out." : undefined),
1412
1525
  });
1413
1526
  outputForSummary = finalizedOutput.displayOutput;
1414
1527
  const acceptance = step.effectiveAcceptance && !finalResult?.stopped && !finalResult?.turnBudgetExceeded && !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted && !ctx.skipAcceptance?.()
@@ -1473,6 +1586,8 @@ async function runSingleStep(
1473
1586
  acceptance: effectiveAcceptance,
1474
1587
  ...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
1475
1588
  launchContractDigest: actualLaunchContractDigest,
1589
+ launchResolvedExtensions,
1590
+ ...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
1476
1591
  ...(transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {}),
1477
1592
  transcriptError: transcriptWriter?.getError(),
1478
1593
  skills: step.skills,
@@ -1488,7 +1603,12 @@ async function runSingleStep(
1488
1603
  context: step.context,
1489
1604
  ...(step.agentContract ? { agentContract: step.agentContract } : {}),
1490
1605
  launchContractDigest: actualLaunchContractDigest,
1606
+ // Authoritative durable output location for parent-facing delivery: the
1607
+ // explicit/generated saved output path when present, otherwise the async
1608
+ // per-child output log (`asyncDir/output-<flat-index>.log`).
1609
+ outputPath: step.outputPath ?? ctx.outputFile,
1491
1610
  output: outputForSummary,
1611
+ outputState,
1492
1612
  exitCode: effectiveFinalExitCode,
1493
1613
  error: effectiveFinalError,
1494
1614
  protocolError: finalResult?.protocolError,
@@ -1504,6 +1624,7 @@ async function runSingleStep(
1504
1624
  interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,
1505
1625
  timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
1506
1626
  stopped: stoppedAfterAcceptance ? true : finalResult?.stopped,
1627
+ processSignal: finalResult?.processSignal,
1507
1628
  turnBudget,
1508
1629
  turnBudgetExceeded: turnBudgetExceeded || undefined,
1509
1630
  wrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined,
@@ -1517,6 +1638,8 @@ async function runSingleStep(
1517
1638
  acceptance: effectiveAcceptance,
1518
1639
  watchdog: finalResult?.watchdog,
1519
1640
  ...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
1641
+ launchResolvedExtensions,
1642
+ ...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
1520
1643
  writerProcesses,
1521
1644
  writerAttemptCount,
1522
1645
  };
@@ -1525,6 +1648,7 @@ async function runSingleStep(
1525
1648
 
1526
1649
  type RunnerStatusStep = NonNullable<AsyncStatus["steps"]>[number] & {
1527
1650
  exitCode?: number | null;
1651
+ description?: string;
1528
1652
  };
1529
1653
 
1530
1654
  function appendCapabilityCeilingAppliedEvent(eventsPath: string, runId: string, stepIndex: number, agent: string, result: StepResult): void {
@@ -1722,6 +1846,10 @@ async function runSubagent(
1722
1846
  let timedOut = false;
1723
1847
  let stopped = false;
1724
1848
  let turnBudgetExceeded = false;
1849
+ let usageBudgetExceeded = false;
1850
+ let checkpointRejected = false;
1851
+ let pendingCheckpointDecision: "approved" | "rejected" | undefined;
1852
+ let wakeCheckpointDecision: (() => void) | undefined;
1725
1853
  const timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;
1726
1854
  const stopMessage = "Subagent stopped by user.";
1727
1855
  const timeoutAbortController = new AbortController();
@@ -1736,6 +1864,19 @@ async function runSubagent(
1736
1864
  let flatStepCount = 0;
1737
1865
  for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
1738
1866
  const step = steps[stepIndex]!;
1867
+ if (isCheckpointRunnerStep(step)) {
1868
+ initialStatusSteps.push({
1869
+ agent: `checkpoint:${step.checkpoint}`,
1870
+ phase: step.phase,
1871
+ label: step.label ?? step.checkpoint,
1872
+ status: "pending",
1873
+ checkpoint: { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending", stepIndex },
1874
+ recentTools: [],
1875
+ recentOutput: [],
1876
+ });
1877
+ flatStepCount++;
1878
+ continue;
1879
+ }
1739
1880
  if (isParallelGroup(step)) {
1740
1881
  parallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });
1741
1882
  for (const task of step.parallel) {
@@ -1743,6 +1884,7 @@ async function runSubagent(
1743
1884
  const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });
1744
1885
  initialStatusSteps.push({
1745
1886
  agent: task.agent,
1887
+ ...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
1746
1888
  ...(task.context ? { context: task.context } : {}),
1747
1889
  phase: task.phase,
1748
1890
  label: task.label,
@@ -1750,6 +1892,7 @@ async function runSubagent(
1750
1892
  structured: task.structured,
1751
1893
  ...(task.agentContract ? { agentContract: task.agentContract } : {}),
1752
1894
  ...(task.launchContractDigest ? { launchContractDigest: task.launchContractDigest } : {}),
1895
+ ...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
1753
1896
  ...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
1754
1897
  status: "pending",
1755
1898
  ...(task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {}),
@@ -1786,6 +1929,7 @@ async function runSubagent(
1786
1929
  const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });
1787
1930
  initialStatusSteps.push({
1788
1931
  agent: step.agent,
1932
+ ...(statusStepDescription(step.task) ? { description: statusStepDescription(step.task) } : {}),
1789
1933
  ...(step.context ? { context: step.context } : {}),
1790
1934
  phase: step.phase,
1791
1935
  label: step.label,
@@ -1793,6 +1937,7 @@ async function runSubagent(
1793
1937
  structured: step.structured,
1794
1938
  ...(step.agentContract ? { agentContract: step.agentContract } : {}),
1795
1939
  ...(step.launchContractDigest ? { launchContractDigest: step.launchContractDigest } : {}),
1940
+ ...(step.launchResolvedExtensions ? { launchResolvedExtensions: step.launchResolvedExtensions } : {}),
1796
1941
  ...(step.capabilityCeiling ? { capabilityCeiling: step.capabilityCeiling } : {}),
1797
1942
  status: "pending",
1798
1943
  ...(step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {}),
@@ -1831,6 +1976,7 @@ async function runSubagent(
1831
1976
  ...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
1832
1977
  ...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),
1833
1978
  ...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
1979
+ ...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
1834
1980
  pid: process.pid,
1835
1981
  cwd,
1836
1982
  currentStep: 0,
@@ -1838,6 +1984,7 @@ async function runSubagent(
1838
1984
  parallelGroups,
1839
1985
  workflowGraph: config.workflowGraph,
1840
1986
  ...(config.launchContractDigest ? { launchContractDigest: config.launchContractDigest } : {}),
1987
+ ...(config.launchResolvedExtensions ? { launchResolvedExtensions: config.launchResolvedExtensions } : {}),
1841
1988
  ...(config.capabilityCeiling ? { capabilityCeiling: config.capabilityCeiling } : {}),
1842
1989
  ...(config.runnerProcessInstanceId ? { processTerminal: { version: 1 as const, state: "pending" as const, runId: id, runnerProcessInstanceId: config.runnerProcessInstanceId } } : {}),
1843
1990
  steps: initialStatusSteps,
@@ -1848,6 +1995,23 @@ async function runSubagent(
1848
1995
 
1849
1996
  fs.mkdirSync(asyncDir, { recursive: true });
1850
1997
  writeAtomicJson(statusPath, statusPayload);
1998
+ let pendingParallelUsageCost: CostSummary = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
1999
+ const currentUsageTotals = (): CostSummary => {
2000
+ const cost = results.reduce<CostSummary>((sum, result) => ({
2001
+ inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? result.usage?.input ?? 0),
2002
+ outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? result.usage?.output ?? 0),
2003
+ costUsd: sum.costUsd + (result.totalCost?.costUsd ?? result.usage?.cost ?? 0),
2004
+ }), { inputTokens: pendingParallelUsageCost.inputTokens, outputTokens: pendingParallelUsageCost.outputTokens, costUsd: pendingParallelUsageCost.costUsd });
2005
+ return {
2006
+ inputTokens: Math.max(cost.inputTokens, statusPayload.totalTokens?.input ?? 0),
2007
+ outputTokens: Math.max(cost.outputTokens, statusPayload.totalTokens?.output ?? 0),
2008
+ costUsd: cost.costUsd,
2009
+ };
2010
+ };
2011
+ const refreshUsageBudget = () => {
2012
+ statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
2013
+ return statusPayload.usageBudget;
2014
+ };
1851
2015
  const emitNestedSelfEvent = (type: "subagent.nested.updated" | "subagent.nested.completed"): void => {
1852
2016
  if (!config.nestedRoute || !config.nestedSelf) return;
1853
2017
  try {
@@ -1873,9 +2037,9 @@ async function runSubagent(
1873
2037
  const refreshWorkflowGraph = (): void => {
1874
2038
  if (!config.workflowGraph) return;
1875
2039
  const graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);
1876
- const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" => {
2040
+ const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" | "rejected" => {
1877
2041
  if (status === "complete" || status === "completed") return "completed";
1878
- if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending") return status;
2042
+ if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending" || status === "rejected") return status;
1879
2043
  return "pending";
1880
2044
  };
1881
2045
  const updateNode = (node: NonNullable<typeof graph.nodes>[number]): void => {
@@ -1885,6 +2049,7 @@ async function runSubagent(
1885
2049
  node.status = normalize(step.status);
1886
2050
  node.error = step.error;
1887
2051
  node.acceptanceStatus = step.acceptance?.status;
2052
+ node.checkpoint = step.checkpoint;
1888
2053
  }
1889
2054
  if (statusPayload.currentStep === node.flatIndex) graph.currentNodeId = node.id;
1890
2055
  }
@@ -1893,10 +2058,11 @@ async function runSubagent(
1893
2058
  if (node.children.every((child) => child.status === "completed")) node.status = "completed";
1894
2059
  else if (node.children.some((child) => child.status === "running")) node.status = "running";
1895
2060
  else if (node.children.some((child) => child.status === "stopped")) node.status = "stopped";
2061
+ else if (node.children.some((child) => child.status === "rejected")) node.status = "rejected";
1896
2062
  else if (node.children.some((child) => child.status === "failed")) node.status = "failed";
1897
2063
  else if (node.children.some((child) => child.status === "paused")) node.status = "paused";
1898
2064
  }
1899
- if (node.error && node.status !== "stopped") node.status = "failed";
2065
+ if (node.error && node.status !== "stopped" && node.status !== "rejected") node.status = "failed";
1900
2066
  };
1901
2067
  for (const node of graph.nodes) updateNode(node);
1902
2068
  statusPayload.workflowGraph = graph;
@@ -2544,6 +2710,7 @@ async function runSubagent(
2544
2710
  const totalInput = statusPayload.totalTokens?.input ?? 0;
2545
2711
  const totalOutput = statusPayload.totalTokens?.output ?? 0;
2546
2712
  statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };
2713
+ refreshUsageBudget();
2547
2714
  }
2548
2715
  statusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);
2549
2716
  updateStepTurnBudget(
@@ -2729,6 +2896,10 @@ async function runSubagent(
2729
2896
  onInterrupt: interruptRunner,
2730
2897
  onTimeout: timeoutRunner,
2731
2898
  onStop: stopRunner,
2899
+ onCheckpointDecision: (decision) => {
2900
+ pendingCheckpointDecision = decision;
2901
+ wakeCheckpointDecision?.();
2902
+ },
2732
2903
  onSteer: (request) => {
2733
2904
  const targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;
2734
2905
  if (targetStep?.status === "pending") {
@@ -2779,14 +2950,95 @@ async function runSubagent(
2779
2950
 
2780
2951
  let flatIndex = 0;
2781
2952
  let stepCursor = 0;
2953
+ const waitForCheckpointDecision = async (): Promise<"approved" | "rejected" | undefined> => {
2954
+ while (!pendingCheckpointDecision && !interrupted && !timedOut && !stopped) {
2955
+ await new Promise<void>((resolve) => {
2956
+ wakeCheckpointDecision = resolve;
2957
+ const timer = setTimeout(resolve, POLL_INTERVAL_MS);
2958
+ timer.unref?.();
2959
+ });
2960
+ wakeCheckpointDecision = undefined;
2961
+ }
2962
+ const decision = pendingCheckpointDecision;
2963
+ pendingCheckpointDecision = undefined;
2964
+ return decision;
2965
+ };
2782
2966
 
2783
2967
  while (true) {
2784
2968
  if (interrupted || timedOut || stopped || turnBudgetExceeded) break;
2785
2969
  consumePendingAppendRequests();
2786
2970
  if (stepCursor >= steps.length) break;
2971
+ refreshUsageBudget();
2972
+ if (statusPayload.usageBudget?.exhausted) {
2973
+ usageBudgetExceeded = true;
2974
+ statusPayload.state = "failed";
2975
+ statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
2976
+ statusPayload.currentStep = flatIndex;
2977
+ statusPayload.lastUpdate = Date.now();
2978
+ writeStatusPayload();
2979
+ break;
2980
+ }
2787
2981
  const stepIndex = stepCursor++;
2788
2982
  const step = steps[stepIndex]!;
2789
2983
 
2984
+ if (isCheckpointRunnerStep(step)) {
2985
+ const now = Date.now();
2986
+ const statusStep = statusPayload.steps[flatIndex];
2987
+ const checkpoint = { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending" as const, stepIndex };
2988
+ statusPayload.state = "paused";
2989
+ statusPayload.currentStep = flatIndex;
2990
+ statusPayload.checkpoint = checkpoint;
2991
+ statusPayload.activityState = undefined;
2992
+ statusPayload.lastUpdate = now;
2993
+ if (statusStep) {
2994
+ statusStep.status = "paused";
2995
+ statusStep.startedAt = now;
2996
+ statusStep.checkpoint = checkpoint;
2997
+ }
2998
+ writeStatusPayload();
2999
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.paused", ts: now, runId: id, stepIndex, checkpoint }));
3000
+ const decision = await waitForCheckpointDecision();
3001
+ if (decision === "approved") {
3002
+ const approvedAt = Date.now();
3003
+ const approved = { ...checkpoint, status: "approved" as const, approvedAt };
3004
+ statusPayload.state = "running";
3005
+ statusPayload.checkpoint = approved;
3006
+ if (statusStep) {
3007
+ statusStep.status = "complete";
3008
+ statusStep.endedAt = approvedAt;
3009
+ statusStep.durationMs = approvedAt - now;
3010
+ statusStep.exitCode = 0;
3011
+ statusStep.checkpoint = approved;
3012
+ }
3013
+ statusPayload.lastUpdate = approvedAt;
3014
+ writeStatusPayload();
3015
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.approved", ts: approvedAt, runId: id, stepIndex, checkpoint: approved }));
3016
+ flatIndex++;
3017
+ continue;
3018
+ }
3019
+ if (decision === "rejected") {
3020
+ const rejectedAt = Date.now();
3021
+ const rejected = { ...checkpoint, status: "rejected" as const, rejectedAt };
3022
+ checkpointRejected = true;
3023
+ statusPayload.state = "rejected";
3024
+ statusPayload.error = `Checkpoint '${step.checkpoint}' rejected.`;
3025
+ statusPayload.checkpoint = rejected;
3026
+ if (statusStep) {
3027
+ statusStep.status = "rejected";
3028
+ statusStep.error = statusPayload.error;
3029
+ statusStep.endedAt = rejectedAt;
3030
+ statusStep.durationMs = rejectedAt - now;
3031
+ statusStep.exitCode = 1;
3032
+ statusStep.checkpoint = rejected;
3033
+ }
3034
+ statusPayload.lastUpdate = rejectedAt;
3035
+ writeStatusPayload();
3036
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.rejected", ts: rejectedAt, runId: id, stepIndex, checkpoint: rejected }));
3037
+ break;
3038
+ }
3039
+ break;
3040
+ }
3041
+
2790
3042
  if (isDynamicRunnerGroup(step)) {
2791
3043
  const groupStartFlatIndex = flatIndex;
2792
3044
  let materialized: ReturnType<typeof materializeDynamicParallelStep>;
@@ -2931,12 +3183,14 @@ async function runSubagent(
2931
3183
  const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });
2932
3184
  return {
2933
3185
  agent: task.agent,
3186
+ ...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
2934
3187
  ...(task.context ? { context: task.context } : {}),
2935
3188
  phase: task.phase ?? step.phase,
2936
3189
  label: task.label,
2937
3190
  outputName: undefined,
2938
3191
  structured: Boolean(task.structuredOutputSchema),
2939
3192
  ...(task.agentContract ? { agentContract: task.agentContract } : {}),
3193
+ ...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
2940
3194
  ...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
2941
3195
  status: "pending",
2942
3196
  ...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),
@@ -2997,6 +3251,22 @@ async function runSubagent(
2997
3251
  let aborted = false;
2998
3252
  const parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {
2999
3253
  const fi = groupStartFlatIndex + taskIdx;
3254
+ refreshUsageBudget();
3255
+ if (statusPayload.usageBudget?.exhausted) {
3256
+ const skippedAt = Date.now();
3257
+ const message = usageBudgetExceededMessage(statusPayload.usageBudget);
3258
+ statusPayload.steps[fi].status = "failed";
3259
+ statusPayload.steps[fi].error = message;
3260
+ statusPayload.steps[fi].startedAt = skippedAt;
3261
+ statusPayload.steps[fi].endedAt = skippedAt;
3262
+ statusPayload.steps[fi].durationMs = 0;
3263
+ statusPayload.steps[fi].exitCode = 1;
3264
+ statusPayload.lastUpdate = skippedAt;
3265
+ usageBudgetExceeded = true;
3266
+ writeStatusPayload();
3267
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0 }));
3268
+ return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
3269
+ }
3000
3270
  if (timedOut) return timedOutStepResult(task.agent, task.context);
3001
3271
  if (stopped) return stoppedStepResult(task.agent, task.context);
3002
3272
  if (interrupted) return pausedStepResult(task.agent, task.context);
@@ -3080,11 +3350,21 @@ async function runSubagent(
3080
3350
  statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
3081
3351
  statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
3082
3352
  statusPayload.steps[fi].totalCost = singleResult.totalCost;
3353
+ if (singleResult.totalCost) {
3354
+ pendingParallelUsageCost = {
3355
+ inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
3356
+ outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
3357
+ costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
3358
+ };
3359
+ refreshUsageBudget();
3360
+ }
3083
3361
  statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
3084
3362
  statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
3085
3363
  statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
3086
3364
  statusPayload.steps[fi].agentContract = singleResult.agentContract;
3087
3365
  statusPayload.steps[fi].launchContractDigest = singleResult.launchContractDigest;
3366
+ statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
3367
+ statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
3088
3368
  statusPayload.steps[fi].effects = singleResult.effects;
3089
3369
  statusPayload.steps[fi].execution = singleResult.execution;
3090
3370
  statusPayload.steps[fi].review = singleResult.review;
@@ -3116,7 +3396,11 @@ async function runSubagent(
3116
3396
  context: pr.context,
3117
3397
  agentContract: pr.agentContract,
3118
3398
  launchContractDigest: pr.launchContractDigest,
3399
+ launchResolvedExtensions: pr.launchResolvedExtensions,
3400
+ runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
3119
3401
  output: pr.output,
3402
+ outputPath: pr.outputPath,
3403
+ outputState: pr.outputState,
3120
3404
  error: pr.error,
3121
3405
  protocolError: pr.protocolError,
3122
3406
  success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
@@ -3151,6 +3435,8 @@ async function runSubagent(
3151
3435
  capabilityAudit: pr.capabilityAudit,
3152
3436
  });
3153
3437
  }
3438
+ pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
3439
+ refreshUsageBudget();
3154
3440
  const collection = collectDynamicResults(step as Parameters<typeof collectDynamicResults>[0], materialized.items, parallelResults);
3155
3441
  const failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
3156
3442
  const acceptanceFailures = parallelResults
@@ -3316,6 +3602,25 @@ async function runSubagent(
3316
3602
  concurrency,
3317
3603
  async (task, taskIdx) => {
3318
3604
  const fi = groupStartFlatIndex + taskIdx;
3605
+ refreshUsageBudget();
3606
+ if (statusPayload.usageBudget?.exhausted) {
3607
+ const skippedAt = Date.now();
3608
+ const message = usageBudgetExceededMessage(statusPayload.usageBudget);
3609
+ statusPayload.steps[fi].status = "failed";
3610
+ statusPayload.steps[fi].error = message;
3611
+ statusPayload.steps[fi].startedAt = skippedAt;
3612
+ statusPayload.steps[fi].endedAt = skippedAt;
3613
+ statusPayload.steps[fi].durationMs = 0;
3614
+ statusPayload.steps[fi].exitCode = 1;
3615
+ statusPayload.steps[fi].activityState = undefined;
3616
+ statusPayload.lastUpdate = skippedAt;
3617
+ usageBudgetExceeded = true;
3618
+ writeStatusPayload();
3619
+ appendJsonl(eventsPath, JSON.stringify({
3620
+ type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0,
3621
+ }));
3622
+ return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
3623
+ }
3319
3624
  if (timedOut) return timedOutStepResult(task.agent, task.context);
3320
3625
  if (stopped) return stoppedStepResult(task.agent, task.context);
3321
3626
  if (interrupted) return pausedStepResult(task.agent, task.context);
@@ -3421,10 +3726,20 @@ async function runSubagent(
3421
3726
  statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
3422
3727
  statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
3423
3728
  statusPayload.steps[fi].totalCost = singleResult.totalCost;
3729
+ if (singleResult.totalCost) {
3730
+ pendingParallelUsageCost = {
3731
+ inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
3732
+ outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
3733
+ costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
3734
+ };
3735
+ refreshUsageBudget();
3736
+ }
3424
3737
  statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
3425
3738
  statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
3426
3739
  statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
3427
3740
  statusPayload.steps[fi].agentContract = singleResult.agentContract;
3741
+ statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
3742
+ statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
3428
3743
  statusPayload.steps[fi].effects = singleResult.effects;
3429
3744
  statusPayload.steps[fi].execution = singleResult.execution;
3430
3745
  statusPayload.steps[fi].review = singleResult.review;
@@ -3492,7 +3807,10 @@ async function runSubagent(
3492
3807
  context: pr.context,
3493
3808
  agentContract: pr.agentContract,
3494
3809
  launchContractDigest: pr.launchContractDigest,
3810
+ launchResolvedExtensions: pr.launchResolvedExtensions,
3495
3811
  output: pr.output,
3812
+ outputPath: pr.outputPath,
3813
+ outputState: pr.outputState,
3496
3814
  error: pr.error,
3497
3815
  protocolError: pr.protocolError,
3498
3816
  success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
@@ -3525,6 +3843,8 @@ async function runSubagent(
3525
3843
  watchdog: pr.watchdog,
3526
3844
  });
3527
3845
  }
3846
+ pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
3847
+ refreshUsageBudget();
3528
3848
  for (let t = 0; t < group.parallel.length; t++) {
3529
3849
  const outputName = group.parallel[t]?.outputName;
3530
3850
  if (outputName) outputs[outputName] = outputEntryFromAsyncResult({
@@ -3564,7 +3884,13 @@ async function runSubagent(
3564
3884
  cleanup,
3565
3885
  results: parallelResults.map((result) => ({
3566
3886
  agent: result.agent,
3567
- status: result.stopped ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
3887
+ status: result.stopped || (result.exitCode !== 0 && isUnexplainedProcessSignal({
3888
+ processSignal: result.processSignal,
3889
+ interrupted: result.interrupted,
3890
+ timedOut: result.timedOut,
3891
+ stopped: result.stopped,
3892
+ turnBudgetExceeded: result.turnBudgetExceeded,
3893
+ })) ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
3568
3894
  summary: result.output || result.error || "(no output)",
3569
3895
  ...(result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {}),
3570
3896
  ...(result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {}),
@@ -3668,7 +3994,11 @@ async function runSubagent(
3668
3994
  context: singleResult.context,
3669
3995
  agentContract: singleResult.agentContract,
3670
3996
  launchContractDigest: singleResult.launchContractDigest,
3997
+ launchResolvedExtensions: singleResult.launchResolvedExtensions,
3998
+ runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
3671
3999
  output: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
4000
+ outputPath: singleResult.outputPath,
4001
+ outputState: singleResult.outputState,
3672
4002
  error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
3673
4003
  protocolError: singleResult.protocolError,
3674
4004
  success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
@@ -3758,6 +4088,8 @@ async function runSubagent(
3758
4088
  statusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;
3759
4089
  statusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;
3760
4090
  statusPayload.steps[flatIndex].agentContract = singleResult.agentContract;
4091
+ statusPayload.steps[flatIndex].launchResolvedExtensions = singleResult.launchResolvedExtensions;
4092
+ statusPayload.steps[flatIndex].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
3761
4093
  statusPayload.steps[flatIndex].effects = singleResult.effects;
3762
4094
  statusPayload.steps[flatIndex].execution = singleResult.execution;
3763
4095
  statusPayload.steps[flatIndex].review = singleResult.review;
@@ -3828,6 +4160,7 @@ async function runSubagent(
3828
4160
  }
3829
4161
 
3830
4162
  const resultMode = config.resultMode ?? statusPayload.mode;
4163
+ const singleRuntimeAcknowledgedExtensions = results.length === 1 ? results[0]?.runtimeAcknowledgedExtensions : undefined;
3831
4164
  const totalCost = results.reduce<CostSummary>((sum, result) => ({
3832
4165
  inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),
3833
4166
  outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),
@@ -3878,7 +4211,14 @@ async function runSubagent(
3878
4211
  clearTimeout(timeoutTimer);
3879
4212
  timeoutTimer = undefined;
3880
4213
  }
3881
- statusPayload.state = stopped ? "stopped" : timedOut || turnBudgetExceeded || statusPayload.error ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed";
4214
+ const signalTerminated = !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal({
4215
+ processSignal: result.processSignal,
4216
+ interrupted: result.interrupted,
4217
+ timedOut: result.timedOut,
4218
+ stopped: result.stopped,
4219
+ turnBudgetExceeded: result.turnBudgetExceeded,
4220
+ }));
4221
+ statusPayload.state = checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded || statusPayload.error ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed";
3882
4222
  closeSteerInbox(asyncDir, statusPayload.state);
3883
4223
  disposeControlInbox();
3884
4224
  for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
@@ -3900,6 +4240,8 @@ async function runSubagent(
3900
4240
  if (stopped) {
3901
4241
  statusPayload.stopped = true;
3902
4242
  statusPayload.error = stopMessage;
4243
+ } else if (signalTerminated && !statusPayload.error) {
4244
+ statusPayload.error = results.find((result) => result.processSignal)?.error;
3903
4245
  }
3904
4246
  if (timedOut) {
3905
4247
  statusPayload.timedOut = true;
@@ -3909,10 +4251,15 @@ async function runSubagent(
3909
4251
  const budget = statusPayload.turnBudget;
3910
4252
  statusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : "Subagent exceeded turn budget.";
3911
4253
  }
4254
+ if (usageBudgetExceeded && statusPayload.usageBudget && !statusPayload.error) {
4255
+ statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
4256
+ }
3912
4257
  statusPayload.endedAt = runEndedAt;
3913
4258
  statusPayload.lastUpdate = runEndedAt;
3914
4259
  statusPayload.sessionFile = effectiveSessionFile;
4260
+ if (singleRuntimeAcknowledgedExtensions) statusPayload.runtimeAcknowledgedExtensions = singleRuntimeAcknowledgedExtensions;
3915
4261
  statusPayload.totalCost = finalTotalCost;
4262
+ statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
3916
4263
  statusPayload.shareUrl = shareUrl;
3917
4264
  statusPayload.gistUrl = gistUrl;
3918
4265
  statusPayload.shareError = shareError;
@@ -3934,6 +4281,7 @@ async function runSubagent(
3934
4281
  durationMs: runEndedAt - overallStartTime,
3935
4282
  totalTokens: statusPayload.totalTokens,
3936
4283
  totalCost: finalTotalCost,
4284
+ usageBudget: statusPayload.usageBudget,
3937
4285
  }),
3938
4286
  );
3939
4287
  writeRunLog(logPath, {
@@ -3961,9 +4309,9 @@ async function runSubagent(
3961
4309
  id,
3962
4310
  agent: agentName,
3963
4311
  mode: resultMode,
3964
- success: !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),
3965
- state: stopped ? "stopped" : timedOut || turnBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
3966
- summary: stopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
4312
+ success: !checkpointRejected && !stopped && !timedOut && !turnBudgetExceeded && !usageBudgetExceeded && !interrupted && !signalTerminated && results.every((r) => r.success),
4313
+ state: checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
4314
+ summary: checkpointRejected ? (statusPayload.error ?? "Checkpoint rejected.") : stopped ? stopMessage : signalTerminated ? (statusPayload.error ?? "Subagent process terminated by signal.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : usageBudgetExceeded ? (statusPayload.error ?? "Usage budget exhausted.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
3967
4315
  ...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),
3968
4316
  ...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
3969
4317
  ...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),
@@ -3971,11 +4319,15 @@ async function runSubagent(
3971
4319
  ...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),
3972
4320
  ...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),
3973
4321
  ...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),
3974
- ...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : turnBudgetExceeded ? { error: statusPayload.error ?? "Subagent exceeded turn budget." } : {}),
4322
+ ...(statusPayload.usageBudget ? { usageBudget: statusPayload.usageBudget } : {}),
4323
+ ...(statusPayload.checkpoint ? { checkpoint: statusPayload.checkpoint } : {}),
4324
+ ...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : turnBudgetExceeded ? { error: statusPayload.error ?? "Subagent exceeded turn budget." } : usageBudgetExceeded ? { error: statusPayload.error ?? "Usage budget exhausted." } : {}),
3975
4325
  results: results.map((r) => ({
3976
4326
  agent: r.agent,
3977
4327
  context: r.context,
4328
+ outputPath: r.outputPath,
3978
4329
  output: r.output,
4330
+ outputState: r.outputState,
3979
4331
  error: r.error,
3980
4332
  protocolError: r.protocolError,
3981
4333
  success: r.success,
@@ -3983,6 +4335,7 @@ async function runSubagent(
3983
4335
  interrupted: r.interrupted || undefined,
3984
4336
  timedOut: r.timedOut || undefined,
3985
4337
  stopped: r.stopped || undefined,
4338
+ processSignal: r.processSignal || undefined,
3986
4339
  turnBudget: r.turnBudget,
3987
4340
  turnBudgetExceeded: r.turnBudgetExceeded || undefined,
3988
4341
  wrapUpRequested: r.wrapUpRequested || undefined,
@@ -4000,6 +4353,8 @@ async function runSubagent(
4000
4353
  transcriptError: r.transcriptError,
4001
4354
  agentContract: r.agentContract,
4002
4355
  launchContractDigest: r.launchContractDigest,
4356
+ launchResolvedExtensions: r.launchResolvedExtensions,
4357
+ runtimeAcknowledgedExtensions: r.runtimeAcknowledgedExtensions,
4003
4358
  execution: r.execution,
4004
4359
  review: r.review,
4005
4360
  effects: r.effects,
@@ -4016,16 +4371,20 @@ async function runSubagent(
4016
4371
  parallelHandoff: statusPayload.parallelHandoff,
4017
4372
  capabilityCeiling: statusPayload.capabilityCeiling,
4018
4373
  capabilityAudit: statusPayload.capabilityAudit,
4019
- exitCode: stopped || timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
4374
+ exitCode: checkpointRejected || stopped || timedOut || turnBudgetExceeded || usageBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
4020
4375
  timestamp: runEndedAt,
4021
4376
  durationMs: runEndedAt - overallStartTime,
4022
4377
  totalTokens: statusPayload.totalTokens,
4023
4378
  totalCost: finalTotalCost,
4379
+ usageBudget: statusPayload.usageBudget,
4380
+ checkpoint: statusPayload.checkpoint,
4024
4381
  truncated,
4025
4382
  artifactsDir,
4026
4383
  cwd,
4027
4384
  asyncDir,
4028
4385
  launchContractDigest: config.launchContractDigest,
4386
+ launchResolvedExtensions: config.launchResolvedExtensions,
4387
+ runtimeAcknowledgedExtensions: singleRuntimeAcknowledgedExtensions,
4029
4388
  sessionId: config.sessionId,
4030
4389
  sessionFile: effectiveSessionFile,
4031
4390
  intercomTarget: config.controlIntercomTarget,