@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
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import * as fs from "node:fs";
3
+ import { isUnexplainedProcessSignal } from "../runs/shared/process-signal.ts";
3
4
  import {
4
5
  type Details,
5
6
  type IntercomEventBus,
@@ -10,6 +11,7 @@ import {
10
11
  type SubagentResultIntercomChild,
11
12
  type SubagentResultIntercomPayload,
12
13
  type SubagentResultStatus,
14
+ type SubagentOutputState,
13
15
  type SubagentRunMode,
14
16
  SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT,
15
17
  SUBAGENT_RESULT_INTERCOM_EVENT,
@@ -21,11 +23,17 @@ export function resolveSubagentResultStatus(input: {
21
23
  state?: string;
22
24
  interrupted?: boolean;
23
25
  detached?: boolean;
26
+ processSignal?: string | null;
27
+ timedOut?: boolean;
28
+ stopped?: boolean;
29
+ turnBudgetExceeded?: boolean;
24
30
  }): SubagentResultStatus {
25
31
  if (input.detached) return "detached";
26
- if (input.state === "stopped") return "stopped";
32
+ if (input.stopped || input.state === "stopped") return "stopped";
27
33
  if (input.interrupted || input.state === "paused") return "paused";
28
- if (typeof input.success === "boolean") return input.success ? "completed" : "failed";
34
+ if (input.success === true) return "completed";
35
+ if (isUnexplainedProcessSignal(input) && input.exitCode !== 0) return "stopped";
36
+ if (input.success === false) return "failed";
29
37
  if (input.state === "complete") return "completed";
30
38
  if (input.state === "failed") return "failed";
31
39
  if (typeof input.exitCode === "number") return input.exitCode === 0 ? "completed" : "failed";
@@ -57,6 +65,21 @@ function formatStatusCounts(counts: Record<SubagentResultStatus, number>): strin
57
65
  return parts.length ? parts.join(", ") : "0 results";
58
66
  }
59
67
 
68
+ function countOutputStates(children: SubagentResultIntercomChild[]): Record<SubagentOutputState, number> {
69
+ const counts: Record<SubagentOutputState, number> = { present: 0, absent: 0, unknown: 0 };
70
+ for (const child of children) counts[child.outputState ?? "unknown"] += 1;
71
+ return counts;
72
+ }
73
+
74
+ function formatOutputCounts(counts: Record<SubagentOutputState, number>): string {
75
+ const parts = [
76
+ counts.present ? `${counts.present} present` : undefined,
77
+ counts.absent ? `${counts.absent} absent` : undefined,
78
+ counts.unknown ? `${counts.unknown} unknown` : undefined,
79
+ ].filter((part): part is string => Boolean(part));
80
+ return parts.length ? parts.join(", ") : "0 outputs";
81
+ }
82
+
60
83
  function resolveGroupedStatus(children: SubagentResultIntercomChild[]): SubagentResultStatus {
61
84
  const counts = countStatuses(children);
62
85
  if (counts.failed > 0) return "failed";
@@ -212,14 +235,19 @@ function formatSubagentResultIntercomMessage(input: {
212
235
  parallelHandoff?: ParallelHandoffReference;
213
236
  }): string {
214
237
  const counts = countStatuses(input.children);
238
+ const outputCounts = countOutputStates(input.children);
215
239
  const lines: string[] = [
216
240
  "subagent results",
217
241
  "",
218
242
  `Run: ${input.runId}`,
219
243
  `Mode: ${input.mode}`,
220
- `Status: ${input.status}`,
244
+ `Process status: ${input.status}`,
221
245
  `Children: ${formatStatusCounts(counts)}`,
246
+ `Outputs: ${formatOutputCounts(outputCounts)} (semantic adequacy unassessed)`,
222
247
  ];
248
+ if (input.children.some((child) => child.status === "failed" && child.outputState === "present")) {
249
+ lines.push("Recovery: At least one failed process produced output. Inspect that output before retrying; output presence does not establish task completion.");
250
+ }
223
251
  if (input.mode === "chain" && typeof input.chainSteps === "number") {
224
252
  lines.push(`Chain steps: ${input.chainSteps}`);
225
253
  }
@@ -238,7 +266,7 @@ function formatSubagentResultIntercomMessage(input: {
238
266
  for (let index = 0; index < input.children.length; index++) {
239
267
  const child = input.children[index]!;
240
268
  lines.push("");
241
- lines.push(`${index + 1}. ${child.agent} — ${child.status}`);
269
+ lines.push(`${index + 1}. ${child.agent} — process ${child.status} · output ${child.outputState ?? "unknown"}`);
242
270
  if (child.intercomTarget) lines.push(`${input.source === "async" ? "Previous intercom target" : "Run intercom target"}: ${child.intercomTarget}`);
243
271
  if (child.artifactPath) lines.push(`Output artifact: ${child.artifactPath}`);
244
272
  if (child.sessionPath) lines.push(`Session: ${child.sessionPath}`);
@@ -253,6 +281,7 @@ function formatSubagentResultIntercomMessage(input: {
253
281
  export function buildSubagentResultIntercomPayload(input: GroupedResultIntercomMessageInput): SubagentResultIntercomPayload {
254
282
  const children = input.children.map((child) => ({
255
283
  ...child,
284
+ outputState: child.outputState ?? "unknown",
256
285
  summary: child.summary.trim() || "(no output)",
257
286
  children: compactNestedResultChildren(child.children),
258
287
  }));
@@ -12,9 +12,9 @@ import { createRequire } from "node:module";
12
12
  import type { ExtensionAPI } from "@selesai/code";
13
13
  import type { AgentConfig } from "../../agents/agents.ts";
14
14
  import { writePrivateAtomicJson } from "../../shared/atomic-json.ts";
15
- import { applyThinkingSuffix, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
15
+ import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
16
16
  import { injectOutputPathSystemPrompt, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.ts";
17
- import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
17
+ import { buildChainInstructions, isCheckpointStep, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile, type ChainStep, type ResolvedStepBehavior, type SequentialStep, type StepOverrides } from "../../shared/settings.ts";
18
18
  import type { RunnerStep } from "../shared/parallel-utils.ts";
19
19
  import type { ContextMode } from "../shared/context-mode.ts";
20
20
  import { resolvePiPackageRoot } from "../shared/pi-spawn.ts";
@@ -42,6 +42,7 @@ import {
42
42
  type ResolvedToolBudget,
43
43
  type SubagentRunMode,
44
44
  type SteeringRecoveryDescriptor,
45
+ type UsageBudgetConfig,
45
46
  ASYNC_DIR,
46
47
  RESULTS_DIR,
47
48
  SUBAGENT_ASYNC_STARTED_EVENT,
@@ -53,11 +54,12 @@ import {
53
54
  import { nestedResultsPath, nestedSummaryFromAsyncStatus, resolveInheritedNestedRouteFromEnv, resolveNestedParentAddressFromEnv, writeNestedEvent } from "../shared/nested-events.ts";
54
55
  import { appendTurnBudgetSystemPrompt, initialTurnBudgetState } from "../shared/turn-budget.ts";
55
56
  import { validateToolBudgetConfig } from "../shared/tool-budget.ts";
57
+ import { usageBudgetState } from "../shared/usage-budget.ts";
56
58
  import type { ImportedAsyncRoot } from "./chain-root-attachment.ts";
57
59
  import type { SessionLeaseRequest } from "../shared/session-lease.ts";
58
60
  import { finalizeProcessTerminal, readProcessTerminal } from "./process-terminal.ts";
59
61
  import { SUBAGENT_PROCESS_TERMINAL_EVENT } from "../../shared/types.ts";
60
- import { decodeSubagentCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV, type ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
62
+ import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV, type ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
61
63
  import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
62
64
 
63
65
  const require = createRequire(import.meta.url);
@@ -159,6 +161,7 @@ interface AsyncChainParams {
159
161
  timeoutMs?: number;
160
162
  turnBudget?: ResolvedTurnBudget;
161
163
  toolBudget?: ResolvedToolBudget;
164
+ usageBudget?: UsageBudgetConfig;
162
165
  configToolBudget?: ResolvedToolBudget;
163
166
  /** Global cap on simultaneously-running subagent tasks within the async run. */
164
167
  globalConcurrencyLimit?: number;
@@ -205,6 +208,7 @@ interface AsyncSingleParams {
205
208
  absoluteDeadlineAt?: number;
206
209
  turnBudget?: ResolvedTurnBudget;
207
210
  toolBudget?: ResolvedToolBudget;
211
+ usageBudget?: UsageBudgetConfig;
208
212
  configToolBudget?: ResolvedToolBudget;
209
213
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
210
214
  }
@@ -592,11 +596,13 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
592
596
  : chain;
593
597
  const firstStep = chain[0];
594
598
  const originalTask = params.task ?? (firstStep
595
- ? (isParallelStep(firstStep)
596
- ? firstStep.parallel[0]?.task
597
- : isDynamicParallelStep(firstStep)
598
- ? firstStep.parallel.task
599
- : (firstStep as SequentialStep).task)
599
+ ? (isCheckpointStep(firstStep)
600
+ ? undefined
601
+ : isParallelStep(firstStep)
602
+ ? firstStep.parallel[0]?.task
603
+ : isDynamicParallelStep(firstStep)
604
+ ? firstStep.parallel.task
605
+ : (firstStep as SequentialStep).task)
600
606
  : undefined);
601
607
  try {
602
608
  if (params.validateOutputBindings !== false) {
@@ -609,11 +615,13 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
609
615
  const workflowGraph = buildWorkflowGraphSnapshot({ runId: id, mode: resultMode, steps: graphChain });
610
616
 
611
617
  for (const s of chain) {
612
- const stepAgents = isParallelStep(s)
613
- ? s.parallel.map((t) => t.agent)
614
- : isDynamicParallelStep(s)
615
- ? [s.parallel.agent]
616
- : [(s as SequentialStep).agent];
618
+ const stepAgents = isCheckpointStep(s)
619
+ ? []
620
+ : isParallelStep(s)
621
+ ? s.parallel.map((t) => t.agent)
622
+ : isDynamicParallelStep(s)
623
+ ? [s.parallel.agent]
624
+ : [(s as SequentialStep).agent];
617
625
  for (const agentName of stepAgents) {
618
626
  if (!agents.find((x) => x.name === agentName)) {
619
627
  return { error: `Unknown agent: ${agentName}` };
@@ -635,6 +643,11 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
635
643
  };
636
644
  const buildSeqStep = (s: SequentialStep, sessionFile?: string, behaviorCwd?: string, progressPrecreated = false, resolvedBehavior?: ResolvedStepBehavior, flatIndex?: number, parallelOutputNamespace?: { stepIndex: number; taskIndex?: number }) => {
637
645
  const a = agents.find((x) => x.name === s.agent)!;
646
+ try {
647
+ assertAgentAllowedByCapabilityCeiling(a.name, intersectSubagentCapabilityCeilings(params.capabilityCeiling, decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV])));
648
+ } catch (error) {
649
+ throw new AsyncStartValidationError(error instanceof Error ? error.message : String(error));
650
+ }
638
651
  const toolBudgetInput = s.toolBudget ?? params.toolBudget ?? a.toolBudget ?? params.configToolBudget;
639
652
  const resolvedToolBudget = validateToolBudgetConfig(toolBudgetInput, s.toolBudget ? "toolBudget" : a.toolBudget ? "agent.toolBudget" : "config.toolBudget");
640
653
  if (resolvedToolBudget.error) throw new AsyncStartValidationError(resolvedToolBudget.error);
@@ -673,9 +686,19 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
673
686
  const isFirstProgressAgent = behavior.progress && !progressPrecreated && !progressInstructionCreated;
674
687
  if (behavior.progress) progressInstructionCreated = true;
675
688
  const progressInstructions = buildChainInstructions({ ...behavior, output: false, reads: false }, progressDir, isFirstProgressAgent);
676
- const outputPath = resolveSingleOutputPath(behavior.output, ctx.cwd, instructionCwd, outputBaseDir);
689
+ const explicitOutput = typeof behavior.output === "string" ? behavior.output : undefined;
690
+ // Omitted output generates a collision-safe per-child durable path
691
+ // `<asyncDir>/outputs/<flat-index>-<agent>.md`; omitted outputMode resolves
692
+ // to file-only whenever an output path is active. Explicit paths,
693
+ // `output: false`, and explicit `outputMode: "inline"` are preserved.
694
+ const outputPath = explicitOutput
695
+ ? resolveSingleOutputPath(explicitOutput, ctx.cwd, instructionCwd, outputBaseDir)
696
+ : behavior.output === false && s.output !== false && s.output !== "false" && flatIndex !== undefined
697
+ ? path.join(asyncDir, "outputs", `${flatIndex}-${s.agent}.md`)
698
+ : undefined;
677
699
  if (!namespaceOutputPath) systemPrompt = injectOutputPathSystemPrompt(systemPrompt, outputPath, a);
678
- const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Async step (${s.agent})`);
700
+ const effectiveOutputMode = s.outputMode ?? (outputPath ? "file-only" : "inline");
701
+ const validationError = validateFileOnlyOutputMode(effectiveOutputMode, outputPath, `Async step (${s.agent})`);
679
702
  if (validationError) throw new AsyncStartValidationError(validationError);
680
703
  let taskTemplate = s.task ?? "{previous}";
681
704
  taskTemplate = taskTemplate.replace(/\{task\}/g, originalTask ?? "");
@@ -695,6 +718,19 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
695
718
  const effectiveThinking = thinkingOverride ?? a.thinking;
696
719
  const model = applyThinkingSuffix(primaryModel, effectiveThinking, thinkingOverride !== undefined);
697
720
  const agentContract = s.agentContract ?? params.agentContract;
721
+ const toolPlan = resolvePiLaunchToolPlan({
722
+ tools: a.tools,
723
+ extensions: a.extensions,
724
+ subagentOnlyExtensions: a.subagentOnlyExtensions,
725
+ mcpDirectTools: a.mcpDirectTools,
726
+ cwd: stepCwd,
727
+ requireReadTool: Boolean(resolvedSkills.length),
728
+ structuredOutput: Boolean(s.outputSchema),
729
+ capabilityCeiling: params.capabilityCeiling,
730
+ inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
731
+ agentName: a.name,
732
+ });
733
+ const launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
698
734
  return {
699
735
  parentSessionId: ctx.parentSessionId ?? ctx.currentSessionId,
700
736
  ...(params.capabilityCeiling ? { capabilityCeiling: params.capabilityCeiling } : {}),
@@ -709,6 +745,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
709
745
  cwd: stepCwd,
710
746
  model,
711
747
  thinking: resolveEffectiveThinking(model, effectiveThinking),
748
+ launchResolvedExtensions,
712
749
  modelCandidates: buildModelCandidates(primaryModel, a.fallbackModels, availableModels, ctx.currentModelProvider, { scope: ctx.modelScope }).map((candidate) =>
713
750
  applyThinkingSuffix(candidate, effectiveThinking, thinkingOverride !== undefined),
714
751
  ),
@@ -724,7 +761,7 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
724
761
  skills: resolvedSkills.map((r) => r.name),
725
762
  outputPath,
726
763
  ...(namespaceOutputPath ? { namespaceOutputPath: true } : {}),
727
- outputMode: behavior.outputMode,
764
+ outputMode: effectiveOutputMode,
728
765
  sessionFile,
729
766
  maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, a.maxSubagentDepth),
730
767
  waitToolEnabled: params.waitToolEnabled,
@@ -762,6 +799,9 @@ export function buildAsyncRunnerSteps(id: string, params: AsyncRunnerStepBuildPa
762
799
 
763
800
  try {
764
801
  const builtSteps = chain.map((s, stepIndex) => {
802
+ if (isCheckpointStep(s)) {
803
+ return { checkpoint: s.checkpoint, ...(s.message ? { message: s.message } : {}), phase: s.phase, label: s.label };
804
+ }
765
805
  if (isParallelStep(s)) {
766
806
  const parallelBehaviors = s.parallel.map((task) => {
767
807
  const agent = agents.find((candidate) => candidate.name === task.agent)!;
@@ -948,6 +988,7 @@ export function executeAsyncChain(
948
988
  const { steps, runnerCwd, workflowGraph, eventChain } = built;
949
989
  const deadlineAt = params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined;
950
990
  const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
991
+ const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
951
992
  let childTargetIndex = 0;
952
993
  const childIntercomTargets = childIntercomTarget ? steps.flatMap((step) => {
953
994
  if (!("parallel" in step) && step.importAsyncRoot) {
@@ -989,6 +1030,7 @@ export function executeAsyncChain(
989
1030
  controlConfig,
990
1031
  turnBudget: params.turnBudget,
991
1032
  toolBudget: params.toolBudget,
1033
+ usageBudget: params.usageBudget,
992
1034
  controlIntercomTarget,
993
1035
  childIntercomTargets,
994
1036
  resultMode,
@@ -1106,6 +1148,7 @@ export function executeAsyncChain(
1106
1148
  asyncDir,
1107
1149
  ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}),
1108
1150
  ...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
1151
+ ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
1109
1152
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
1110
1153
  nestedRoute,
1111
1154
  });
@@ -1119,7 +1162,7 @@ export function executeAsyncChain(
1119
1162
 
1120
1163
  return {
1121
1164
  content: [{ type: "text", text: formatAsyncStartedMessage(`Async ${resultMode}: ${chainDesc} [${id}]`, ctx.interactive === true) }],
1122
- details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}) },
1165
+ details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) },
1123
1166
  };
1124
1167
  }
1125
1168
 
@@ -1151,7 +1194,12 @@ export function executeAsyncSingle(
1151
1194
  nestedRoute,
1152
1195
  } = params;
1153
1196
  const task = params.task ?? "";
1154
- const capabilityCeiling = params.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
1197
+ const capabilityCeiling = intersectSubagentCapabilityCeilings(params.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId), decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]));
1198
+ try {
1199
+ assertAgentAllowedByCapabilityCeiling(agentConfig.name, capabilityCeiling);
1200
+ } catch (error) {
1201
+ return formatAsyncStartError("single", error instanceof Error ? error.message : String(error));
1202
+ }
1155
1203
  const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
1156
1204
  const skillNames = params.skills ?? agentConfig.skills ?? [];
1157
1205
  const availableModels = params.availableModels;
@@ -1190,9 +1238,17 @@ export function executeAsyncSingle(
1190
1238
  }
1191
1239
 
1192
1240
  const effectiveOutput = normalizeSingleOutputOverride(params.output, agentConfig.output);
1193
- const outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, runnerCwd, params.outputBaseDir ?? (artifactsDir ? path.join(artifactsDir, "outputs", id) : undefined));
1241
+ // Omitted output resolves to a generated per-run durable path
1242
+ // `<asyncDir>/outputs/0-<agent>.md`; omitted outputMode resolves to file-only
1243
+ // whenever an output path is active. Explicit paths, `output: false`, and
1244
+ // explicit `outputMode: "inline"` are preserved exactly.
1245
+ const outputPath = typeof effectiveOutput === "string"
1246
+ ? resolveSingleOutputPath(effectiveOutput, ctx.cwd, runnerCwd, params.outputBaseDir ?? (artifactsDir ? path.join(artifactsDir, "outputs", id) : undefined))
1247
+ : effectiveOutput === false
1248
+ ? undefined
1249
+ : path.join(asyncDir, "outputs", `0-${agent}.md`);
1194
1250
  systemPrompt = injectOutputPathSystemPrompt(systemPrompt, outputPath, agentConfig);
1195
- const outputMode = params.outputMode ?? "inline";
1251
+ const outputMode = params.outputMode ?? (outputPath ? "file-only" : "inline");
1196
1252
  const validationError = validateFileOnlyOutputMode(outputMode, outputPath, `Async single run (${agent})`);
1197
1253
  if (validationError) return formatAsyncStartError("single", validationError);
1198
1254
  const taskWithOutputInstruction = injectSingleOutputInstruction(task, outputPath, agentConfig);
@@ -1213,6 +1269,7 @@ export function executeAsyncSingle(
1213
1269
  : params.timeoutMs;
1214
1270
  if (timeoutMs !== undefined && timeoutMs <= 0) return formatAsyncStartError("single", "The source run's absolute deadline expired before recovery could launch.");
1215
1271
  const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
1272
+ const initialUsageBudget = usageBudgetState(params.usageBudget, undefined);
1216
1273
  const resolvedSessionDir = params.sessionDir ?? (sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined);
1217
1274
  const structuredOutput = params.structuredOutputSchema
1218
1275
  ? createStructuredOutputRuntime(params.structuredOutputSchema, path.join(asyncDir, "structured-output"))
@@ -1231,7 +1288,9 @@ export function executeAsyncSingle(
1231
1288
  structuredOutput: Boolean(params.structuredOutputSchema),
1232
1289
  capabilityCeiling,
1233
1290
  inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
1291
+ agentName: agentConfig.name,
1234
1292
  });
1293
+ const launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1235
1294
  const launchContractDigest = launchBindingDigest({
1236
1295
  definitionDigest: agentDefinitionDigest(agentConfig),
1237
1296
  task,
@@ -1265,6 +1324,7 @@ export function executeAsyncSingle(
1265
1324
  sourceRunId: id,
1266
1325
  ...(params.agentContract ? { agentContract: params.agentContract } : {}),
1267
1326
  agent,
1327
+ launchResolvedExtensions,
1268
1328
  ...(sessionFile ? { sessionFile } : {}),
1269
1329
  cwd: runnerCwd,
1270
1330
  ...(model ? { model } : {}),
@@ -1339,6 +1399,7 @@ export function executeAsyncSingle(
1339
1399
  definitionDigest: agentDefinitionDigest(agentConfig),
1340
1400
  launchBindingTask: task,
1341
1401
  launchContractDigest,
1402
+ launchResolvedExtensions,
1342
1403
  effectiveAcceptance: resolvedAcceptance,
1343
1404
  ...(structuredOutput ? { structuredOutput } : {}),
1344
1405
  ...(params.structuredOutputSchema ? { structuredOutputSchema: params.structuredOutputSchema } : {}),
@@ -1366,10 +1427,12 @@ export function executeAsyncSingle(
1366
1427
  deadlineAt,
1367
1428
  turnBudget: params.turnBudget,
1368
1429
  toolBudget: params.toolBudget,
1430
+ usageBudget: params.usageBudget,
1369
1431
  controlIntercomTarget,
1370
1432
  childIntercomTargets: childIntercomTarget ? [childIntercomTarget(agent, 0)] : undefined,
1371
1433
  resultMode: "single",
1372
1434
  launchContractDigest,
1435
+ launchResolvedExtensions,
1373
1436
  ...(params.revivalLease ? { revivalLease: params.revivalLease } : {}),
1374
1437
  nestedRoute: nestedRoute ?? inheritedNestedRoute,
1375
1438
  nestedSelf: inheritedNestedRoute && nestedAddress ? {
@@ -1441,8 +1504,10 @@ export function executeAsyncSingle(
1441
1504
  cwd: runnerCwd,
1442
1505
  asyncDir,
1443
1506
  launchContractDigest,
1507
+ launchResolvedExtensions,
1444
1508
  ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}),
1445
1509
  ...(initialTurnBudget ? { turnBudget: initialTurnBudget } : {}),
1510
+ ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}),
1446
1511
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
1447
1512
  nestedRoute,
1448
1513
  });
@@ -1450,6 +1515,6 @@ export function executeAsyncSingle(
1450
1515
 
1451
1516
  return {
1452
1517
  content: [{ type: "text", text: formatAsyncStartedMessage(`Async: ${agent} [${id}]`, ctx.interactive === true) }],
1453
- details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}) },
1518
+ details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, launchContractDigest, launchResolvedExtensions, ...(capabilityCeiling ? { capabilityCeiling } : {}), ...(params.context ? { context: params.context } : {}), ...(timeoutMs !== undefined ? { timeoutMs, deadlineAt } : {}), ...(params.turnBudget ? { turnBudget: params.turnBudget } : {}), ...(params.toolBudget ? { toolBudget: params.toolBudget } : {}), ...(initialUsageBudget ? { usageBudget: initialUsageBudget } : {}) },
1454
1519
  };
1455
1520
  }
@@ -60,6 +60,19 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
60
60
  renderWidget(ctx, options.widgetEnabled === false ? [] : jobs);
61
61
  ctx.ui.requestRender?.();
62
62
  };
63
+ const rerenderLastWidget = (jobs = Array.from(state.asyncJobs.values())) => {
64
+ const ctx = state.lastUiContext;
65
+ if (!ctx) return;
66
+ try {
67
+ if (ctx.hasUI) rerenderWidget(ctx, jobs);
68
+ } catch (error) {
69
+ if (error instanceof Error && error.message.includes("extension ctx is stale")) {
70
+ state.lastUiContext = null;
71
+ return;
72
+ }
73
+ throw error;
74
+ }
75
+ };
63
76
  const refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);
64
77
  const restoredControlEventCursor = (asyncDir: string) => {
65
78
  try {
@@ -131,9 +144,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
131
144
  const timer = setTimeout(() => {
132
145
  state.cleanupTimers.delete(asyncId);
133
146
  state.asyncJobs.delete(asyncId);
134
- if (state.lastUiContext) {
135
- rerenderWidget(state.lastUiContext);
136
- }
147
+ rerenderLastWidget();
137
148
  }, completionRetentionMs);
138
149
  state.cleanupTimers.set(asyncId, timer);
139
150
  };
@@ -154,6 +165,10 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
154
165
  const startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;
155
166
  if (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;
156
167
  if (stat.size <= cursor) return;
168
+ const previousByte = Buffer.alloc(1);
169
+ const startsMidLine = cursor > 0
170
+ && fs.readSync(fd, previousByte, 0, 1, cursor - 1) === 1
171
+ && previousByte[0] !== 0x0a;
157
172
  const scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);
158
173
  const handleLine = (line: string) => {
159
174
  if (!line.trim()) return;
@@ -206,7 +221,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
206
221
  let lastCompleteCursor = cursor;
207
222
  let lineParts: Buffer[] = [];
208
223
  let lineBytes = 0;
209
- let skippingOversizedLine = startedFromTail;
224
+ let skippingOversizedLine = startedFromTail || startsMidLine;
210
225
  const appendLineSegment = (segment: Buffer) => {
211
226
  if (segment.length === 0 || skippingOversizedLine) return;
212
227
  if (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {
@@ -254,7 +269,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
254
269
  if (state.poller) return;
255
270
  state.poller = setInterval(() => {
256
271
  if (state.asyncJobs.size === 0) {
257
- if (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);
272
+ rerenderLastWidget([]);
258
273
  if (state.poller) {
259
274
  clearInterval(state.poller);
260
275
  state.poller = null;
@@ -378,7 +393,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
378
393
  if (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;
379
394
  }
380
395
 
381
- if (widgetChanged && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);
396
+ if (widgetChanged) rerenderLastWidget();
382
397
  }, pollIntervalMs);
383
398
  state.poller.unref?.();
384
399
  };
@@ -421,9 +436,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
421
436
  });
422
437
  rememberFleetJob(state, state.asyncJobs.get(info.id)!);
423
438
  ensurePoller();
424
- if (state.lastUiContext) {
425
- rerenderWidget(state.lastUiContext);
426
- }
439
+ rerenderLastWidget();
427
440
  };
428
441
 
429
442
  const handleComplete = (data: unknown) => {
@@ -446,9 +459,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
446
459
  }
447
460
  }
448
461
  if (job) rememberFleetJob(state, job);
449
- if (state.lastUiContext) {
450
- rerenderWidget(state.lastUiContext);
451
- }
462
+ rerenderLastWidget();
452
463
  if (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);
453
464
  };
454
465
 
@@ -485,7 +496,7 @@ export function createAsyncJobTracker(pi: Pick<ExtensionAPI, "events">, state: S
485
496
  }
486
497
  if (runs.length === 0) return;
487
498
  ensurePoller();
488
- if (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);
499
+ rerenderLastWidget();
489
500
  };
490
501
 
491
502
  return { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };
@@ -256,6 +256,7 @@ function validateStatusForResume(status: AsyncStatus | null, source: string): vo
256
256
  if (stepRecord.sessionFile !== undefined && typeof stepRecord.sessionFile !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);
257
257
  if (stepRecord.model !== undefined && typeof stepRecord.model !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].model must be a string.`);
258
258
  if (stepRecord.thinking !== undefined && typeof stepRecord.thinking !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].thinking must be a string.`);
259
+ if (stepRecord.launchContractDigest !== undefined && typeof stepRecord.launchContractDigest !== "string") throw new Error(`Invalid async status '${source}': steps[${index}].launchContractDigest must be a string.`);
259
260
  if (stepRecord.capabilityCeiling !== undefined) stepRecord.capabilityCeiling = parseSubagentCapabilityCeiling(stepRecord.capabilityCeiling, `async status '${source}' steps[${index}].capabilityCeiling`);
260
261
  });
261
262
  }
@@ -285,10 +286,11 @@ export function readAsyncRecoveryDescriptor(asyncDir: string | undefined): Steer
285
286
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': expected an object.`);
286
287
  const parsed = value as Record<string, unknown>;
287
288
  const allowedFields = new Set([
288
- "version", "sourceRunId", "agentContract", "agent", "sessionFile", "cwd", "model", "fallbackModels", "thinking", "tools", "extensions",
289
+ "version", "launchContractDigest", "sourceRunId", "agentContract", "agent", "sessionFile", "cwd", "model", "fallbackModels", "thinking", "tools", "extensions",
289
290
  "subagentOnlyExtensions", "mcpDirectTools", "systemPrompt", "systemPromptMode", "inheritProjectContext", "inheritSkills", "skills",
290
291
  "skillPath", "agentFilePath", "completionGuard", "memory", "outputPath", "outputMode", "structuredOutputSchema", "acceptance", "sessionDir", "artifactConfig",
291
292
  "artifactsDir", "maxOutput", "controlConfig", "absoluteDeadlineAt", "initialTurnBudget", "initialToolBudget", "maxSubagentDepth", "share", "capabilityCeiling",
293
+ "launchResolvedExtensions",
292
294
  ]);
293
295
  for (const field of Object.keys(parsed)) {
294
296
  if (!allowedFields.has(field)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': unknown field '${field}'.`);
@@ -315,7 +317,7 @@ export function readAsyncRecoveryDescriptor(asyncDir: string | undefined): Steer
315
317
  if (item !== undefined && (!Array.isArray(item) || item.some((entry) => typeof entry !== "string" || !entry.trim()))) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must contain non-empty strings.`);
316
318
  }
317
319
  if (parsed.systemPrompt !== undefined && typeof parsed.systemPrompt !== "string") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': systemPrompt must be a string.`);
318
- for (const field of ["sessionFile", "model", "thinking", "agentFilePath", "outputPath", "sessionDir", "artifactsDir"] as const) {
320
+ for (const field of ["launchContractDigest", "sessionFile", "model", "thinking", "agentFilePath", "outputPath", "sessionDir", "artifactsDir"] as const) {
319
321
  if (parsed[field] !== undefined && (typeof parsed[field] !== "string" || !(parsed[field] as string).trim())) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);
320
322
  }
321
323
  if (parsed.completionGuard !== undefined && typeof parsed.completionGuard !== "boolean") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': completionGuard must be a boolean.`);
@@ -427,7 +429,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
427
429
  sessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
428
430
  model: selectedStep.model,
429
431
  thinking: selectedStep.thinking,
430
- launchContractDigest: selectedStep.launchContractDigest ?? result?.results?.[requestedIndex]?.launchContractDigest ?? result?.launchContractDigest,
432
+ launchContractDigest: selectedStep.launchContractDigest ?? result?.results?.[requestedIndex]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
431
433
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
432
434
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
433
435
  };
@@ -454,7 +456,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
454
456
  sessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,
455
457
  model: selected.step.model,
456
458
  thinking: selected.step.thinking,
457
- launchContractDigest: selected.step.launchContractDigest ?? result?.results?.[selected.index]?.launchContractDigest ?? result?.launchContractDigest,
459
+ launchContractDigest: selected.step.launchContractDigest ?? result?.results?.[selected.index]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
458
460
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
459
461
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
460
462
  };
@@ -490,7 +492,7 @@ export function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncR
490
492
  ...(resolvedSessionFile ? { sessionFile: resolvedSessionFile } : {}),
491
493
  ...(stepModel ? { model: stepModel } : {}),
492
494
  ...(stepThinking ? { thinking: stepThinking } : {}),
493
- launchContractDigest: statusSteps[index]?.launchContractDigest ?? resultSteps[index]?.launchContractDigest ?? result?.launchContractDigest,
495
+ launchContractDigest: statusSteps[index]?.launchContractDigest ?? resultSteps[index]?.launchContractDigest ?? result?.launchContractDigest ?? recoveryDescriptor?.launchContractDigest,
494
496
  ...(capabilityCeiling ? { capabilityCeiling } : {}),
495
497
  ...(recoveryDescriptor ? { recoveryDescriptor } : {}),
496
498
  };
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../../shared/formatters.ts";
4
4
  import { formatActivityLabel, formatParallelOutcome } from "../../shared/status-format.ts";
5
- import { type ActivityState, type AsyncJobStep, type AsyncParallelGroupStatus, type AsyncStatus, type CostSummary, type NestedRunSummary, type SteeringStatus, type SubagentRunMode, type TokenUsage, type TurnBudgetState } from "../../shared/types.ts";
5
+ import { type ActivityState, type AsyncJobStep, type AsyncParallelGroupStatus, type AsyncStatus, type CostSummary, type LaunchResolvedChildExtensionsV1, type RuntimeAcknowledgedChildExtensionsV1, type NestedRunSummary, type SteeringStatus, type SubagentRunMode, type TokenUsage, type TurnBudgetState, type UsageBudgetState, type ChainCheckpointState } from "../../shared/types.ts";
6
6
  import type { ResolvedSubagentCapabilityCeiling, SubagentCapabilityAudit } from "../shared/capability-ceiling.ts";
7
7
  import { readStatus } from "../../shared/utils.ts";
8
8
  import { attachRootChildrenToSteps, buildNestedRouteIndex, type NestedRoute, projectNestedEvents } from "../shared/nested-events.ts";
@@ -17,9 +17,11 @@ interface AsyncRunStepSummary {
17
17
  agent: string;
18
18
  context?: ContextMode;
19
19
  label?: string;
20
+ description?: string;
20
21
  phase?: string;
21
22
  outputName?: string;
22
23
  structured?: boolean;
24
+ checkpoint?: ChainCheckpointState;
23
25
  status: AsyncJobStep["status"];
24
26
  activityState?: ActivityState;
25
27
  lastActivityAt?: number;
@@ -53,6 +55,8 @@ interface AsyncRunStepSummary {
53
55
  review?: AsyncJobStep["review"];
54
56
  effects?: AsyncJobStep["effects"];
55
57
  processTerminal?: AsyncJobStep["processTerminal"];
58
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
59
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
56
60
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
57
61
  capabilityAudit?: SubagentCapabilityAudit;
58
62
  children?: NestedRunSummary[];
@@ -62,7 +66,7 @@ export interface AsyncRunSummary {
62
66
  id: string;
63
67
  asyncDir: string;
64
68
  sessionId?: string;
65
- state: "queued" | "running" | "complete" | "failed" | "paused" | "stopped";
69
+ state: "queued" | "running" | "complete" | "failed" | "paused" | "stopped" | "rejected";
66
70
  error?: string;
67
71
  activityState?: ActivityState;
68
72
  lastActivityAt?: number;
@@ -90,14 +94,18 @@ export interface AsyncRunSummary {
90
94
  pendingAppends?: number;
91
95
  parallelGroups?: AsyncParallelGroupStatus[];
92
96
  steps: AsyncRunStepSummary[];
97
+ checkpoint?: ChainCheckpointState;
93
98
  sessionDir?: string;
94
99
  outputFile?: string;
95
100
  totalTokens?: TokenUsage;
96
101
  totalCost?: CostSummary;
102
+ usageBudget?: UsageBudgetState;
97
103
  sessionFile?: string;
98
104
  nestedChildren?: NestedRunSummary[];
99
105
  nestedWarnings?: string[];
100
106
  processTerminal?: AsyncStatus["processTerminal"];
107
+ launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
108
+ runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
101
109
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
102
110
  capabilityAudit?: SubagentCapabilityAudit;
103
111
  }
@@ -225,9 +233,11 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
225
233
  agent: step.agent,
226
234
  ...(step.context ? { context: step.context } : {}),
227
235
  ...(step.label ? { label: step.label } : {}),
236
+ ...(step.description ? { description: step.description } : {}),
228
237
  ...(step.phase ? { phase: step.phase } : {}),
229
238
  ...(step.outputName ? { outputName: step.outputName } : {}),
230
239
  ...(step.structured ? { structured: step.structured } : {}),
240
+ ...(step.checkpoint ? { checkpoint: step.checkpoint } : {}),
231
241
  status: step.status,
232
242
  ...(stepActivityState ? { activityState: stepActivityState } : {}),
233
243
  ...(stepLastActivityAt ? { lastActivityAt: stepLastActivityAt } : {}),
@@ -258,6 +268,8 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
258
268
  ...(step.acceptance ? { acceptance: step.acceptance } : {}),
259
269
  ...(step.agentContract ? { agentContract: step.agentContract } : {}),
260
270
  ...(step.launchContractDigest ? { launchContractDigest: step.launchContractDigest } : {}),
271
+ ...(step.launchResolvedExtensions ? { launchResolvedExtensions: step.launchResolvedExtensions } : {}),
272
+ ...(step.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: step.runtimeAcknowledgedExtensions } : {}),
261
273
  ...(step.execution ? { execution: step.execution } : {}),
262
274
  ...(step.review ? { review: step.review } : {}),
263
275
  ...(step.effects ? { effects: step.effects } : {}),
@@ -300,16 +312,20 @@ function statusToSummary(asyncDir: string, status: AsyncStatus & { cwd?: string
300
312
  ...(status.pendingAppends !== undefined ? { pendingAppends: status.pendingAppends } : {}),
301
313
  ...(parallelGroups.length ? { parallelGroups } : {}),
302
314
  steps: summarizedSteps,
315
+ ...(status.checkpoint ? { checkpoint: status.checkpoint } : {}),
303
316
  ...(nestedChildren.length ? { nestedChildren } : {}),
304
317
  ...(nestedWarnings.length ? { nestedWarnings } : {}),
305
318
  ...(processTerminal ? { processTerminal } : {}),
306
319
  ...(status.launchContractDigest ? { launchContractDigest: status.launchContractDigest } : {}),
320
+ ...(status.launchResolvedExtensions ? { launchResolvedExtensions: status.launchResolvedExtensions } : {}),
321
+ ...(status.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: status.runtimeAcknowledgedExtensions } : {}),
307
322
  ...(status.capabilityCeiling ? { capabilityCeiling: status.capabilityCeiling } : {}),
308
323
  ...(status.capabilityAudit ? { capabilityAudit: status.capabilityAudit } : {}),
309
324
  ...(status.sessionDir ? { sessionDir: status.sessionDir } : {}),
310
325
  ...(status.outputFile ? { outputFile: status.outputFile } : {}),
311
326
  ...(status.totalTokens ? { totalTokens: status.totalTokens } : {}),
312
327
  ...(status.totalCost ? { totalCost: status.totalCost } : {}),
328
+ ...(status.usageBudget ? { usageBudget: status.usageBudget } : {}),
313
329
  ...(status.sessionFile ? { sessionFile: status.sessionFile } : {}),
314
330
  };
315
331
  }