@selesai/code 0.13.39 → 0.14.0

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 (1401) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/dist/bun/runtime-setup.js +4 -1
  3. package/dist/cli/args.d.ts +3 -1
  4. package/dist/cli/args.js +76 -33
  5. package/dist/cli/auth-check.d.ts +18 -0
  6. package/dist/cli/auth-check.js +49 -0
  7. package/dist/cli/credential-print.d.ts +5 -15
  8. package/dist/cli/credential-print.js +42 -82
  9. package/dist/cli/file-processor.d.ts +1 -1
  10. package/dist/cli/file-processor.js +2 -1
  11. package/dist/cli/list-models.d.ts +1 -1
  12. package/dist/cli/list-models.js +2 -2
  13. package/dist/cli/startup-ui.js +38 -30
  14. package/dist/config.d.ts +35 -6
  15. package/dist/config.js +95 -17
  16. package/dist/core/agent-session-custom-tools.test.js +64 -0
  17. package/dist/core/agent-session-length-continuation.test.js +7 -3
  18. package/dist/core/agent-session-runtime.js +2 -2
  19. package/dist/core/agent-session-services.d.ts +1 -0
  20. package/dist/core/agent-session-services.js +14 -0
  21. package/dist/core/agent-session.d.ts +180 -40
  22. package/dist/core/agent-session.js +1061 -485
  23. package/dist/core/auth-storage.d.ts +25 -15
  24. package/dist/core/auth-storage.js +242 -66
  25. package/dist/core/bash-executor.js +42 -52
  26. package/dist/core/bug-report.js +1 -1
  27. package/dist/core/cache-warmer.d.ts +1 -0
  28. package/dist/core/cache-warmer.js +15 -1
  29. package/dist/core/compaction/branch-summarization.js +3 -0
  30. package/dist/core/compaction/compaction.d.ts +3 -1
  31. package/dist/core/compaction/compaction.js +156 -79
  32. package/dist/core/compaction/utils.d.ts +2 -1
  33. package/dist/core/compaction/utils.js +25 -18
  34. package/dist/core/crash-log.d.ts +5 -0
  35. package/dist/core/crash-log.js +69 -0
  36. package/dist/core/defaults.d.ts +1 -1
  37. package/dist/core/defaults.js +1 -1
  38. package/dist/core/export-html/template.css +10 -0
  39. package/dist/core/export-html/template.js +72 -18
  40. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  41. package/dist/core/export-html/tool-renderer.js +5 -3
  42. package/dist/core/extensions/index.d.ts +2 -2
  43. package/dist/core/extensions/index.js +1 -1
  44. package/dist/core/extensions/loader.js +138 -55
  45. package/dist/core/extensions/runner.d.ts +38 -5
  46. package/dist/core/extensions/runner.js +220 -7
  47. package/dist/core/extensions/types.d.ts +438 -51
  48. package/dist/core/extensions/types.js +3 -0
  49. package/dist/core/extensions/virtual-modules.js +6 -0
  50. package/dist/core/extensions/wrapper.d.ts +2 -2
  51. package/dist/core/extensions/wrapper.js +3 -3
  52. package/dist/core/footer-data-provider.d.ts +1 -1
  53. package/dist/core/footer-data-provider.js +1 -1
  54. package/dist/core/handoff.d.ts +0 -1
  55. package/dist/core/handoff.js +0 -1
  56. package/dist/core/http-dispatcher.js +5 -0
  57. package/dist/core/index.d.ts +1 -1
  58. package/dist/core/intercom-rpc.d.ts +135 -0
  59. package/dist/core/intercom-rpc.js +64 -0
  60. package/dist/core/keybindings.d.ts +25 -24
  61. package/dist/core/keybindings.js +27 -6
  62. package/dist/core/mcp-servers.d.ts +134 -0
  63. package/dist/core/mcp-servers.js +223 -0
  64. package/dist/core/model-config.d.ts +122 -5
  65. package/dist/core/model-config.js +35 -1
  66. package/dist/core/model-registry.d.ts +23 -15
  67. package/dist/core/model-registry.js +46 -22
  68. package/dist/core/model-resolver.d.ts +6 -5
  69. package/dist/core/model-resolver.js +51 -21
  70. package/dist/core/model-runtime.d.ts +73 -14
  71. package/dist/core/model-runtime.js +398 -104
  72. package/dist/core/models-store.d.ts +12 -7
  73. package/dist/core/models-store.js +85 -15
  74. package/dist/core/nested-tool-calls.d.ts +102 -0
  75. package/dist/core/nested-tool-calls.js +178 -0
  76. package/dist/core/package-manager.d.ts +8 -1
  77. package/dist/core/package-manager.js +144 -61
  78. package/dist/core/package-manager.test.js +5 -5
  79. package/dist/core/pi-manifest.d.ts +9 -0
  80. package/dist/core/pi-manifest.js +25 -0
  81. package/dist/core/prompt-templates.d.ts +6 -1
  82. package/dist/core/prompt-templates.js +61 -35
  83. package/dist/core/provider-composer.d.ts +44 -19
  84. package/dist/core/provider-composer.js +166 -64
  85. package/dist/core/radius.d.ts +2 -0
  86. package/dist/core/radius.js +2 -0
  87. package/dist/core/release-rpc.d.ts +137 -0
  88. package/dist/core/release-rpc.js +77 -0
  89. package/dist/core/remote-catalog-provider.d.ts +8 -1
  90. package/dist/core/remote-catalog-provider.js +25 -13
  91. package/dist/core/resource-loader.d.ts +12 -1
  92. package/dist/core/resource-loader.js +180 -45
  93. package/dist/core/runtime-credentials.d.ts +5 -5
  94. package/dist/core/runtime-credentials.js +11 -8
  95. package/dist/core/sdk.d.ts +16 -7
  96. package/dist/core/sdk.js +57 -24
  97. package/dist/core/session-manager.d.ts +45 -9
  98. package/dist/core/session-manager.js +124 -31
  99. package/dist/core/settings-diagnostics.d.ts +8 -0
  100. package/dist/core/settings-diagnostics.js +20 -0
  101. package/dist/core/settings-manager.d.ts +62 -32
  102. package/dist/core/settings-manager.js +147 -69
  103. package/dist/core/skills.d.ts +5 -2
  104. package/dist/core/skills.js +58 -35
  105. package/dist/core/slash-commands.js +2 -1
  106. package/dist/core/source-info.d.ts +8 -0
  107. package/dist/core/source-info.js +16 -0
  108. package/dist/core/subagent-rpc.d.ts +110 -0
  109. package/dist/core/subagent-rpc.js +60 -0
  110. package/dist/core/system-prompt.d.ts +9 -3
  111. package/dist/core/system-prompt.js +9 -12
  112. package/dist/core/system-prompt.test.js +2 -7
  113. package/dist/core/tools/bash.d.ts +12 -0
  114. package/dist/core/tools/bash.js +33 -2
  115. package/dist/core/tools/edit-diff.d.ts +0 -5
  116. package/dist/core/tools/edit-diff.js +2 -5
  117. package/dist/core/tools/edit.d.ts +4 -0
  118. package/dist/core/tools/edit.js +31 -11
  119. package/dist/core/tools/find.d.ts +7 -0
  120. package/dist/core/tools/find.js +16 -19
  121. package/dist/core/tools/grep.d.ts +4 -0
  122. package/dist/core/tools/grep.js +5 -1
  123. package/dist/core/tools/index.d.ts +1 -1
  124. package/dist/core/tools/index.js +11 -2
  125. package/dist/core/tools/ls.d.ts +4 -0
  126. package/dist/core/tools/ls.js +5 -1
  127. package/dist/core/tools/output-accumulator.d.ts +11 -0
  128. package/dist/core/tools/output-accumulator.js +40 -10
  129. package/dist/core/tools/read.d.ts +17 -2
  130. package/dist/core/tools/read.js +23 -2
  131. package/dist/core/tools/render-utils.d.ts +6 -0
  132. package/dist/core/tools/render-utils.js +26 -0
  133. package/dist/core/tools/renderers/bash.js +19 -35
  134. package/dist/core/tools/renderers/edit.js +5 -4
  135. package/dist/core/tools/renderers/index.d.ts +2 -2
  136. package/dist/core/tools/renderers/read.js +3 -2
  137. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  138. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  139. package/dist/core/tools/truncate.d.ts +14 -0
  140. package/dist/core/tools/truncate.js +29 -0
  141. package/dist/core/tools/write.d.ts +4 -0
  142. package/dist/core/tools/write.js +6 -2
  143. package/dist/core/trust-manager.js +3 -1
  144. package/dist/core/usage-totals.d.ts +2 -0
  145. package/dist/core/usage-totals.js +23 -0
  146. package/dist/core/virtual-models.d.ts +116 -0
  147. package/dist/core/virtual-models.js +123 -0
  148. package/dist/defaults/models.json +32 -0
  149. package/dist/defaults/settings.json +1 -9
  150. package/dist/extensions/agent-browser.ts +9 -0
  151. package/dist/extensions/codemode/execute.d.ts +15 -0
  152. package/dist/extensions/codemode/execute.js +633 -0
  153. package/dist/extensions/codemode/execute.lazy.d.ts +2 -0
  154. package/dist/extensions/codemode/execute.lazy.js +2 -0
  155. package/dist/extensions/codemode/index.d.ts +20 -0
  156. package/dist/extensions/codemode/index.js +31 -0
  157. package/dist/extensions/codemode/renderer.d.ts +11 -0
  158. package/dist/extensions/codemode/renderer.js +136 -0
  159. package/dist/extensions/codemode/tool.d.ts +129 -0
  160. package/dist/extensions/codemode/tool.js +275 -0
  161. package/dist/extensions/context-compaction-reminder.ts +1 -1
  162. package/dist/extensions/grep-app/index.ts +2 -10
  163. package/dist/extensions/herdr-agent-state.ts +1 -1
  164. package/dist/extensions/{pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts → index.d.ts} +0 -1
  165. package/dist/extensions/index.js +12 -0
  166. package/dist/extensions/jev/classifier-context.ts +54 -0
  167. package/dist/extensions/jev/classifier.test.ts +85 -0
  168. package/dist/extensions/jev/classifier.ts +105 -0
  169. package/dist/extensions/jev/decisions.test.ts +35 -47
  170. package/dist/extensions/jev/decisions.ts +58 -104
  171. package/dist/extensions/jev/test-support.ts +33 -38
  172. package/dist/extensions/jev-advisory-lifecycle.test.ts +12 -12
  173. package/dist/extensions/jev-advisory-memory.test.ts +9 -9
  174. package/dist/extensions/jev-advisory-recommendations.test.ts +8 -8
  175. package/dist/extensions/jev-ask-tool.test.ts +41 -45
  176. package/dist/extensions/jev-ask-tool.ts +10 -38
  177. package/dist/extensions/jev-find-source.test.ts +26 -0
  178. package/dist/extensions/jev-find-source.ts +58 -19
  179. package/dist/{core → extensions}/llama/client.d.ts +2 -0
  180. package/dist/{core → extensions}/llama/client.js +7 -3
  181. package/dist/{core → extensions}/llama/index.js +13 -2
  182. package/dist/{core → extensions}/llama/provider.d.ts +1 -1
  183. package/dist/extensions/llama/provider.js +235 -0
  184. package/dist/extensions/mcp/cli.d.ts +20 -0
  185. package/dist/extensions/mcp/cli.js +496 -0
  186. package/dist/extensions/mcp/cli.lazy.d.ts +2 -0
  187. package/dist/extensions/mcp/cli.lazy.js +2 -0
  188. package/dist/extensions/mcp/config.d.ts +83 -0
  189. package/dist/extensions/mcp/config.js +193 -0
  190. package/dist/extensions/mcp/index.d.ts +78 -0
  191. package/dist/extensions/mcp/index.js +1201 -0
  192. package/dist/extensions/mcp/log.d.ts +15 -0
  193. package/dist/extensions/mcp/log.js +65 -0
  194. package/dist/extensions/mcp/oauth.d.ts +97 -0
  195. package/dist/extensions/mcp/oauth.js +401 -0
  196. package/dist/extensions/mcp/resources.d.ts +41 -0
  197. package/dist/extensions/mcp/resources.js +260 -0
  198. package/dist/extensions/mcp/runtime.d.ts +96 -0
  199. package/dist/extensions/mcp/runtime.js +412 -0
  200. package/dist/extensions/mcp/runtime.lazy.d.ts +2 -0
  201. package/dist/extensions/mcp/runtime.lazy.js +2 -0
  202. package/dist/extensions/mcp/tools.d.ts +86 -0
  203. package/dist/extensions/mcp/tools.js +252 -0
  204. package/dist/extensions/mcp/ui.d.ts +59 -0
  205. package/dist/extensions/mcp/ui.js +185 -0
  206. package/dist/extensions/package.json +1 -1
  207. package/dist/extensions/pi-graft/tools.ts +6 -0
  208. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +25 -0
  209. package/dist/extensions/pi-hermes-memory/README.md +140 -4
  210. package/dist/extensions/pi-hermes-memory/package-lock.json +624 -2720
  211. package/dist/extensions/pi-hermes-memory/package.json +9 -7
  212. package/dist/extensions/pi-hermes-memory/scripts/benchmark-memory-startup.mjs +72 -0
  213. package/dist/extensions/pi-hermes-memory/scripts/check-production-install.mjs +107 -0
  214. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +2 -1
  215. package/dist/extensions/pi-hermes-memory/src/config.ts +35 -0
  216. package/dist/extensions/pi-hermes-memory/src/constants.ts +62 -15
  217. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +374 -50
  218. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +7 -4
  219. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +19 -14
  220. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +75 -1
  221. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +322 -22
  222. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +8 -0
  223. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +193 -54
  224. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +6 -2
  225. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +33 -5
  226. package/dist/extensions/pi-hermes-memory/src/index.ts +116 -47
  227. package/dist/extensions/pi-hermes-memory/src/memory-initialization.ts +101 -0
  228. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +10 -2
  229. package/dist/extensions/pi-hermes-memory/src/store/db.ts +34 -9
  230. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +44 -8
  231. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +3 -1
  232. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +141 -0
  233. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +17 -6
  234. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +20 -10
  235. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +1 -17
  236. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +2 -10
  237. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +4 -8
  238. package/dist/extensions/pi-hermes-memory/src/types.ts +48 -0
  239. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +108 -0
  240. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +1185 -42
  241. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +57 -1
  242. package/dist/extensions/pi-hermes-memory/tests/handlers/lazy-memory-hooks.test.ts +128 -0
  243. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +844 -1
  244. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +16 -0
  245. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +512 -3
  246. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +38 -0
  247. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +183 -2
  248. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +1 -3
  249. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +17 -0
  250. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +21 -0
  251. package/dist/extensions/pi-hermes-memory/tests/lazy-startup.test.ts +313 -0
  252. package/dist/extensions/pi-hermes-memory/tests/memory-initialization.test.ts +182 -0
  253. package/dist/extensions/pi-hermes-memory/tests/prompt-injection.test.ts +184 -0
  254. package/dist/extensions/pi-hermes-memory/tests/skill-discovery-contract.test.ts +60 -0
  255. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-lazy-probe.test.ts +80 -0
  256. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +2 -0
  257. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +79 -0
  258. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +268 -0
  259. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +29 -0
  260. package/dist/extensions/pi-hermes-memory/tests/store/usage-tracking.test.ts +170 -0
  261. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +80 -1
  262. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +51 -0
  263. package/dist/extensions/pi-intercom/CHANGELOG.md +66 -0
  264. package/dist/extensions/pi-intercom/README.md +115 -12
  265. package/dist/extensions/pi-intercom/broker/broker.ts +304 -24
  266. package/dist/extensions/pi-intercom/broker/client.ts +9 -2
  267. package/dist/extensions/pi-intercom/broker/cross-machine-provenance.test.ts +63 -0
  268. package/dist/extensions/pi-intercom/broker/mailbox-persistence.test.ts +523 -0
  269. package/dist/extensions/pi-intercom/broker/paths.test.ts +4 -4
  270. package/dist/extensions/pi-intercom/broker/paths.ts +4 -2
  271. package/dist/extensions/pi-intercom/broker/protocol.ts +64 -0
  272. package/dist/extensions/pi-intercom/broker/spawn.test.ts +58 -169
  273. package/dist/extensions/pi-intercom/broker/spawn.ts +40 -87
  274. package/dist/extensions/pi-intercom/cli.mjs +6 -0
  275. package/dist/extensions/pi-intercom/cli.test.ts +428 -0
  276. package/dist/extensions/pi-intercom/cli.ts +343 -0
  277. package/dist/extensions/pi-intercom/config.test.ts +61 -1
  278. package/dist/extensions/pi-intercom/config.ts +53 -2
  279. package/dist/extensions/pi-intercom/cross-machine-discovery.test.ts +218 -0
  280. package/dist/extensions/pi-intercom/cross-machine-discovery.ts +140 -0
  281. package/dist/extensions/pi-intercom/cross-machine-envelope.test.ts +106 -0
  282. package/dist/extensions/pi-intercom/cross-machine-envelope.ts +92 -0
  283. package/dist/extensions/pi-intercom/cross-machine-integration.test.ts +25 -0
  284. package/dist/extensions/pi-intercom/cross-machine-transport.test.ts +106 -0
  285. package/dist/extensions/pi-intercom/cross-machine-transport.ts +110 -0
  286. package/dist/extensions/pi-intercom/extension-api.ts +24 -0
  287. package/dist/extensions/pi-intercom/handover.test.ts +88 -0
  288. package/dist/extensions/pi-intercom/handover.ts +115 -0
  289. package/dist/extensions/pi-intercom/herdr-location.test.ts +173 -0
  290. package/dist/extensions/pi-intercom/herdr-location.ts +137 -0
  291. package/dist/extensions/pi-intercom/human-priority.pi.test.ts +489 -0
  292. package/dist/extensions/pi-intercom/index.ts +770 -172
  293. package/dist/extensions/pi-intercom/intercom.integration.test.ts +869 -21
  294. package/dist/extensions/pi-intercom/package.json +12 -2
  295. package/dist/extensions/pi-intercom/project-agent.ts +1 -1
  296. package/dist/extensions/pi-intercom/release-readiness.test.ts +116 -0
  297. package/dist/extensions/pi-intercom/release-readiness.ts +93 -0
  298. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +26 -2
  299. package/dist/extensions/pi-intercom/test/handover-picker.test.ts +134 -0
  300. package/dist/extensions/pi-intercom/test/inline-message.test.ts +43 -0
  301. package/dist/extensions/pi-intercom/types.d.ts +247 -0
  302. package/dist/extensions/pi-intercom/types.js +2 -0
  303. package/dist/extensions/pi-intercom/types.ts +39 -1
  304. package/dist/extensions/pi-intercom/ui/handover-picker.ts +318 -0
  305. package/dist/extensions/pi-intercom/ui/inline-message.ts +10 -3
  306. package/dist/extensions/pi-intercom/ui/session-list.ts +28 -15
  307. package/dist/extensions/pi-subagents/.github/workflows/release.yml +5 -1
  308. package/dist/extensions/pi-subagents/.github/workflows/test.yml +188 -18
  309. package/dist/extensions/pi-subagents/CHANGELOG.md +514 -1
  310. package/dist/extensions/pi-subagents/README.md +7 -5
  311. package/dist/extensions/pi-subagents/VISION.md +6 -0
  312. package/dist/extensions/pi-subagents/agents/reviewer.md +7 -5
  313. package/dist/extensions/pi-subagents/agents/worker.md +1 -1
  314. package/dist/extensions/pi-subagents/docs/agents.md +75 -35
  315. package/dist/extensions/pi-subagents/docs/configuration.md +156 -25
  316. package/dist/extensions/pi-subagents/docs/extension-api.md +121 -29
  317. package/dist/extensions/pi-subagents/docs/missions.md +46 -14
  318. package/dist/extensions/pi-subagents/docs/models.md +22 -84
  319. package/dist/extensions/pi-subagents/docs/observability.md +57 -24
  320. package/dist/extensions/pi-subagents/docs/standalone-background.md +59 -0
  321. package/dist/extensions/pi-subagents/docs/tool-reference.md +167 -116
  322. package/dist/extensions/pi-subagents/docs/watchdog.md +41 -10
  323. package/dist/extensions/pi-subagents/docs/workflows.md +239 -163
  324. package/dist/extensions/pi-subagents/examples/typed-gate/.pi/agents/classifier.md +14 -0
  325. package/dist/extensions/pi-subagents/examples/typed-gate/README.md +42 -0
  326. package/dist/extensions/pi-subagents/examples/typed-gate/classify +38 -0
  327. package/dist/extensions/pi-subagents/examples/typed-gate/workflow.js +32 -0
  328. package/dist/extensions/pi-subagents/index.ts +11 -3
  329. package/dist/extensions/pi-subagents/inspector-runner.mjs +3 -3
  330. package/dist/extensions/pi-subagents/package-lock.json +517 -1129
  331. package/dist/extensions/pi-subagents/package.json +22 -11
  332. package/dist/extensions/pi-subagents/prompts/council.md +7 -4
  333. package/dist/extensions/pi-subagents/prompts/parallel-review.md +2 -2
  334. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  335. package/dist/extensions/pi-subagents/runner-peer-loader.mjs +21 -0
  336. package/dist/extensions/pi-subagents/runner-peer-preload.mjs +30 -0
  337. package/dist/extensions/pi-subagents/scripts/build-package.mjs +79 -0
  338. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +2 -2
  339. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +46 -27
  340. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +11 -7
  341. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +78 -73
  342. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +4 -5
  343. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +10 -2
  344. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +69 -67
  345. package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +3 -3
  346. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +21 -10
  347. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +113 -113
  348. package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +91 -4
  349. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +15 -9
  350. package/dist/extensions/pi-subagents/src/agents/agents.ts +432 -193
  351. package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +6 -1
  352. package/dist/extensions/pi-subagents/src/agents/global-npm-root.ts +58 -0
  353. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +5 -2
  354. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +22 -18
  355. package/dist/extensions/pi-subagents/src/agents/skills.ts +43 -10
  356. package/dist/extensions/pi-subagents/src/api/delegation.ts +20 -1
  357. package/dist/extensions/pi-subagents/src/api/inspectors.ts +27 -0
  358. package/dist/extensions/pi-subagents/src/api/preflight.ts +140 -62
  359. package/dist/extensions/pi-subagents/src/api/required-child-extensions.ts +6 -0
  360. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
  361. package/dist/extensions/pi-subagents/src/extension/config.ts +24 -40
  362. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +4 -1
  363. package/dist/extensions/pi-subagents/src/extension/doctor.ts +18 -15
  364. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +87 -13
  365. package/dist/extensions/pi-subagents/src/extension/herdr-pi-bridge.ts +162 -0
  366. package/dist/extensions/pi-subagents/src/extension/index.ts +331 -269
  367. package/dist/extensions/pi-subagents/src/extension/observability.ts +164 -0
  368. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +76 -37
  369. package/dist/extensions/pi-subagents/src/extension/release-readiness.ts +367 -0
  370. package/dist/extensions/pi-subagents/src/extension/reply-workflow-script.ts +67 -0
  371. package/dist/extensions/pi-subagents/src/extension/rpc.ts +42 -12
  372. package/dist/extensions/pi-subagents/src/extension/schemas.ts +116 -205
  373. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +13 -5
  374. package/dist/extensions/pi-subagents/src/extension/tool-activation.ts +146 -0
  375. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +77 -90
  376. package/dist/extensions/pi-subagents/src/extension/upgrade-notice.ts +40 -0
  377. package/dist/extensions/pi-subagents/src/inspectors/actions.ts +148 -0
  378. package/dist/extensions/pi-subagents/src/inspectors/ghostty/actions.ts +74 -0
  379. package/dist/extensions/pi-subagents/src/inspectors/ghostty/plugin.ts +29 -0
  380. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +100 -180
  381. package/dist/extensions/pi-subagents/src/inspectors/herdr/plugin.ts +20 -0
  382. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -2
  383. package/dist/extensions/pi-subagents/src/inspectors/{herdr/inspector-runner.ts → inspector-runner.ts} +13 -13
  384. package/dist/extensions/pi-subagents/src/inspectors/plugins.ts +75 -0
  385. package/dist/extensions/pi-subagents/src/inspectors/{herdr/session-roots-codec.ts → session-roots-codec.ts} +4 -15
  386. package/dist/extensions/pi-subagents/src/inspectors/{herdr/shell-command.ts → shell-command.ts} +1 -1
  387. package/dist/extensions/pi-subagents/src/inspectors/types.ts +51 -0
  388. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +38 -53
  389. package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +7 -1
  390. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +53 -9
  391. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +69 -55
  392. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +7 -2
  393. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +45 -32
  394. package/dist/extensions/pi-subagents/src/missions/store.ts +11 -2
  395. package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +1 -44
  396. package/dist/extensions/pi-subagents/src/policy/authority.ts +5 -1
  397. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +30 -18
  398. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +59 -9
  399. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +18 -2
  400. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +463 -248
  401. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +112 -66
  402. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +33 -20
  403. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +47 -17
  404. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -5
  405. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +24 -11
  406. package/dist/extensions/pi-subagents/src/runs/background/await-async-run.ts +78 -0
  407. package/dist/extensions/pi-subagents/src/runs/background/binary-bootstrap.ts +66 -0
  408. package/dist/extensions/pi-subagents/src/runs/background/calendar-schedule.ts +90 -0
  409. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -2
  410. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +19 -38
  411. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +62 -3
  412. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +82 -10
  413. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +272 -24
  414. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +30 -3
  415. package/dist/extensions/pi-subagents/src/runs/background/pid-namespace.ts +18 -0
  416. package/dist/extensions/pi-subagents/src/runs/background/process-terminal-candidate.ts +98 -0
  417. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +18 -97
  418. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +269 -7
  419. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +14 -5
  420. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +77 -22
  421. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +4 -3
  422. package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +15 -3
  423. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +126 -45
  424. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +11 -6
  425. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +18 -7
  426. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +43 -51
  427. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +8 -1
  428. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +5 -4
  429. package/dist/extensions/pi-subagents/src/runs/background/runner-http-dispatcher.ts +119 -0
  430. package/dist/extensions/pi-subagents/src/runs/background/runner-startup-failure.ts +56 -0
  431. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +297 -69
  432. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +67 -16
  433. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +21 -3
  434. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner-bootstrap.ts +276 -0
  435. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +660 -578
  436. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +177 -29
  437. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +77 -28
  438. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +10 -4
  439. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +7 -13
  440. package/dist/extensions/pi-subagents/src/runs/background/workflow-terminal-proof.ts +41 -23
  441. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +19 -8
  442. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +130 -7
  443. package/dist/extensions/pi-subagents/src/runs/foreground/command-action.ts +41 -0
  444. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +267 -385
  445. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +4 -2
  446. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +6 -10
  447. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1158 -413
  448. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +3 -1
  449. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +2 -1
  450. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +200 -74
  451. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +133 -34
  452. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +6 -1
  453. package/dist/extensions/pi-subagents/src/runs/shared/child-commands.ts +228 -0
  454. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +18 -18
  455. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +16 -4
  456. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +55 -12
  457. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +6 -3
  458. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +11 -1
  459. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +367 -74
  460. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +50 -86
  461. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +288 -0
  462. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  463. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  464. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +5 -5
  465. package/dist/extensions/pi-subagents/src/runs/shared/effective-system-prompt.ts +33 -0
  466. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +49 -10
  467. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +61 -9
  468. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +16 -9
  469. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +55 -1
  470. package/dist/extensions/pi-subagents/src/runs/shared/git-environment.ts +1 -1
  471. package/dist/extensions/pi-subagents/src/runs/shared/herdr-connection.ts +134 -0
  472. package/dist/extensions/pi-subagents/src/runs/shared/herdr-external-adapters.ts +169 -0
  473. package/dist/extensions/pi-subagents/src/runs/shared/herdr-machine.ts +279 -0
  474. package/dist/extensions/pi-subagents/src/runs/shared/herdr-pi-protocol.ts +59 -0
  475. package/dist/extensions/pi-subagents/src/runs/shared/herdr-placed-run.ts +263 -0
  476. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +6 -2
  477. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +108 -13
  478. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +23 -7
  479. package/dist/extensions/pi-subagents/src/runs/shared/model-resolution-diagnostic.ts +76 -0
  480. package/dist/extensions/pi-subagents/src/runs/shared/{model-fallback.ts → model-resolution.ts} +65 -245
  481. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +30 -11
  482. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +24 -3
  483. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +5 -4
  484. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +55 -7
  485. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +14 -4
  486. package/dist/extensions/pi-subagents/src/runs/shared/partial-output.ts +48 -0
  487. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +12 -4
  488. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +88 -1
  489. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +12 -3
  490. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +160 -9
  491. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +49 -35
  492. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +58 -19
  493. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +2 -2
  494. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +21 -0
  495. package/dist/extensions/pi-subagents/src/runs/shared/usage-reconciliation.ts +73 -0
  496. package/dist/extensions/pi-subagents/src/runs/shared/workflow-async-child-guidance.ts +18 -0
  497. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-apply.ts +160 -0
  498. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +42 -20
  499. package/dist/extensions/pi-subagents/src/runs/shared/worktree-lock.ts +29 -0
  500. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +27 -4
  501. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +94 -26
  502. package/dist/extensions/pi-subagents/src/shared/child-cache-retention.ts +43 -0
  503. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +5 -3
  504. package/dist/extensions/pi-subagents/src/shared/disabled-features.ts +123 -0
  505. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +14 -1
  506. package/dist/extensions/pi-subagents/src/shared/file-lease.ts +74 -0
  507. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +27 -77
  508. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +70 -10
  509. package/dist/extensions/pi-subagents/src/shared/model-info.ts +10 -1
  510. package/dist/extensions/pi-subagents/src/shared/opencode-session-headers.ts +30 -0
  511. package/dist/extensions/pi-subagents/src/shared/owner-record.ts +107 -0
  512. package/dist/extensions/pi-subagents/src/shared/package-version.ts +17 -0
  513. package/dist/extensions/pi-subagents/src/shared/parent-wake.ts +66 -0
  514. package/dist/extensions/pi-subagents/src/shared/process-identity.ts +87 -0
  515. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +71 -58
  516. package/dist/extensions/pi-subagents/src/shared/required-child-extensions.ts +115 -0
  517. package/dist/extensions/pi-subagents/src/shared/settings-file-lease.ts +36 -0
  518. package/dist/extensions/pi-subagents/src/shared/settings.ts +7 -4
  519. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +1 -5
  520. package/dist/extensions/pi-subagents/src/shared/types.ts +155 -48
  521. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +28 -2
  522. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +15 -1
  523. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +19 -4
  524. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +13 -2
  525. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +15 -15
  526. package/dist/extensions/pi-subagents/src/slash/subagent-cost.ts +46 -9
  527. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +29 -16
  528. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +201 -26
  529. package/dist/extensions/pi-subagents/src/tui/fleet.ts +33 -16
  530. package/dist/extensions/pi-subagents/src/tui/render.ts +334 -103
  531. package/dist/extensions/pi-subagents/src/tui/running-tone.ts +28 -0
  532. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +27 -28
  533. package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +47 -12
  534. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +2 -2
  535. package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +22 -2
  536. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +17 -17
  537. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +24 -8
  538. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +43 -39
  539. package/dist/extensions/pi-subagents/src/watchdog/render.ts +2 -2
  540. package/dist/extensions/pi-subagents/src/watchdog/review.ts +127 -78
  541. package/dist/extensions/pi-subagents/src/watchdog/rules.ts +1 -1
  542. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +107 -31
  543. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +1 -1
  544. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +22 -14
  545. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +14 -13
  546. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +35 -6
  547. package/dist/extensions/pi-subagents/src/watchdog/types.ts +6 -4
  548. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +2 -2
  549. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  550. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +500 -65
  551. package/dist/extensions/pi-subagents/src/workflows/structured-workflow-scripts.ts +177 -0
  552. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +8 -2
  553. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +5 -3
  554. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +70 -10
  555. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +57 -18
  556. package/dist/extensions/pi-subagents/src/workflows/workflow-reuse.ts +120 -0
  557. package/dist/extensions/pi-subagents/src/workflows/workflow-revival.ts +123 -0
  558. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +5 -2
  559. package/dist/extensions/pi-subagents/test/fixtures/cwd-workflow-child.ts +37 -0
  560. package/dist/extensions/pi-subagents/test/fixtures/herdr-allocation-lock-child.ts +16 -0
  561. package/dist/extensions/pi-subagents/test/fixtures/herdr-provision-child.ts +15 -0
  562. package/dist/extensions/pi-subagents/test/fixtures/native-nested-wait-provider.ts +76 -0
  563. package/dist/extensions/pi-subagents/test/fixtures/runner-bootstrap-harness.ts +36 -0
  564. package/dist/extensions/pi-subagents/test/fixtures/schedule-history-writer.mjs +48 -0
  565. package/dist/extensions/pi-subagents/test/fixtures/settings-race-writer.mjs +57 -0
  566. package/dist/extensions/pi-subagents/test/fixtures/workflow-cwd-access-failure.ts +33 -0
  567. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +40 -7
  568. package/dist/extensions/pi-subagents/test/integration/async-attention-clearing.test.ts +192 -0
  569. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +435 -276
  570. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +435 -397
  571. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +918 -497
  572. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +264 -17
  573. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +185 -22
  574. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +3 -2
  575. package/dist/extensions/pi-subagents/test/integration/claude-code-dispatch.test.ts +127 -0
  576. package/dist/extensions/pi-subagents/test/integration/deadline-checkpoint.test.ts +126 -0
  577. package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +29 -1
  578. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +88 -0
  579. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +450 -13
  580. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +10 -6
  581. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +105 -86
  582. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +403 -18
  583. package/dist/extensions/pi-subagents/test/integration/inline-workflow-visibility.test.ts +351 -0
  584. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +195 -10
  585. package/dist/extensions/pi-subagents/test/integration/model-resolution-diagnostic.test.ts +108 -0
  586. package/dist/extensions/pi-subagents/test/integration/nested-async-wait.test.ts +61 -0
  587. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +5 -4
  588. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +1 -1
  589. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +6 -4
  590. package/dist/extensions/pi-subagents/test/integration/render-widget-mouse.test.ts +84 -0
  591. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +242 -16
  592. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +2 -2
  593. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +221 -4
  594. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +1435 -248
  595. package/dist/extensions/pi-subagents/test/integration/single-execution.part-2.test.ts +454 -515
  596. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +140 -21
  597. package/dist/extensions/pi-subagents/test/integration/stop-all-background.test.ts +142 -0
  598. package/dist/extensions/pi-subagents/test/integration/structured-workflows.test.ts +105 -0
  599. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +90 -11
  600. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +18 -15
  601. package/dist/extensions/pi-subagents/test/integration/workflow-worktree-admission.test.ts +100 -0
  602. package/dist/extensions/pi-subagents/test/smoke/clean-install.mjs +106 -0
  603. package/dist/extensions/pi-subagents/test/smoke/npm-background.mjs +43 -0
  604. package/dist/extensions/pi-subagents/test/smoke/packed-runner-selection.mjs +42 -0
  605. package/dist/extensions/pi-subagents/test/smoke/runner-loader-capability.mjs +50 -0
  606. package/dist/extensions/pi-subagents/test/smoke/sdk-child.ts +57 -0
  607. package/dist/extensions/pi-subagents/test/smoke/{pi085-extension.ts → sdk-extension.ts} +2 -2
  608. package/dist/extensions/pi-subagents/test/smoke/standalone-background.mjs +140 -0
  609. package/dist/extensions/pi-subagents/test/smoke/standalone-fault.ts +43 -0
  610. package/dist/extensions/pi-subagents/test/smoke/standalone-matrix.mjs +65 -0
  611. package/dist/extensions/pi-subagents/test/smoke/standalone-observer.ts +8 -0
  612. package/dist/extensions/pi-subagents/test/smoke/standalone-parent.ts +220 -0
  613. package/dist/extensions/pi-subagents/test/smoke/standalone-provider.ts +58 -0
  614. package/dist/extensions/pi-subagents/test/smoke/standalone-release.json +8 -0
  615. package/dist/extensions/pi-subagents/test/smoke/standalone-revival.ts +109 -0
  616. package/dist/extensions/pi-subagents/test/smoke/standalone-shared.ts +79 -0
  617. package/dist/extensions/pi-subagents/test/smoke/tool-activation.test.ts +128 -0
  618. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +6 -25
  619. package/dist/extensions/pi-subagents/test/support/async-result-timeout-evidence.ts +61 -0
  620. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +130 -9
  621. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +15 -7
  622. package/dist/extensions/pi-subagents/test/support/helpers.ts +11 -14
  623. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +21 -3
  624. package/dist/extensions/pi-subagents/test/support/native-peer-loader.mjs +15 -0
  625. package/dist/extensions/pi-subagents/test/support/node-command.ts +29 -6
  626. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +5 -3
  627. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +7 -15
  628. package/dist/extensions/pi-subagents/test/support/watchdog-stable-host-loader.mjs +23 -0
  629. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +3 -3
  630. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +158 -155
  631. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +52 -1
  632. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +21 -17
  633. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +105 -36
  634. package/dist/extensions/pi-subagents/test/unit/advertisement-barrier.test.ts +151 -0
  635. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -2
  636. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +33 -3
  637. package/dist/extensions/pi-subagents/test/unit/agent-end-auto-drain.test.ts +149 -0
  638. package/dist/extensions/pi-subagents/test/unit/agent-exclude-dirs.test.ts +246 -0
  639. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +62 -87
  640. package/dist/extensions/pi-subagents/test/unit/agent-global-root-override.test.ts +86 -0
  641. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +398 -48
  642. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +126 -1
  643. package/dist/extensions/pi-subagents/test/unit/agent-name-resolution.test.ts +75 -0
  644. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +94 -42
  645. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +73 -3
  646. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +428 -2
  647. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +4 -4
  648. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +112 -1
  649. package/dist/extensions/pi-subagents/test/unit/async-result-timeout-evidence.test.ts +53 -0
  650. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +92 -4
  651. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +58 -6
  652. package/dist/extensions/pi-subagents/test/unit/async-run-history.test.ts +123 -0
  653. package/dist/extensions/pi-subagents/test/unit/async-spawn-package-dir.test.ts +203 -0
  654. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +26 -35
  655. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +185 -0
  656. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +9 -1
  657. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +106 -1
  658. package/dist/extensions/pi-subagents/test/unit/await-async-run.test.ts +202 -0
  659. package/dist/extensions/pi-subagents/test/unit/binary-async-spawn.test.ts +115 -0
  660. package/dist/extensions/pi-subagents/test/unit/binary-pi-spawn.test.ts +27 -0
  661. package/dist/extensions/pi-subagents/test/unit/calendar-schedule.test.ts +70 -0
  662. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +38 -0
  663. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +10 -2
  664. package/dist/extensions/pi-subagents/test/unit/changelog-format.test.ts +11 -0
  665. package/dist/extensions/pi-subagents/test/unit/child-cache-retention.test.ts +87 -0
  666. package/dist/extensions/pi-subagents/test/unit/child-commands.test.ts +243 -0
  667. package/dist/extensions/pi-subagents/test/unit/child-external-job-bridge.test.ts +126 -0
  668. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +12 -1
  669. package/dist/extensions/pi-subagents/test/unit/child-lifecycle.test.ts +36 -0
  670. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +24 -0
  671. package/dist/extensions/pi-subagents/test/unit/child-session-commands.test.ts +162 -0
  672. package/dist/extensions/pi-subagents/test/unit/child-session-host-sdk.test.ts +226 -0
  673. package/dist/extensions/pi-subagents/test/unit/child-session-parent-providers.test.ts +200 -0
  674. package/dist/extensions/pi-subagents/test/unit/child-session-queued.test.ts +260 -0
  675. package/dist/extensions/pi-subagents/test/unit/child-tool-plan-permission-system.test.ts +3 -98
  676. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +222 -1
  677. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +314 -0
  678. package/dist/extensions/pi-subagents/test/unit/claude-code-dispatch.test.ts +182 -0
  679. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +157 -0
  680. package/dist/extensions/pi-subagents/test/unit/command-action.test.ts +50 -0
  681. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +25 -11
  682. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +3 -1
  683. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +18 -0
  684. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +7 -1
  685. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +220 -0
  686. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +104 -32
  687. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +138 -1
  688. package/dist/extensions/pi-subagents/test/unit/disabled-features.test.ts +227 -0
  689. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +48 -9
  690. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +7 -4
  691. package/dist/extensions/pi-subagents/test/unit/extension-lazy-loading.test.ts +21 -0
  692. package/dist/extensions/pi-subagents/test/unit/extension-maintenance-lifecycle.test.ts +66 -0
  693. package/dist/extensions/pi-subagents/test/unit/extension-module-preload.test.ts +49 -0
  694. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +104 -3
  695. package/dist/extensions/pi-subagents/test/unit/file-lease.test.ts +17 -0
  696. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +316 -0
  697. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +58 -7
  698. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +25 -96
  699. package/dist/extensions/pi-subagents/test/unit/ghostty-inspector.test.ts +92 -0
  700. package/dist/extensions/pi-subagents/test/unit/global-npm-root.test.ts +108 -0
  701. package/dist/extensions/pi-subagents/test/unit/herdr-connection.test.ts +43 -0
  702. package/dist/extensions/pi-subagents/test/unit/herdr-external-adapters.test.ts +89 -0
  703. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +11 -20
  704. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +113 -19
  705. package/dist/extensions/pi-subagents/test/unit/herdr-machine.test.ts +161 -0
  706. package/dist/extensions/pi-subagents/test/unit/herdr-native-placement.test.ts +187 -0
  707. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +7 -12
  708. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  709. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +182 -87
  710. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +68 -49
  711. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +295 -135
  712. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +3 -3
  713. package/dist/extensions/pi-subagents/test/unit/inspector-authority-policy.test.ts +144 -0
  714. package/dist/extensions/pi-subagents/test/unit/inspector-registration.test.ts +128 -0
  715. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +49 -1
  716. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +74 -1
  717. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-resolution.test.ts +112 -0
  718. package/dist/extensions/pi-subagents/test/unit/mission-global-projection.test.ts +215 -0
  719. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +65 -1
  720. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +2 -1
  721. package/dist/extensions/pi-subagents/test/unit/model-resolution-diagnostic.test.ts +78 -0
  722. package/dist/extensions/pi-subagents/test/unit/model-resolution.test.ts +153 -0
  723. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +43 -1
  724. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +1 -21
  725. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +279 -2
  726. package/dist/extensions/pi-subagents/test/unit/nested-control-fanout.test.ts +73 -0
  727. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +297 -3
  728. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +1 -1
  729. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +431 -23
  730. package/dist/extensions/pi-subagents/test/unit/observability.test.ts +198 -0
  731. package/dist/extensions/pi-subagents/test/unit/opencode-session-headers.test.ts +32 -0
  732. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +89 -21
  733. package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +31 -1
  734. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +18 -24
  735. package/dist/extensions/pi-subagents/test/unit/parent-wake.test.ts +206 -0
  736. package/dist/extensions/pi-subagents/test/unit/partial-output.test.ts +53 -0
  737. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +216 -32
  738. package/dist/extensions/pi-subagents/test/unit/pi-spawn-host-root.test.ts +82 -0
  739. package/dist/extensions/pi-subagents/test/unit/pi-subagents-policy-guidance.test.ts +28 -0
  740. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +193 -104
  741. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +16 -1
  742. package/dist/extensions/pi-subagents/test/unit/process-identity.test.ts +75 -0
  743. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +17 -1
  744. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +89 -9
  745. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +6 -0
  746. package/dist/extensions/pi-subagents/test/unit/prompt-audit-provider-routing.test.ts +69 -0
  747. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +2 -2
  748. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +23 -1
  749. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +117 -3
  750. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +35 -14
  751. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +3 -2
  752. package/dist/extensions/pi-subagents/test/unit/release-readiness.test.ts +715 -0
  753. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +261 -9
  754. package/dist/extensions/pi-subagents/test/unit/reply-workflow-script.test.ts +37 -0
  755. package/dist/extensions/pi-subagents/test/unit/required-child-extensions.test.ts +114 -0
  756. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +11 -1
  757. package/dist/extensions/pi-subagents/test/unit/result-takeover.test.ts +332 -0
  758. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +22 -2
  759. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +125 -18
  760. package/dist/extensions/pi-subagents/test/unit/run-child-session.test.ts +230 -0
  761. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +50 -1
  762. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +301 -4
  763. package/dist/extensions/pi-subagents/test/unit/runner-bootstrap.test.ts +182 -0
  764. package/dist/extensions/pi-subagents/test/unit/runner-http-dispatcher.test.ts +136 -0
  765. package/dist/extensions/pi-subagents/test/unit/runner-peer-loader.test.ts +68 -0
  766. package/dist/extensions/pi-subagents/test/unit/runner-peer-symlinks.test.ts +50 -0
  767. package/dist/extensions/pi-subagents/test/unit/running-tone.test.ts +13 -0
  768. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +155 -4
  769. package/dist/extensions/pi-subagents/test/unit/schedule-claim-initialization.test.ts +71 -0
  770. package/dist/extensions/pi-subagents/test/unit/schedule-claim-preservation.test.ts +98 -0
  771. package/dist/extensions/pi-subagents/test/unit/schedule-history-transactions.test.ts +201 -0
  772. package/dist/extensions/pi-subagents/test/unit/scheduled-mission.test.ts +317 -0
  773. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +412 -11
  774. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +2 -8
  775. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +70 -71
  776. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +748 -5
  777. package/dist/extensions/pi-subagents/test/unit/session-liveness-delivery.test.ts +337 -0
  778. package/dist/extensions/pi-subagents/test/unit/settings-atomic-save.test.ts +419 -0
  779. package/dist/extensions/pi-subagents/test/unit/settings-transactions.test.ts +88 -0
  780. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +13 -1
  781. package/dist/extensions/pi-subagents/test/unit/skills-disable-model-invocation.test.ts +164 -0
  782. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +35 -2
  783. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +2 -2
  784. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +334 -9
  785. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +170 -0
  786. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +34 -5
  787. package/dist/extensions/pi-subagents/test/unit/structured-output-validation.test.ts +199 -0
  788. package/dist/extensions/pi-subagents/test/unit/structured-workflow-resources.test.ts +241 -0
  789. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +47 -38
  790. package/dist/extensions/pi-subagents/test/unit/subagent-cost.test.ts +97 -0
  791. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +10 -0
  792. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +343 -44
  793. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +410 -11
  794. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +459 -22
  795. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +43 -3
  796. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +11 -1
  797. package/dist/extensions/pi-subagents/test/unit/tool-activation-stale-peer.test.ts +32 -0
  798. package/dist/extensions/pi-subagents/test/unit/tool-activation.test.ts +313 -0
  799. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +14 -0
  800. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -89
  801. package/dist/extensions/pi-subagents/test/unit/typed-gate-output.test.ts +141 -0
  802. package/dist/extensions/pi-subagents/test/unit/upgrade-notice.test.ts +31 -0
  803. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation-owners.test.ts +66 -0
  804. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation.test.ts +23 -0
  805. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +195 -1
  806. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +3 -1
  807. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +48 -45
  808. package/dist/extensions/pi-subagents/test/unit/watchdog-compaction-scope.test.ts +94 -0
  809. package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +48 -3
  810. package/dist/extensions/pi-subagents/test/unit/watchdog-native-scheduling.test.ts +107 -0
  811. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +95 -7
  812. package/dist/extensions/pi-subagents/test/unit/watchdog-register-child.test.ts +79 -0
  813. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -4
  814. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +111 -24
  815. package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +1 -1
  816. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +283 -2
  817. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +3 -0
  818. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +12 -1
  819. package/dist/extensions/pi-subagents/test/unit/watchdog-stable-host-layout.test.ts +23 -0
  820. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +30 -0
  821. package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +39 -2
  822. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +18 -1
  823. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +8 -4
  824. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +10 -0
  825. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +6 -3
  826. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +44 -1
  827. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +28 -1
  828. package/dist/extensions/pi-subagents/test/unit/workflow-revival.test.ts +85 -0
  829. package/dist/extensions/pi-subagents/test/unit/workflow-scripts-feature.test.ts +177 -0
  830. package/dist/extensions/pi-subagents/test/unit/workflow-terminal-proof.test.ts +8 -0
  831. package/dist/extensions/pi-subagents/test/unit/workflow-worktree-admission.test.ts +29 -0
  832. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +343 -4
  833. package/dist/extensions/pi-subagents/test/unit/worktree-lock.test.ts +123 -0
  834. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +252 -22
  835. package/dist/extensions/pi-subagents/tsconfig.build.json +13 -0
  836. package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +1 -1
  837. package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +1 -1
  838. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +24 -1
  839. package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +6 -2
  840. package/dist/extensions/pi-web-agent/src/extension.ts +1 -5
  841. package/dist/extensions/pi-zentui/.github/workflows/ci.yml +67 -4
  842. package/dist/extensions/pi-zentui/AGENTS.md +3 -2
  843. package/dist/extensions/pi-zentui/README.md +60 -32
  844. package/dist/extensions/pi-zentui/docs/configuration.md +662 -51
  845. package/dist/extensions/pi-zentui/docs/footer-format.md +174 -5
  846. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +15 -4
  847. package/dist/extensions/pi-zentui/extensions/zentui/average-token-rate.ts +146 -0
  848. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota-display.ts +34 -0
  849. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota.ts +298 -0
  850. package/dist/extensions/pi-zentui/extensions/zentui/component-colors.ts +172 -0
  851. package/dist/extensions/pi-zentui/extensions/zentui/component-settings.ts +243 -0
  852. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +851 -114
  853. package/dist/extensions/pi-zentui/extensions/zentui/custom-value-colors.ts +93 -0
  854. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-demand.ts +61 -0
  855. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-format.ts +80 -0
  856. package/dist/extensions/pi-zentui/extensions/zentui/custom-variables.ts +152 -0
  857. package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +138 -23
  858. package/dist/extensions/pi-zentui/extensions/zentui/editor-mouse.ts +89 -0
  859. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-controller.ts +148 -0
  860. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-settings.ts +40 -0
  861. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +109 -1
  862. package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +203 -23
  863. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +80 -3
  864. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +1 -1
  865. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +432 -125
  866. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +92 -4
  867. package/dist/extensions/pi-zentui/extensions/zentui/git.ts +47 -30
  868. package/dist/extensions/pi-zentui/extensions/zentui/github-status.ts +575 -0
  869. package/dist/extensions/pi-zentui/extensions/zentui/host-project-changes.ts +25 -0
  870. package/dist/extensions/pi-zentui/extensions/zentui/host-template-values.ts +29 -0
  871. package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +53 -13
  872. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +778 -258
  873. package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +70 -5
  874. package/dist/extensions/pi-zentui/extensions/zentui/layered-editor.ts +55 -0
  875. package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +6 -1
  876. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-demand.ts +72 -0
  877. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-display.ts +21 -0
  878. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata.ts +255 -0
  879. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +476 -36
  880. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-settings.ts +118 -0
  881. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-template.ts +177 -0
  882. package/dist/extensions/pi-zentui/extensions/zentui/omp-editor-frame.ts +148 -0
  883. package/dist/extensions/pi-zentui/extensions/zentui/omp-statusline.ts +569 -0
  884. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-lookups.ts +344 -0
  885. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-metrics.ts +91 -0
  886. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-modes.ts +323 -0
  887. package/dist/extensions/pi-zentui/extensions/zentui/omp-ui.ts +210 -0
  888. package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +30 -12
  889. package/dist/extensions/pi-zentui/extensions/zentui/project-demand.ts +46 -0
  890. package/dist/extensions/pi-zentui/extensions/zentui/project-discovery.ts +58 -0
  891. package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +10 -3
  892. package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +37 -0
  893. package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +1 -0
  894. package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +119 -43
  895. package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +40 -29
  896. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1268 -722
  897. package/dist/extensions/pi-zentui/extensions/zentui/settings-keys.ts +59 -0
  898. package/dist/extensions/pi-zentui/extensions/zentui/settings-list-selection.ts +13 -0
  899. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +11 -4
  900. package/dist/extensions/pi-zentui/extensions/zentui/state.ts +24 -11
  901. package/dist/extensions/pi-zentui/extensions/zentui/style.ts +6 -0
  902. package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +113 -11
  903. package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +234 -46
  904. package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +20 -5
  905. package/dist/extensions/pi-zentui/extensions/zentui/token-rate.ts +313 -0
  906. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-format.ts +59 -0
  907. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-rate.ts +52 -0
  908. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +640 -172
  909. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +72 -34
  910. package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +219 -34
  911. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +495 -119
  912. package/dist/extensions/pi-zentui/omp.ts +157 -0
  913. package/dist/extensions/pi-zentui/package-lock.json +3762 -1507
  914. package/dist/extensions/pi-zentui/package.json +50 -12
  915. package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +13 -2
  916. package/dist/extensions/pi-zentui/test/average-token-rate.test.ts +297 -0
  917. package/dist/extensions/pi-zentui/test/behavior-compatibility.mjs +89 -0
  918. package/dist/extensions/pi-zentui/test/codex-quota-lifecycle.test.ts +284 -0
  919. package/dist/extensions/pi-zentui/test/codex-quota-rendering.test.ts +466 -0
  920. package/dist/extensions/pi-zentui/test/codex-quota.test.ts +440 -0
  921. package/dist/extensions/pi-zentui/test/component-colors.test.ts +554 -0
  922. package/dist/extensions/pi-zentui/test/component-settings.test.ts +364 -0
  923. package/dist/extensions/pi-zentui/test/config-component-independence.test.ts +402 -0
  924. package/dist/extensions/pi-zentui/test/config-extension-status-choice.test.ts +233 -0
  925. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-colors.test.ts +118 -0
  926. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-placement.test.ts +142 -0
  927. package/dist/extensions/pi-zentui/test/config-minimalist-templates.test.ts +240 -0
  928. package/dist/extensions/pi-zentui/test/config-template-variables.test.ts +85 -0
  929. package/dist/extensions/pi-zentui/test/config.test.ts +80 -17
  930. package/dist/extensions/pi-zentui/test/custom-value-colors-integration.test.ts +453 -0
  931. package/dist/extensions/pi-zentui/test/custom-value-colors.test.ts +399 -0
  932. package/dist/extensions/pi-zentui/test/custom-variable-alias-prototypes.test.ts +177 -0
  933. package/dist/extensions/pi-zentui/test/custom-variable-consumers.test.ts +194 -0
  934. package/dist/extensions/pi-zentui/test/custom-variable-demand.test.ts +169 -0
  935. package/dist/extensions/pi-zentui/test/custom-variable-probe-reservation.test.ts +141 -0
  936. package/dist/extensions/pi-zentui/test/custom-variables-lifecycle.integration.test.ts +365 -0
  937. package/dist/extensions/pi-zentui/test/custom-variables.test.ts +330 -0
  938. package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +121 -0
  939. package/dist/extensions/pi-zentui/test/editor-mouse.test.ts +507 -0
  940. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +247 -20
  941. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +204 -260
  942. package/dist/extensions/pi-zentui/test/extension-status-controller.test.ts +323 -0
  943. package/dist/extensions/pi-zentui/test/extension-status-lifecycle.integration.test.ts +466 -0
  944. package/dist/extensions/pi-zentui/test/extension-status-settings.test.ts +79 -0
  945. package/dist/extensions/pi-zentui/test/footer-alignment.test.ts +135 -0
  946. package/dist/extensions/pi-zentui/test/footer-authority.test.ts +69 -0
  947. package/dist/extensions/pi-zentui/test/footer-auto-compaction.test.ts +148 -0
  948. package/dist/extensions/pi-zentui/test/footer-format-cache.test.ts +186 -0
  949. package/dist/extensions/pi-zentui/test/footer-format.test.ts +154 -4
  950. package/dist/extensions/pi-zentui/test/footer-hidden.test.ts +312 -0
  951. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +22 -0
  952. package/dist/extensions/pi-zentui/test/footer-layout.test.ts +80 -0
  953. package/dist/extensions/pi-zentui/test/footer-thinking-level.test.ts +123 -0
  954. package/dist/extensions/pi-zentui/test/format.test.ts +75 -1
  955. package/dist/extensions/pi-zentui/test/git-probes.test.ts +182 -0
  956. package/dist/extensions/pi-zentui/test/github-status.test.ts +931 -0
  957. package/dist/extensions/pi-zentui/test/host-template-surfaces.test.ts +287 -0
  958. package/dist/extensions/pi-zentui/test/icons.test.ts +86 -16
  959. package/dist/extensions/pi-zentui/test/layered-editor.test.ts +53 -0
  960. package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +154 -7
  961. package/dist/extensions/pi-zentui/test/live-context.test.ts +45 -0
  962. package/dist/extensions/pi-zentui/test/live-metadata-lifecycle.integration.test.ts +963 -0
  963. package/dist/extensions/pi-zentui/test/live-metadata.test.ts +767 -0
  964. package/dist/extensions/pi-zentui/test/minimalist-cache-hit-colors.test.ts +183 -0
  965. package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +222 -4
  966. package/dist/extensions/pi-zentui/test/minimalist-settings.test.ts +103 -0
  967. package/dist/extensions/pi-zentui/test/minimalist-templates.test.ts +489 -0
  968. package/dist/extensions/pi-zentui/test/omp-editor-composers.test.ts +324 -0
  969. package/dist/extensions/pi-zentui/test/omp-statusline.test.ts +579 -0
  970. package/dist/extensions/pi-zentui/test/omp-template-lookups.test.ts +630 -0
  971. package/dist/extensions/pi-zentui/test/omp-template-metrics.test.ts +72 -0
  972. package/dist/extensions/pi-zentui/test/omp-template-modes.test.ts +557 -0
  973. package/dist/extensions/pi-zentui/test/omp-ui.test.ts +93 -0
  974. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  975. package/dist/extensions/pi-zentui/test/pi-version-policy.test.ts +37 -0
  976. package/dist/extensions/pi-zentui/test/project-demand-integration.test.ts +542 -0
  977. package/dist/extensions/pi-zentui/test/project-discovery.test.ts +412 -0
  978. package/dist/extensions/pi-zentui/test/project-refresh.test.ts +44 -0
  979. package/dist/extensions/pi-zentui/test/project-state.test.ts +38 -1
  980. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +7 -7
  981. package/dist/extensions/pi-zentui/test/runtime.test.ts +127 -2
  982. package/dist/extensions/pi-zentui/test/selesai-v030-gate.json +939 -0
  983. package/dist/extensions/pi-zentui/test/settings-command.test.ts +1330 -82
  984. package/dist/extensions/pi-zentui/test/settings-keys.test.ts +41 -0
  985. package/dist/extensions/pi-zentui/test/settings-list-selection.test.ts +88 -0
  986. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +4 -1
  987. package/dist/extensions/pi-zentui/test/state.test.ts +15 -1
  988. package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +214 -12
  989. package/dist/extensions/pi-zentui/test/telemetry-snapshot.test.ts +246 -0
  990. package/dist/extensions/pi-zentui/test/thinking-experimental-cache.test.ts +246 -0
  991. package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +22 -0
  992. package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +113 -51
  993. package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +576 -76
  994. package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +23 -0
  995. package/dist/extensions/pi-zentui/test/token-rate.test.ts +450 -0
  996. package/dist/extensions/pi-zentui/test/turn-summary-format.test.ts +207 -0
  997. package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +72 -5
  998. package/dist/extensions/pi-zentui/test/turn-summary-rate.test.ts +158 -0
  999. package/dist/extensions/pi-zentui/test/usage-lifecycle-integration.test.ts +421 -0
  1000. package/dist/extensions/pi-zentui/test/usage-snapshot.test.ts +154 -0
  1001. package/dist/extensions/pi-zentui/test/user-message-cache.test.ts +239 -0
  1002. package/dist/extensions/pi-zentui/test/user-message-native-reduced-capabilities.test.ts +61 -0
  1003. package/dist/extensions/pi-zentui/test/user-message-native.test.ts +447 -0
  1004. package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +2 -2
  1005. package/dist/extensions/pi-zentui/test/working-line-editor-placement.test.ts +317 -0
  1006. package/dist/extensions/pi-zentui/test/working-line-generation-cache.test.ts +238 -0
  1007. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +674 -179
  1008. package/dist/extensions/pi-zentui/test/working-line-message-ownership.test.ts +239 -0
  1009. package/dist/extensions/pi-zentui/test/working-line-metric-animation.test.ts +284 -0
  1010. package/dist/extensions/pi-zentui/test/working-line-placement.test.ts +298 -0
  1011. package/dist/extensions/pi-zentui/test/working-line.test.ts +386 -18
  1012. package/dist/extensions/pi-zentui/test/wrapped-editor-consumers.integration.test.ts +579 -0
  1013. package/dist/extensions/pi-zentui/test/wrapped-editor-usage.integration.test.ts +298 -0
  1014. package/dist/extensions/pi-zentui/tsconfig.json +1 -1
  1015. package/dist/extensions/pi-zentui/vitest.host.config.ts +33 -0
  1016. package/dist/extensions/question/index.ts +1 -5
  1017. package/dist/extensions/rtk.test.ts +28 -15
  1018. package/dist/extensions/rtk.ts +22 -22
  1019. package/dist/extensions/skills-index/index.test.ts +99 -0
  1020. package/dist/extensions/skills-index/index.ts +105 -0
  1021. package/dist/extensions/skills-index/package.json +9 -0
  1022. package/dist/extensions/tokenin-onboarding.ts +52 -210
  1023. package/dist/extensions/tool-search/index.d.ts +11 -0
  1024. package/dist/extensions/tool-search/index.js +14 -0
  1025. package/dist/extensions/tool-search/tool.d.ts +72 -0
  1026. package/dist/extensions/tool-search/tool.js +188 -0
  1027. package/dist/index.d.ts +21 -9
  1028. package/dist/index.js +17 -5
  1029. package/dist/main.d.ts +10 -0
  1030. package/dist/main.js +107 -43
  1031. package/dist/migrations.js +4 -3
  1032. package/dist/modes/index.d.ts +2 -1
  1033. package/dist/modes/interactive/bug-report.js +4 -0
  1034. package/dist/modes/interactive/components/armin.d.ts +3 -0
  1035. package/dist/modes/interactive/components/armin.js +7 -5
  1036. package/dist/modes/interactive/components/assistant-message.js +1 -1
  1037. package/dist/modes/interactive/components/auth-url.d.ts +13 -0
  1038. package/dist/modes/interactive/components/auth-url.js +36 -0
  1039. package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
  1040. package/dist/modes/interactive/components/bash-execution.js +17 -14
  1041. package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
  1042. package/dist/modes/interactive/components/branch-summary-message.js +5 -2
  1043. package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
  1044. package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
  1045. package/dist/modes/interactive/components/config-selector.js +13 -3
  1046. package/dist/modes/interactive/components/custom-editor.js +7 -0
  1047. package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
  1048. package/dist/modes/interactive/components/custom-entry.js +8 -2
  1049. package/dist/modes/interactive/components/custom-message.js +1 -0
  1050. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  1051. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  1052. package/dist/modes/interactive/components/footer.d.ts +7 -0
  1053. package/dist/modes/interactive/components/footer.js +44 -4
  1054. package/dist/modes/interactive/components/index.d.ts +0 -1
  1055. package/dist/modes/interactive/components/index.js +0 -1
  1056. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  1057. package/dist/modes/interactive/components/login-dialog.js +11 -5
  1058. package/dist/modes/interactive/components/mermaid.d.ts +10 -0
  1059. package/dist/modes/interactive/components/mermaid.js +74 -0
  1060. package/dist/modes/interactive/components/model-selector.d.ts +14 -9
  1061. package/dist/modes/interactive/components/model-selector.js +79 -31
  1062. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  1063. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  1064. package/dist/modes/interactive/components/pi-logo.d.ts +18 -0
  1065. package/dist/modes/interactive/components/pi-logo.js +36 -0
  1066. package/dist/modes/interactive/components/radius-login-selector.d.ts +14 -0
  1067. package/dist/modes/interactive/components/radius-login-selector.js +84 -0
  1068. package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
  1069. package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
  1070. package/dist/modes/interactive/components/settings-selector.d.ts +8 -11
  1071. package/dist/modes/interactive/components/settings-selector.js +60 -102
  1072. package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
  1073. package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
  1074. package/dist/modes/interactive/components/themed-text.d.ts +16 -0
  1075. package/dist/modes/interactive/components/themed-text.js +28 -0
  1076. package/dist/modes/interactive/components/tool-execution.d.ts +11 -18
  1077. package/dist/modes/interactive/components/tool-execution.js +34 -47
  1078. package/dist/modes/interactive/components/tree-selector.js +7 -0
  1079. package/dist/modes/interactive/components/user-message.d.ts +3 -1
  1080. package/dist/modes/interactive/components/user-message.js +14 -6
  1081. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  1082. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  1083. package/dist/modes/interactive/external-editor.js +2 -1
  1084. package/dist/modes/interactive/interactive-mode.d.ts +41 -8
  1085. package/dist/modes/interactive/interactive-mode.js +854 -492
  1086. package/dist/modes/interactive/program-status-reporter.d.ts +33 -0
  1087. package/dist/modes/interactive/program-status-reporter.js +109 -0
  1088. package/dist/modes/interactive/theme/dark.json +59 -72
  1089. package/dist/modes/interactive/theme/light.json +57 -69
  1090. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  1091. package/dist/modes/interactive/theme/system-theme.js +545 -0
  1092. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  1093. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  1094. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  1095. package/dist/modes/interactive/theme/theme-json.js +3 -1
  1096. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  1097. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  1098. package/dist/modes/interactive/theme/theme.js +243 -320
  1099. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  1100. package/dist/modes/interactive/tui-renderer.js +1 -0
  1101. package/dist/modes/json-event.d.ts +33 -0
  1102. package/dist/modes/json-event.js +28 -0
  1103. package/dist/modes/print-mode.js +12 -2
  1104. package/dist/modes/rpc/intercom-bridge.d.ts +14 -0
  1105. package/dist/modes/rpc/intercom-bridge.js +75 -0
  1106. package/dist/modes/rpc/intercom-bridge.test.js +65 -0
  1107. package/dist/modes/rpc/release-bridge.d.ts +35 -0
  1108. package/dist/modes/rpc/release-bridge.js +159 -0
  1109. package/dist/modes/rpc/release-bridge.test.d.ts +1 -0
  1110. package/dist/modes/rpc/release-bridge.test.js +347 -0
  1111. package/dist/modes/rpc/rpc-client.d.ts +43 -27
  1112. package/dist/modes/rpc/rpc-client.js +97 -37
  1113. package/dist/modes/rpc/rpc-intercom-transport.test.d.ts +1 -0
  1114. package/dist/modes/rpc/rpc-intercom-transport.test.js +85 -0
  1115. package/dist/modes/rpc/rpc-mode.d.ts +1 -13
  1116. package/dist/modes/rpc/rpc-mode.js +250 -34
  1117. package/dist/modes/rpc/rpc-release-transport.test.d.ts +1 -0
  1118. package/dist/modes/rpc/rpc-release-transport.test.js +329 -0
  1119. package/dist/modes/rpc/rpc-subagent-transport.test.d.ts +1 -0
  1120. package/dist/modes/rpc/rpc-subagent-transport.test.js +60 -0
  1121. package/dist/modes/rpc/rpc-types.d.ts +22 -23
  1122. package/dist/modes/rpc/rpc-types.js +0 -6
  1123. package/dist/modes/rpc/subagent-bridge.d.ts +23 -0
  1124. package/dist/modes/rpc/subagent-bridge.js +93 -0
  1125. package/dist/modes/rpc/test-fixtures/intercom-host.d.ts +1 -0
  1126. package/dist/modes/rpc/test-fixtures/intercom-host.js +13 -0
  1127. package/dist/package-manager-cli.js +16 -5
  1128. package/dist/rpc-entry.js +1 -0
  1129. package/dist/skills/pi-subagents/SKILL.md +109 -35
  1130. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +38 -238
  1131. package/dist/skills/pi-subagents/references/execution-controls.md +181 -83
  1132. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -9
  1133. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +24 -2
  1134. package/dist/skills/pi-subagents/references/prompting-and-roles.md +121 -91
  1135. package/dist/skills/pi-subagents/references/review-and-validation.md +73 -0
  1136. package/dist/utils/ansi.d.ts +8 -0
  1137. package/dist/utils/ansi.js +30 -11
  1138. package/dist/utils/clipboard-image.js +14 -17
  1139. package/dist/utils/clipboard.d.ts +2 -0
  1140. package/dist/utils/clipboard.js +17 -11
  1141. package/dist/utils/frontmatter.js +2 -1
  1142. package/dist/utils/image-convert.d.ts +12 -0
  1143. package/dist/utils/image-convert.js +45 -6
  1144. package/dist/utils/image-resize-core.d.ts +12 -0
  1145. package/dist/utils/image-resize-core.js +5 -0
  1146. package/dist/utils/image-resize-worker.js +3 -2
  1147. package/dist/utils/image-resize.js +9 -10
  1148. package/dist/utils/mime.js +1 -1
  1149. package/dist/utils/output-files.d.ts +14 -0
  1150. package/dist/utils/output-files.js +29 -0
  1151. package/dist/utils/paths.d.ts +6 -3
  1152. package/dist/utils/paths.js +28 -5
  1153. package/dist/utils/shell.d.ts +1 -3
  1154. package/dist/utils/shell.js +3 -30
  1155. package/dist/utils/syntax-highlight.d.ts +1 -0
  1156. package/dist/utils/syntax-highlight.js +68 -2
  1157. package/dist/utils/tool-result-images.d.ts +20 -0
  1158. package/dist/utils/tool-result-images.js +47 -0
  1159. package/dist/utils/tools-manager.d.ts +5 -0
  1160. package/dist/utils/tools-manager.js +6 -6
  1161. package/dist/utils/version-check.d.ts +4 -0
  1162. package/dist/utils/version-check.js +20 -2
  1163. package/docs/cli-integration.md +104 -0
  1164. package/docs/cli.md +333 -0
  1165. package/docs/codemode.md +230 -0
  1166. package/docs/configuration.md +47 -0
  1167. package/docs/environment-variables.md +5 -0
  1168. package/docs/extensions.md +107 -30
  1169. package/docs/json.md +8 -4
  1170. package/docs/keybindings.md +10 -10
  1171. package/docs/mcp.md +262 -0
  1172. package/docs/models.md +104 -3
  1173. package/docs/providers.md +20 -2
  1174. package/docs/rpc-subagent.schema.json +491 -0
  1175. package/docs/rpc.md +223 -13
  1176. package/docs/sdk.md +41 -33
  1177. package/docs/security.md +21 -20
  1178. package/docs/settings.md +18 -46
  1179. package/docs/terminal-setup.md +14 -0
  1180. package/docs/virtual-models.md +114 -0
  1181. package/examples/extensions/jev-router.ts +113 -0
  1182. package/examples/extensions/tokenin-usage-widget.ts +124 -0
  1183. package/examples/rpc-client.ts +35 -0
  1184. package/examples/sdk/14-codemode-mcp.ts +67 -0
  1185. package/package.json +16 -8
  1186. package/dist/core/agent-session-auto-handoff.test.js +0 -195
  1187. package/dist/core/built-in-extensions.d.ts +0 -2
  1188. package/dist/core/built-in-extensions.js +0 -2
  1189. package/dist/core/llama/provider.js +0 -143
  1190. package/dist/core/settings-manager-auto-handoff.test.js +0 -53
  1191. package/dist/extensions/capability-gateway/catalog.ts +0 -177
  1192. package/dist/extensions/capability-gateway/index.test.ts +0 -226
  1193. package/dist/extensions/capability-gateway/index.ts +0 -669
  1194. package/dist/extensions/capability-gateway/integration.test.ts +0 -803
  1195. package/dist/extensions/capability-gateway/package.json +0 -16
  1196. package/dist/extensions/capability-gateway/routing.test.ts +0 -574
  1197. package/dist/extensions/capability-gateway/routing.ts +0 -403
  1198. package/dist/extensions/pi-subagents/runner-server-preload.mjs +0 -13
  1199. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +0 -89
  1200. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +0 -259
  1201. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +0 -312
  1202. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +0 -374
  1203. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +0 -69
  1204. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +0 -307
  1205. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +0 -211
  1206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +0 -3
  1207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +0 -2
  1208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +0 -17
  1209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +0 -57
  1210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +0 -16
  1211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +0 -15
  1212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +0 -18
  1213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +0 -9
  1214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +0 -10
  1215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +0 -10
  1216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +0 -20
  1217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +0 -3
  1218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +0 -96
  1219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +0 -119
  1220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +0 -85
  1221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +0 -620
  1222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +0 -5
  1223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +0 -56
  1224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +0 -32
  1225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +0 -49
  1226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +0 -93
  1227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +0 -128
  1228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +0 -7
  1229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +0 -38
  1230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +0 -3
  1231. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +0 -15
  1232. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +0 -9
  1233. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +0 -29
  1234. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +0 -2
  1235. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +0 -22
  1236. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +0 -37
  1237. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +0 -34
  1238. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +0 -12
  1239. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +0 -23
  1240. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +0 -171
  1241. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +0 -1261
  1242. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +0 -20
  1243. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +0 -54
  1244. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +0 -22
  1245. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +0 -13
  1246. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +0 -358
  1247. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +0 -77
  1248. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +0 -512
  1249. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +0 -43
  1250. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +0 -121
  1251. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +0 -82
  1252. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +0 -17
  1253. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +0 -7
  1254. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +0 -210
  1255. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +0 -15
  1256. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +0 -54
  1257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +0 -4
  1258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +0 -55
  1259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +0 -2
  1260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +0 -5
  1261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +0 -30
  1262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +0 -206
  1263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +0 -15
  1264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +0 -106
  1265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +0 -19
  1266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +0 -356
  1267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +0 -297
  1268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +0 -60
  1269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +0 -15
  1270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +0 -18
  1271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +0 -28
  1272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +0 -3
  1273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +0 -10
  1274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +0 -68
  1275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +0 -106
  1276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +0 -51
  1277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +0 -6
  1278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +0 -35
  1279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +0 -37
  1280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +0 -40
  1281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +0 -37
  1282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +0 -52
  1283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +0 -10
  1284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +0 -35
  1285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +0 -24
  1286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
  1287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +0 -70
  1288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +0 -26
  1289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +0 -36
  1290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +0 -19
  1291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +0 -61
  1292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +0 -23
  1293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +0 -3
  1294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +0 -10
  1295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +0 -42
  1296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +0 -35
  1297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +0 -12
  1298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +0 -33
  1299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +0 -9
  1300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +0 -34
  1301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +0 -22
  1302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  1303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  1304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  1305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  1306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +0 -102
  1307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  1308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  1309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +0 -19
  1310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +0 -20
  1311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  1312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +0 -12
  1313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  1314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  1315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +0 -22
  1316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +0 -23
  1317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +0 -26
  1318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +0 -25
  1319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +0 -32
  1320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +0 -34
  1321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +0 -13
  1322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +0 -52
  1323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +0 -54
  1324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +0 -33
  1325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
  1326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  1327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +0 -95
  1328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +0 -77
  1329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  1330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  1331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +0 -28
  1332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  1333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  1334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +0 -63
  1335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +0 -94
  1336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +0 -23
  1337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  1338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +0 -14
  1339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
  1340. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +0 -394
  1341. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +0 -12
  1342. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +0 -29
  1343. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +0 -120
  1344. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +0 -28
  1345. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +0 -17
  1346. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +0 -246
  1347. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +0 -20
  1348. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +0 -457
  1349. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +0 -8
  1350. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +0 -3
  1351. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +0 -2
  1352. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +0 -22
  1353. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +0 -18
  1354. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +0 -11
  1355. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +0 -11
  1356. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +0 -4
  1357. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +0 -4
  1358. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +0 -5
  1359. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +0 -8
  1360. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +0 -5
  1361. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +0 -26
  1362. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +0 -7
  1363. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +0 -10
  1364. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +0 -18
  1365. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +0 -30
  1366. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +0 -2
  1367. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +0 -16
  1368. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +0 -3
  1369. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +0 -3
  1370. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +0 -9
  1371. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +0 -31
  1372. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +0 -21
  1373. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +0 -2
  1374. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +0 -31
  1375. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +0 -5
  1376. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +0 -12
  1377. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +0 -3
  1378. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +0 -15
  1379. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +0 -3
  1380. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +0 -31
  1381. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +0 -74
  1382. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +0 -150
  1383. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +0 -766
  1384. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +0 -327
  1385. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +0 -309
  1386. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +0 -1093
  1387. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +0 -94
  1388. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +0 -1329
  1389. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +0 -153
  1390. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +0 -457
  1391. package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +0 -669
  1392. package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +0 -51
  1393. package/dist/modes/interactive/components/daxnuts.d.ts +0 -22
  1394. package/dist/modes/interactive/components/daxnuts.js +0 -139
  1395. /package/dist/core/{agent-session-auto-handoff.test.d.ts → agent-session-custom-tools.test.d.ts} +0 -0
  1396. /package/dist/{core → extensions}/llama/huggingface.d.ts +0 -0
  1397. /package/dist/{core → extensions}/llama/huggingface.js +0 -0
  1398. /package/dist/{core → extensions}/llama/index.d.ts +0 -0
  1399. /package/dist/{core → extensions}/llama/ui.d.ts +0 -0
  1400. /package/dist/{core → extensions}/llama/ui.js +0 -0
  1401. /package/dist/{core/settings-manager-auto-handoff.test.d.ts → modes/rpc/intercom-bridge.test.d.ts} +0 -0
@@ -1,28 +1,10 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { EventEmitter } from "node:events";
3
2
  import * as fs from "node:fs";
4
- import { createRequire } from "node:module";
5
3
  import * as path from "node:path";
4
+ import { performance } from "node:perf_hooks";
6
5
  import { pathToFileURL } from "node:url";
7
6
  import type { Message } from "@earendil-works/pi-ai";
8
- import { arbitrateCompletionGuardRescue, createTaskMutationArbiter } from "../shared/llm-intent-arbiter.ts";
9
-
10
- // Detached runners skip Pi's CLI proxy setup. Keep fetch on the same Undici dispatcher.
11
- function ensureProxyAwareHttpDispatcher(): void {
12
- try {
13
- // SAFETY: require loads the pinned direct dependency described by these types.
14
- const undici = createRequire(import.meta.url)("undici") as typeof import("undici");
15
- const dispatcher = new undici.EnvHttpProxyAgent({ allowH2: false });
16
- // Fetch rejects stream errors; the listener prevents an unhandled EventEmitter error.
17
- EventEmitter.prototype.on.call(dispatcher, "error", () => {});
18
- undici.setGlobalDispatcher(dispatcher);
19
- undici.install();
20
- } catch (error) {
21
- console.error(`[pi-subagents] proxy-aware HTTP dispatcher not installed: ${error instanceof Error ? error.message : String(error)}`);
22
- }
23
- }
24
- const isRunnerEntrypoint = Boolean(process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href);
25
- if (isRunnerEntrypoint) ensureProxyAwareHttpDispatcher();
7
+ import { installRunnerHttpDispatcher } from "./runner-http-dispatcher.ts";
26
8
  import { writeAtomicJson } from "../../shared/atomic-json.ts";
27
9
  import { writeAsyncResultFile, writePendingAsyncResultFile } from "./result-files.ts";
28
10
  import { createFileCoalescer } from "../../shared/file-coalescer.ts";
@@ -30,11 +12,12 @@ import { createCapacityResilientJsonWriter } from "../../shared/capacity-resilie
30
12
  import { isStorageCapacityError } from "../../shared/file-system-retry.ts";
31
13
  import { updateActiveRunIndex } from "./active-run-index.ts";
32
14
  import { createChildTranscriptWriter, type ChildTranscriptWriter } from "../../shared/child-transcript.ts";
33
- import { closeSteerInbox, consumeInterruptRequest, consumeSteerRequests, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, watchAsyncControlInbox, type SteerRequest, type StopRequest } from "./control-channel.ts";
15
+ import { closeSteerInbox, closeStopInbox, consumeInterruptRequest, consumeSteerRequests, consumeStopRequestPayloads, deliverInterruptRequest, deliverStopRequest, deliverTimeoutRequest, watchAsyncControlInbox, type SteerRequest, type StopRequest } from "./control-channel.ts";
34
16
  import { appendJsonl as appendRawJsonl, formatOutputArtifactContent, getArtifactPaths, writeArtifact, writeMetadata } from "../../shared/artifacts.ts";
35
17
  import { SELESAI_CODING_AGENT_PACKAGE, resolveInstalledPiPackageRoot } from "../shared/pi-spawn.ts";
36
18
  import { preflightLaunchCwd } from "../shared/launch-cwd.ts";
37
19
  import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, injectSingleOutputInstruction, resolveSingleOutput, type SingleOutputSnapshot } from "../shared/single-output.ts";
20
+ import { runSetupCommand } from "../shared/worktree-setup-command.ts";
38
21
  import {
39
22
  type ActivityState,
40
23
  type ArtifactConfig,
@@ -49,7 +32,6 @@ import {
49
32
  type CostSummary,
50
33
  type LaunchResolvedChildExtensions,
51
34
  type RuntimeAcknowledgedChildExtensions,
52
- type ModelAttempt,
53
35
  type PiWriterProcessInstanceExit,
54
36
  type NestedRouteInfo,
55
37
  type NestedRunSummary,
@@ -66,6 +48,7 @@ import {
66
48
  type SteeringTargetStatus,
67
49
  type SubagentChildStatusEvent,
68
50
  type WorkflowLaneMetadata,
51
+ type HerdrMachineReference,
69
52
  DEFAULT_MAX_OUTPUT,
70
53
  type MaxOutputConfig,
71
54
  SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
@@ -79,6 +62,7 @@ import {
79
62
  formatControlIntercomMessage,
80
63
  formatControlNoticeMessage,
81
64
  shouldEmitOpenToolAttention,
65
+ forgetControlNotifications,
82
66
  } from "../shared/subagent-control.ts";
83
67
  import {
84
68
  type RunnerSubagentStep as SubagentStep,
@@ -96,10 +80,8 @@ import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLau
96
80
  import type { InheritedChildRuntime } from "../shared/child-launch.ts";
97
81
  import { buildRunnerChildLaunch } from "./runner-child-launch.ts";
98
82
  import { normalizeExtensionBindings } from "../shared/extension-bindings.ts";
99
- import type { ChildSessionFactory } from "../shared/child-session.ts";
100
- import { getSettledReadonlyChild, runChildSession, type ChildEvent, type RunChildSessionInput, type RunChildSessionResult, type StepSteerHandler } from "./run-child-session.ts";
101
- import { planReadonlyModelContinuation, READONLY_CONTINUATION_PROMPT, type LogicalRecoveryState } from "../shared/readonly-model-continuation.ts";
102
- import { getReadonlySessionEvidence } from "../shared/readonly-session-evidence.ts";
83
+ import type { ChildSessionFactory, DefaultChildSessionFactoryOptions } from "../shared/child-session.ts";
84
+ import { runChildSession, type ChildEvent, type RunChildSessionInput, type RunChildSessionResult, type SteerDelivery, type StepSteerHandler } from "./run-child-session.ts";
103
85
  import { loadRunnerChildSessionFactory } from "./runner-child-sessions.ts";
104
86
  import { SUBAGENT_CHILD_ENV } from "../shared/child-runtime-config.ts";
105
87
  import { deriveChildSessionName } from "../../shared/child-session-name.ts";
@@ -112,12 +94,13 @@ import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTr
112
94
  import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
113
95
  import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.ts";
114
96
  import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
115
- import { formatModelAttemptNote, formatSubagentModelVerificationError, isContextOverflow, isRetryableModelFailureAttempt, recordRetryableModelFailure } from "../shared/model-fallback.ts";
116
- import { markProcessTerminalCandidateLeaseRelease, processTerminalPath, writeProcessTerminalCandidate, type ProcessTerminalCandidate } from "./process-terminal.ts";
117
- import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.ts";
118
- import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.ts";
119
- import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.ts";
120
- import { planCompletionEvidence, projectSettlementDiagnostic } from "../shared/completion-evidence.ts";
97
+ import { formatSubagentModelVerificationError, isContextOverflow } from "../shared/model-resolution.ts";
98
+ import { processTerminalPath, writeProcessTerminalCandidate, type ProcessTerminalCandidate } from "./process-terminal.ts";
99
+ import { persistRunnerStartupFailure } from "./runner-startup-failure.ts";
100
+ import { currentPidNamespaceScope } from "./pid-namespace.ts";
101
+ import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, unconsumedSteerReason, updateSteeringTarget } from "./steering.ts";
102
+ import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getAgentDir, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.ts";
103
+ import { planBackgroundRunHistory, recordRun } from "../shared/run-history.ts";
121
104
  import { planAbortRecovery } from "../shared/abort-recovery.ts";
122
105
  import {
123
106
  createMutatingFailureState,
@@ -147,10 +130,10 @@ import {
147
130
  } from "../shared/worktree.ts";
148
131
  import { findModelInfo, resolveEffectiveThinking, splitKnownThinkingSuffix } from "../../shared/model-info.ts";
149
132
  import { assertThinkingWithinCeiling } from "../../shared/thinking-ceiling.ts";
150
- import { launchBindingDigest } from "../../shared/launch-contract.ts";
133
+ import { resolveLaunchBinding } from "../../shared/launch-contract.ts";
151
134
  import { writeInitialProgressFile } from "../../shared/settings.ts";
152
135
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
153
- import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveAcceptanceReportMode, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.ts";
136
+ import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, captureStagedIndexBaseline, evaluateAcceptance, formatAcceptancePrompt, resolveAcceptanceReportMode, resolveEffectiveAcceptance, stripAcceptanceReport, typedVerifyOutput } from "../shared/acceptance.ts";
154
137
  import { attachContractProjections, isAgentContract } from "../shared/agent-contract.ts";
155
138
  import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
156
139
  import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
@@ -160,9 +143,14 @@ import { effectiveToolTimeoutMs, formatToolTimeoutMessage, toolTimeoutCallKey }
160
143
  import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
161
144
  import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.ts";
162
145
  import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
163
- import { acquireSessionLease, type SessionLeaseRequest } from "../shared/session-lease.ts";
146
+ import type { SessionLeaseRequest } from "../shared/session-lease.ts";
164
147
  import { buildExternalCliPrompt, runExternalCli } from "../shared/external-cli-runner.ts";
148
+ import { resolveClaudeCodeLaunch } from "../shared/claude-code-adapter.ts";
149
+ import { resolveCodexExecLaunch } from "../shared/codex-exec-adapter.ts";
150
+ import { resolveCursorAgentLaunch } from "../shared/cursor-agent-adapter.ts";
165
151
  import { resolveExternalCliRunnerStatus } from "../shared/external-cli-contract.ts";
152
+ import { formatHerdrMachineHint, prepareHerdrMachineExternalCliRun } from "../shared/herdr-machine.ts";
153
+ import { HerdrExternalNeedsAttentionError, createHerdrExternalAdapter, prepareInternalHerdrExternalAdapter, type HerdrExternalAdapterId, type HerdrExternalResult } from "../shared/herdr-external-adapters.ts";
166
154
  import { runExternalJob } from "../shared/external-job-runner.ts";
167
155
  import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-progress-tabs.ts";
168
156
  import type { ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
@@ -181,7 +169,7 @@ const INTERCOM_DETACH_RECEIPT = "Detached for intercom coordination before task
181
169
  // child host.
182
170
  process.env[SUBAGENT_CHILD_ENV] = "1";
183
171
 
184
- interface SubagentRunConfig {
172
+ export interface SubagentRunConfig {
185
173
  id: string;
186
174
  steps: RunnerStep[];
187
175
  resultPath: string;
@@ -202,6 +190,8 @@ interface SubagentRunConfig {
202
190
  childSessionFactoryModule?: string;
203
191
  /** The launching executor's own child runtime when it was itself an in-process child. */
204
192
  inheritedChildRuntime?: InheritedChildRuntime;
193
+ /** The launching session's project trust; undefined keeps Pi's default for hosts without trust. */
194
+ projectTrusted?: boolean;
205
195
  worktreeSetupHook?: string;
206
196
  worktreeSetupHookTimeoutMs?: number;
207
197
  worktreeBaseDir?: string;
@@ -221,6 +211,8 @@ interface SubagentRunConfig {
221
211
  deadlineAt?: number;
222
212
  /** Resolved configured hard per-tool-call timeout (ms); fast tools still have a default when undefined. */
223
213
  toolTimeoutMs?: number;
214
+ /** Steer the running steps to checkpoint and stop this many ms before `deadlineAt`; absent = no checkpoint steer. */
215
+ checkpointBeforeDeadlineMs?: number;
224
216
  toolBudget?: ResolvedToolBudget;
225
217
  usageBudget?: UsageBudgetConfig;
226
218
  revivalLease?: SessionLeaseRequest;
@@ -229,6 +221,7 @@ interface SubagentRunConfig {
229
221
  globalConcurrencyLimit?: number;
230
222
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
231
223
  runFanoutBudget?: RunFanoutBudgetDescriptor;
224
+ /** Builtin tool names the host runtime provides; used to intersect agent-declared tools. */
232
225
  launchContractDigest?: string;
233
226
  launchResolvedExtensions?: LaunchResolvedChildExtensions;
234
227
  runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
@@ -250,6 +243,7 @@ interface StepResult {
250
243
  runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
251
244
  output: string;
252
245
  outputState?: SubagentOutputState;
246
+ outputPartial?: boolean;
253
247
  error?: string;
254
248
  success?: boolean;
255
249
  exitCode: number | null;
@@ -267,14 +261,15 @@ interface StepResult {
267
261
  sessionFile?: string;
268
262
  intercomTarget?: string;
269
263
  model?: string;
264
+ nativeMachine?: import("../../shared/types.ts").SingleResult["nativeMachine"];
270
265
  thinking?: string;
271
- attemptedModels?: string[];
272
- modelAttempts?: ModelAttempt[];
266
+ requestedModel?: string;
273
267
  /** True when the dispatch failed because the input exceeded the model's context window. */
274
268
  contextOverflow?: boolean;
275
269
  totalCost?: CostSummary;
276
270
  artifactPaths?: ArtifactPaths;
277
271
  outputSaveError?: string;
272
+ artifactOutputSaveFailed?: true;
278
273
  metadataSaveError?: string;
279
274
  truncated?: boolean;
280
275
  transcriptPath?: string;
@@ -418,50 +413,22 @@ function emptyUsage(): Usage {
418
413
  return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
419
414
  }
420
415
 
421
- function tokenUsageFromAttempts(attempts: ModelAttempt[] | undefined): TokenUsage | null {
422
- if (!attempts || attempts.length === 0) return null;
423
- let input = 0;
424
- let output = 0;
425
- for (const attempt of attempts) {
426
- input += attempt.usage?.input ?? 0;
427
- output += attempt.usage?.output ?? 0;
428
- }
416
+ function tokenUsageFromUsage(usage: Usage | undefined): TokenUsage | null {
417
+ const input = usage?.input ?? 0;
418
+ const output = usage?.output ?? 0;
429
419
  const total = input + output;
430
420
  return total > 0 ? { input, output, total } : null;
431
421
  }
432
422
 
433
- function costSummaryFromAttempts(attempts: ModelAttempt[] | undefined): CostSummary | undefined {
434
- if (!attempts || attempts.length === 0) return undefined;
435
- let inputTokens = 0;
436
- let outputTokens = 0;
437
- let costUsd = 0;
438
- for (const attempt of attempts) {
439
- inputTokens += attempt.usage?.input ?? 0;
440
- outputTokens += attempt.usage?.output ?? 0;
441
- costUsd += attempt.usage?.cost ?? 0;
442
- }
423
+ function costSummaryFromUsage(usage: Usage | undefined): CostSummary | undefined {
424
+ const inputTokens = usage?.input ?? 0;
425
+ const outputTokens = usage?.output ?? 0;
426
+ const costUsd = usage?.cost ?? 0;
443
427
  return inputTokens > 0 || outputTokens > 0 || costUsd > 0
444
428
  ? { inputTokens, outputTokens, costUsd }
445
429
  : undefined;
446
430
  }
447
431
 
448
- function usageFromAttempts(attempts: ModelAttempt[] | undefined): Usage | undefined {
449
- if (!attempts || attempts.length === 0) return undefined;
450
- const usage = emptyUsage();
451
- for (const attempt of attempts) {
452
- if (!attempt.usage) continue;
453
- usage.input += attempt.usage.input;
454
- usage.output += attempt.usage.output;
455
- usage.cacheRead += attempt.usage.cacheRead;
456
- usage.cacheWrite += attempt.usage.cacheWrite;
457
- usage.cost += attempt.usage.cost;
458
- usage.turns += attempt.usage.turns;
459
- }
460
- return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0
461
- ? usage
462
- : undefined;
463
- }
464
-
465
432
  function appendRecentStepOutput(step: RunnerStatusStep, lines: string[]): void {
466
433
  const nonEmpty = lines.filter((line) => line.trim());
467
434
  if (nonEmpty.length === 0) return;
@@ -655,6 +622,38 @@ function writeRunLog(
655
622
  write(logPath, lines.join("\n"));
656
623
  }
657
624
 
625
+ function expectedMissingGitEvidence(error: unknown): boolean {
626
+ if (typeof (error as { code?: unknown })?.code !== "number") return false;
627
+ const stderr = (error as { stderr?: unknown }).stderr;
628
+ const detail = Buffer.isBuffer(stderr) ? stderr.toString("utf-8") : String(stderr ?? "");
629
+ return /not a git repository|Needed a single revision/i.test(detail);
630
+ }
631
+
632
+ async function readGitFingerprint(cwd: string, signal: AbortSignal, onError: (error: unknown) => void): Promise<string | undefined> {
633
+ try {
634
+ const runGit = async (args: string[]) => {
635
+ const result = await runSetupCommand("git", args, {
636
+ cwd, signal, maxBuffer: 16 * 1024 * 1024, deadlineAt: Date.now() + 30_000,
637
+ acceptedExitCodes: Array.from({ length: 256 }, (_, code) => code),
638
+ });
639
+ if (result.error) throw result.error;
640
+ if (result.status !== 0) {
641
+ throw Object.assign(new Error(result.stderr || `git exited with ${result.status}`), { code: result.status, stderr: result.stderr });
642
+ }
643
+ return result.stdoutBuffer;
644
+ };
645
+ const headOutput = await runGit(["rev-parse", "--verify", "HEAD"]);
646
+ const head = headOutput.toString("utf-8").trim();
647
+ if (!head) return undefined;
648
+ const status = await runGit(["status", "--porcelain=v1", "-z", "--untracked-files=normal"]);
649
+ return `${head}\0${status.toString("base64")}`;
650
+ } catch (error) {
651
+ if ((error as NodeJS.ErrnoException)?.code === "PROCESS_TREE_UNVERIFIED") throw error;
652
+ if (!signal.aborted && !expectedMissingGitEvidence(error)) onError(error);
653
+ return undefined;
654
+ }
655
+ }
656
+
658
657
  /** Context for running a single step */
659
658
  interface SingleStepContext {
660
659
  previousOutput: string;
@@ -675,11 +674,14 @@ interface SingleStepContext {
675
674
  childSessions: ChildSessionFactory;
676
675
  /** The launching executor's own child runtime; nested route, depth, and ceilings come from here. */
677
676
  inheritedChildRuntime?: InheritedChildRuntime;
677
+ projectTrusted?: boolean;
678
678
  registerInterrupt?: (interrupt: (() => void) | undefined) => void;
679
679
  registerTimeout?: (interrupt: (() => void) | undefined) => void;
680
680
  registerStop?: (stop: (() => void) | undefined) => void;
681
681
  /** Receives the live child's steer handler while its session runs. */
682
682
  registerSteer?: (steer: StepSteerHandler | undefined) => void;
683
+ /** Reports a live child's later steer consumption or unconsumed settlement. */
684
+ onSteerOutcome?: (request: SteerRequest, delivery: SteerDelivery) => void;
683
685
  timeoutSignal?: AbortSignal;
684
686
  stopSignal?: AbortSignal;
685
687
  timeoutMessage?: string;
@@ -696,22 +698,41 @@ interface SingleStepContext {
696
698
  onAttemptStart?: (attempt: { model?: string; thinking?: string; contextLimit?: number }) => void;
697
699
  onChildEvent?: (event: ChildEvent) => void;
698
700
  onExternalProcess?: (process: ExternalProcessStatus) => void;
701
+ prepareExternalActivity?: (cwd: string, signal: AbortSignal) => Promise<void>;
702
+ onExternalStreamActivity?: () => void;
699
703
  onExternalJob?: (status: ExternalJobStatus) => void;
700
704
  skipAcceptance?: () => boolean;
701
705
  /** Authoritative owner decision after event delivery; undefined includes incomplete run-wide usage. */
702
706
  usageBudgetExhausted?: () => boolean | undefined;
703
707
  /** Existing run-owned budget configuration; cost allowance is not settled by the live token ledger. */
704
708
  usageBudget?: UsageBudgetConfig;
705
- /** False when sibling work in the same Git worktree could have caused the tracked diff. */
706
- trackedMutationEvidenceForCompletionGuard?: boolean;
707
709
  orcaProgressTab?: OrcaProgressTab;
708
710
  }
709
711
 
710
- /** Run a single pi agent step, returning output and metadata */
712
+ /** Machine runs: a one-line hint for predictable remote failures, and a note that writer changes live on the machine. */
713
+ function decorateHerdrMachineResult<T extends { output: string; exitCode: number | null; error?: string; externalProcess: { stderrPath: string } }>(result: T, machine: HerdrMachineReference, adapter: string | undefined): T {
714
+ let stderrTail = "";
715
+ try {
716
+ const stderr = fs.readFileSync(result.externalProcess.stderrPath, "utf-8");
717
+ stderrTail = stderr.slice(-4096);
718
+ } catch { /* stderr log is best-effort evidence. */ }
719
+ const hint = result.exitCode === 0 ? undefined : formatHerdrMachineHint(machine, `${result.error ?? ""}\n${stderrTail}\nexit code ${result.exitCode}`);
720
+ const error = hint ? `${result.error ?? `Remote command exited with code ${result.exitCode}.`}\n${hint}` : result.error;
721
+ const note = result.exitCode === 0 && adapter?.endsWith("-writer") ? `Changes made by this run live on ${machine.label ?? machine.id} at ${machine.cwd}; the local checkout is unchanged.` : undefined;
722
+ const output = note ? (result.output.trim() ? `${result.output.trimEnd()}\n\n${note}` : note) : result.output;
723
+ return { ...result, output, ...(error !== undefined ? { error } : {}) };
724
+ }
725
+
726
+ export async function settleHerdrExternalRunnerError(error: unknown, adapter: HerdrExternalAdapterId, evidence: Parameters<ReturnType<typeof createHerdrExternalAdapter>["normalize"]>[0], retain: () => Promise<void>): Promise<HerdrExternalResult> {
727
+ await retain();
728
+ if (!(error instanceof HerdrExternalNeedsAttentionError)) throw error;
729
+ return createHerdrExternalAdapter(adapter).normalize(evidence, error.message);
730
+ }
731
+
711
732
  export async function runSingleStepInner(
712
733
  step: SubagentStep,
713
734
  ctx: SingleStepContext,
714
- ): Promise<StepResult & { completionGuardTriggered?: boolean }> {
735
+ ): Promise<StepResult> {
715
736
  if (step.importAsyncRoot) {
716
737
  let importTimedOut = false;
717
738
  let importStopped = false;
@@ -766,8 +787,7 @@ export async function runSingleStepInner(
766
787
  sessionFile: imported.sessionFile,
767
788
  intercomTarget: imported.intercomTarget,
768
789
  model: imported.model,
769
- attemptedModels: imported.attemptedModels,
770
- modelAttempts: imported.modelAttempts,
790
+ requestedModel: imported.requestedModel,
771
791
  contextOverflow: imported.contextOverflow,
772
792
  totalCost: imported.totalCost,
773
793
  usage: imported.usage,
@@ -790,7 +810,6 @@ export async function runSingleStepInner(
790
810
  const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
791
811
  let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
792
812
  if (ctx.outputs) task = resolveOutputReferences(task, ctx.outputs);
793
- const taskForCompletionGuard = task;
794
813
  let resolvedTaskToolPlan: ReturnType<typeof resolvePiLaunchToolPlan> | undefined;
795
814
  if (!step.runner) {
796
815
  resolvedTaskToolPlan = resolvePiLaunchToolPlan(omitUndefinedProperties({
@@ -801,37 +820,16 @@ export async function runSingleStepInner(
801
820
  subagentOnlyExtensions: step.subagentOnlyExtensions,
802
821
  fast: step.fast,
803
822
  model: step.model,
804
- modelCandidates: step.modelCandidates,
805
823
  mcpDirectTools: step.mcpDirectTools,
824
+ builtinMcpTools: step.builtinMcpTools,
806
825
  cwd: step.cwd ?? ctx.cwd,
807
826
  requireReadTool: Boolean(step.skills?.length),
808
827
  structuredOutput: Boolean(effectiveStructuredOutput),
809
828
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
810
829
  inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
830
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
811
831
  permissionRules: step.permissionRules,
812
832
  }));
813
- const contractTools = resolvedTaskToolPlan.explicitToolAllowlist ? resolvedTaskToolPlan.effectiveToolAllowlist : undefined;
814
- const contractError = validateImplementationToolContract({
815
- agent: step.agent,
816
- task: taskForCompletionGuard,
817
- tools: contractTools,
818
- mcpDirectTools: resolvedTaskToolPlan.effectiveMcpTools,
819
- configuredExtensions: resolvedTaskToolPlan.configuredExtensions,
820
- requestedTools: resolvedTaskToolPlan.requestedBuiltinTools,
821
- acceptanceRole: step.acceptanceRole,
822
- completionGuard: step.completionGuard,
823
- });
824
- if (contractError) {
825
- return omitUndefinedProperties({
826
- agent: step.agent,
827
- context: step.context,
828
- output: contractError,
829
- error: contractError,
830
- exitCode: 1,
831
- capabilityCeiling: resolvedTaskToolPlan.capabilityCeiling,
832
- capabilityAudit: resolvedTaskToolPlan.capabilityAudit,
833
- });
834
- }
835
833
  }
836
834
  // Derive from the pre-acceptance task so internal acceptance/recovery
837
835
  // instructions never leak into the display name.
@@ -866,24 +864,91 @@ export async function runSingleStepInner(
866
864
  transcriptWriter?.writeInitialUserMessage(`${PROMPT_REDACTED}; live Prompt Audit only.`);
867
865
 
868
866
  if (step.runner?.type === "external-cli") {
869
- const externalCwd = step.cwd ?? ctx.cwd;
870
- const runner = resolveExternalCliRunnerStatus({ ...step.runner });
867
+ const externalCwd = step.machine?.cwd ?? step.cwd ?? ctx.cwd;
868
+ const externalAbortSignal = combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]);
869
+ if (!step.machine && externalAbortSignal) await ctx.prepareExternalActivity?.(externalCwd, externalAbortSignal);
870
+ if (externalAbortSignal?.aborted) {
871
+ const stopped = ctx.stopSignal?.aborted === true;
872
+ const message = stopped ? ctx.stopMessage ?? "Subagent stopped by user." : ctx.timeoutMessage ?? "Subagent timed out.";
873
+ return omitUndefinedProperties({ agent: step.agent, context: step.context, output: message, error: message, exitCode: 1, stopped: stopped || undefined, timedOut: stopped ? undefined : true });
874
+ }
875
+ if (step.machine) {
876
+ const runner = resolveExternalCliRunnerStatus({ ...step.runner, machine: step.machine });
877
+ const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
878
+ const placedRunId = `${ctx.id}-${ctx.flatIndex}`;
879
+ const session = await prepareInternalHerdrExternalAdapter({ adapter: step.runner.adapter as HerdrExternalAdapterId, machine: step.machine, runId: placedRunId }, {});
880
+ let timedOut = false, stopped = false, retain = false;
881
+ const evidenceInput = { runId: placedRunId, requestId: `prompt-${ctx.flatIndex}`, task: buildExternalCliPrompt(step.systemPrompt ?? "", task), cwd: externalCwd, nativeSessionId: session.launch.nativeSessionId };
882
+ let resolveInterruption!: (value: "timeout" | "stop") => void, rejectInterruption!: (error: unknown) => void;
883
+ const interruption = new Promise<"timeout" | "stop">((resolve, reject) => { resolveInterruption = resolve; rejectInterruption = reject; });
884
+ ctx.registerTimeout?.(() => { timedOut = true; retain = true; resolveInterruption("timeout"); });
885
+ ctx.registerStop?.(() => { stopped = true; void session.abort().then(() => resolveInterruption("stop"), rejectInterruption); });
886
+ try {
887
+ let settled: HerdrExternalResult;
888
+ try {
889
+ const raced = await Promise.race([session.promptAndSettle(evidenceInput).then((value) => ({ kind: "settled" as const, value })), interruption.then((kind) => ({ kind }))]);
890
+ if (raced.kind === "settled") settled = raced.value;
891
+ else if (raced.kind === "timeout") settled = createHerdrExternalAdapter(step.runner.adapter as HerdrExternalAdapterId).normalize(evidenceInput, "Placed external run timed out; truthful pane retained for inspection.");
892
+ else return { agent: step.agent, context: step.context, output: "Placed external run stopped by user.", outputState: "present", exitCode: 1, stopped: true, runner, execution: { status: "stopped", success: false, exitCode: 1, stopped: true } };
893
+ } catch (error) {
894
+ retain = true;
895
+ settled = await settleHerdrExternalRunnerError(error, step.runner.adapter as HerdrExternalAdapterId, evidenceInput, () => session.retain());
896
+ }
897
+ const output = settled.output;
898
+ try { fs.writeFileSync(ctx.outputFile, output, "utf-8"); } catch { /* Observability output is best-effort. */ }
899
+ const resolvedOutput = step.outputPath ? resolveSingleOutput(step.outputPath, output, outputSnapshot, step.outputClaimPath) : { fullOutput: output };
900
+ const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, resolvedOutput.fullOutput) : undefined;
901
+ const finalizedOutput = finalizeSingleOutput(omitUndefinedProperties({ fullOutput: resolvedOutput.fullOutput, outputPath: step.outputPath, outputMode: step.outputMode, exitCode: 1, preserveSavedOutput: true, savedPath: resolvedOutput.savedPath, outputReference, saveError: resolvedOutput.saveError }));
902
+ const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false ? persistStepArtifacts({ artifactPaths, artifactConfig: ctx.artifactConfig, output: formatOutputArtifactContent(omitUndefinedProperties({ output: resolvedOutput.fullOutput, metadataPath: ctx.artifactConfig?.includeMetadata === false ? undefined : artifactPaths.metadataPath })), metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, placement: session.owner.identity, settlement: settled.settlement, outcome: settled.outcome, timestamp: Date.now() } }) : {};
903
+ return omitUndefinedProperties({ agent: step.agent, ...(childSessionName ? { sessionName: childSessionName } : {}), context: step.context, output: finalizedOutput.displayOutput, outputState: output.trim() ? "present" : "absent", exitCode: 1, error: resolvedOutput.fatalError ? resolvedOutput.saveError : undefined, timedOut, stopped, artifactPaths, outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined, metadataSaveError: artifactErrors.metadataSaveError, runner, execution: { status: "partial", success: false, exitCode: 1 } });
904
+ } catch (error) {
905
+ // Any post-allocation uncertainty retains the pane; only explicit stop
906
+ // and successful exact settlement are destructive.
907
+ retain = true;
908
+ throw error;
909
+ } finally {
910
+ ctx.registerTimeout?.(undefined); ctx.registerStop?.(undefined);
911
+ if (retain) await session.retain(); else await session.dispose();
912
+ }
913
+ }
914
+ const adapterLaunch = step.runner.adapter === "codex-exec" || step.runner.adapter === "codex-exec-writer"
915
+ ? resolveCodexExecLaunch({ adapter: step.runner.adapter, command: step.runner.command, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
916
+ : step.runner.adapter === "claude-code" || step.runner.adapter === "claude-code-writer"
917
+ ? resolveClaudeCodeLaunch({ adapter: step.runner.adapter, command: step.runner.command, overrideArgs: step.claudeCodeOverrideArgs })
918
+ : step.runner.adapter === "cursor-agent" || step.runner.adapter === "cursor-agent-writer"
919
+ ? resolveCursorAgentLaunch({ adapter: step.runner.adapter, command: step.runner.command, cwd: externalCwd, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
920
+ : undefined;
921
+ const runner = resolveExternalCliRunnerStatus({ ...step.runner, ...(adapterLaunch ? { args: adapterLaunch.args } : {}), ...(step.machine ? { machine: step.machine } : {}) });
871
922
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
872
- const external = await runExternalCli(omitUndefinedProperties({
873
- command: runner.command,
874
- args: runner.args,
923
+ const onExternalOutput = (chunk: Buffer): void => {
924
+ if (chunk.length > 0) ctx.onExternalStreamActivity?.();
925
+ ctx.orcaProgressTab?.append(chunk.toString("utf-8"));
926
+ };
927
+ const externalInput = omitUndefinedProperties({
928
+ command: adapterLaunch?.command ?? runner.command,
929
+ args: adapterLaunch?.args ?? runner.args,
875
930
  cwd: externalCwd,
876
931
  prompt: buildExternalCliPrompt(step.systemPrompt ?? "", task),
877
932
  asyncDir: path.dirname(ctx.outputFile),
878
933
  stepIndex: ctx.flatIndex,
934
+ environment: adapterLaunch?.environment,
935
+ preflight: adapterLaunch?.preflight,
936
+ parser: adapterLaunch?.parser,
937
+ finalOutputPath: adapterLaunch?.finalOutputPath,
938
+ promptFilePath: adapterLaunch?.promptFilePath,
939
+ temporaryDirectories: adapterLaunch?.temporaryDirectories,
879
940
  registerTimeout: ctx.registerTimeout,
880
941
  registerStop: ctx.registerStop,
881
942
  timeoutMessage: ctx.timeoutMessage,
882
943
  stopMessage: ctx.stopMessage,
883
944
  onProcess: ctx.onExternalProcess,
884
- onStdout: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8")),
885
- onStderr: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8")),
886
- }));
945
+ onStdout: onExternalOutput,
946
+ onStderr: onExternalOutput,
947
+ });
948
+ const preparedExternal = prepareHerdrMachineExternalCliRun(externalInput, step.machine ? { machine: step.machine, ...(step.machineEnv ? { env: step.machineEnv } : {}) } : undefined, { localCwd: ctx.cwd });
949
+ const ran = await runExternalCli(preparedExternal.input);
950
+ const externalProcess = preparedExternal.decorateProcess(ran.externalProcess);
951
+ const external = step.machine ? decorateHerdrMachineResult(ran, step.machine, step.runner.adapter) : ran;
887
952
  try { fs.writeFileSync(ctx.outputFile, external.output, "utf-8"); } catch { /* Observability output is best-effort. */ }
888
953
  const resolvedOutput = step.outputPath && external.exitCode === 0
889
954
  ? resolveSingleOutput(step.outputPath, external.output, outputSnapshot, step.outputClaimPath)
@@ -907,7 +972,7 @@ export async function runSingleStepInner(
907
972
  artifactPaths,
908
973
  artifactConfig: ctx.artifactConfig,
909
974
  output: formatOutputArtifactContent(omitUndefinedProperties({ output: resolvedOutput.fullOutput, error: external.error, metadataPath: ctx.artifactConfig?.includeMetadata === false ? undefined : artifactPaths.metadataPath })),
910
- metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, externalProcess: external.externalProcess, exitCode: external.exitCode, error: external.error, timestamp: Date.now() },
975
+ metadata: { runId: ctx.id, agent: step.agent, task: PROMPT_REDACTED, runner, externalProcess: externalProcess, exitCode: external.exitCode, error: external.error, timestamp: Date.now() },
911
976
  })
912
977
  : {};
913
978
  return omitUndefinedProperties({
@@ -923,9 +988,10 @@ export async function runSingleStepInner(
923
988
  processSignal: external.processSignal,
924
989
  artifactPaths,
925
990
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
991
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
926
992
  metadataSaveError: artifactErrors.metadataSaveError,
927
993
  runner,
928
- externalProcess: external.externalProcess,
994
+ externalProcess: externalProcess,
929
995
  });
930
996
  }
931
997
 
@@ -992,6 +1058,7 @@ export async function runSingleStepInner(
992
1058
  stopped: external.stopped,
993
1059
  artifactPaths,
994
1060
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
1061
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
995
1062
  metadataSaveError: artifactErrors.metadataSaveError,
996
1063
  runner,
997
1064
  externalJob: external.externalJob,
@@ -1005,73 +1072,39 @@ export async function runSingleStepInner(
1005
1072
  alignForkedSessionCwd(step.sessionFile, effectiveCwd);
1006
1073
  }
1007
1074
 
1008
- const candidates = step.modelCandidates !== undefined
1009
- ? step.modelCandidates.length > 0 ? step.modelCandidates : [undefined]
1010
- : step.model
1011
- ? [step.model]
1012
- : [undefined];
1013
- const attemptedModels: string[] = [];
1075
+ const candidate = step.model;
1014
1076
  let capabilityAudit: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit | undefined;
1015
1077
  let launchResolvedExtensions = step.launchResolvedExtensions;
1016
- const modelAttempts: ModelAttempt[] = [];
1017
- const attemptNotes: string[] = [];
1018
- const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
1019
1078
  let finalRequiredOutputMissing: boolean | undefined;
1079
+ const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
1020
1080
  let finalResult: RunChildSessionResult | undefined;
1021
1081
  let finalOutputSnapshot: SingleOutputSnapshot | undefined;
1022
1082
  let structuredAcceptanceReport: unknown;
1023
1083
  let structuredAcceptanceReportError: string | undefined;
1024
- let completionGuardTriggeredFinal = false;
1025
1084
  let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
1026
1085
  let toolBudgetBlocked = false;
1027
1086
  let actualLaunchContractDigest = step.launchContractDigest;
1028
- const mutationSnapshot = snapshotTrackedMutations(step.cwd ?? ctx.cwd);
1087
+ const mutationSnapshot = step.machine ? { source: "tracked-files" as const, trackedOnly: true as const, cwd: step.cwd ?? ctx.cwd, dirtyFiles: [], fingerprints: {}, unavailable: "Local Git evidence is not authoritative for a pane-native remote run." } : snapshotTrackedMutations(step.cwd ?? ctx.cwd);
1029
1088
  let finalMutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1030
1089
 
1031
- let modelIndex = 0;
1032
1090
  let contextOverflow = false;
1033
1091
  let launchWarningsEmitted = false;
1034
- let recoveryState: LogicalRecoveryState = "unused";
1035
- let readonlyContinuation: RunChildSessionInput["readonlyContinuation"];
1036
- const continuationBudget = () => {
1037
- if (step.toolBudget) return "tool-budget-configured" as const;
1038
- // Refresh the authoritative run ledger, already fed synchronously by onChildEvent.
1039
- const exhausted = ctx.usageBudgetExhausted?.();
1040
- if (exhausted === true) return "exhausted" as const;
1041
- if (!ctx.usageBudget) return "unconfigured" as const;
1042
- if (ctx.usageBudget.costUsd || !ctx.onChildEvent || exhausted !== false) return "unknown" as const;
1043
- return "available" as const;
1044
- };
1045
- const lifecycleAllowsContinuation = () => !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted
1046
- && !ctx.skipAcceptance?.() && (ctx.deadlineAt === undefined || Date.now() < ctx.deadlineAt);
1047
- const canContinue = () => lifecycleAllowsContinuation() && ["available", "unconfigured"].includes(continuationBudget());
1048
- const failContinuationLaunch = (candidate: string | undefined, error: unknown) => {
1049
- const message = error instanceof Error ? error.message : String(error);
1050
- modelAttempts.push({ model: candidate ?? "default", success: false, exitCode: 1, error: message });
1051
- if (candidate) attemptedModels.push(candidate);
1052
- if (finalResult) finalResult = { ...finalResult, exitCode: 1, error: message };
1053
- };
1054
- let nextAttemptTask = task;
1055
- modelAttemptsLoop: while (modelIndex < candidates.length) {
1056
- if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
1057
- if (readonlyContinuation && !canContinue()) break;
1058
- const recoveringAbort = recoveryState === "abort-recovery";
1059
- const attemptTask = nextAttemptTask;
1060
- const candidate = candidates[modelIndex];
1061
- const expectedModelForVerification = candidate && !(step.skipPrimaryModelVerification && modelIndex === 0) ? candidate : undefined;
1092
+ const aggregateUsage = emptyUsage();
1093
+ let launched = false;
1094
+ let recoveryTask = task;
1095
+ let stagedIndexBaseline: string | undefined;
1096
+ singleLaunch: for (let attemptIndex = 0; attemptIndex < 2; attemptIndex++) {
1097
+ if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break singleLaunch;
1098
+ const expectedModelForVerification = candidate && !step.skipPrimaryModelVerification ? candidate : undefined;
1062
1099
  try {
1063
1100
  assertThinkingWithinCeiling({ model: candidate, configThinking: step.thinking, ceiling: step.thinkingCeiling, agent: step.agent, runId: ctx.id });
1064
1101
  } catch (error) {
1065
1102
  const message = error instanceof Error ? error.message : String(error);
1066
- if (readonlyContinuation) {
1067
- failContinuationLaunch(candidate, error);
1068
- break modelAttemptsLoop;
1069
- }
1070
1103
  return omitUndefinedProperties({ agent: step.agent, output: message, error: message, exitCode: 1, context: step.context, thinkingCeiling: step.thinkingCeiling });
1071
1104
  }
1105
+ const attemptModel = omitUndefinedProperties({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
1072
1106
  ctx.onAttemptStart?.(omitUndefinedProperties({
1073
- model: candidate,
1074
- thinking: resolveEffectiveThinking(candidate, step.thinking),
1107
+ ...attemptModel,
1075
1108
  contextLimit: findModelInfo(candidate, step.modelVerificationRegistry)?.contextWindow,
1076
1109
  }));
1077
1110
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
@@ -1103,11 +1136,7 @@ export async function runSingleStepInner(
1103
1136
  childWatchdog,
1104
1137
  watchdogStatus: (event) => watchdogSink?.(event),
1105
1138
  });
1106
- } catch (error) {
1107
- if (!readonlyContinuation) throw error;
1108
- failContinuationLaunch(candidate, error);
1109
- break modelAttemptsLoop;
1110
- }
1139
+ } catch (error) { throw error; }
1111
1140
  if (effectiveStructuredOutput && launch.config.structuredOutput) {
1112
1141
  // The runner reads the value back from the runtime's files after the run.
1113
1142
  launch.config.structuredOutput.capture = createStructuredOutputFileCapture(effectiveStructuredOutput);
@@ -1126,51 +1155,52 @@ export async function runSingleStepInner(
1126
1155
  subagentOnlyExtensions: step.subagentOnlyExtensions,
1127
1156
  fast: step.fast,
1128
1157
  model: step.model,
1129
- modelCandidates: step.modelCandidates,
1130
1158
  mcpDirectTools: step.mcpDirectTools,
1159
+ builtinMcpTools: step.builtinMcpTools,
1131
1160
  cwd: step.cwd ?? ctx.cwd,
1132
1161
  requireReadTool: Boolean(step.skills?.length),
1133
1162
  structuredOutput: Boolean(effectiveStructuredOutput),
1134
1163
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1135
1164
  inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
1165
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
1136
1166
  permissionRules: step.permissionRules,
1137
1167
  }));
1138
1168
  launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1139
- actualLaunchContractDigest = launchBindingDigest(omitUndefinedProperties({
1169
+ actualLaunchContractDigest = resolveLaunchBinding({
1140
1170
  definitionDigest: step.definitionDigest,
1141
- task: step.launchBindingTask ?? task,
1142
- ...(candidate ? { model: candidate } : {}),
1143
- modelCandidates: candidates as string[],
1144
- ...(step.fast !== undefined ? { fast: step.fast } : {}),
1145
- ...(resolveEffectiveThinking(candidate, step.thinking) ? { thinking: resolveEffectiveThinking(candidate, step.thinking) } : {}),
1146
- ...(step.thinkingCeiling ? { thinkingCeiling: step.thinkingCeiling } : {}),
1147
- systemPrompt: step.systemPrompt ?? "",
1148
1171
  systemPromptMode: step.systemPromptMode,
1149
1172
  inheritProjectContext: step.inheritProjectContext,
1150
1173
  inheritGlobalContext: step.inheritGlobalContext,
1151
1174
  inheritSkills: step.inheritSkills,
1175
+ task: step.launchBindingTask ?? task,
1176
+ model: candidate,
1177
+ fast: step.fast,
1178
+ thinking: resolveEffectiveThinking(candidate, step.thinking),
1179
+ systemPrompt: step.systemPrompt ?? "",
1152
1180
  skills: step.skills,
1153
- tools: toolPlan.effectiveToolAllowlist,
1154
- ...(toolPlan.excludeTools.length > 0 ? { excludeTools: toolPlan.excludeTools } : {}),
1155
- extensions: toolPlan.extensionArgs,
1156
- mcpDirectTools: toolPlan.effectiveMcpTools,
1157
- ...(step.outputPath ? { outputPath: step.outputPath } : {}),
1158
- ...(step.outputMode ? { outputMode: step.outputMode } : {}),
1159
- ...(step.structuredOutputSchema ? { structuredOutputSchema: step.structuredOutputSchema } : {}),
1160
- ...(extensionBindings ? { extensionBindings } : {}),
1161
- }));
1181
+ toolPlan,
1182
+ outputPath: step.outputPath,
1183
+ outputMode: step.outputMode,
1184
+ structuredOutputSchema: step.structuredOutputSchema,
1185
+ extensionBindings,
1186
+ }).launchContractDigest;
1162
1187
  }
1163
1188
  capabilityAudit = attemptCapabilityAudit;
1164
1189
  // Each attempt rewrites the step output log; synchronous appends keep a
1165
1190
  // retried attempt from interleaving with the previous attempt's flush.
1166
1191
  fs.writeFileSync(ctx.outputFile, "", "utf-8");
1192
+ if (step.effectiveAcceptance?.preserveStagedIndex && stagedIndexBaseline === undefined) {
1193
+ try {
1194
+ stagedIndexBaseline = captureStagedIndexBaseline(step.cwd ?? ctx.cwd);
1195
+ } catch (error) {
1196
+ const message = error instanceof Error ? error.message : String(error);
1197
+ return { agent: step.agent, output: message, error: message, exitCode: 1, context: step.context };
1198
+ }
1199
+ }
1167
1200
  const run = await runChildSession(omitUndefinedProperties({
1168
1201
  factory: ctx.childSessions,
1169
1202
  launch,
1170
- collectReadonlyEvidence: true,
1171
- readonlyContinuation,
1172
- canContinue,
1173
- prompt: `Task: ${attemptTask}`,
1203
+ prompt: `Task: ${recoveryTask}`,
1174
1204
  childWatchdog,
1175
1205
  childEventContext: { runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },
1176
1206
  appendChildEvent: (event) => appendDiagnosticJsonl(eventsPath, JSON.stringify(event), typeof event.type === "string" ? event.type : undefined),
@@ -1186,10 +1216,12 @@ export async function runSingleStepInner(
1186
1216
  registerTimeout: ctx.registerTimeout,
1187
1217
  registerStop: ctx.registerStop,
1188
1218
  registerSteer: ctx.registerSteer,
1219
+ onSteerOutcome: ctx.onSteerOutcome,
1189
1220
  registerWatchdogStatus: (sink) => { watchdogSink = sink; },
1190
1221
  timeoutMessage: ctx.timeoutMessage,
1191
1222
  stopMessage: ctx.stopMessage,
1192
1223
  onChildEvent: ctx.onChildEvent,
1224
+ onContextWindow: (contextLimit) => ctx.onAttemptStart?.({ ...attemptModel, contextLimit }),
1193
1225
  transcriptWriter,
1194
1226
  toolTimeoutMs: ctx.toolTimeoutMs,
1195
1227
  runDeadlineAt: ctx.deadlineAt,
@@ -1198,6 +1230,16 @@ export async function runSingleStepInner(
1198
1230
  modelResponseAliases: step.modelResponseAliases,
1199
1231
  mutationTools: step.mutationTools,
1200
1232
  }));
1233
+ launched = true;
1234
+ aggregateUsage.input += run.usage.input;
1235
+ aggregateUsage.output += run.usage.output;
1236
+ aggregateUsage.cacheRead += run.usage.cacheRead;
1237
+ aggregateUsage.cacheWrite += run.usage.cacheWrite;
1238
+ aggregateUsage.cost += run.usage.cost;
1239
+ aggregateUsage.turns += run.usage.turns;
1240
+ // A parked run still owes output diagnostics when it actually finishes.
1241
+ // Stopped/timedOut runs already have terminal failures, so terminal output diagnostics are deferred.
1242
+ const terminalDiagnosticsEligible = !run.interrupted && !run.stopped && !run.timedOut;
1201
1243
  const toolDiagnostic = run.exitCode === 0 && !run.error ? launch.capture.toolDiagnostic() : undefined;
1202
1244
  const toolAvailabilityError = toolDiagnostic ? formatChildToolDiagnostic(toolDiagnostic) : undefined;
1203
1245
  const runtimeAcknowledgedExtensions = launch.capture.runtimeAcknowledgedExtensions();
@@ -1213,17 +1255,23 @@ export async function runSingleStepInner(
1213
1255
  let structuredOutput: unknown;
1214
1256
  let structuredError: string | undefined;
1215
1257
  let validatedStructuredOutput = false;
1216
- if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError) {
1217
- if (!run.structuredOutputToolInvoked) {
1258
+ if (effectiveStructuredOutput) {
1259
+ const otherwiseSuccessful = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError;
1260
+ if (!run.structuredOutputToolInvoked && otherwiseSuccessful) {
1218
1261
  structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
1219
- } else {
1262
+ } else if (run.structuredOutputToolInvoked) {
1220
1263
  const structured = await readStructuredOutput({
1221
1264
  schema: effectiveStructuredOutput.schema,
1222
1265
  schemaPath: effectiveStructuredOutput.schemaPath,
1223
1266
  outputPath: effectiveStructuredOutput.outputPath,
1224
1267
  });
1225
- if (structured.error === MISSING_STRUCTURED_OUTPUT_CALL_ERROR) structuredError = formatStructuredOutputRejectionError(run.messages);
1226
- else if (structured.error) structuredError = structured.error;
1268
+ if (structured.error) {
1269
+ if (otherwiseSuccessful) {
1270
+ structuredError = structured.error === MISSING_STRUCTURED_OUTPUT_CALL_ERROR
1271
+ ? formatStructuredOutputRejectionError(run.messages)
1272
+ : structured.error;
1273
+ }
1274
+ }
1227
1275
  else {
1228
1276
  structuredOutput = structured.value;
1229
1277
  const acceptanceReport = readStructuredOutputAcceptanceReport(effectiveStructuredOutput);
@@ -1236,13 +1284,13 @@ export async function runSingleStepInner(
1236
1284
  const errorMessages = validatedStructuredOutput
1237
1285
  ? run.messages.slice(run.structuredOutputMessageStartIndex ?? run.messages.length)
1238
1286
  : run.messages;
1239
- const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
1287
+ const hiddenError = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
1240
1288
  ? detectSubagentError(errorMessages)
1241
1289
  : null;
1242
1290
  const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
1243
1291
  && hasEmptyTerminalAssistantResponse(run.messages)
1244
1292
  && (run.toolCount > 0 || Boolean(run.finalOutput.trim()));
1245
- const emptyOutputError = run.exitCode === 0
1293
+ const emptyOutputError = terminalDiagnosticsEligible && run.exitCode === 0
1246
1294
  && !run.error
1247
1295
  && !toolAvailabilityError
1248
1296
  && !structuredError
@@ -1251,57 +1299,20 @@ export async function runSingleStepInner(
1251
1299
  && (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages))
1252
1300
  ? formatEmptyTerminalAssistantResponseError(run.messages)
1253
1301
  : undefined;
1254
- const completionGuardEnabled = isAgentContract(step.agentContract) ? step.completionGuard === true : step.completionGuard !== false;
1255
- const completionToolPlan = resolvedTaskToolPlan;
1256
- const completionTools = completionToolPlan ? (completionToolPlan.explicitToolAllowlist ? completionToolPlan.effectiveToolAllowlist : undefined) : step.tools;
1257
- const mutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1302
+ const remoteGitChanged = run.nativeMachine?.initialGit && run.nativeMachine.finalGit ? run.nativeMachine.initialGit.head !== run.nativeMachine.finalGit.head || run.nativeMachine.initialGit.dirty !== run.nativeMachine.finalGit.dirty : undefined;
1303
+ const mutationEvidence = run.nativeMachine ? { source: "tracked-files" as const, trackedOnly: true as const, changedFiles: [], attemptedMutation: remoteGitChanged === true, ...(remoteGitChanged === undefined ? { unavailable: "Remote Git before/after evidence was incomplete." } : {}) } : collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1258
1304
  finalMutationEvidence = mutationEvidence;
1259
- const completionMutationEvidence = ctx.trackedMutationEvidenceForCompletionGuard === false ? undefined : mutationEvidence;
1260
- const completionGuard = run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !midToolExitError && !emptyOutputError && completionGuardEnabled
1261
- ? evaluateCompletionMutationGuard(omitUndefinedProperties({
1262
- agent: step.agent,
1263
- task: taskForCompletionGuard,
1264
- messages: run.messages,
1265
- tools: completionTools,
1266
- mcpDirectTools: completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools,
1267
- mutationTools: step.mutationTools,
1268
- toolAvailabilityError,
1269
- mutationEvidence: completionMutationEvidence,
1270
- }))
1271
- : undefined;
1272
- const mutationAttemptObserved = run.observedMutationAttempt === true || completionMutationEvidence?.attemptedMutation === true;
1273
- let arbitration = { triggered: completionGuard?.triggered === true && !mutationAttemptObserved, rescued: false };
1274
- if (arbitration.triggered) {
1275
- const modelContext = launch.capture.completionIntentContext?.();
1276
- arbitration = await arbitrateCompletionGuardRescue({
1277
- guardTriggered: true,
1278
- task: taskForCompletionGuard,
1279
- // Construct lazily too: the shared gate refuses overlength tasks before
1280
- // registry/auth/model work. The child has already shut down normally.
1281
- arbiter: modelContext ? async (task) => createTaskMutationArbiter(modelContext)?.(task) ?? "unavailable" : undefined,
1282
- });
1283
- }
1284
- const completionEvidence = planCompletionEvidence({
1285
- guard: completionGuard,
1286
- guardTriggered: arbitration.triggered,
1287
- arbiterRescued: arbitration.rescued,
1288
- completionGuardEnabled,
1289
- mutationCapable: hasMutationToolCapability(completionTools, completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools),
1290
- implementationMutationExpected: expectsImplementationMutation(step.agent, taskForCompletionGuard),
1291
- mutationAttemptObserved,
1292
- mutationEvidence: completionMutationEvidence,
1293
- agentContractEnabled: isAgentContract(step.agentContract),
1294
- });
1305
+ const mutationAttemptObserved = run.observedMutationAttempt === true || mutationEvidence.attemptedMutation === true;
1295
1306
  const finalOutputHasPersistableFileContent = run.exitCode === 0 && !run.error && !emptyOutputError && Boolean(stripAcceptanceReport(run.finalOutput).trim());
1296
1307
  const requiredOutput = step.outputMode === "file-only" && step.outputPath
1297
1308
  ? { kind: "file-only" as const, path: step.outputPath, missing: !fs.existsSync(step.outputPath) && !finalOutputHasPersistableFileContent }
1298
1309
  : effectiveStructuredOutput
1299
1310
  ? { kind: "structured" as const, path: effectiveStructuredOutput.outputPath, missing: !fs.existsSync(effectiveStructuredOutput.outputPath) }
1300
1311
  : undefined;
1301
- const missingRequiredOutputError = formatRequiredOutputError(requiredOutput);
1302
1312
  finalRequiredOutputMissing = requiredOutput?.missing;
1313
+ const missingRequiredOutputError = terminalDiagnosticsEligible ? formatRequiredOutputError(requiredOutput) : undefined;
1303
1314
  const missingRequiredOutputAfterMutation = Boolean(missingRequiredOutputError) && (mutationAttemptObserved || Boolean(mutationEvidence.changedFiles.length));
1304
- const effectiveExitCode = toolAvailabilityError || completionEvidence.legacyFailureError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
1315
+ const effectiveExitCode = toolAvailabilityError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
1305
1316
  ? 1
1306
1317
  : hiddenError?.hasError
1307
1318
  ? (hiddenError.exitCode ?? 1)
@@ -1319,17 +1330,7 @@ export async function runSingleStepInner(
1319
1330
  ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
1320
1331
  : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
1321
1332
  : undefined);
1322
- const error = underlyingError ?? missingRequiredOutputError ?? completionEvidence.legacyFailureError;
1323
- const attempt: ModelAttempt = omitUndefinedProperties({
1324
- model: candidate ?? run.model ?? step.model ?? "default",
1325
- success: effectiveExitCode === 0 && !error,
1326
- exitCode: effectiveExitCode,
1327
- error,
1328
- usage: run.usage,
1329
- });
1330
- modelAttempts.push(attempt);
1331
- if (!recoveringAbort && candidate) attemptedModels.push(candidate);
1332
- completionGuardTriggeredFinal = completionEvidence.guardTriggered && !underlyingError && !missingRequiredOutputError;
1333
+ const error = underlyingError ?? missingRequiredOutputError;
1333
1334
  finalOutputSnapshot = outputSnapshot;
1334
1335
  if (step.toolBudget) {
1335
1336
  const toolMessages = run.messages.filter((message) => message.role === "toolResult");
@@ -1337,20 +1338,21 @@ export async function runSingleStepInner(
1337
1338
  toolBudgetBlocked = Boolean(blockedMessage);
1338
1339
  toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
1339
1340
  }
1340
- const settlementDiagnostic = projectSettlementDiagnostic(completionEvidence, {
1341
- terminalFailed: effectiveExitCode !== 0,
1341
+ const settlementDiagnostic = effectiveExitCode !== 0 ? {
1342
1342
  finalTextPresent: Boolean(stripAcceptanceReport(run.finalOutput).trim()),
1343
- mutationObserved: mutationEvidence.attemptedMutation,
1344
- requiredOutput,
1343
+ mutation: { attempted: mutationAttemptObserved, observed: mutationEvidence.attemptedMutation },
1344
+ ...(requiredOutput ? { requiredOutput } : {}),
1345
1345
  afterCompactionSettlement: run.afterCompactionSettlement === true,
1346
- });
1347
- const fileMutationEffect = completionEvidence.fileMutation ?? (missingRequiredOutputAfterMutation ? { status: "observed" as const, expected: completionEvidence.mutationExpected, attempted: true, evidence: mutationEvidence } : undefined);
1346
+ } : undefined;
1347
+ const fileMutationEffect = missingRequiredOutputAfterMutation ? { status: "observed" as const, attempted: true as const, evidence: mutationEvidence } : undefined;
1348
1348
  finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, structuredOutputFailed: structuredError ? true : undefined, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect || settlementDiagnostic ? { effects: { ...(fileMutationEffect ? { fileMutation: fileMutationEffect } : {}), ...(settlementDiagnostic ? { settlementDiagnostic } : {}) } } : {}) } as RunChildSessionResult;
1349
- const abortRecovery = !attempt.success ? planAbortRecovery({
1349
+ if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break singleLaunch;
1350
+ if (effectiveExitCode === 0 && !error) break singleLaunch;
1351
+ const recovery = planAbortRecovery({
1350
1352
  messages: run.messages,
1351
1353
  error,
1352
1354
  sessionAvailable: Boolean(step.sessionFile && fs.existsSync(step.sessionFile)),
1353
- alreadyResumed: recoveryState !== "unused",
1355
+ alreadyResumed: attemptIndex > 0,
1354
1356
  stopped: run.stopped || ctx.stopSignal?.aborted || ctx.skipAcceptance?.(),
1355
1357
  interrupted: run.interrupted,
1356
1358
  timedOut: run.timedOut || ctx.timeoutSignal?.aborted,
@@ -1360,86 +1362,30 @@ export async function runSingleStepInner(
1360
1362
  acceptanceFailed: false,
1361
1363
  currentTool: run.currentTool,
1362
1364
  afterCompactionSettlement: run.afterCompactionSettlement,
1363
- }) : undefined;
1364
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) {
1365
- attempt.error = attempt.error
1366
- ? `${abortRecovery.diagnostic}\n${attempt.error.slice(0, 8_000)}`
1367
- : abortRecovery.diagnostic;
1368
- if (finalResult) finalResult.abortRecoveryDiagnostic = abortRecovery.diagnostic;
1369
- }
1370
- if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
1371
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) break modelAttemptsLoop;
1372
- if (attempt.success) break modelAttemptsLoop;
1373
- // The shared token is consumed before sibling creation; no third dispatch of any kind.
1374
- if (recoveryState === "readonly-continuation") break modelAttemptsLoop;
1375
- if (recoveringAbort) break modelAttemptsLoop;
1376
- if (abortRecovery?.action === "resume") {
1377
- recoveryState = "abort-recovery";
1378
- nextAttemptTask = abortRecovery.prompt;
1379
- attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
1380
- continue;
1365
+ });
1366
+ if (recovery.action === "resume") {
1367
+ recoveryTask = recovery.prompt;
1368
+ continue singleLaunch;
1381
1369
  }
1382
- if (completionEvidence.guardTriggered) break modelAttemptsLoop;
1383
-
1384
- const source = getSettledReadonlyChild(run);
1385
- if (source) {
1386
- const captured = launch.capture.completionIntentContext?.();
1387
- const sourceModel = captured?.model;
1388
- const retained = getReadonlySessionEvidence(source)!;
1389
- // Modality/capacity assessment, not another history/provenance validator.
1390
- // Images and unknown content have no certified token bound in this host slice.
1391
- const textOnly = (JSON.parse(retained.contextJson) as Message[]).every((message) => typeof message.content === "string"
1392
- || (Array.isArray(message.content) && message.content.every((block) => ["text", "thinking", "toolCall"].includes(block.type))));
1393
- const retainedBytes = Buffer.byteLength(retained.contextJson, "utf8");
1394
- const resolvedCandidates = candidates.map((reference, index) => {
1395
- // Only exact registry identities qualify; aliases/default guesses remain ineligible.
1396
- const base = reference ? splitKnownThinkingSuffix(reference).baseModel : "";
1397
- const slash = base.indexOf("/");
1398
- const model = slash > 0 ? captured?.modelRegistry.find(base.slice(0, slash), base.slice(slash + 1)) : undefined;
1399
- // Reserve the source window for runtime/system/tool overhead, plus a conservative
1400
- // byte bound for the complete retained text and new prompt; never assume a fit
1401
- // merely because a 429 request was sent. Equal/smaller windows remain denied.
1402
- const compatible = textOnly && model && sourceModel && model.input?.includes("text")
1403
- && Number.isFinite(sourceModel.contextWindow) && sourceModel.contextWindow > 0
1404
- && model.contextWindow >= sourceModel.contextWindow + retainedBytes + Buffer.byteLength(READONLY_CONTINUATION_PROMPT, "utf8")
1405
- && model.maxTokens > 0 && model.maxTokens <= sourceModel.maxTokens;
1406
- return { resolved: model ? { provider: model.provider, model: model.id, api: model.api } : undefined,
1407
- tried: index <= modelIndex, compatibility: compatible ? "compatible" as const : "unknown" as const };
1408
- });
1409
- const plan = planReadonlyModelContinuation({ source, recoveryState, candidates: resolvedCandidates, currentIndex: modelIndex,
1410
- lifecycleAllowsContinuation: lifecycleAllowsContinuation() && !run.interrupted && !run.stopped && !run.timedOut,
1411
- effectsAllowContinuation: !run.currentTool && !run.observedMutationAttempt && !mutationEvidence.attemptedMutation
1412
- && !structuredError && !effectiveStructuredOutput && !missingRequiredOutputError && !toolAvailabilityError
1413
- && !completionEvidence.guardTriggered && !midToolExitError && !hiddenError?.hasError,
1414
- budget: continuationBudget(), knownContextOverflow: isContextOverflow(error) });
1415
- if (plan.kind === "continue" && canContinue()) {
1416
- recoveryState = plan.recoveryState;
1417
- const selected = resolvedCandidates[plan.candidateIndex]!.resolved!;
1418
- readonlyContinuation = { source, expected: plan.expected, modelId: `${selected.provider}/${selected.model}` };
1419
- nextAttemptTask = plan.prompt;
1420
- modelIndex = plan.candidateIndex;
1421
- attemptNotes.push(`[readonly-continuation] ${attempt.model} returned HTTP 429 after read-only progress; continuing the retained session once with ${candidates[modelIndex]}.`);
1422
- continue;
1423
- }
1370
+ if (recovery.diagnostic) {
1371
+ finalResult.abortRecoveryDiagnostic = recovery.diagnostic;
1424
1372
  }
1425
1373
 
1426
- const retryableModelFailure = isRetryableModelFailureAttempt({ error, messages: run.messages, toolCount: run.toolCount });
1427
- if (retryableModelFailure) recordRetryableModelFailure(candidate ?? run.model ?? step.model, error);
1428
1374
  if (isContextOverflow(error)) {
1429
1375
  contextOverflow = true;
1430
- attemptNotes.push(`[fallback] ${attempt.model} failed: context overflow — the input exceeds this model's context window. Reduce the task input or use a model with a larger context window.`);
1431
- break modelAttemptsLoop;
1376
+ break singleLaunch;
1432
1377
  }
1433
- if (!retryableModelFailure || modelIndex === candidates.length - 1) break modelAttemptsLoop;
1434
- attemptNotes.push(formatModelAttemptNote(attempt, candidates[modelIndex + 1]));
1435
- modelIndex += 1;
1378
+ break singleLaunch;
1436
1379
  }
1437
1380
 
1438
1381
  const rawOutput = finalResult?.finalOutput ?? "";
1439
- const outputForPersistence = stripAcceptanceReport(rawOutput);
1382
+ const structuredText = finalResult?.structuredOutput === undefined ? undefined : JSON.stringify(finalResult.structuredOutput, null, 2);
1383
+ let replyOutput = stripAcceptanceReport(rawOutput);
1384
+ if (!replyOutput.trim() && structuredText !== undefined) replyOutput = structuredText;
1385
+ // The schema is the caller's contract: a bound output file holds the structured result, not closing prose.
1440
1386
  const resolvedOutput = step.outputPath && finalResult?.exitCode === 0
1441
- ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot, step.outputClaimPath)
1442
- : { fullOutput: outputForPersistence };
1387
+ ? resolveSingleOutput(step.outputPath, structuredText ?? replyOutput, finalOutputSnapshot, step.outputClaimPath)
1388
+ : { fullOutput: replyOutput };
1443
1389
  if (resolvedOutput.fatalError) {
1444
1390
  if (finalResult) {
1445
1391
  finalResult.exitCode = 1;
@@ -1449,13 +1395,11 @@ export async function runSingleStepInner(
1449
1395
  const output = stripAcceptanceReport(resolvedOutput.fullOutput);
1450
1396
  const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;
1451
1397
  let outputForSummary = output;
1452
- if (attemptNotes.length > 0) {
1453
- outputForSummary = `${attemptNotes.join("\n")}\n\n${outputForSummary}`.trim();
1454
- }
1455
1398
  if (finalResult?.stopped && !outputForSummary.trim()) {
1456
1399
  outputForSummary = ctx.stopMessage ?? "Subagent stopped by user.";
1457
1400
  }
1458
- const outputForAcceptance = rawOutput;
1401
+ // Unfinished streamed text never stands in for the child's completed reply.
1402
+ const outputForAcceptance = finalResult?.outputPartial ? "" : rawOutput;
1459
1403
  const childWrittenOutput = step.outputPath
1460
1404
  ? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
1461
1405
  : undefined;
@@ -1502,6 +1446,7 @@ export async function runSingleStepInner(
1502
1446
  ? { content: childWrittenOutput, path: step.outputPath, authoritative: step.outputMode === "file-only", durable: resolvedOutput.savedPath !== undefined }
1503
1447
  : undefined,
1504
1448
  cwd: step.cwd ?? ctx.cwd,
1449
+ stagedIndexBaseline,
1505
1450
  signal: combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]),
1506
1451
  abortMessage: ctx.stopSignal?.aborted ? ctx.stopMessage ?? "Subagent stopped by user." : ctx.timeoutMessage ?? "Subagent timed out.",
1507
1452
  reportOptional: isAgentContract(step.agentContract),
@@ -1522,6 +1467,12 @@ export async function runSingleStepInner(
1522
1467
  const acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;
1523
1468
  const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !isAgentContract(step.agentContract);
1524
1469
  const effectiveFinalExitCode = timedOutAfterAcceptance || stoppedAfterAcceptance ? 1 : acceptanceCanFailRun ? 1 : finalResult?.exitCode ?? 1;
1470
+ // A passing typed gate supplies the structured output for runs that have no
1471
+ // outputSchema of their own; preflight rejects the combination.
1472
+ const typedGate = typedVerifyOutput(effectiveAcceptance);
1473
+ if (typedGate && finalResult && finalResult.structuredOutput === undefined && effectiveFinalExitCode === 0) {
1474
+ finalResult = { ...finalResult, structuredOutput: typedGate.value };
1475
+ }
1525
1476
  const intercomDetachReceipt = finalResult?.finalOutput === INTERCOM_DETACH_RECEIPT;
1526
1477
  const baseFinalError = stoppedAfterAcceptance
1527
1478
  ? ctx.stopMessage ?? "Subagent stopped by user."
@@ -1536,7 +1487,7 @@ export async function runSingleStepInner(
1536
1487
  abortRecoveryDiagnostic: effectiveFinalExitCode !== 0 ? finalResult?.abortRecoveryDiagnostic : undefined,
1537
1488
  requiredOutput: effectiveFinalExitCode !== 0 ? finalResult?.effects?.settlementDiagnostic?.requiredOutput : undefined,
1538
1489
  });
1539
- const usage = usageFromAttempts(modelAttempts);
1490
+ const usage = launched ? aggregateUsage : undefined;
1540
1491
 
1541
1492
  const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false
1542
1493
  ? persistStepArtifacts({
@@ -1554,8 +1505,8 @@ export async function runSingleStepInner(
1554
1505
  task: PROMPT_REDACTED,
1555
1506
  exitCode: effectiveFinalExitCode,
1556
1507
  model: finalResult?.model,
1557
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1558
- modelAttempts,
1508
+ nativeMachine: finalResult?.nativeMachine,
1509
+ requestedModel: step.requestedModel,
1559
1510
  usage,
1560
1511
  error: effectiveFinalError,
1561
1512
  acceptance: effectiveAcceptance,
@@ -1571,7 +1522,7 @@ export async function runSingleStepInner(
1571
1522
  })
1572
1523
  : {};
1573
1524
 
1574
- const result: StepResult & { completionGuardTriggered?: boolean } = omitUndefinedProperties({
1525
+ const result: StepResult = omitUndefinedProperties({
1575
1526
  agent: step.agent,
1576
1527
  ...(childSessionName ? { sessionName: childSessionName } : {}),
1577
1528
  context: step.context,
@@ -1579,20 +1530,22 @@ export async function runSingleStepInner(
1579
1530
  launchContractDigest: actualLaunchContractDigest,
1580
1531
  output: outputForSummary,
1581
1532
  outputState,
1533
+ outputPartial: finalResult?.outputPartial,
1582
1534
  exitCode: effectiveFinalExitCode,
1583
1535
  error: effectiveFinalError,
1584
1536
  sessionFile: step.sessionFile,
1585
1537
  intercomTarget: ctx.childIntercomTarget,
1586
1538
  model: finalResult?.model,
1539
+ nativeMachine: finalResult?.nativeMachine,
1587
1540
  thinking: resolveEffectiveThinking(finalResult?.model, step.thinking),
1588
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1589
- modelAttempts,
1541
+ requestedModel: step.requestedModel,
1590
1542
  contextOverflow: contextOverflow || undefined,
1591
- totalCost: costSummaryFromAttempts(modelAttempts),
1543
+ totalCost: costSummaryFromUsage(usage),
1592
1544
  usage,
1593
1545
  artifactPaths,
1594
1546
  savedOutputPath: finalizedOutput.savedPath,
1595
1547
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
1548
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
1596
1549
  metadataSaveError: artifactErrors.metadataSaveError,
1597
1550
  transcriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,
1598
1551
  transcriptError: transcriptWriter?.getError(),
@@ -1602,7 +1555,6 @@ export async function runSingleStepInner(
1602
1555
  timeoutRecovery,
1603
1556
  toolBudget,
1604
1557
  toolBudgetBlocked: toolBudgetBlocked || undefined,
1605
- completionGuardTriggered: completionGuardTriggeredFinal,
1606
1558
  ...((finalResult as (RunChildSessionResult & { effects?: import("../../shared/types.ts").EffectsProjection }) | undefined)?.effects ? { effects: (finalResult as RunChildSessionResult & { effects?: import("../../shared/types.ts").EffectsProjection }).effects } : {}),
1607
1559
  structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : (finalResult as (RunChildSessionResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput,
1608
1560
  structuredOutputFailed: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : finalResult?.structuredOutputFailed,
@@ -1620,7 +1572,7 @@ export async function runSingleStepInner(
1620
1572
  async function runSingleStep(
1621
1573
  step: SubagentStep,
1622
1574
  ctx: SingleStepContext,
1623
- ): Promise<StepResult & { completionGuardTriggered?: boolean }> {
1575
+ ): Promise<StepResult> {
1624
1576
  if (!step.importAsyncRoot) ctx.orcaProgressTab?.section({ agent: step.agent, index: ctx.flatIndex, count: ctx.flatStepCount });
1625
1577
  return runSingleStepInner(step, ctx);
1626
1578
  }
@@ -1707,7 +1659,12 @@ function markParallelGroupSetupFailure(input: {
1707
1659
  if (!task) throw new Error(`Missing parallel task at index ${taskIndex}`);
1708
1660
  const stopped = statusStep.stopped || statusStep.stopRequested || input.statusPayload.stopped;
1709
1661
  const paused = !stopped && input.statusPayload.state === "paused";
1662
+ const timedOut = !stopped && !paused && input.statusPayload.timedOut === true;
1710
1663
  statusStep.status = stopped ? "stopped" : paused ? "paused" : "failed";
1664
+ // Mirror the run-level timeout onto the step so consumers (status readers,
1665
+ // run-history recording) see timed_out rather than a bare failure — the
1666
+ // StepResult below already carries it, the status step must too.
1667
+ if (timedOut) statusStep.timedOut = true;
1711
1668
  statusStep.startedAt = input.failedAt;
1712
1669
  statusStep.endedAt = input.failedAt;
1713
1670
  statusStep.durationMs = 0;
@@ -1837,8 +1794,12 @@ function missingRequiredOutputAfterUsefulMutation(result: SingleStepResult): boo
1837
1794
  }
1838
1795
 
1839
1796
  function partialExecutionWithUsefulMutation(result: SingleStepResult): boolean {
1797
+ if (result.execution?.status !== "partial") return false;
1798
+ // Pane-native external results are deliberately partial from bounded terminal
1799
+ // evidence alone; Pi mutation-based partials retain their existing behavior.
1800
+ if (result.runner?.type === "external-cli" && result.runner.machine) return true;
1840
1801
  const fileMutation = result.effects?.fileMutation;
1841
- return result.execution?.status === "partial" && (fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length));
1802
+ return fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length);
1842
1803
  }
1843
1804
 
1844
1805
  function partialEvidenceResult(result: SingleStepResult): boolean {
@@ -1920,6 +1881,11 @@ export async function runSubagent(
1920
1881
  let previousOutput = "";
1921
1882
  const outputs: ChainOutputMap = {};
1922
1883
  const results: StepResult[] = [];
1884
+ // Flat indices of steps a child session was actually dispatched for — the
1885
+ // ground truth for run-history: stopRunner/timeoutRunner/fail-fast/budget
1886
+ // skips relabel never-launched steps to terminal statuses, so status alone
1887
+ // cannot distinguish them from steps that really ran.
1888
+ const launchedFlatIndices = new Set<number>();
1923
1889
  const overallStartTime = Date.now();
1924
1890
  const shareEnabled = config.share === true;
1925
1891
  const asyncDir = config.asyncDir;
@@ -1941,6 +1907,7 @@ export async function runSubagent(
1941
1907
  let currentActivityState: ActivityState | undefined;
1942
1908
  let activityTimer: NodeJS.Timeout | undefined;
1943
1909
  let timeoutTimer: NodeJS.Timeout | undefined;
1910
+ let checkpointTimer: NodeJS.Timeout | undefined;
1944
1911
  let timedOut = false;
1945
1912
  let stopped = false;
1946
1913
  let usageBudgetExceeded = false;
@@ -1949,6 +1916,7 @@ export async function runSubagent(
1949
1916
  const timeoutAbortController = new AbortController();
1950
1917
  const stopAbortController = new AbortController();
1951
1918
  const setupInterruptController = new AbortController();
1919
+ const runStopSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal]);
1952
1920
  const setupSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal, setupInterruptController.signal]);
1953
1921
  let previousCumulativeTokens: TokenUsage = { input: 0, output: 0, total: 0 };
1954
1922
  let latestSessionFile: string | undefined;
@@ -1990,7 +1958,7 @@ export async function runSubagent(
1990
1958
  model: task.model,
1991
1959
  ...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
1992
1960
  thinking: task.thinking,
1993
- attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
1961
+ requestedModel: task.requestedModel,
1994
1962
  recentTools: [],
1995
1963
  recentOutput: [],
1996
1964
  }));
@@ -2044,7 +2012,7 @@ export async function runSubagent(
2044
2012
  model: step.model,
2045
2013
  ...(step.contextLimit !== undefined ? { contextLimit: step.contextLimit } : {}),
2046
2014
  thinking: step.thinking,
2047
- attemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,
2015
+ requestedModel: step.requestedModel,
2048
2016
  recentTools: [],
2049
2017
  recentOutput: [],
2050
2018
  }));
@@ -2089,6 +2057,7 @@ export async function runSubagent(
2089
2057
  ...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
2090
2058
  ...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
2091
2059
  pid: process.pid,
2060
+ pidNamespaceScope: currentPidNamespaceScope(),
2092
2061
  cwd,
2093
2062
  currentStep: 0,
2094
2063
  chainStepCount: steps.length,
@@ -2271,9 +2240,7 @@ export async function runSubagent(
2271
2240
  sessionFile: step.sessionFile,
2272
2241
  model: step.model,
2273
2242
  thinking: step.thinking,
2274
- attemptedModels: step.attemptedModels,
2275
- modelAttempts: step.modelAttempts,
2276
- usage: usageFromAttempts(step.modelAttempts),
2243
+ requestedModel: step.requestedModel,
2277
2244
  contextOverflow: step.contextOverflow,
2278
2245
  })),
2279
2246
  exitCode: state === "complete" || state === "paused" ? 0 : 1,
@@ -2438,6 +2405,8 @@ export async function runSubagent(
2438
2405
  yield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));
2439
2406
  }
2440
2407
  };
2408
+ const isNestedControlDescendant = (run: NestedRunSummary): boolean =>
2409
+ !config.nestedSelf || run.path.some((entry) => entry.runId === id);
2441
2410
  const interruptNestedAsyncDescendants = (): void => {
2442
2411
  if (!config.nestedRoute) return;
2443
2412
  let registry: ReturnType<typeof projectNestedEvents>;
@@ -2453,7 +2422,7 @@ export async function runSubagent(
2453
2422
  return;
2454
2423
  }
2455
2424
  for (const run of nestedRuns(registry.children)) {
2456
- if (run.state !== "running" && run.state !== "queued") continue;
2425
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2457
2426
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2458
2427
  if (!nestedAsyncDir) continue;
2459
2428
  try {
@@ -2484,7 +2453,7 @@ export async function runSubagent(
2484
2453
  return;
2485
2454
  }
2486
2455
  for (const run of nestedRuns(registry.children)) {
2487
- if (run.state !== "running" && run.state !== "queued") continue;
2456
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2488
2457
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2489
2458
  if (!nestedAsyncDir) continue;
2490
2459
  try {
@@ -2515,7 +2484,7 @@ export async function runSubagent(
2515
2484
  return;
2516
2485
  }
2517
2486
  for (const run of nestedRuns(registry.children)) {
2518
- if (run.state !== "running" && run.state !== "queued") continue;
2487
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2519
2488
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2520
2489
  if (!nestedAsyncDir) continue;
2521
2490
  try {
@@ -2571,6 +2540,7 @@ export async function runSubagent(
2571
2540
  }
2572
2541
  const appendedSteps = requests.flatMap((request) => request.steps);
2573
2542
  steps.push(...appendedSteps);
2543
+ flatSteps.push(...flattenSteps(appendedSteps));
2574
2544
  const now = Date.now();
2575
2545
  const pendingAppends = countPendingChainAppendRequests(asyncDir);
2576
2546
  const added = appendRunnerStepsToStatus({
@@ -2604,9 +2574,66 @@ export async function runSubagent(
2604
2574
  setOptionalProperty(groupNode, "acceptanceStatus", acceptance?.status ?? groupNode.acceptanceStatus);
2605
2575
  };
2606
2576
 
2577
+ const EXTERNAL_GIT_PROBE_MIN_INTERVAL_MS = 2_000;
2578
+ type ExternalActivityEvidence = {
2579
+ cwd?: string;
2580
+ lastStreamActivityAt?: number;
2581
+ fingerprint?: string;
2582
+ probeInFlight?: Promise<void>;
2583
+ lastProbeStartedAt?: number;
2584
+ };
2585
+ const externalActivityEvidence = new Map<number, ExternalActivityEvidence>();
2586
+ const gitProbesByCwd = new Map<string, Promise<string | undefined>>();
2587
+ let periodicGitProbeFailure: { index: number; error: Error; message: string } | undefined;
2588
+ const reportedGitProbeErrors = new Set<string>();
2589
+ const reportGitProbeError = (externalCwd: string, error: unknown): void => {
2590
+ if (reportedGitProbeErrors.has(externalCwd)) return;
2591
+ reportedGitProbeErrors.add(externalCwd);
2592
+ const detail = error instanceof Error ? error.message : String(error);
2593
+ console.error(`[pi-subagents] Git activity evidence unavailable for '${externalCwd.slice(-300)}'; check the cwd and Git installation: ${detail.slice(0, 500)}`);
2594
+ };
2595
+ const readSharedGitFingerprint = (externalCwd: string): Promise<string | undefined> => {
2596
+ const inFlight = gitProbesByCwd.get(externalCwd);
2597
+ if (inFlight) return inFlight;
2598
+ const probe = readGitFingerprint(externalCwd, runStopSignal, (error) => reportGitProbeError(externalCwd, error)).finally(() => gitProbesByCwd.delete(externalCwd));
2599
+ gitProbesByCwd.set(externalCwd, probe);
2600
+ return probe;
2601
+ };
2602
+ const recordPeriodicGitProbeFailure = (index: number, error: unknown): void => {
2603
+ if (periodicGitProbeFailure) return;
2604
+ const cause = error instanceof Error ? error : new Error(String(error));
2605
+ const message = `PROCESS_TREE_UNVERIFIED: ${cause.message}`;
2606
+ periodicGitProbeFailure = { index, error: cause, message };
2607
+ statusPayload.error = message;
2608
+ const step = statusPayload.steps[index];
2609
+ if (step) step.error = message;
2610
+ statusPayload.lastUpdate = Date.now();
2611
+ writeStatusPayload();
2612
+ appendJsonl(eventsPath, JSON.stringify({
2613
+ type: "subagent.run.process_tree_unverified",
2614
+ ts: statusPayload.lastUpdate,
2615
+ runId: id,
2616
+ index,
2617
+ code: "PROCESS_TREE_UNVERIFIED",
2618
+ message,
2619
+ }));
2620
+ };
2621
+ const prepareExternalActivity = async (index: number, externalCwd: string, signal: AbortSignal): Promise<void> => {
2622
+ if (!controlConfig.enabled) return;
2623
+ const resolvedCwd = path.resolve(externalCwd);
2624
+ const evidence: ExternalActivityEvidence = { cwd: resolvedCwd, lastProbeStartedAt: performance.now() };
2625
+ externalActivityEvidence.set(index, evidence);
2626
+ evidence.fingerprint = await readGitFingerprint(resolvedCwd, signal, (error) => reportGitProbeError(resolvedCwd, error));
2627
+ };
2628
+ const recordExternalStreamActivity = (index: number): void => {
2629
+ const evidence = externalActivityEvidence.get(index) ?? {};
2630
+ externalActivityEvidence.set(index, evidence);
2631
+ evidence.lastStreamActivityAt = Date.now();
2632
+ };
2607
2633
  const stepOutputActivityAt = (index: number): number => {
2608
2634
  const step = statusPayload.steps[index];
2609
2635
  let lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;
2636
+ lastActivityAt = Math.max(lastActivityAt, externalActivityEvidence.get(index)?.lastStreamActivityAt ?? 0);
2610
2637
  const outputPath = path.join(asyncDir, `output-${index}.log`);
2611
2638
  try {
2612
2639
  lastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);
@@ -2621,7 +2648,7 @@ export async function runSubagent(
2621
2648
  const activeLongRunningSteps = new Set<number>();
2622
2649
  const mutatingFailureStates = initialStatusSteps.map(() => createMutatingFailureState());
2623
2650
  const pendingToolResults: Array<{ tool: string; path?: string; mutates: boolean; startedAt?: number } | undefined> = initialStatusSteps.map(() => undefined);
2624
- type ActiveToolCall = { key: string; tool: string; args: string; startedAt: number; path?: string; blocksSupervisor: boolean };
2651
+ type ActiveToolCall = { attentionEmitted?: boolean; key: string; tool: string; args: string; startedAt: number; path?: string; blocksSupervisor: boolean };
2625
2652
  const activeToolCalls = initialStatusSteps.map(() => new Map<string, ActiveToolCall>());
2626
2653
  const activeToolKeysByName = initialStatusSteps.map(() => new Map<string, string[]>());
2627
2654
  const activeToolSequences = initialStatusSteps.map(() => 0);
@@ -2685,8 +2712,11 @@ export async function runSubagent(
2685
2712
  return key ? removeActiveToolCallKey(flatIndex, key) : undefined;
2686
2713
  };
2687
2714
  const openToolAttentionTarget = (flatIndex: number, now: number): ActiveToolCall | undefined => [...(activeToolCalls[flatIndex]?.values() ?? [])]
2688
- .filter((active) => shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }))
2715
+ .filter((active) => !active.attentionEmitted && shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }))
2689
2716
  .sort((left, right) => left.startedAt - right.startedAt)[0];
2717
+ /** D12: whether any open tool is still past the threshold, including ones whose one-shot attention was already emitted. */
2718
+ const hasOpenToolPastThreshold = (flatIndex: number, now: number): boolean => [...(activeToolCalls[flatIndex]?.values() ?? [])]
2719
+ .some((active) => shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }));
2690
2720
  const supervisorAttentionSteps = new Map<number, ActivityState | undefined>();
2691
2721
  const mutatingFailureWindowMs = 5 * 60_000;
2692
2722
  const appendControlEvent = (rawEvent: ReturnType<typeof buildControlEvent>) => {
@@ -2735,13 +2765,64 @@ export async function runSubagent(
2735
2765
  currentActivityState = nextRunState;
2736
2766
  setOptionalProperty(statusPayload, "activityState", nextRunState);
2737
2767
  };
2768
+ /**
2769
+ * Why a step is flagged `needs_attention`, by flat index, so the flag is dropped when THAT cause resolves (decision D12).
2770
+ * `supervisor_request` is tracked separately by `supervisorAttentionSteps`. Terminal handling (stop/interrupt/timeout/final
2771
+ * status) still clears the flag unconditionally, and the `partial`-with-evidence and completion-guard paths stay terminal-only.
2772
+ */
2773
+ type AttentionCause = "tool_open_threshold" | "tool_failures" | "idle" | "steering";
2774
+ const attentionCauses = new Map<number, Set<AttentionCause>>();
2775
+ const attentionResumeState = new Map<number, ActivityState | undefined>();
2776
+ const noteAttentionCause = (flatIndex: number, cause: AttentionCause, previous: ActivityState | undefined): void => {
2777
+ const causes = attentionCauses.get(flatIndex) ?? new Set<AttentionCause>();
2778
+ if (causes.size === 0 && previous !== "needs_attention") attentionResumeState.set(flatIndex, previous);
2779
+ causes.add(cause);
2780
+ attentionCauses.set(flatIndex, causes);
2781
+ };
2782
+ const emitAttentionCleared = (flatIndex: number, cause: AttentionCause | "supervisor_request", to: ActivityState | undefined, now: number): void => {
2783
+ const step = statusPayload.steps[flatIndex];
2784
+ appendJsonl(eventsPath, JSON.stringify({
2785
+ type: "subagent.attention.cleared",
2786
+ ts: now,
2787
+ runId: id,
2788
+ ...(step?.agent ? { agent: step.agent } : {}),
2789
+ index: flatIndex,
2790
+ from: "needs_attention",
2791
+ to: to ?? null,
2792
+ reason: cause,
2793
+ }));
2794
+ };
2795
+ /**
2796
+ * Drops one `needs_attention` cause. When it was the last one holding the step, restores the step's previous non-attention state,
2797
+ * recomputes the run-level state, lets the same problem notify again if it recurs and appends `subagent.attention.cleared`.
2798
+ * The caller persists status. Returns true when the step's state changed.
2799
+ */
2800
+ const resolveAttentionCause = (flatIndex: number, cause: AttentionCause, now: number): boolean => {
2801
+ const causes = attentionCauses.get(flatIndex);
2802
+ if (!causes?.delete(cause) || causes.size > 0) return false;
2803
+ attentionCauses.delete(flatIndex);
2804
+ const resumeState = attentionResumeState.get(flatIndex);
2805
+ attentionResumeState.delete(flatIndex);
2806
+ const step = statusPayload.steps[flatIndex];
2807
+ if (!step || step.status !== "running" || step.activityState !== "needs_attention") return false;
2808
+ if (supervisorAttentionSteps.has(flatIndex)) return false;
2809
+ setOptionalProperty(step, "activityState", resumeState);
2810
+ syncAggregateActivityState();
2811
+ if (cause !== "steering") forgetControlNotifications(emittedControlEventKeys, { runId: id, index: flatIndex }, cause, config.childIntercomTargets?.[flatIndex]);
2812
+ emitAttentionCleared(flatIndex, cause, resumeState, now);
2813
+ return true;
2814
+ };
2738
2815
  const maybeEmitOpenToolAttention = (flatIndex: number, now: number): boolean => {
2739
2816
  const step = statusPayload.steps[flatIndex];
2740
- if (!step || step.status !== "running" || step.activityState === "needs_attention") return false;
2817
+ if (!step || step.status !== "running") return false;
2741
2818
  const target = openToolAttentionTarget(flatIndex, now);
2742
2819
  if (!target) return false;
2820
+ target.attentionEmitted = true;
2821
+ // Keep this attention when a concurrent supervisor request ends and restores its saved state.
2822
+ if (supervisorAttentionSteps.has(flatIndex)) supervisorAttentionSteps.set(flatIndex, "needs_attention");
2743
2823
  const previous = step.activityState;
2744
2824
  step.activityState = "needs_attention";
2825
+ noteAttentionCause(flatIndex, "tool_open_threshold", previous);
2745
2826
  statusPayload.activityState = "needs_attention";
2746
2827
  const toolDurationMs = Math.max(0, now - target.startedAt);
2747
2828
  appendControlEvent(buildControlEvent(omitUndefinedProperties({
@@ -2758,6 +2839,7 @@ export async function runSubagent(
2758
2839
  tokens: step.tokens?.total,
2759
2840
  toolCount: step.toolCount,
2760
2841
  currentTool: target.tool,
2842
+ toolCallId: target.key.startsWith("id:") ? target.key.slice(3) : undefined,
2761
2843
  currentToolDurationMs: toolDurationMs,
2762
2844
  currentPath: target.path,
2763
2845
  })));
@@ -2802,7 +2884,10 @@ export async function runSubagent(
2802
2884
  const steeringMarkerPath = (requestId: string): string => path.join(asyncDir, "control", "steer-recovery", `${Buffer.from(requestId).toString("base64url")}.json`);
2803
2885
  const markSteeringAttention = (index: number): void => {
2804
2886
  const step = statusPayload.steps[index];
2805
- if (step) step.activityState = "needs_attention";
2887
+ if (step) {
2888
+ noteAttentionCause(index, "steering", step.activityState);
2889
+ step.activityState = "needs_attention";
2890
+ }
2806
2891
  statusPayload.activityState = "needs_attention";
2807
2892
  };
2808
2893
  const emitSteeringEvent = (type: string, request: SteerRequest, index?: number, extra: Record<string, unknown> = {}): void => {
@@ -2898,11 +2983,16 @@ export async function runSubagent(
2898
2983
  const applySteerDelivery = (requestId: string, index: number, delivery: { state: "delivered" | "queued" | "failed"; message: string }): void => {
2899
2984
  const lifecycle = steeringStatus(statusPayload);
2900
2985
  const request = lifecycle.recent.find((candidate) => candidate.id === requestId);
2901
- if (!request || !request.targets.some((target) => target.index === index)) return;
2986
+ const target = request?.targets.find((candidate) => candidate.index === index);
2987
+ if (!request || !target) return;
2988
+ if (target.state === "delivered" || target.state === "late" || target.state === "failed") return;
2989
+ if (target.state === delivery.state) return;
2902
2990
  const late = fs.existsSync(steeringMarkerPath(requestId));
2903
2991
  const now = Date.now();
2904
2992
  if (delivery.state === "delivered") {
2905
2993
  updateSteeringLifecycleTarget(requestId, index, late ? "late" : "delivered", now, omitUndefinedProperties({ reason: late ? "acknowledged after recovery commit" : undefined }));
2994
+ // A delivered (or late-acknowledged) steer shows the child accepts steering again: the steering problem is over.
2995
+ resolveAttentionCause(index, "steering", now);
2906
2996
  emitSteeringEvent("subagent.steer.delivered", { type: "steer", id: requestId, ts: now, message: delivery.message }, index, { late, deliveryStatus: "delivered", message: delivery.message });
2907
2997
  } else if (delivery.state === "queued") {
2908
2998
  updateSteeringLifecycleTarget(requestId, index, "queued", now);
@@ -2971,7 +3061,7 @@ export async function runSubagent(
2971
3061
  return;
2972
3062
  }
2973
3063
  if (event.type === "message_end") {
2974
- const next = applyChildWatchdogMessage(step.watchdog, event.message, now);
3064
+ const next = applyChildWatchdogMessage(step.watchdog, event.message);
2975
3065
  if (next) step.watchdog = next;
2976
3066
  if (next && (event.message as { role?: unknown } | undefined)?.role === "custom") {
2977
3067
  statusPayload.lastUpdate = now;
@@ -3029,9 +3119,11 @@ export async function runSubagent(
3029
3119
  const supervisorPreviousActivity = supervisorAttentionSteps.get(flatIndex);
3030
3120
  const stillBlockingSupervisor = [...(activeToolCalls[flatIndex]?.values() ?? [])].some((active) => active.blocksSupervisor);
3031
3121
  const clearedSupervisorAttention = endedTool?.blocksSupervisor && !stillBlockingSupervisor ? supervisorAttentionSteps.delete(flatIndex) : false;
3032
- if (clearedSupervisorAttention && step.activityState === "needs_attention") {
3122
+ // Another unresolved cause (e.g. a failed steer) keeps the step flagged; its own resolution restores the state.
3123
+ if (clearedSupervisorAttention && step.activityState === "needs_attention" && !attentionCauses.get(flatIndex)?.size) {
3033
3124
  setOptionalProperty(step, "activityState", supervisorPreviousActivity);
3034
3125
  syncAggregateActivityState();
3126
+ emitAttentionCleared(flatIndex, "supervisor_request", supervisorPreviousActivity, now);
3035
3127
  }
3036
3128
  syncTopLevelCurrentTool();
3037
3129
  } else if (event.type === "tool_result_end" && event.message) {
@@ -3059,6 +3151,7 @@ export async function runSubagent(
3059
3151
  if (controlConfig.enabled && shouldEscalateMutatingFailures(state, controlConfig.failedToolAttemptsBeforeAttention) && step.activityState !== "needs_attention") {
3060
3152
  const previous = step.activityState;
3061
3153
  step.activityState = "needs_attention";
3154
+ noteAttentionCause(flatIndex, "tool_failures", previous);
3062
3155
  statusPayload.activityState = "needs_attention";
3063
3156
  appendControlEvent(buildControlEvent(omitUndefinedProperties({
3064
3157
  type: "needs_attention",
@@ -3081,6 +3174,8 @@ export async function runSubagent(
3081
3174
  }
3082
3175
  } else if (toolSnapshot?.mutates) {
3083
3176
  resetMutatingFailureState(mutatingFailureStates[flatIndex]!);
3177
+ // The failure streak that raised the flag is broken by a successful mutating tool.
3178
+ resolveAttentionCause(flatIndex, "tool_failures", now);
3084
3179
  }
3085
3180
  } else if (event.type === "message_end" && event.message?.role === "assistant") {
3086
3181
  appendRecentStepOutput(step, stripAcceptanceReport(extractTextFromContent(event.message.content)).split("\n").slice(-10));
@@ -3108,11 +3203,13 @@ export async function runSubagent(
3108
3203
  step.lastActivityAt = now;
3109
3204
  statusPayload.lastActivityAt = now;
3110
3205
  statusPayload.lastUpdate = now;
3206
+ // The open tool that raised `tool_open_threshold` ended (or no remaining open tool is past the threshold): the step recovered.
3207
+ if (attentionCauses.get(flatIndex)?.has("tool_open_threshold") && !hasOpenToolPastThreshold(flatIndex, now)) resolveAttentionCause(flatIndex, "tool_open_threshold", now);
3111
3208
  maybeEmitActiveLongRunning(flatIndex, now);
3112
3209
  // A sibling may keep aggregate attention unchanged; publish this step's transition.
3113
3210
  writeStatusPayload(step.activityState !== previousActivityState);
3114
3211
  };
3115
- const updateRunnerActivityState = (now: number): boolean => {
3212
+ const updateRunnerActivityState = (now: number, skipExternalProbeIndex?: number): boolean => {
3116
3213
  if (!controlConfig.enabled) return false;
3117
3214
  let changed = false;
3118
3215
  let runLastActivityAt = statusPayload.lastActivityAt ?? overallStartTime;
@@ -3129,14 +3226,38 @@ export async function runSubagent(
3129
3226
  config: controlConfig,
3130
3227
  startedAt: step.startedAt ?? overallStartTime,
3131
3228
  lastActivityAt,
3132
- turnCount: step.turnCount,
3229
+ turnCount: flatSteps[index]?.runner?.type === "external-cli" ? 1 : step.turnCount,
3133
3230
  currentTool: step.currentTool,
3134
3231
  thinking: step.thinking,
3135
3232
  now,
3136
3233
  }));
3137
3234
  if (idleState === "needs_attention") {
3235
+ const evidence = externalActivityEvidence.get(index);
3236
+ if (index !== skipExternalProbeIndex && evidence?.cwd && evidence.fingerprint) {
3237
+ if (evidence.probeInFlight) continue;
3238
+ if (performance.now() - (evidence.lastProbeStartedAt ?? 0) >= EXTERNAL_GIT_PROBE_MIN_INTERVAL_MS) {
3239
+ evidence.lastProbeStartedAt = performance.now();
3240
+ const baseline = evidence.fingerprint;
3241
+ evidence.probeInFlight = readSharedGitFingerprint(evidence.cwd).then((fingerprint) => {
3242
+ if (requiredStatusStep(statusPayload, index).status !== "running") return;
3243
+ if (fingerprint && fingerprint !== baseline) {
3244
+ evidence.fingerprint = fingerprint;
3245
+ evidence.lastStreamActivityAt = Date.now();
3246
+ updateRunnerActivityState(Date.now());
3247
+ } else {
3248
+ updateRunnerActivityState(Date.now(), index);
3249
+ }
3250
+ }).catch((error: unknown) => {
3251
+ recordPeriodicGitProbeFailure(index, error);
3252
+ }).finally(() => {
3253
+ delete evidence.probeInFlight;
3254
+ });
3255
+ continue;
3256
+ }
3257
+ }
3138
3258
  const previous = step.activityState;
3139
3259
  step.activityState = "needs_attention";
3260
+ noteAttentionCause(index, "idle", previous);
3140
3261
  if (previous !== "needs_attention") {
3141
3262
  appendControlEvent(buildControlEvent(omitUndefinedProperties({
3142
3263
  from: previous,
@@ -3149,10 +3270,11 @@ export async function runSubagent(
3149
3270
  })));
3150
3271
  changed = true;
3151
3272
  }
3152
- } else if (maybeEmitOpenToolAttention(index, now)) {
3153
- changed = true;
3154
- } else if (maybeEmitActiveLongRunning(index, now)) {
3155
- changed = true;
3273
+ } else {
3274
+ // New activity (or an open tool) ended the idle period that raised the flag.
3275
+ if (resolveAttentionCause(index, "idle", now)) changed = true;
3276
+ if (maybeEmitOpenToolAttention(index, now)) changed = true;
3277
+ else if (maybeEmitActiveLongRunning(index, now)) changed = true;
3156
3278
  }
3157
3279
  }
3158
3280
  if (statusPayload.lastActivityAt !== runLastActivityAt) {
@@ -3196,11 +3318,15 @@ export async function runSubagent(
3196
3318
  };
3197
3319
  const finalizeWorktree = async (setup: WorktreeSetup, stepIndex: number, flatStartIndex: number, action: () => void, deadlineAt?: number): Promise<void> => {
3198
3320
  let admitted = false;
3199
- try { await withWorktreeTransaction(() => {
3200
- if (deadlineAt !== undefined && Date.now() >= deadlineAt) throw new Error("Run deadline expired before worktree cleanup");
3201
- admitted = true;
3202
- action();
3203
- }); }
3321
+ try {
3322
+ await Promise.all([...externalActivityEvidence.values()].map((evidence) => evidence.probeInFlight).filter((probe): probe is Promise<void> => probe !== undefined));
3323
+ if (periodicGitProbeFailure) throw periodicGitProbeFailure.error;
3324
+ await withWorktreeTransaction(() => {
3325
+ if (deadlineAt !== undefined && Date.now() >= deadlineAt) throw new Error("Run deadline expired before worktree cleanup");
3326
+ admitted = true;
3327
+ action();
3328
+ });
3329
+ }
3204
3330
  catch (error) {
3205
3331
  if (admitted) throw error;
3206
3332
  const reason = `Worktree finalization retained; manual reconciliation required: ${error instanceof Error ? error.message : String(error)}`;
@@ -3255,16 +3381,17 @@ export async function runSubagent(
3255
3381
  interruptActiveChildren();
3256
3382
  };
3257
3383
  const stopRunner = () => {
3258
- if (stopped || timedOut || interrupted || statusPayload.state !== "running") return;
3384
+ if (stopped || timedOut || (statusPayload.state !== "running" && statusPayload.state !== "paused")) return;
3259
3385
  stopped = true;
3386
+ interrupted = false;
3260
3387
  const now = Date.now();
3261
3388
  statusPayload.stopped = true;
3262
3389
  statusPayload.error = stopMessage;
3263
3390
  currentActivityState = undefined;
3264
3391
  delete statusPayload.activityState;
3265
3392
  statusPayload.lastUpdate = now;
3266
- for (const step of statusPayload.steps) {
3267
- if (step.status !== "running" && step.status !== "pending") continue;
3393
+ for (const [index, step] of statusPayload.steps.entries()) {
3394
+ if (step.status !== "running" && step.status !== "pending" && step.status !== "paused") continue;
3268
3395
  step.status = "stopped";
3269
3396
  step.error = stopMessage;
3270
3397
  step.exitCode = 1;
@@ -3273,6 +3400,8 @@ export async function runSubagent(
3273
3400
  step.endedAt = now;
3274
3401
  step.durationMs = step.startedAt ? now - step.startedAt : 0;
3275
3402
  step.lastActivityAt = now;
3403
+ const result = results[index];
3404
+ if (result?.interrupted) results[index] = { ...result, output: stopMessage, error: stopMessage, exitCode: 1, success: false, interrupted: false, stopped: true };
3276
3405
  }
3277
3406
  writeStatusPayload();
3278
3407
  appendJsonl(eventsPath, JSON.stringify({
@@ -3344,6 +3473,30 @@ export async function runSubagent(
3344
3473
  const remainingMs = Math.max(0, config.deadlineAt - Date.now());
3345
3474
  timeoutTimer = setTimeout(timeoutRunner, remainingMs);
3346
3475
  timeoutTimer.unref?.();
3476
+ // Route the pre-deadline checkpoint like any external steer so its lifecycle records the receipt.
3477
+ const checkpointBeforeDeadlineMs = config.checkpointBeforeDeadlineMs;
3478
+ const checkpointDelayMs = checkpointBeforeDeadlineMs === undefined || !Number.isInteger(checkpointBeforeDeadlineMs) || checkpointBeforeDeadlineMs <= 0
3479
+ ? undefined
3480
+ : remainingMs - checkpointBeforeDeadlineMs;
3481
+ if (checkpointDelayMs !== undefined && checkpointDelayMs >= 1_000) {
3482
+ const deadlineAt = config.deadlineAt;
3483
+ checkpointTimer = setTimeout(() => {
3484
+ checkpointTimer = undefined;
3485
+ if (timedOut || stopped || interrupted) return;
3486
+ if (!statusPayload.steps.some((step) => step.status === "running")) return;
3487
+ const now = Date.now();
3488
+ const seconds = Math.round(Math.max(0, deadlineAt - now) / 1000);
3489
+ deliverSteerRequest({
3490
+ type: "steer",
3491
+ id: `deadline-checkpoint-${now}`,
3492
+ ts: now,
3493
+ mode: "steer",
3494
+ source: "deadline-checkpoint",
3495
+ message: `Deadline checkpoint from the runner: this run is killed in about ${seconds} seconds. Finish the current tool call only, then stop and reply with a handoff: changed files, build/test state, remaining work, and commit/PR state. Do not start new work.`,
3496
+ });
3497
+ }, checkpointDelayMs);
3498
+ checkpointTimer.unref?.();
3499
+ }
3347
3500
  }
3348
3501
  appendJsonl(
3349
3502
  eventsPath,
@@ -3389,14 +3542,7 @@ export async function runSubagent(
3389
3542
  const thinkingOverride = step.thinkingOverrides?.[itemIndex];
3390
3543
  const model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;
3391
3544
  const configThinking = thinkingOverride ? thinkingOverride : step.parallel.thinking;
3392
- const candidates = step.parallel.modelCandidates !== undefined
3393
- ? step.parallel.modelCandidates.length > 0
3394
- ? step.parallel.modelCandidates.map((candidate) => thinkingOverride ? applyThinkingSuffix(candidate, thinkingOverride, true) ?? candidate : candidate)
3395
- : [undefined]
3396
- : model ? [model] : [undefined];
3397
- for (const candidate of candidates) {
3398
- assertThinkingWithinCeiling({ model: candidate, configThinking, ceiling: step.parallel.thinkingCeiling, agent: step.parallel.agent, runId: id });
3399
- }
3545
+ assertThinkingWithinCeiling({ model, configThinking, ceiling: step.parallel.thinkingCeiling, agent: step.parallel.agent, runId: id });
3400
3546
  }
3401
3547
  if (materialized.collectedOnEmpty) await validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);
3402
3548
  if (!config.runFanoutBudget) throw new Error("Async runner is missing its run fan-out budget identity.");
@@ -3529,10 +3675,6 @@ export async function runSubagent(
3529
3675
  ...(thinkingOverride ? {
3530
3676
  ...(model ? { model } : {}),
3531
3677
  ...(thinking ? { thinking } : {}),
3532
- ...(step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.flatMap((candidate) => {
3533
- const resolved = applyThinkingSuffix(candidate, thinkingOverride, true);
3534
- return resolved ? [resolved] : [];
3535
- }) } : {}),
3536
3678
  } : {}),
3537
3679
  structuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema,
3538
3680
  });
@@ -3543,6 +3685,7 @@ export async function runSubagent(
3543
3685
  return omitUndefinedProperties({
3544
3686
  agent: task.agent,
3545
3687
  ...(task.sessionName ? { sessionName: task.sessionName } : {}),
3688
+ ...(externalRunnerStatus(task.runner) ? { runner: externalRunnerStatus(task.runner) } : {}),
3546
3689
  ...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
3547
3690
  ...(task.context ? { context: task.context } : {}),
3548
3691
  ...(task.phase ?? step.phase ? { phase: task.phase ?? step.phase } : {}),
@@ -3559,7 +3702,7 @@ export async function runSubagent(
3559
3702
  ...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
3560
3703
  ...(task.thinking ? { thinking: task.thinking } : {}),
3561
3704
  ...(task.thinkingCeiling ? { thinkingCeiling: task.thinkingCeiling } : {}),
3562
- ...(task.modelCandidates && task.modelCandidates.length > 0 ? { attemptedModels: task.modelCandidates } : task.model ? { attemptedModels: [task.model] } : {}),
3705
+ ...(task.requestedModel ? { requestedModel: task.requestedModel } : {}),
3563
3706
  recentTools: [],
3564
3707
  recentOutput: [],
3565
3708
  });
@@ -3645,6 +3788,7 @@ export async function runSubagent(
3645
3788
  return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: "(skipped — fail-fast)", exitCode: -1 as number | null, skipped: true });
3646
3789
  }
3647
3790
  const taskStartTime = Date.now();
3791
+ launchedFlatIndices.add(fi);
3648
3792
  statusPayload.currentStep = fi;
3649
3793
  requiredStatusStep(statusPayload, fi).status = "running";
3650
3794
  delete requiredStatusStep(statusPayload, fi).error;
@@ -3665,6 +3809,7 @@ export async function runSubagent(
3665
3809
  artifactsDir, artifactConfig, id,
3666
3810
  flatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),
3667
3811
  outputFile: path.join(asyncDir, `output-${fi}.log`),
3812
+ projectTrusted: config.projectTrusted,
3668
3813
  piPackageRoot: config.piPackageRoot,
3669
3814
  childSessions,
3670
3815
  inheritedChildRuntime: config.inheritedChildRuntime,
@@ -3677,15 +3822,17 @@ export async function runSubagent(
3677
3822
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
3678
3823
  registerStop: (stop) => registerStepStop(fi, stop),
3679
3824
  registerSteer: (steer) => registerStepSteer(fi, steer),
3825
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
3680
3826
  timeoutSignal: timeoutAbortController.signal,
3681
3827
  stopSignal: stopAbortController.signal,
3682
- trackedMutationEvidenceForCompletionGuard: false,
3683
3828
  timeoutMessage,
3684
3829
  stopMessage,
3685
3830
  toolTimeoutMs: task.toolTimeoutMs ?? config.toolTimeoutMs,
3686
3831
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
3687
3832
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
3688
3833
  onExternalProcess: (process) => updateExternalProcess(fi, process),
3834
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
3835
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
3689
3836
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
3690
3837
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
3691
3838
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -3695,7 +3842,7 @@ export async function runSubagent(
3695
3842
  const taskEndTime = Date.now();
3696
3843
  const childInterrupted = singleResult.interrupted === true;
3697
3844
  const childStopped = singleResult.stopped === true;
3698
- requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
3845
+ requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
3699
3846
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
3700
3847
  requiredStatusStep(statusPayload, fi).durationMs = taskEndTime - taskStartTime;
3701
3848
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -3708,8 +3855,7 @@ export async function runSubagent(
3708
3855
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
3709
3856
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
3710
3857
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
3711
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
3712
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
3858
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
3713
3859
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
3714
3860
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
3715
3861
  if (singleResult.totalCost) {
@@ -3765,8 +3911,9 @@ export async function runSubagent(
3765
3911
  runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
3766
3912
  output: pr.output,
3767
3913
  outputState: pr.outputState,
3914
+ outputPartial: pr.outputPartial,
3768
3915
  error: pr.error,
3769
- success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
3916
+ success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
3770
3917
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
3771
3918
  skipped: pr.skipped,
3772
3919
  interrupted: pr.interrupted,
@@ -3778,12 +3925,13 @@ export async function runSubagent(
3778
3925
  intercomTarget: pr.intercomTarget,
3779
3926
  model: pr.model,
3780
3927
  thinking: pr.thinking,
3781
- attemptedModels: pr.attemptedModels,
3782
- modelAttempts: pr.modelAttempts,
3928
+ requestedModel: pr.requestedModel,
3783
3929
  contextOverflow: pr.contextOverflow,
3784
3930
  totalCost: pr.totalCost,
3785
3931
  usage: pr.usage,
3786
3932
  artifactPaths: pr.artifactPaths,
3933
+ outputSaveError: pr.outputSaveError,
3934
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
3787
3935
  transcriptPath: pr.transcriptPath,
3788
3936
  transcriptError: pr.transcriptError,
3789
3937
  effects: pr.effects,
@@ -4045,6 +4193,7 @@ export async function runSubagent(
4045
4193
  }
4046
4194
 
4047
4195
  const taskStartTime = Date.now();
4196
+ launchedFlatIndices.add(fi);
4048
4197
  statusPayload.currentStep = fi;
4049
4198
  requiredStatusStep(statusPayload, fi).status = "running";
4050
4199
  delete requiredStatusStep(statusPayload, fi).error;
@@ -4075,6 +4224,7 @@ export async function runSubagent(
4075
4224
  sessionDir: taskSessionDir,
4076
4225
  artifactsDir, artifactConfig, id,
4077
4226
  flatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),
4227
+ projectTrusted: config.projectTrusted,
4078
4228
  outputFile: path.join(asyncDir, `output-${fi}.log`),
4079
4229
  piPackageRoot: config.piPackageRoot,
4080
4230
  childSessions,
@@ -4088,15 +4238,17 @@ export async function runSubagent(
4088
4238
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
4089
4239
  registerStop: (stop) => registerStepStop(fi, stop),
4090
4240
  registerSteer: (steer) => registerStepSteer(fi, steer),
4241
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
4091
4242
  timeoutSignal: timeoutAbortController.signal,
4092
4243
  stopSignal: stopAbortController.signal,
4093
- trackedMutationEvidenceForCompletionGuard: Boolean(worktreeSetup),
4094
4244
  timeoutMessage,
4095
4245
  stopMessage,
4096
4246
  toolTimeoutMs: taskForRun.toolTimeoutMs ?? config.toolTimeoutMs,
4097
4247
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
4098
4248
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
4099
4249
  onExternalProcess: (process) => updateExternalProcess(fi, process),
4250
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
4251
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
4100
4252
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
4101
4253
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
4102
4254
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -4112,7 +4264,7 @@ export async function runSubagent(
4112
4264
  const childInterrupted = singleResult.interrupted === true;
4113
4265
  const childStopped = singleResult.stopped === true;
4114
4266
 
4115
- requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
4267
+ requiredStatusStep(statusPayload, fi).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
4116
4268
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
4117
4269
  requiredStatusStep(statusPayload, fi).durationMs = taskDuration;
4118
4270
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4125,8 +4277,7 @@ export async function runSubagent(
4125
4277
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
4126
4278
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
4127
4279
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
4128
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
4129
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
4280
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
4130
4281
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
4131
4282
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
4132
4283
  if (singleResult.totalCost) {
@@ -4166,20 +4317,6 @@ export async function runSubagent(
4166
4317
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskDuration,
4167
4318
  }));
4168
4319
  if (stopped || childStopped) appendTerminalChildStatusEvent(fi, taskEndTime);
4169
- if (singleResult.completionGuardTriggered) {
4170
- const event = buildControlEvent(omitUndefinedProperties({
4171
- from: requiredStatusStep(statusPayload, fi).activityState,
4172
- to: "needs_attention",
4173
- runId: id,
4174
- agent: task.agent,
4175
- index: fi,
4176
- ts: taskEndTime,
4177
- message: `${task.agent} completed without making edits for an implementation task`,
4178
- reason: "completion_guard",
4179
- }));
4180
- appendControlEvent(event);
4181
- }
4182
-
4183
4320
  if (singleResult.exitCode !== 0 && failFast && !childStopped) aborted = true;
4184
4321
  return stopped || childStopped ? { ...singleResult, output: stopMessage, error: stopMessage, exitCode: 1, interrupted: false, timedOut: false, stopped: true, skipped: false } : timedOut ? { ...singleResult, output: singleResult.output || (timeoutMessage ?? "Subagent timed out."), error: singleResult.error ?? timeoutMessage ?? "Subagent timed out.", exitCode: 1, interrupted: false, timedOut: true, skipped: false } : { ...singleResult, skipped: false };
4185
4322
  },
@@ -4193,7 +4330,7 @@ export async function runSubagent(
4193
4330
  const sessionTokens = config.sessionDir
4194
4331
  ? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`))
4195
4332
  : null;
4196
- const fallbackTokens = tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);
4333
+ const fallbackTokens = tokenUsageFromUsage(parallelResults[t]?.usage);
4197
4334
  const observedTokens = requiredStatusStep(statusPayload, fi).tokens;
4198
4335
  const taskTokens = sessionTokens ?? (fallbackTokens
4199
4336
  ? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
@@ -4223,8 +4360,9 @@ export async function runSubagent(
4223
4360
  launchResolvedExtensions: pr.launchResolvedExtensions,
4224
4361
  output: pr.output,
4225
4362
  outputState: pr.outputState,
4363
+ outputPartial: pr.outputPartial,
4226
4364
  error: pr.error,
4227
- success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
4365
+ success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
4228
4366
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
4229
4367
  skipped: pr.skipped,
4230
4368
  interrupted: pr.interrupted,
@@ -4236,20 +4374,21 @@ export async function runSubagent(
4236
4374
  intercomTarget: pr.intercomTarget,
4237
4375
  model: pr.model,
4238
4376
  thinking: pr.thinking,
4239
- attemptedModels: pr.attemptedModels,
4240
- modelAttempts: pr.modelAttempts,
4377
+ requestedModel: pr.requestedModel,
4241
4378
  contextOverflow: pr.contextOverflow,
4242
4379
  totalCost: pr.totalCost,
4243
4380
  usage: pr.usage,
4244
4381
  artifactPaths: pr.artifactPaths,
4382
+ outputSaveError: pr.outputSaveError,
4383
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
4245
4384
  transcriptPath: pr.transcriptPath,
4246
4385
  transcriptError: pr.transcriptError,
4247
- effects: pr.effects,
4248
- execution: pr.execution,
4249
- review: pr.review,
4250
- timeoutRecovery: pr.timeoutRecovery,
4251
- structuredOutput: pr.structuredOutput,
4252
- structuredOutputFailed: pr.structuredOutputFailed,
4386
+ effects: pr.effects,
4387
+ execution: pr.execution,
4388
+ review: pr.review,
4389
+ timeoutRecovery: pr.timeoutRecovery,
4390
+ structuredOutput: pr.structuredOutput,
4391
+ structuredOutputFailed: pr.structuredOutputFailed,
4253
4392
  structuredOutputPath: pr.structuredOutputPath,
4254
4393
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
4255
4394
  acceptance: pr.acceptance,
@@ -4275,7 +4414,7 @@ export async function runSubagent(
4275
4414
  exitCode: r.exitCode,
4276
4415
  error: r.error,
4277
4416
  model: r.model,
4278
- attemptedModels: r.attemptedModels,
4417
+ requestedModel: r.requestedModel,
4279
4418
  })),
4280
4419
  );
4281
4420
  if (worktreeSetup) {
@@ -4443,6 +4582,7 @@ export async function runSubagent(
4443
4582
  }
4444
4583
  const singleCwd = singleWorktreeSetup?.worktrees[0]?.agentCwd ?? cwd;
4445
4584
  const stepStartTime = Date.now();
4585
+ launchedFlatIndices.add(flatIndex);
4446
4586
  statusPayload.currentStep = flatIndex;
4447
4587
  requiredStatusStep(statusPayload, flatIndex).status = "running";
4448
4588
  delete requiredStatusStep(statusPayload, flatIndex).activityState;
@@ -4475,6 +4615,7 @@ export async function runSubagent(
4475
4615
  outputs: statusPayload.mode === "single" ? undefined : outputs,
4476
4616
  sessionDir: config.sessionDir,
4477
4617
  artifactsDir, artifactConfig, id,
4618
+ projectTrusted: config.projectTrusted,
4478
4619
  flatIndex, flatStepCount: Math.max(statusPayload.steps.length, 1),
4479
4620
  outputFile: path.join(asyncDir, `output-${flatIndex}.log`),
4480
4621
  piPackageRoot: config.piPackageRoot,
@@ -4489,6 +4630,7 @@ export async function runSubagent(
4489
4630
  registerTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),
4490
4631
  registerStop: (stop) => registerStepStop(flatIndex, stop),
4491
4632
  registerSteer: (steer) => registerStepSteer(flatIndex, steer),
4633
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, flatIndex, delivery),
4492
4634
  timeoutSignal: timeoutAbortController.signal,
4493
4635
  stopSignal: stopAbortController.signal,
4494
4636
  timeoutMessage,
@@ -4497,6 +4639,8 @@ export async function runSubagent(
4497
4639
  onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking, attempt.contextLimit),
4498
4640
  onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
4499
4641
  onExternalProcess: (process) => updateExternalProcess(flatIndex, process),
4642
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(flatIndex, externalCwd, signal),
4643
+ onExternalStreamActivity: () => recordExternalStreamActivity(flatIndex),
4500
4644
  onExternalJob: (externalJob) => updateExternalJob(flatIndex, externalJob),
4501
4645
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(flatIndex),
4502
4646
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -4523,20 +4667,22 @@ export async function runSubagent(
4523
4667
  runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
4524
4668
  output: stopped || childStopped ? stopMessage : timedOut ? singleResult.output || (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
4525
4669
  outputState: singleResult.outputState,
4670
+ outputPartial: singleResult.outputPartial,
4526
4671
  error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
4527
- success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
4672
+ success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0 && singleResult.execution?.status !== "partial",
4528
4673
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,
4529
4674
  sessionFile: singleResult.sessionFile,
4530
4675
  intercomTarget: singleResult.intercomTarget,
4531
4676
  model: singleResult.model,
4532
4677
  thinking: singleResult.thinking,
4533
- attemptedModels: singleResult.attemptedModels,
4534
- modelAttempts: singleResult.modelAttempts,
4678
+ requestedModel: singleResult.requestedModel,
4535
4679
  contextOverflow: singleResult.contextOverflow,
4536
4680
  totalCost: singleResult.totalCost,
4537
4681
  usage: singleResult.usage,
4538
4682
  artifactPaths: singleResult.artifactPaths,
4539
4683
  savedOutputPath: singleResult.savedOutputPath,
4684
+ outputSaveError: singleResult.outputSaveError,
4685
+ artifactOutputSaveFailed: singleResult.artifactOutputSaveFailed,
4540
4686
  transcriptPath: singleResult.transcriptPath,
4541
4687
  transcriptError: singleResult.transcriptError,
4542
4688
  effects: singleResult.effects,
@@ -4582,7 +4728,7 @@ export async function runSubagent(
4582
4728
  if (cumulativeTokens) {
4583
4729
  previousCumulativeTokens = cumulativeTokens;
4584
4730
  } else {
4585
- const fallbackTokens = tokenUsageFromAttempts(singleResult.modelAttempts);
4731
+ const fallbackTokens = tokenUsageFromUsage(singleResult.usage);
4586
4732
  const observedTokens = requiredStatusStep(statusPayload, flatIndex).tokens;
4587
4733
  stepTokens = fallbackTokens
4588
4734
  ? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
@@ -4602,7 +4748,7 @@ export async function runSubagent(
4602
4748
 
4603
4749
  const stepEndTime = Date.now();
4604
4750
  const childInterrupted = singleResult.interrupted === true;
4605
- requiredStatusStep(statusPayload, flatIndex).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.exitCode === 0 ? "complete" : "failed";
4751
+ requiredStatusStep(statusPayload, flatIndex).status = stopped || childStopped ? "stopped" : timedOut ? "failed" : childInterrupted ? "paused" : singleResult.execution?.status === "partial" ? "partial" : singleResult.exitCode === 0 ? "complete" : "failed";
4606
4752
  requiredStatusStep(statusPayload, flatIndex).endedAt = stepEndTime;
4607
4753
  requiredStatusStep(statusPayload, flatIndex).durationMs = stepEndTime - stepStartTime;
4608
4754
  requiredStatusStep(statusPayload, flatIndex).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4615,8 +4761,7 @@ export async function runSubagent(
4615
4761
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "sessionName", singleResult.sessionName);
4616
4762
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "model", singleResult.model);
4617
4763
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, flatIndex).thinking));
4618
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "attemptedModels", singleResult.attemptedModels);
4619
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "modelAttempts", singleResult.modelAttempts);
4764
+ setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "requestedModel", singleResult.requestedModel);
4620
4765
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "contextOverflow", singleResult.contextOverflow);
4621
4766
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "totalCost", singleResult.totalCost);
4622
4767
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "error", stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error);
@@ -4705,20 +4850,6 @@ export async function runSubagent(
4705
4850
  });
4706
4851
  }
4707
4852
 
4708
- if (singleResult.completionGuardTriggered) {
4709
- const event = buildControlEvent(omitUndefinedProperties({
4710
- from: requiredStatusStep(statusPayload, flatIndex).activityState,
4711
- to: "needs_attention",
4712
- runId: id,
4713
- agent: seqStep.agent,
4714
- index: flatIndex,
4715
- ts: stepEndTime,
4716
- message: `${seqStep.agent} completed without making edits for an implementation task`,
4717
- reason: "completion_guard",
4718
- }));
4719
- appendControlEvent(event);
4720
- }
4721
-
4722
4853
  flatIndex++;
4723
4854
  if (isAgentContract(seqStep.agentContract) && seqStep.gateOn === "acceptance" && singleResult.acceptance?.status === "rejected") {
4724
4855
  statusPayload.error = acceptanceFailureMessage(singleResult.acceptance) ?? "Chain acceptance gate rejected the step.";
@@ -4731,6 +4862,34 @@ export async function runSubagent(
4731
4862
  }
4732
4863
  }
4733
4864
 
4865
+ await Promise.all([...externalActivityEvidence.values()].map((evidence) => evidence.probeInFlight).filter((probe): probe is Promise<void> => probe !== undefined));
4866
+ if (periodicGitProbeFailure) {
4867
+ stopped = false;
4868
+ timedOut = false;
4869
+ interrupted = false;
4870
+ delete statusPayload.stopped;
4871
+ delete statusPayload.timedOut;
4872
+ statusPayload.error = periodicGitProbeFailure.message;
4873
+ const step = statusPayload.steps[periodicGitProbeFailure.index];
4874
+ if (step) {
4875
+ step.status = "failed";
4876
+ step.error = periodicGitProbeFailure.message;
4877
+ step.exitCode = 1;
4878
+ delete step.stopped;
4879
+ delete step.timedOut;
4880
+ }
4881
+ const result = results[periodicGitProbeFailure.index];
4882
+ if (result) {
4883
+ result.success = false;
4884
+ result.exitCode = 1;
4885
+ result.error = periodicGitProbeFailure.message;
4886
+ result.output = periodicGitProbeFailure.message;
4887
+ result.stopped = false;
4888
+ result.timedOut = false;
4889
+ result.interrupted = false;
4890
+ }
4891
+ }
4892
+
4734
4893
  let summary = results.map((r) => `${r.agent}:\n${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join("\n\n");
4735
4894
  let truncated = false;
4736
4895
 
@@ -4796,9 +4955,21 @@ export async function runSubagent(
4796
4955
  clearTimeout(timeoutTimer);
4797
4956
  timeoutTimer = undefined;
4798
4957
  }
4958
+ if (checkpointTimer) {
4959
+ clearTimeout(checkpointTimer);
4960
+ checkpointTimer = undefined;
4961
+ }
4799
4962
  if (!timedOut && !stopped && !interrupted && config.timeoutMs !== undefined && timeoutMessage !== undefined && results.some((result) => result.timedOut === true && result.error?.startsWith(timeoutMessage))) {
4800
4963
  timedOut = true;
4801
4964
  }
4965
+ disposeControlInbox();
4966
+ try {
4967
+ closeStopInbox(asyncDir);
4968
+ } catch (error) {
4969
+ // Result publication must not depend on the marker; without it a late stop is accepted as before.
4970
+ appendJsonl(eventsPath, JSON.stringify({ type: "subagent.run.stop_inbox_close_failed", ts: Date.now(), runId: id, message: error instanceof Error ? error.message : String(error) }));
4971
+ }
4972
+ for (const request of consumeStopRequestPayloads(asyncDir)) stopChildStep(request);
4802
4973
  const signalTerminated = !stopped && !timedOut && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
4803
4974
  processSignal: result.processSignal,
4804
4975
  interrupted: result.interrupted,
@@ -4813,7 +4984,6 @@ export async function runSubagent(
4813
4984
  });
4814
4985
  statusPayload.state = stopped || signalTerminated ? "stopped" : timedOut || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : partialWithEvidence ? "partial" : "failed";
4815
4986
  closeSteerInbox(asyncDir, statusPayload.state, (filePath, payload) => runPersistence.write(filePath, payload));
4816
- disposeControlInbox();
4817
4987
  for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
4818
4988
  const effectiveSessionFile = sessionFile ?? latestSessionFile;
4819
4989
  const steeringLifecycle = steeringStatus(statusPayload);
@@ -4822,7 +4992,7 @@ export async function runSubagent(
4822
4992
  for (const target of request.targets) {
4823
4993
  if (target.state !== "scheduled" && target.state !== "routed" && target.state !== "queued") continue;
4824
4994
  changed = true;
4825
- const reason = target.state === "queued" ? "run ended before queued follow-up delivery" : "child terminated before steering delivery";
4995
+ const reason = target.state === "queued" ? unconsumedSteerReason() : "child terminated before steering delivery";
4826
4996
  updateSteeringLifecycleTarget(request.id, target.index, "failed", Date.now(), { reason });
4827
4997
  markSteeringAttention(target.index);
4828
4998
  emitSteeringEvent("subagent.steer.failed", { type: "steer", id: request.id, ts: request.requestedAt, message: reason }, target.index, { reason });
@@ -4849,7 +5019,7 @@ export async function runSubagent(
4849
5019
  statusPayload.activityState = "needs_attention";
4850
5020
  statusPayload.error = partialResult?.error ?? statusPayload.error;
4851
5021
  for (const step of statusPayload.steps) {
4852
- if (step.status === "failed") step.activityState = "needs_attention";
5022
+ if (step.status === "failed" || step.status === "partial") step.activityState = "needs_attention";
4853
5023
  }
4854
5024
  }
4855
5025
  statusPayload.endedAt = runEndedAt;
@@ -4893,6 +5063,7 @@ export async function runSubagent(
4893
5063
  context: r.context,
4894
5064
  output: r.output,
4895
5065
  outputState: r.outputState,
5066
+ outputPartial: r.outputPartial,
4896
5067
  error: r.error,
4897
5068
  success: r.success,
4898
5069
  skipped: r.skipped || undefined,
@@ -4906,14 +5077,14 @@ export async function runSubagent(
4906
5077
  intercomTarget: r.intercomTarget,
4907
5078
  model: r.model,
4908
5079
  thinking: r.thinking,
4909
- attemptedModels: r.attemptedModels,
4910
- modelAttempts: r.modelAttempts,
5080
+ requestedModel: r.requestedModel,
4911
5081
  contextOverflow: r.contextOverflow,
4912
5082
  totalCost: r.totalCost,
4913
5083
  usage: r.usage,
4914
5084
  artifactPaths: r.artifactPaths,
4915
5085
  savedOutputPath: r.savedOutputPath,
4916
5086
  outputSaveError: r.outputSaveError,
5087
+ artifactOutputSaveFailed: r.artifactOutputSaveFailed,
4917
5088
  metadataSaveError: r.metadataSaveError,
4918
5089
  truncated: r.truncated,
4919
5090
  transcriptPath: r.transcriptPath,
@@ -4995,6 +5166,26 @@ export async function runSubagent(
4995
5166
  usageBudget: statusPayload.usageBudget,
4996
5167
  }),
4997
5168
  );
5169
+ // Paused runs record an interrupted attempt; a later resume records another.
5170
+ for (const historyEntry of planBackgroundRunHistory({
5171
+ steps,
5172
+ resultMode,
5173
+ statusSteps: statusPayload.steps.map((step, index) => ({
5174
+ agent: step.agent,
5175
+ status: step.status,
5176
+ durationMs: step.durationMs,
5177
+ timedOut: step.timedOut,
5178
+ stopped: step.stopped,
5179
+ launched: launchedFlatIndices.has(index),
5180
+ })),
5181
+ stepResults: results,
5182
+ runDurationMs: runEndedAt - overallStartTime,
5183
+ stopped,
5184
+ interrupted,
5185
+ timedOut,
5186
+ })) {
5187
+ recordRun(historyEntry.agent, historyEntry.task, historyEntry.exitCode, historyEntry.durationMs, historyEntry.terminal);
5188
+ }
4998
5189
  writeRunLog(logPath, omitUndefinedProperties({
4999
5190
  id,
5000
5191
  mode: statusPayload.mode,
@@ -5047,149 +5238,40 @@ export async function runSubagent(
5047
5238
  }
5048
5239
  }
5049
5240
 
5050
- async function waitForStartupControl(
5051
- controlPath: string,
5052
- token: string,
5053
- action: "ack" | "proceed",
5054
- timeoutMs = 30_000,
5055
- ): Promise<void> {
5056
- const deadline = Date.now() + timeoutMs;
5057
- while (Date.now() <= deadline) {
5058
- if (fs.existsSync(controlPath)) {
5059
- let payload: { action?: unknown; token?: unknown };
5060
- try {
5061
- payload = JSON.parse(fs.readFileSync(controlPath, "utf-8")) as { action?: unknown; token?: unknown };
5062
- } catch (error) {
5063
- throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
5064
- }
5065
- if (payload.token !== token) throw new Error("Runner startup control token does not match.");
5066
- if (payload.action === action) return;
5067
- if (payload.action !== "ack" && payload.action !== "proceed") throw new Error("Runner startup control action is invalid.");
5068
- }
5069
- await new Promise((resolve) => setTimeout(resolve, 20));
5070
- }
5071
- throw new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);
5072
- }
5073
-
5074
- async function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {
5075
- let lease: ReturnType<typeof acquireSessionLease> | undefined;
5076
- let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
5077
- const startupPath = path.join(config.asyncDir, "runner-startup.json");
5078
- const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
5079
- const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
5080
- const releaseOnExit = (): void => {
5081
- try {
5082
- lease?.release();
5083
- } catch {
5084
- // Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.
5085
- }
5086
- };
5087
- process.once("exit", releaseOnExit);
5241
+ /** Heavy execution entry loaded by the bootstrap only after startup commits. */
5242
+ export async function runConfiguredSubagentExecution(config: SubagentRunConfig, options?: DefaultChildSessionFactoryOptions): Promise<void> {
5243
+ let childSessions: ChildSessionFactory;
5088
5244
  try {
5089
- if (config.launchBarrierToken) {
5090
- await waitForStartupControl(startupProceedPath, config.launchBarrierToken, "proceed");
5091
- startupCommitted = true;
5092
- try {
5093
- fs.rmSync(startupProceedPath, { force: true });
5094
- } catch {
5095
- // Startup control cleanup is best effort after the parent commits the run.
5096
- }
5097
- } else if (config.revivalLease) {
5098
- lease = acquireSessionLease(config.revivalLease);
5099
- config.revivalLeaseToken = lease.owner.token;
5100
- writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
5101
- await waitForStartupControl(startupAckPath, lease.owner.token, "ack");
5102
- writeAtomicJson(startupPath, { state: "acknowledged", token: lease.owner.token, pid: process.pid });
5103
- await waitForStartupControl(startupProceedPath, lease.owner.token, "proceed");
5104
- startupCommitted = true;
5105
- for (const controlPath of [startupAckPath, startupProceedPath]) {
5106
- try {
5107
- fs.rmSync(controlPath, { force: true });
5108
- } catch {
5109
- // Startup control cleanup is best effort after the parent commits the run.
5110
- }
5111
- }
5112
- }
5113
- const childSessions = await loadRunnerChildSessionFactory(config);
5114
- try {
5115
- await runSubagent(config, childSessions);
5116
- } finally {
5117
- try {
5118
- await childSessions.dispose();
5119
- } catch (error) {
5120
- console.error("Failed to dispose runner child sessions:", error);
5121
- }
5122
- }
5245
+ // Detached Node runners do not receive Pi's CLI dispatcher setup. Binary
5246
+ // hosts install the same dispatcher before entering the shared bootstrap.
5247
+ if (!options?.loadPiCodingAgent) installRunnerHttpDispatcher({ agentDir: getAgentDir(), cwd: process.cwd() });
5248
+ childSessions = await loadRunnerChildSessionFactory(config, options);
5123
5249
  } catch (error) {
5124
- if (!startupCommitted) {
5125
- try {
5126
- writeAtomicJson(startupPath, { state: "error", pid: process.pid, error: error instanceof Error ? error.message : String(error) });
5127
- } catch {
5128
- // The parent will time out and terminate this runner if the handshake cannot be written.
5129
- }
5250
+ try {
5251
+ persistRunnerStartupFailure({
5252
+ asyncDir: config.asyncDir,
5253
+ runId: config.id,
5254
+ runnerProcessInstanceId: config.runnerProcessInstanceId ?? "unknown-runner-instance",
5255
+ message: `Subagent runner startup failed: ${error instanceof Error ? error.message : String(error)}`,
5256
+ ...(config.sessionId ? { sessionId: config.sessionId } : {}),
5257
+ ...(config.completionOwnerId ? { completionOwnerId: config.completionOwnerId } : {}),
5258
+ candidate: {
5259
+ ...(config.revivalLease?.sessionFile ? { sessionFile: config.revivalLease.sessionFile } : {}),
5260
+ ...(config.revivalLeaseToken ? { revivalLeaseToken: config.revivalLeaseToken } : {}),
5261
+ },
5262
+ });
5263
+ } catch (persistenceError) {
5264
+ console.error("Failed to persist runner setup failure:", persistenceError);
5130
5265
  }
5131
5266
  throw error;
5132
- } finally {
5133
- process.off("exit", releaseOnExit);
5134
- if (lease) {
5135
- let acknowledged = false;
5136
- try {
5137
- acknowledged = lease.release();
5138
- } catch (error) {
5139
- console.error("Failed to release session revival lease:", error);
5140
- }
5141
- try {
5142
- markProcessTerminalCandidateLeaseRelease(config.asyncDir, lease.owner.token, acknowledged);
5143
- } catch (error) {
5144
- console.error("Failed to record session revival lease release:", error);
5145
- }
5146
- }
5147
5267
  }
5148
- }
5149
-
5150
- function startConfiguredSubagent(config: SubagentRunConfig): void {
5151
- // Child sessions and the extensions loaded into them may leave handles
5152
- // behind even after shutdown; the run is fully persisted by now, so exit
5153
- // explicitly instead of waiting for the event loop to drain.
5154
- runConfiguredSubagent(config).then(
5155
- () => process.exit(0),
5156
- (runErr) => {
5157
- console.error("Subagent runner error:", runErr);
5158
- process.exit(1);
5159
- },
5160
- );
5161
- }
5162
-
5163
- if (isRunnerEntrypoint) {
5164
- const configArg = process.argv[2];
5165
- if (configArg) {
5166
5268
  try {
5167
- const configJson = fs.readFileSync(configArg, "utf-8");
5168
- const config = JSON.parse(configJson) as SubagentRunConfig;
5269
+ await runSubagent(config, childSessions);
5270
+ } finally {
5169
5271
  try {
5170
- fs.unlinkSync(configArg);
5171
- } catch {
5172
- // Temp config cleanup is best effort.
5272
+ await childSessions.dispose();
5273
+ } catch (error) {
5274
+ console.error("Failed to dispose runner child sessions:", error);
5173
5275
  }
5174
- startConfiguredSubagent(config);
5175
- } catch (err) {
5176
- console.error("Subagent runner error:", err);
5177
- process.exit(1);
5178
5276
  }
5179
- } else {
5180
- let input = "";
5181
- process.stdin.setEncoding("utf-8");
5182
- process.stdin.on("data", (chunk) => {
5183
- input += chunk;
5184
- });
5185
- process.stdin.on("end", () => {
5186
- try {
5187
- const config = JSON.parse(input) as SubagentRunConfig;
5188
- startConfiguredSubagent(config);
5189
- } catch (err) {
5190
- console.error("Subagent runner error:", err);
5191
- process.exit(1);
5192
- }
5193
- });
5194
- }
5195
5277
  }