@selesai/code 0.13.40 → 0.14.3

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 (1360) 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 +45 -7
  15. package/dist/config.js +134 -18
  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/keybindings.d.ts +25 -24
  59. package/dist/core/keybindings.js +27 -6
  60. package/dist/core/mcp-servers.d.ts +134 -0
  61. package/dist/core/mcp-servers.js +223 -0
  62. package/dist/core/model-config.d.ts +122 -5
  63. package/dist/core/model-config.js +35 -1
  64. package/dist/core/model-registry.d.ts +23 -15
  65. package/dist/core/model-registry.js +46 -22
  66. package/dist/core/model-resolver.d.ts +6 -5
  67. package/dist/core/model-resolver.js +51 -21
  68. package/dist/core/model-runtime.d.ts +73 -14
  69. package/dist/core/model-runtime.js +398 -104
  70. package/dist/core/models-store.d.ts +12 -7
  71. package/dist/core/models-store.js +85 -15
  72. package/dist/core/nested-tool-calls.d.ts +102 -0
  73. package/dist/core/nested-tool-calls.js +178 -0
  74. package/dist/core/package-manager.d.ts +8 -1
  75. package/dist/core/package-manager.js +144 -61
  76. package/dist/core/package-manager.test.js +5 -5
  77. package/dist/core/pi-manifest.d.ts +9 -0
  78. package/dist/core/pi-manifest.js +25 -0
  79. package/dist/core/prompt-templates.d.ts +6 -1
  80. package/dist/core/prompt-templates.js +61 -35
  81. package/dist/core/provider-composer.d.ts +44 -19
  82. package/dist/core/provider-composer.js +166 -64
  83. package/dist/core/radius.d.ts +2 -0
  84. package/dist/core/radius.js +2 -0
  85. package/dist/core/remote-catalog-provider.d.ts +8 -1
  86. package/dist/core/remote-catalog-provider.js +25 -13
  87. package/dist/core/resource-loader.d.ts +9 -1
  88. package/dist/core/resource-loader.js +179 -45
  89. package/dist/core/runtime-credentials.d.ts +5 -5
  90. package/dist/core/runtime-credentials.js +11 -8
  91. package/dist/core/sdk.d.ts +16 -7
  92. package/dist/core/sdk.js +57 -24
  93. package/dist/core/session-manager.d.ts +45 -9
  94. package/dist/core/session-manager.js +124 -31
  95. package/dist/core/settings-diagnostics.d.ts +8 -0
  96. package/dist/core/settings-diagnostics.js +20 -0
  97. package/dist/core/settings-manager.d.ts +62 -32
  98. package/dist/core/settings-manager.js +147 -69
  99. package/dist/core/skills.d.ts +5 -2
  100. package/dist/core/skills.js +58 -35
  101. package/dist/core/slash-commands.js +2 -1
  102. package/dist/core/source-info.d.ts +8 -0
  103. package/dist/core/source-info.js +16 -0
  104. package/dist/core/system-prompt.d.ts +9 -3
  105. package/dist/core/system-prompt.js +9 -12
  106. package/dist/core/system-prompt.test.js +2 -7
  107. package/dist/core/tools/bash.d.ts +12 -0
  108. package/dist/core/tools/bash.js +33 -2
  109. package/dist/core/tools/edit-diff.d.ts +0 -5
  110. package/dist/core/tools/edit-diff.js +2 -5
  111. package/dist/core/tools/edit.d.ts +4 -0
  112. package/dist/core/tools/edit.js +31 -11
  113. package/dist/core/tools/find.d.ts +7 -0
  114. package/dist/core/tools/find.js +16 -19
  115. package/dist/core/tools/grep.d.ts +4 -0
  116. package/dist/core/tools/grep.js +5 -1
  117. package/dist/core/tools/index.d.ts +1 -1
  118. package/dist/core/tools/index.js +11 -2
  119. package/dist/core/tools/ls.d.ts +4 -0
  120. package/dist/core/tools/ls.js +5 -1
  121. package/dist/core/tools/output-accumulator.d.ts +11 -0
  122. package/dist/core/tools/output-accumulator.js +40 -10
  123. package/dist/core/tools/read.d.ts +17 -2
  124. package/dist/core/tools/read.js +23 -2
  125. package/dist/core/tools/render-utils.d.ts +6 -0
  126. package/dist/core/tools/render-utils.js +26 -0
  127. package/dist/core/tools/renderers/bash.js +19 -35
  128. package/dist/core/tools/renderers/edit.js +5 -4
  129. package/dist/core/tools/renderers/index.d.ts +2 -2
  130. package/dist/core/tools/renderers/read.js +3 -2
  131. package/dist/core/tools/tool-definition-wrapper.d.ts +5 -3
  132. package/dist/core/tools/tool-definition-wrapper.js +3 -1
  133. package/dist/core/tools/truncate.d.ts +14 -0
  134. package/dist/core/tools/truncate.js +29 -0
  135. package/dist/core/tools/write.d.ts +4 -0
  136. package/dist/core/tools/write.js +6 -2
  137. package/dist/core/trust-manager.js +3 -1
  138. package/dist/core/usage-totals.d.ts +2 -0
  139. package/dist/core/usage-totals.js +23 -0
  140. package/dist/core/virtual-models.d.ts +116 -0
  141. package/dist/core/virtual-models.js +123 -0
  142. package/dist/defaults/models.json +32 -0
  143. package/dist/defaults/settings.json +1 -9
  144. package/dist/extensions/codemode/execute.d.ts +15 -0
  145. package/dist/extensions/codemode/execute.js +645 -0
  146. package/dist/extensions/codemode/execute.lazy.d.ts +2 -0
  147. package/dist/extensions/codemode/execute.lazy.js +2 -0
  148. package/dist/extensions/codemode/index.d.ts +20 -0
  149. package/dist/extensions/codemode/index.js +31 -0
  150. package/dist/extensions/codemode/renderer.d.ts +11 -0
  151. package/dist/extensions/codemode/renderer.js +136 -0
  152. package/dist/extensions/codemode/tool.d.ts +129 -0
  153. package/dist/extensions/codemode/tool.js +275 -0
  154. package/dist/extensions/context-compaction-reminder.ts +1 -1
  155. package/dist/extensions/grep-app/index.ts +2 -10
  156. package/dist/extensions/herdr-agent-state.ts +1 -1
  157. package/dist/extensions/{pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts → index.d.ts} +0 -1
  158. package/dist/extensions/index.js +12 -0
  159. package/dist/extensions/jev/classifier-context.ts +54 -0
  160. package/dist/extensions/jev/classifier.test.ts +150 -0
  161. package/dist/extensions/jev/classifier.ts +191 -0
  162. package/dist/extensions/jev/decisions.test.ts +56 -47
  163. package/dist/extensions/jev/decisions.ts +94 -109
  164. package/dist/extensions/jev/test-support.ts +33 -38
  165. package/dist/extensions/jev-advisory-lifecycle.test.ts +12 -12
  166. package/dist/extensions/jev-advisory-memory.test.ts +9 -9
  167. package/dist/extensions/jev-advisory-recommendations.test.ts +8 -8
  168. package/dist/extensions/jev-ask-tool.test.ts +41 -45
  169. package/dist/extensions/jev-ask-tool.ts +11 -39
  170. package/dist/extensions/jev-find-source.test.ts +26 -0
  171. package/dist/extensions/jev-find-source.ts +58 -19
  172. package/dist/extensions/jev-tool-ranker.test.ts +185 -0
  173. package/dist/extensions/jev-tool-ranker.ts +169 -0
  174. package/dist/{core → extensions}/llama/client.d.ts +2 -0
  175. package/dist/{core → extensions}/llama/client.js +7 -3
  176. package/dist/{core → extensions}/llama/index.js +13 -2
  177. package/dist/{core → extensions}/llama/provider.d.ts +1 -1
  178. package/dist/extensions/llama/provider.js +235 -0
  179. package/dist/extensions/mcp/cli.d.ts +20 -0
  180. package/dist/extensions/mcp/cli.js +496 -0
  181. package/dist/extensions/mcp/cli.lazy.d.ts +2 -0
  182. package/dist/extensions/mcp/cli.lazy.js +2 -0
  183. package/dist/extensions/mcp/config.d.ts +83 -0
  184. package/dist/extensions/mcp/config.js +193 -0
  185. package/dist/extensions/mcp/index.d.ts +78 -0
  186. package/dist/extensions/mcp/index.js +1201 -0
  187. package/dist/extensions/mcp/log.d.ts +15 -0
  188. package/dist/extensions/mcp/log.js +65 -0
  189. package/dist/extensions/mcp/oauth.d.ts +97 -0
  190. package/dist/extensions/mcp/oauth.js +401 -0
  191. package/dist/extensions/mcp/resources.d.ts +41 -0
  192. package/dist/extensions/mcp/resources.js +260 -0
  193. package/dist/extensions/mcp/runtime.d.ts +96 -0
  194. package/dist/extensions/mcp/runtime.js +412 -0
  195. package/dist/extensions/mcp/runtime.lazy.d.ts +2 -0
  196. package/dist/extensions/mcp/runtime.lazy.js +2 -0
  197. package/dist/extensions/mcp/tools.d.ts +86 -0
  198. package/dist/extensions/mcp/tools.js +252 -0
  199. package/dist/extensions/mcp/ui.d.ts +59 -0
  200. package/dist/extensions/mcp/ui.js +185 -0
  201. package/dist/extensions/package.json +2 -1
  202. package/dist/extensions/pi-graft/index.ts +4 -19
  203. package/dist/extensions/pi-graft/lifecycle.test.ts +32 -25
  204. package/dist/extensions/pi-graft/tools.ts +6 -0
  205. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +25 -0
  206. package/dist/extensions/pi-hermes-memory/README.md +140 -4
  207. package/dist/extensions/pi-hermes-memory/package-lock.json +624 -2720
  208. package/dist/extensions/pi-hermes-memory/package.json +9 -7
  209. package/dist/extensions/pi-hermes-memory/scripts/benchmark-memory-startup.mjs +72 -0
  210. package/dist/extensions/pi-hermes-memory/scripts/check-production-install.mjs +107 -0
  211. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +2 -1
  212. package/dist/extensions/pi-hermes-memory/src/config.ts +35 -0
  213. package/dist/extensions/pi-hermes-memory/src/constants.ts +62 -15
  214. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +374 -50
  215. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +7 -4
  216. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +19 -14
  217. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +75 -1
  218. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +322 -22
  219. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +8 -0
  220. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +193 -54
  221. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +6 -2
  222. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +33 -5
  223. package/dist/extensions/pi-hermes-memory/src/index.ts +116 -47
  224. package/dist/extensions/pi-hermes-memory/src/memory-initialization.ts +101 -0
  225. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +10 -2
  226. package/dist/extensions/pi-hermes-memory/src/store/db.ts +34 -9
  227. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +44 -8
  228. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +3 -1
  229. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +141 -0
  230. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +17 -6
  231. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +20 -10
  232. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +1 -17
  233. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +2 -10
  234. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +4 -8
  235. package/dist/extensions/pi-hermes-memory/src/types.ts +48 -0
  236. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +108 -0
  237. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +1185 -42
  238. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +57 -1
  239. package/dist/extensions/pi-hermes-memory/tests/handlers/lazy-memory-hooks.test.ts +128 -0
  240. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +844 -1
  241. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +16 -0
  242. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +512 -3
  243. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +38 -0
  244. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +183 -2
  245. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +1 -3
  246. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +17 -0
  247. package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +21 -0
  248. package/dist/extensions/pi-hermes-memory/tests/lazy-startup.test.ts +313 -0
  249. package/dist/extensions/pi-hermes-memory/tests/memory-initialization.test.ts +182 -0
  250. package/dist/extensions/pi-hermes-memory/tests/prompt-injection.test.ts +184 -0
  251. package/dist/extensions/pi-hermes-memory/tests/skill-discovery-contract.test.ts +60 -0
  252. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-lazy-probe.test.ts +80 -0
  253. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +2 -0
  254. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +79 -0
  255. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +268 -0
  256. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +29 -0
  257. package/dist/extensions/pi-hermes-memory/tests/store/usage-tracking.test.ts +170 -0
  258. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +80 -1
  259. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +51 -0
  260. package/dist/extensions/pi-intercom/CHANGELOG.md +66 -0
  261. package/dist/extensions/pi-intercom/README.md +100 -12
  262. package/dist/extensions/pi-intercom/broker/broker.ts +28 -12
  263. package/dist/extensions/pi-intercom/broker/client.ts +3 -0
  264. package/dist/extensions/pi-intercom/broker/cross-machine-provenance.test.ts +63 -0
  265. package/dist/extensions/pi-intercom/broker/protocol.ts +64 -0
  266. package/dist/extensions/pi-intercom/broker/spawn.test.ts +58 -167
  267. package/dist/extensions/pi-intercom/broker/spawn.ts +40 -87
  268. package/dist/extensions/pi-intercom/cli.mjs +6 -0
  269. package/dist/extensions/pi-intercom/cli.test.ts +428 -0
  270. package/dist/extensions/pi-intercom/cli.ts +343 -0
  271. package/dist/extensions/pi-intercom/config.test.ts +61 -1
  272. package/dist/extensions/pi-intercom/config.ts +53 -2
  273. package/dist/extensions/pi-intercom/cross-machine-discovery.test.ts +218 -0
  274. package/dist/extensions/pi-intercom/cross-machine-discovery.ts +140 -0
  275. package/dist/extensions/pi-intercom/cross-machine-envelope.test.ts +106 -0
  276. package/dist/extensions/pi-intercom/cross-machine-envelope.ts +92 -0
  277. package/dist/extensions/pi-intercom/cross-machine-integration.test.ts +25 -0
  278. package/dist/extensions/pi-intercom/cross-machine-transport.test.ts +106 -0
  279. package/dist/extensions/pi-intercom/cross-machine-transport.ts +110 -0
  280. package/dist/extensions/pi-intercom/extension-api.ts +14 -0
  281. package/dist/extensions/pi-intercom/handover.test.ts +88 -0
  282. package/dist/extensions/pi-intercom/handover.ts +115 -0
  283. package/dist/extensions/pi-intercom/herdr-location.test.ts +173 -0
  284. package/dist/extensions/pi-intercom/herdr-location.ts +137 -0
  285. package/dist/extensions/pi-intercom/human-priority.pi.test.ts +489 -0
  286. package/dist/extensions/pi-intercom/index.ts +582 -164
  287. package/dist/extensions/pi-intercom/intercom.integration.test.ts +590 -22
  288. package/dist/extensions/pi-intercom/package.json +12 -2
  289. package/dist/extensions/pi-intercom/project-agent.ts +1 -1
  290. package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +26 -2
  291. package/dist/extensions/pi-intercom/test/handover-picker.test.ts +134 -0
  292. package/dist/extensions/pi-intercom/test/inline-message.test.ts +43 -0
  293. package/dist/extensions/pi-intercom/types.d.ts +247 -0
  294. package/dist/extensions/pi-intercom/types.js +2 -0
  295. package/dist/extensions/pi-intercom/types.ts +39 -1
  296. package/dist/extensions/pi-intercom/ui/handover-picker.ts +318 -0
  297. package/dist/extensions/pi-intercom/ui/inline-message.ts +10 -3
  298. package/dist/extensions/pi-intercom/ui/session-list.ts +28 -15
  299. package/dist/extensions/pi-subagents/.github/workflows/release.yml +5 -1
  300. package/dist/extensions/pi-subagents/.github/workflows/test.yml +188 -18
  301. package/dist/extensions/pi-subagents/CHANGELOG.md +514 -1
  302. package/dist/extensions/pi-subagents/README.md +7 -5
  303. package/dist/extensions/pi-subagents/VISION.md +6 -0
  304. package/dist/extensions/pi-subagents/agents/reviewer.md +7 -5
  305. package/dist/extensions/pi-subagents/agents/worker.md +1 -1
  306. package/dist/extensions/pi-subagents/docs/agents.md +75 -35
  307. package/dist/extensions/pi-subagents/docs/configuration.md +156 -25
  308. package/dist/extensions/pi-subagents/docs/extension-api.md +113 -29
  309. package/dist/extensions/pi-subagents/docs/missions.md +46 -14
  310. package/dist/extensions/pi-subagents/docs/models.md +22 -84
  311. package/dist/extensions/pi-subagents/docs/observability.md +49 -24
  312. package/dist/extensions/pi-subagents/docs/standalone-background.md +59 -0
  313. package/dist/extensions/pi-subagents/docs/tool-reference.md +167 -116
  314. package/dist/extensions/pi-subagents/docs/watchdog.md +41 -10
  315. package/dist/extensions/pi-subagents/docs/workflows.md +239 -163
  316. package/dist/extensions/pi-subagents/examples/typed-gate/.pi/agents/classifier.md +14 -0
  317. package/dist/extensions/pi-subagents/examples/typed-gate/README.md +42 -0
  318. package/dist/extensions/pi-subagents/examples/typed-gate/classify +38 -0
  319. package/dist/extensions/pi-subagents/examples/typed-gate/workflow.js +32 -0
  320. package/dist/extensions/pi-subagents/index.ts +11 -3
  321. package/dist/extensions/pi-subagents/inspector-runner.mjs +3 -3
  322. package/dist/extensions/pi-subagents/package-lock.json +517 -1129
  323. package/dist/extensions/pi-subagents/package.json +22 -11
  324. package/dist/extensions/pi-subagents/prompts/council.md +7 -4
  325. package/dist/extensions/pi-subagents/prompts/parallel-review.md +2 -2
  326. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  327. package/dist/extensions/pi-subagents/runner-peer-loader.mjs +21 -0
  328. package/dist/extensions/pi-subagents/runner-peer-preload.mjs +30 -0
  329. package/dist/extensions/pi-subagents/scripts/build-package.mjs +79 -0
  330. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +2 -2
  331. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +46 -27
  332. package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +11 -7
  333. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +78 -73
  334. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +4 -5
  335. package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +10 -2
  336. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +69 -67
  337. package/dist/extensions/pi-subagents/skills/pi-subagents/references/review-and-validation.md +3 -3
  338. package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +21 -10
  339. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +113 -113
  340. package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +91 -4
  341. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +15 -9
  342. package/dist/extensions/pi-subagents/src/agents/agents.ts +432 -193
  343. package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +6 -1
  344. package/dist/extensions/pi-subagents/src/agents/global-npm-root.ts +58 -0
  345. package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +5 -2
  346. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +22 -18
  347. package/dist/extensions/pi-subagents/src/agents/skills.ts +43 -10
  348. package/dist/extensions/pi-subagents/src/api/delegation.ts +20 -1
  349. package/dist/extensions/pi-subagents/src/api/inspectors.ts +27 -0
  350. package/dist/extensions/pi-subagents/src/api/preflight.ts +140 -62
  351. package/dist/extensions/pi-subagents/src/api/required-child-extensions.ts +6 -0
  352. package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
  353. package/dist/extensions/pi-subagents/src/extension/config.ts +24 -40
  354. package/dist/extensions/pi-subagents/src/extension/control-notices.ts +4 -1
  355. package/dist/extensions/pi-subagents/src/extension/doctor.ts +18 -15
  356. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +87 -13
  357. package/dist/extensions/pi-subagents/src/extension/herdr-pi-bridge.ts +162 -0
  358. package/dist/extensions/pi-subagents/src/extension/index.ts +280 -268
  359. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +76 -37
  360. package/dist/extensions/pi-subagents/src/extension/reply-workflow-script.ts +67 -0
  361. package/dist/extensions/pi-subagents/src/extension/rpc.ts +34 -11
  362. package/dist/extensions/pi-subagents/src/extension/schemas.ts +116 -205
  363. package/dist/extensions/pi-subagents/src/extension/subagent-guide.ts +13 -5
  364. package/dist/extensions/pi-subagents/src/extension/tool-activation.ts +146 -0
  365. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +77 -90
  366. package/dist/extensions/pi-subagents/src/extension/upgrade-notice.ts +40 -0
  367. package/dist/extensions/pi-subagents/src/inspectors/actions.ts +148 -0
  368. package/dist/extensions/pi-subagents/src/inspectors/ghostty/actions.ts +74 -0
  369. package/dist/extensions/pi-subagents/src/inspectors/ghostty/plugin.ts +29 -0
  370. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +100 -180
  371. package/dist/extensions/pi-subagents/src/inspectors/herdr/plugin.ts +20 -0
  372. package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +2 -2
  373. package/dist/extensions/pi-subagents/src/inspectors/{herdr/inspector-runner.ts → inspector-runner.ts} +13 -13
  374. package/dist/extensions/pi-subagents/src/inspectors/plugins.ts +75 -0
  375. package/dist/extensions/pi-subagents/src/inspectors/{herdr/session-roots-codec.ts → session-roots-codec.ts} +4 -15
  376. package/dist/extensions/pi-subagents/src/inspectors/{herdr/shell-command.ts → shell-command.ts} +1 -1
  377. package/dist/extensions/pi-subagents/src/inspectors/types.ts +51 -0
  378. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +38 -53
  379. package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +53 -9
  380. package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +69 -55
  381. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +7 -2
  382. package/dist/extensions/pi-subagents/src/missions/goal-driver.ts +45 -32
  383. package/dist/extensions/pi-subagents/src/missions/store.ts +11 -2
  384. package/dist/extensions/pi-subagents/src/policy/authority.ts +5 -1
  385. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +30 -18
  386. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +59 -9
  387. package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +18 -2
  388. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +463 -248
  389. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +106 -66
  390. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +33 -20
  391. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +47 -17
  392. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -5
  393. package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +24 -11
  394. package/dist/extensions/pi-subagents/src/runs/background/await-async-run.ts +78 -0
  395. package/dist/extensions/pi-subagents/src/runs/background/binary-bootstrap.ts +66 -0
  396. package/dist/extensions/pi-subagents/src/runs/background/calendar-schedule.ts +90 -0
  397. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -2
  398. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +19 -38
  399. package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +62 -3
  400. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +82 -10
  401. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +259 -21
  402. package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +30 -3
  403. package/dist/extensions/pi-subagents/src/runs/background/pid-namespace.ts +18 -0
  404. package/dist/extensions/pi-subagents/src/runs/background/process-terminal-candidate.ts +98 -0
  405. package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +18 -97
  406. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +14 -5
  407. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +66 -12
  408. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +4 -3
  409. package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +126 -45
  410. package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +11 -6
  411. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +18 -7
  412. package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +43 -51
  413. package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +8 -1
  414. package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +5 -4
  415. package/dist/extensions/pi-subagents/src/runs/background/runner-http-dispatcher.ts +119 -0
  416. package/dist/extensions/pi-subagents/src/runs/background/runner-startup-failure.ts +56 -0
  417. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +233 -69
  418. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +67 -16
  419. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +21 -3
  420. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner-bootstrap.ts +276 -0
  421. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +592 -573
  422. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +177 -29
  423. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +77 -28
  424. package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +10 -4
  425. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +7 -13
  426. package/dist/extensions/pi-subagents/src/runs/background/workflow-terminal-proof.ts +41 -23
  427. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +19 -8
  428. package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +130 -7
  429. package/dist/extensions/pi-subagents/src/runs/foreground/command-action.ts +41 -0
  430. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +267 -385
  431. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +4 -2
  432. package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +6 -10
  433. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1158 -413
  434. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +3 -1
  435. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +2 -1
  436. package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +200 -74
  437. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +133 -34
  438. package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +6 -1
  439. package/dist/extensions/pi-subagents/src/runs/shared/child-commands.ts +228 -0
  440. package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +18 -18
  441. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +16 -4
  442. package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +55 -12
  443. package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +6 -3
  444. package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +11 -1
  445. package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +367 -74
  446. package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +50 -86
  447. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +288 -0
  448. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  449. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  450. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +5 -5
  451. package/dist/extensions/pi-subagents/src/runs/shared/effective-system-prompt.ts +33 -0
  452. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +49 -10
  453. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +61 -9
  454. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +16 -9
  455. package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +55 -1
  456. package/dist/extensions/pi-subagents/src/runs/shared/git-environment.ts +1 -1
  457. package/dist/extensions/pi-subagents/src/runs/shared/herdr-connection.ts +134 -0
  458. package/dist/extensions/pi-subagents/src/runs/shared/herdr-external-adapters.ts +169 -0
  459. package/dist/extensions/pi-subagents/src/runs/shared/herdr-machine.ts +279 -0
  460. package/dist/extensions/pi-subagents/src/runs/shared/herdr-pi-protocol.ts +59 -0
  461. package/dist/extensions/pi-subagents/src/runs/shared/herdr-placed-run.ts +263 -0
  462. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +6 -2
  463. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +108 -13
  464. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +23 -7
  465. package/dist/extensions/pi-subagents/src/runs/shared/model-resolution-diagnostic.ts +76 -0
  466. package/dist/extensions/pi-subagents/src/runs/shared/{model-fallback.ts → model-resolution.ts} +65 -245
  467. package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +30 -11
  468. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +24 -3
  469. package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +5 -4
  470. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +55 -7
  471. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +14 -4
  472. package/dist/extensions/pi-subagents/src/runs/shared/partial-output.ts +48 -0
  473. package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +12 -4
  474. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +88 -1
  475. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +12 -3
  476. package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +160 -9
  477. package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +35 -34
  478. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +58 -19
  479. package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +2 -2
  480. package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +21 -0
  481. package/dist/extensions/pi-subagents/src/runs/shared/usage-reconciliation.ts +73 -0
  482. package/dist/extensions/pi-subagents/src/runs/shared/workflow-async-child-guidance.ts +18 -0
  483. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-apply.ts +160 -0
  484. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +42 -20
  485. package/dist/extensions/pi-subagents/src/runs/shared/worktree-lock.ts +29 -0
  486. package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +27 -4
  487. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +94 -26
  488. package/dist/extensions/pi-subagents/src/shared/child-cache-retention.ts +43 -0
  489. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +5 -3
  490. package/dist/extensions/pi-subagents/src/shared/disabled-features.ts +123 -0
  491. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +14 -1
  492. package/dist/extensions/pi-subagents/src/shared/file-lease.ts +74 -0
  493. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +27 -77
  494. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +70 -10
  495. package/dist/extensions/pi-subagents/src/shared/model-info.ts +10 -1
  496. package/dist/extensions/pi-subagents/src/shared/opencode-session-headers.ts +30 -0
  497. package/dist/extensions/pi-subagents/src/shared/package-version.ts +17 -0
  498. package/dist/extensions/pi-subagents/src/shared/parent-wake.ts +66 -0
  499. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +71 -58
  500. package/dist/extensions/pi-subagents/src/shared/required-child-extensions.ts +115 -0
  501. package/dist/extensions/pi-subagents/src/shared/settings-file-lease.ts +36 -0
  502. package/dist/extensions/pi-subagents/src/shared/settings.ts +7 -4
  503. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +1 -5
  504. package/dist/extensions/pi-subagents/src/shared/types.ts +146 -48
  505. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +28 -2
  506. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +15 -1
  507. package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +19 -4
  508. package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +13 -2
  509. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +15 -15
  510. package/dist/extensions/pi-subagents/src/slash/subagent-cost.ts +46 -9
  511. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +29 -16
  512. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +201 -26
  513. package/dist/extensions/pi-subagents/src/tui/fleet.ts +33 -16
  514. package/dist/extensions/pi-subagents/src/tui/render.ts +334 -103
  515. package/dist/extensions/pi-subagents/src/tui/running-tone.ts +28 -0
  516. package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +27 -28
  517. package/dist/extensions/pi-subagents/src/watchdog/diff-tool.ts +47 -12
  518. package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +2 -2
  519. package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +22 -2
  520. package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +17 -17
  521. package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +24 -8
  522. package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +43 -39
  523. package/dist/extensions/pi-subagents/src/watchdog/render.ts +2 -2
  524. package/dist/extensions/pi-subagents/src/watchdog/review.ts +127 -78
  525. package/dist/extensions/pi-subagents/src/watchdog/rules.ts +1 -1
  526. package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +107 -31
  527. package/dist/extensions/pi-subagents/src/watchdog/scope.ts +1 -1
  528. package/dist/extensions/pi-subagents/src/watchdog/settings.ts +22 -14
  529. package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +14 -13
  530. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +35 -6
  531. package/dist/extensions/pi-subagents/src/watchdog/types.ts +6 -4
  532. package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +2 -2
  533. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
  534. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +500 -65
  535. package/dist/extensions/pi-subagents/src/workflows/structured-workflow-scripts.ts +177 -0
  536. package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +8 -2
  537. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +5 -3
  538. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +70 -10
  539. package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +57 -18
  540. package/dist/extensions/pi-subagents/src/workflows/workflow-reuse.ts +120 -0
  541. package/dist/extensions/pi-subagents/src/workflows/workflow-revival.ts +123 -0
  542. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +5 -2
  543. package/dist/extensions/pi-subagents/test/fixtures/cwd-workflow-child.ts +37 -0
  544. package/dist/extensions/pi-subagents/test/fixtures/herdr-allocation-lock-child.ts +16 -0
  545. package/dist/extensions/pi-subagents/test/fixtures/herdr-provision-child.ts +15 -0
  546. package/dist/extensions/pi-subagents/test/fixtures/native-nested-wait-provider.ts +76 -0
  547. package/dist/extensions/pi-subagents/test/fixtures/runner-bootstrap-harness.ts +36 -0
  548. package/dist/extensions/pi-subagents/test/fixtures/schedule-history-writer.mjs +48 -0
  549. package/dist/extensions/pi-subagents/test/fixtures/settings-race-writer.mjs +57 -0
  550. package/dist/extensions/pi-subagents/test/fixtures/workflow-cwd-access-failure.ts +33 -0
  551. package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +40 -7
  552. package/dist/extensions/pi-subagents/test/integration/async-attention-clearing.test.ts +9 -8
  553. package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +435 -276
  554. package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +435 -397
  555. package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +918 -497
  556. package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +264 -17
  557. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +185 -22
  558. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +3 -2
  559. package/dist/extensions/pi-subagents/test/integration/claude-code-dispatch.test.ts +127 -0
  560. package/dist/extensions/pi-subagents/test/integration/deadline-checkpoint.test.ts +126 -0
  561. package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +29 -1
  562. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +88 -0
  563. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +450 -13
  564. package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +10 -6
  565. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +105 -86
  566. package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +403 -18
  567. package/dist/extensions/pi-subagents/test/integration/inline-workflow-visibility.test.ts +351 -0
  568. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +195 -10
  569. package/dist/extensions/pi-subagents/test/integration/model-resolution-diagnostic.test.ts +108 -0
  570. package/dist/extensions/pi-subagents/test/integration/nested-async-wait.test.ts +61 -0
  571. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +5 -4
  572. package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +1 -1
  573. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +6 -4
  574. package/dist/extensions/pi-subagents/test/integration/render-widget-mouse.test.ts +84 -0
  575. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +242 -16
  576. package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +2 -2
  577. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +158 -4
  578. package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +1435 -248
  579. package/dist/extensions/pi-subagents/test/integration/single-execution.part-2.test.ts +454 -515
  580. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +140 -21
  581. package/dist/extensions/pi-subagents/test/integration/structured-workflows.test.ts +105 -0
  582. package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +90 -11
  583. package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +18 -15
  584. package/dist/extensions/pi-subagents/test/integration/workflow-worktree-admission.test.ts +100 -0
  585. package/dist/extensions/pi-subagents/test/smoke/clean-install.mjs +106 -0
  586. package/dist/extensions/pi-subagents/test/smoke/npm-background.mjs +43 -0
  587. package/dist/extensions/pi-subagents/test/smoke/packed-runner-selection.mjs +42 -0
  588. package/dist/extensions/pi-subagents/test/smoke/runner-loader-capability.mjs +50 -0
  589. package/dist/extensions/pi-subagents/test/smoke/sdk-child.ts +57 -0
  590. package/dist/extensions/pi-subagents/test/smoke/{pi085-extension.ts → sdk-extension.ts} +2 -2
  591. package/dist/extensions/pi-subagents/test/smoke/standalone-background.mjs +140 -0
  592. package/dist/extensions/pi-subagents/test/smoke/standalone-fault.ts +43 -0
  593. package/dist/extensions/pi-subagents/test/smoke/standalone-matrix.mjs +65 -0
  594. package/dist/extensions/pi-subagents/test/smoke/standalone-observer.ts +8 -0
  595. package/dist/extensions/pi-subagents/test/smoke/standalone-parent.ts +220 -0
  596. package/dist/extensions/pi-subagents/test/smoke/standalone-provider.ts +58 -0
  597. package/dist/extensions/pi-subagents/test/smoke/standalone-release.json +8 -0
  598. package/dist/extensions/pi-subagents/test/smoke/standalone-revival.ts +109 -0
  599. package/dist/extensions/pi-subagents/test/smoke/standalone-shared.ts +79 -0
  600. package/dist/extensions/pi-subagents/test/smoke/tool-activation.test.ts +128 -0
  601. package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +6 -25
  602. package/dist/extensions/pi-subagents/test/support/async-result-timeout-evidence.ts +61 -0
  603. package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +122 -9
  604. package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +15 -7
  605. package/dist/extensions/pi-subagents/test/support/helpers.ts +11 -14
  606. package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +21 -3
  607. package/dist/extensions/pi-subagents/test/support/native-peer-loader.mjs +15 -0
  608. package/dist/extensions/pi-subagents/test/support/node-command.ts +29 -6
  609. package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +5 -3
  610. package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +7 -15
  611. package/dist/extensions/pi-subagents/test/support/watchdog-stable-host-loader.mjs +23 -0
  612. package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +3 -3
  613. package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +158 -155
  614. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +52 -1
  615. package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +21 -17
  616. package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +105 -36
  617. package/dist/extensions/pi-subagents/test/unit/advertisement-barrier.test.ts +151 -0
  618. package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -2
  619. package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +33 -3
  620. package/dist/extensions/pi-subagents/test/unit/agent-end-auto-drain.test.ts +149 -0
  621. package/dist/extensions/pi-subagents/test/unit/agent-exclude-dirs.test.ts +246 -0
  622. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +62 -87
  623. package/dist/extensions/pi-subagents/test/unit/agent-global-root-override.test.ts +86 -0
  624. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +398 -48
  625. package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +126 -1
  626. package/dist/extensions/pi-subagents/test/unit/agent-name-resolution.test.ts +75 -0
  627. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +94 -42
  628. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +73 -3
  629. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +428 -2
  630. package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +4 -4
  631. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +112 -1
  632. package/dist/extensions/pi-subagents/test/unit/async-result-timeout-evidence.test.ts +53 -0
  633. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +92 -4
  634. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +58 -6
  635. package/dist/extensions/pi-subagents/test/unit/async-run-history.test.ts +123 -0
  636. package/dist/extensions/pi-subagents/test/unit/async-spawn-package-dir.test.ts +203 -0
  637. package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +26 -35
  638. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +185 -0
  639. package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +9 -1
  640. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +106 -1
  641. package/dist/extensions/pi-subagents/test/unit/await-async-run.test.ts +202 -0
  642. package/dist/extensions/pi-subagents/test/unit/binary-async-spawn.test.ts +115 -0
  643. package/dist/extensions/pi-subagents/test/unit/binary-pi-spawn.test.ts +27 -0
  644. package/dist/extensions/pi-subagents/test/unit/calendar-schedule.test.ts +70 -0
  645. package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +38 -0
  646. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +10 -2
  647. package/dist/extensions/pi-subagents/test/unit/changelog-format.test.ts +11 -0
  648. package/dist/extensions/pi-subagents/test/unit/child-cache-retention.test.ts +87 -0
  649. package/dist/extensions/pi-subagents/test/unit/child-commands.test.ts +243 -0
  650. package/dist/extensions/pi-subagents/test/unit/child-external-job-bridge.test.ts +126 -0
  651. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +12 -1
  652. package/dist/extensions/pi-subagents/test/unit/child-lifecycle.test.ts +36 -0
  653. package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +24 -0
  654. package/dist/extensions/pi-subagents/test/unit/child-session-commands.test.ts +162 -0
  655. package/dist/extensions/pi-subagents/test/unit/child-session-host-sdk.test.ts +226 -0
  656. package/dist/extensions/pi-subagents/test/unit/child-session-parent-providers.test.ts +200 -0
  657. package/dist/extensions/pi-subagents/test/unit/child-session-queued.test.ts +260 -0
  658. package/dist/extensions/pi-subagents/test/unit/child-tool-plan-permission-system.test.ts +3 -98
  659. package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +222 -1
  660. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +314 -0
  661. package/dist/extensions/pi-subagents/test/unit/claude-code-dispatch.test.ts +182 -0
  662. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +157 -0
  663. package/dist/extensions/pi-subagents/test/unit/command-action.test.ts +50 -0
  664. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +25 -11
  665. package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +3 -1
  666. package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +18 -0
  667. package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +7 -1
  668. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +220 -0
  669. package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +104 -32
  670. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +138 -1
  671. package/dist/extensions/pi-subagents/test/unit/disabled-features.test.ts +227 -0
  672. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +48 -9
  673. package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +7 -4
  674. package/dist/extensions/pi-subagents/test/unit/extension-lazy-loading.test.ts +21 -0
  675. package/dist/extensions/pi-subagents/test/unit/extension-maintenance-lifecycle.test.ts +66 -0
  676. package/dist/extensions/pi-subagents/test/unit/extension-module-preload.test.ts +49 -0
  677. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +104 -3
  678. package/dist/extensions/pi-subagents/test/unit/file-lease.test.ts +17 -0
  679. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +316 -0
  680. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +58 -7
  681. package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +25 -96
  682. package/dist/extensions/pi-subagents/test/unit/ghostty-inspector.test.ts +92 -0
  683. package/dist/extensions/pi-subagents/test/unit/global-npm-root.test.ts +108 -0
  684. package/dist/extensions/pi-subagents/test/unit/herdr-connection.test.ts +43 -0
  685. package/dist/extensions/pi-subagents/test/unit/herdr-external-adapters.test.ts +89 -0
  686. package/dist/extensions/pi-subagents/test/unit/herdr-inspector-bootstrap.test.ts +11 -20
  687. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +113 -19
  688. package/dist/extensions/pi-subagents/test/unit/herdr-machine.test.ts +161 -0
  689. package/dist/extensions/pi-subagents/test/unit/herdr-native-placement.test.ts +187 -0
  690. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +7 -12
  691. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  692. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +182 -87
  693. package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +68 -49
  694. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +295 -135
  695. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +3 -3
  696. package/dist/extensions/pi-subagents/test/unit/inspector-authority-policy.test.ts +144 -0
  697. package/dist/extensions/pi-subagents/test/unit/inspector-registration.test.ts +128 -0
  698. package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +49 -1
  699. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +74 -1
  700. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-resolution.test.ts +112 -0
  701. package/dist/extensions/pi-subagents/test/unit/mission-global-projection.test.ts +215 -0
  702. package/dist/extensions/pi-subagents/test/unit/mission-goal-driver.test.ts +65 -1
  703. package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +2 -1
  704. package/dist/extensions/pi-subagents/test/unit/model-resolution-diagnostic.test.ts +78 -0
  705. package/dist/extensions/pi-subagents/test/unit/model-resolution.test.ts +153 -0
  706. package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +43 -1
  707. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +1 -21
  708. package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +279 -2
  709. package/dist/extensions/pi-subagents/test/unit/nested-control-fanout.test.ts +73 -0
  710. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +297 -3
  711. package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +1 -1
  712. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +431 -23
  713. package/dist/extensions/pi-subagents/test/unit/opencode-session-headers.test.ts +32 -0
  714. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +89 -21
  715. package/dist/extensions/pi-subagents/test/unit/owned-process-tree.test.ts +31 -1
  716. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +18 -24
  717. package/dist/extensions/pi-subagents/test/unit/parent-wake.test.ts +206 -0
  718. package/dist/extensions/pi-subagents/test/unit/partial-output.test.ts +53 -0
  719. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +216 -32
  720. package/dist/extensions/pi-subagents/test/unit/pi-spawn-host-root.test.ts +82 -0
  721. package/dist/extensions/pi-subagents/test/unit/pi-subagents-policy-guidance.test.ts +28 -0
  722. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +193 -104
  723. package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +16 -1
  724. package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +17 -1
  725. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +89 -9
  726. package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +6 -0
  727. package/dist/extensions/pi-subagents/test/unit/prompt-audit-provider-routing.test.ts +69 -0
  728. package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +2 -2
  729. package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +23 -1
  730. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +117 -3
  731. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +35 -14
  732. package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +3 -2
  733. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +261 -9
  734. package/dist/extensions/pi-subagents/test/unit/reply-workflow-script.test.ts +37 -0
  735. package/dist/extensions/pi-subagents/test/unit/required-child-extensions.test.ts +114 -0
  736. package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +11 -1
  737. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +22 -2
  738. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +125 -18
  739. package/dist/extensions/pi-subagents/test/unit/run-child-session.test.ts +230 -0
  740. package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +50 -1
  741. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +301 -4
  742. package/dist/extensions/pi-subagents/test/unit/runner-bootstrap.test.ts +182 -0
  743. package/dist/extensions/pi-subagents/test/unit/runner-http-dispatcher.test.ts +136 -0
  744. package/dist/extensions/pi-subagents/test/unit/runner-peer-loader.test.ts +68 -0
  745. package/dist/extensions/pi-subagents/test/unit/runner-peer-symlinks.test.ts +50 -0
  746. package/dist/extensions/pi-subagents/test/unit/running-tone.test.ts +13 -0
  747. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +155 -4
  748. package/dist/extensions/pi-subagents/test/unit/schedule-claim-initialization.test.ts +71 -0
  749. package/dist/extensions/pi-subagents/test/unit/schedule-claim-preservation.test.ts +98 -0
  750. package/dist/extensions/pi-subagents/test/unit/schedule-history-transactions.test.ts +201 -0
  751. package/dist/extensions/pi-subagents/test/unit/scheduled-mission.test.ts +317 -0
  752. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +412 -11
  753. package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +2 -8
  754. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +70 -71
  755. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +748 -5
  756. package/dist/extensions/pi-subagents/test/unit/session-liveness-delivery.test.ts +337 -0
  757. package/dist/extensions/pi-subagents/test/unit/settings-atomic-save.test.ts +419 -0
  758. package/dist/extensions/pi-subagents/test/unit/settings-transactions.test.ts +88 -0
  759. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +13 -1
  760. package/dist/extensions/pi-subagents/test/unit/skills-disable-model-invocation.test.ts +164 -0
  761. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +35 -2
  762. package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +2 -2
  763. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +334 -9
  764. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +170 -0
  765. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +34 -5
  766. package/dist/extensions/pi-subagents/test/unit/structured-output-validation.test.ts +199 -0
  767. package/dist/extensions/pi-subagents/test/unit/structured-workflow-resources.test.ts +241 -0
  768. package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +47 -38
  769. package/dist/extensions/pi-subagents/test/unit/subagent-cost.test.ts +97 -0
  770. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +10 -0
  771. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +343 -44
  772. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +410 -11
  773. package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +459 -22
  774. package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +43 -3
  775. package/dist/extensions/pi-subagents/test/unit/timeout-defaults.test.ts +11 -1
  776. package/dist/extensions/pi-subagents/test/unit/tool-activation-stale-peer.test.ts +32 -0
  777. package/dist/extensions/pi-subagents/test/unit/tool-activation.test.ts +313 -0
  778. package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +14 -0
  779. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +76 -89
  780. package/dist/extensions/pi-subagents/test/unit/typed-gate-output.test.ts +141 -0
  781. package/dist/extensions/pi-subagents/test/unit/upgrade-notice.test.ts +31 -0
  782. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation-owners.test.ts +66 -0
  783. package/dist/extensions/pi-subagents/test/unit/usage-reconciliation.test.ts +23 -0
  784. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +195 -1
  785. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +3 -1
  786. package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +48 -45
  787. package/dist/extensions/pi-subagents/test/unit/watchdog-compaction-scope.test.ts +94 -0
  788. package/dist/extensions/pi-subagents/test/unit/watchdog-diff-tool.test.ts +48 -3
  789. package/dist/extensions/pi-subagents/test/unit/watchdog-native-scheduling.test.ts +107 -0
  790. package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +95 -7
  791. package/dist/extensions/pi-subagents/test/unit/watchdog-register-child.test.ts +79 -0
  792. package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +7 -4
  793. package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +111 -24
  794. package/dist/extensions/pi-subagents/test/unit/watchdog-rules.test.ts +1 -1
  795. package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +283 -2
  796. package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +3 -0
  797. package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +12 -1
  798. package/dist/extensions/pi-subagents/test/unit/watchdog-stable-host-layout.test.ts +23 -0
  799. package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +30 -0
  800. package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +39 -2
  801. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +18 -1
  802. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +8 -4
  803. package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +10 -0
  804. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +6 -3
  805. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +44 -1
  806. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +28 -1
  807. package/dist/extensions/pi-subagents/test/unit/workflow-revival.test.ts +85 -0
  808. package/dist/extensions/pi-subagents/test/unit/workflow-scripts-feature.test.ts +177 -0
  809. package/dist/extensions/pi-subagents/test/unit/workflow-terminal-proof.test.ts +8 -0
  810. package/dist/extensions/pi-subagents/test/unit/workflow-worktree-admission.test.ts +29 -0
  811. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +343 -4
  812. package/dist/extensions/pi-subagents/test/unit/worktree-lock.test.ts +123 -0
  813. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +252 -22
  814. package/dist/extensions/pi-subagents/tsconfig.build.json +13 -0
  815. package/dist/extensions/pi-tool-display/tests/custom-tool-overrides.test.ts +1 -1
  816. package/dist/extensions/pi-tool-display/tests/tool-overrides-config.test.ts +1 -1
  817. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +24 -1
  818. package/dist/extensions/pi-tool-display/tests/tool-overrides-registration.test.ts +6 -2
  819. package/dist/extensions/pi-web-agent/src/extension.ts +1 -5
  820. package/dist/extensions/pi-zentui/.github/workflows/ci.yml +67 -4
  821. package/dist/extensions/pi-zentui/AGENTS.md +3 -2
  822. package/dist/extensions/pi-zentui/README.md +60 -32
  823. package/dist/extensions/pi-zentui/docs/configuration.md +662 -51
  824. package/dist/extensions/pi-zentui/docs/footer-format.md +174 -5
  825. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-editor.ts +15 -4
  826. package/dist/extensions/pi-zentui/extensions/zentui/average-token-rate.ts +146 -0
  827. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota-display.ts +34 -0
  828. package/dist/extensions/pi-zentui/extensions/zentui/codex-quota.ts +298 -0
  829. package/dist/extensions/pi-zentui/extensions/zentui/component-colors.ts +172 -0
  830. package/dist/extensions/pi-zentui/extensions/zentui/component-settings.ts +243 -0
  831. package/dist/extensions/pi-zentui/extensions/zentui/config.ts +851 -114
  832. package/dist/extensions/pi-zentui/extensions/zentui/custom-value-colors.ts +93 -0
  833. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-demand.ts +61 -0
  834. package/dist/extensions/pi-zentui/extensions/zentui/custom-variable-format.ts +80 -0
  835. package/dist/extensions/pi-zentui/extensions/zentui/custom-variables.ts +152 -0
  836. package/dist/extensions/pi-zentui/extensions/zentui/editor-metadata-format.ts +138 -23
  837. package/dist/extensions/pi-zentui/extensions/zentui/editor-mouse.ts +89 -0
  838. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-controller.ts +148 -0
  839. package/dist/extensions/pi-zentui/extensions/zentui/extension-status-settings.ts +40 -0
  840. package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +109 -1
  841. package/dist/extensions/pi-zentui/extensions/zentui/footer-format.ts +203 -23
  842. package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +80 -3
  843. package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +1 -1
  844. package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +432 -125
  845. package/dist/extensions/pi-zentui/extensions/zentui/format.ts +92 -4
  846. package/dist/extensions/pi-zentui/extensions/zentui/git.ts +47 -30
  847. package/dist/extensions/pi-zentui/extensions/zentui/github-status.ts +575 -0
  848. package/dist/extensions/pi-zentui/extensions/zentui/host-project-changes.ts +25 -0
  849. package/dist/extensions/pi-zentui/extensions/zentui/host-template-values.ts +29 -0
  850. package/dist/extensions/pi-zentui/extensions/zentui/icons.ts +53 -13
  851. package/dist/extensions/pi-zentui/extensions/zentui/index.ts +778 -258
  852. package/dist/extensions/pi-zentui/extensions/zentui/interaction-summary.ts +70 -5
  853. package/dist/extensions/pi-zentui/extensions/zentui/layered-editor.ts +55 -0
  854. package/dist/extensions/pi-zentui/extensions/zentui/live-context.ts +6 -1
  855. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-demand.ts +72 -0
  856. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata-display.ts +21 -0
  857. package/dist/extensions/pi-zentui/extensions/zentui/live-metadata.ts +255 -0
  858. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-editor.ts +476 -36
  859. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-settings.ts +118 -0
  860. package/dist/extensions/pi-zentui/extensions/zentui/minimalist-template.ts +177 -0
  861. package/dist/extensions/pi-zentui/extensions/zentui/omp-editor-frame.ts +148 -0
  862. package/dist/extensions/pi-zentui/extensions/zentui/omp-statusline.ts +569 -0
  863. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-lookups.ts +344 -0
  864. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-metrics.ts +91 -0
  865. package/dist/extensions/pi-zentui/extensions/zentui/omp-template-modes.ts +323 -0
  866. package/dist/extensions/pi-zentui/extensions/zentui/omp-ui.ts +210 -0
  867. package/dist/extensions/pi-zentui/extensions/zentui/package-version.ts +30 -12
  868. package/dist/extensions/pi-zentui/extensions/zentui/project-demand.ts +46 -0
  869. package/dist/extensions/pi-zentui/extensions/zentui/project-discovery.ts +58 -0
  870. package/dist/extensions/pi-zentui/extensions/zentui/project-refresh.ts +10 -3
  871. package/dist/extensions/pi-zentui/extensions/zentui/project-state.ts +37 -0
  872. package/dist/extensions/pi-zentui/extensions/zentui/repository-root.ts +1 -0
  873. package/dist/extensions/pi-zentui/extensions/zentui/runtime.ts +119 -43
  874. package/dist/extensions/pi-zentui/extensions/zentui/selector-border.ts +40 -29
  875. package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +1268 -722
  876. package/dist/extensions/pi-zentui/extensions/zentui/settings-keys.ts +59 -0
  877. package/dist/extensions/pi-zentui/extensions/zentui/settings-list-selection.ts +13 -0
  878. package/dist/extensions/pi-zentui/extensions/zentui/settings-previews.ts +11 -4
  879. package/dist/extensions/pi-zentui/extensions/zentui/state.ts +24 -11
  880. package/dist/extensions/pi-zentui/extensions/zentui/style.ts +6 -0
  881. package/dist/extensions/pi-zentui/extensions/zentui/telemetry.ts +113 -11
  882. package/dist/extensions/pi-zentui/extensions/zentui/thinking-experimental.ts +234 -46
  883. package/dist/extensions/pi-zentui/extensions/zentui/thinking-steps.ts +20 -5
  884. package/dist/extensions/pi-zentui/extensions/zentui/token-rate.ts +313 -0
  885. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-format.ts +59 -0
  886. package/dist/extensions/pi-zentui/extensions/zentui/turn-summary-rate.ts +52 -0
  887. package/dist/extensions/pi-zentui/extensions/zentui/ui.ts +640 -172
  888. package/dist/extensions/pi-zentui/extensions/zentui/user-message-styles.ts +72 -34
  889. package/dist/extensions/pi-zentui/extensions/zentui/user-message.ts +219 -34
  890. package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +495 -119
  891. package/dist/extensions/pi-zentui/omp.ts +157 -0
  892. package/dist/extensions/pi-zentui/package-lock.json +3762 -1507
  893. package/dist/extensions/pi-zentui/package.json +50 -12
  894. package/dist/extensions/pi-zentui/test/accent-rail-editor.test.ts +13 -2
  895. package/dist/extensions/pi-zentui/test/average-token-rate.test.ts +297 -0
  896. package/dist/extensions/pi-zentui/test/behavior-compatibility.mjs +89 -0
  897. package/dist/extensions/pi-zentui/test/codex-quota-lifecycle.test.ts +284 -0
  898. package/dist/extensions/pi-zentui/test/codex-quota-rendering.test.ts +466 -0
  899. package/dist/extensions/pi-zentui/test/codex-quota.test.ts +440 -0
  900. package/dist/extensions/pi-zentui/test/component-colors.test.ts +554 -0
  901. package/dist/extensions/pi-zentui/test/component-settings.test.ts +364 -0
  902. package/dist/extensions/pi-zentui/test/config-component-independence.test.ts +402 -0
  903. package/dist/extensions/pi-zentui/test/config-extension-status-choice.test.ts +233 -0
  904. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-colors.test.ts +118 -0
  905. package/dist/extensions/pi-zentui/test/config-hidden-extension-status-placement.test.ts +142 -0
  906. package/dist/extensions/pi-zentui/test/config-minimalist-templates.test.ts +240 -0
  907. package/dist/extensions/pi-zentui/test/config-template-variables.test.ts +85 -0
  908. package/dist/extensions/pi-zentui/test/config.test.ts +80 -17
  909. package/dist/extensions/pi-zentui/test/custom-value-colors-integration.test.ts +453 -0
  910. package/dist/extensions/pi-zentui/test/custom-value-colors.test.ts +399 -0
  911. package/dist/extensions/pi-zentui/test/custom-variable-alias-prototypes.test.ts +177 -0
  912. package/dist/extensions/pi-zentui/test/custom-variable-consumers.test.ts +194 -0
  913. package/dist/extensions/pi-zentui/test/custom-variable-demand.test.ts +169 -0
  914. package/dist/extensions/pi-zentui/test/custom-variable-probe-reservation.test.ts +141 -0
  915. package/dist/extensions/pi-zentui/test/custom-variables-lifecycle.integration.test.ts +365 -0
  916. package/dist/extensions/pi-zentui/test/custom-variables.test.ts +330 -0
  917. package/dist/extensions/pi-zentui/test/editor-metadata-format.test.ts +121 -0
  918. package/dist/extensions/pi-zentui/test/editor-mouse.test.ts +507 -0
  919. package/dist/extensions/pi-zentui/test/editor-viewport-indicators.test.ts +247 -20
  920. package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +204 -260
  921. package/dist/extensions/pi-zentui/test/extension-status-controller.test.ts +323 -0
  922. package/dist/extensions/pi-zentui/test/extension-status-lifecycle.integration.test.ts +466 -0
  923. package/dist/extensions/pi-zentui/test/extension-status-settings.test.ts +79 -0
  924. package/dist/extensions/pi-zentui/test/footer-alignment.test.ts +135 -0
  925. package/dist/extensions/pi-zentui/test/footer-authority.test.ts +69 -0
  926. package/dist/extensions/pi-zentui/test/footer-auto-compaction.test.ts +148 -0
  927. package/dist/extensions/pi-zentui/test/footer-format-cache.test.ts +186 -0
  928. package/dist/extensions/pi-zentui/test/footer-format.test.ts +154 -4
  929. package/dist/extensions/pi-zentui/test/footer-hidden.test.ts +312 -0
  930. package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +22 -0
  931. package/dist/extensions/pi-zentui/test/footer-layout.test.ts +80 -0
  932. package/dist/extensions/pi-zentui/test/footer-thinking-level.test.ts +123 -0
  933. package/dist/extensions/pi-zentui/test/format.test.ts +75 -1
  934. package/dist/extensions/pi-zentui/test/git-probes.test.ts +182 -0
  935. package/dist/extensions/pi-zentui/test/github-status.test.ts +931 -0
  936. package/dist/extensions/pi-zentui/test/host-template-surfaces.test.ts +287 -0
  937. package/dist/extensions/pi-zentui/test/icons.test.ts +86 -16
  938. package/dist/extensions/pi-zentui/test/layered-editor.test.ts +53 -0
  939. package/dist/extensions/pi-zentui/test/live-context-integration.test.ts +154 -7
  940. package/dist/extensions/pi-zentui/test/live-context.test.ts +45 -0
  941. package/dist/extensions/pi-zentui/test/live-metadata-lifecycle.integration.test.ts +963 -0
  942. package/dist/extensions/pi-zentui/test/live-metadata.test.ts +767 -0
  943. package/dist/extensions/pi-zentui/test/minimalist-cache-hit-colors.test.ts +183 -0
  944. package/dist/extensions/pi-zentui/test/minimalist-editor.test.ts +222 -4
  945. package/dist/extensions/pi-zentui/test/minimalist-settings.test.ts +103 -0
  946. package/dist/extensions/pi-zentui/test/minimalist-templates.test.ts +489 -0
  947. package/dist/extensions/pi-zentui/test/omp-editor-composers.test.ts +324 -0
  948. package/dist/extensions/pi-zentui/test/omp-statusline.test.ts +579 -0
  949. package/dist/extensions/pi-zentui/test/omp-template-lookups.test.ts +630 -0
  950. package/dist/extensions/pi-zentui/test/omp-template-metrics.test.ts +72 -0
  951. package/dist/extensions/pi-zentui/test/omp-template-modes.test.ts +557 -0
  952. package/dist/extensions/pi-zentui/test/omp-ui.test.ts +93 -0
  953. package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
  954. package/dist/extensions/pi-zentui/test/pi-version-policy.test.ts +37 -0
  955. package/dist/extensions/pi-zentui/test/project-demand-integration.test.ts +542 -0
  956. package/dist/extensions/pi-zentui/test/project-discovery.test.ts +412 -0
  957. package/dist/extensions/pi-zentui/test/project-refresh.test.ts +44 -0
  958. package/dist/extensions/pi-zentui/test/project-state.test.ts +38 -1
  959. package/dist/extensions/pi-zentui/test/responsive-dependencies.test.ts +7 -7
  960. package/dist/extensions/pi-zentui/test/runtime.test.ts +127 -2
  961. package/dist/extensions/pi-zentui/test/selesai-v030-gate.json +939 -0
  962. package/dist/extensions/pi-zentui/test/settings-command.test.ts +1330 -82
  963. package/dist/extensions/pi-zentui/test/settings-keys.test.ts +41 -0
  964. package/dist/extensions/pi-zentui/test/settings-list-selection.test.ts +88 -0
  965. package/dist/extensions/pi-zentui/test/settings-previews.test.ts +4 -1
  966. package/dist/extensions/pi-zentui/test/state.test.ts +15 -1
  967. package/dist/extensions/pi-zentui/test/telemetry-lifecycle-integration.test.ts +214 -12
  968. package/dist/extensions/pi-zentui/test/telemetry-snapshot.test.ts +246 -0
  969. package/dist/extensions/pi-zentui/test/thinking-experimental-cache.test.ts +246 -0
  970. package/dist/extensions/pi-zentui/test/thinking-experimental-rows.test.ts +22 -0
  971. package/dist/extensions/pi-zentui/test/thinking-experimental-tui.mjs +113 -51
  972. package/dist/extensions/pi-zentui/test/thinking-experimental.test.ts +576 -76
  973. package/dist/extensions/pi-zentui/test/thinking-steps.test.ts +23 -0
  974. package/dist/extensions/pi-zentui/test/token-rate.test.ts +450 -0
  975. package/dist/extensions/pi-zentui/test/turn-summary-format.test.ts +207 -0
  976. package/dist/extensions/pi-zentui/test/turn-summary-lifecycle.integration.test.ts +72 -5
  977. package/dist/extensions/pi-zentui/test/turn-summary-rate.test.ts +158 -0
  978. package/dist/extensions/pi-zentui/test/usage-lifecycle-integration.test.ts +421 -0
  979. package/dist/extensions/pi-zentui/test/usage-snapshot.test.ts +154 -0
  980. package/dist/extensions/pi-zentui/test/user-message-cache.test.ts +239 -0
  981. package/dist/extensions/pi-zentui/test/user-message-native-reduced-capabilities.test.ts +61 -0
  982. package/dist/extensions/pi-zentui/test/user-message-native.test.ts +447 -0
  983. package/dist/extensions/pi-zentui/test/user-message-styles.test.ts +2 -2
  984. package/dist/extensions/pi-zentui/test/working-line-editor-placement.test.ts +317 -0
  985. package/dist/extensions/pi-zentui/test/working-line-generation-cache.test.ts +238 -0
  986. package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +674 -179
  987. package/dist/extensions/pi-zentui/test/working-line-message-ownership.test.ts +239 -0
  988. package/dist/extensions/pi-zentui/test/working-line-metric-animation.test.ts +284 -0
  989. package/dist/extensions/pi-zentui/test/working-line-placement.test.ts +298 -0
  990. package/dist/extensions/pi-zentui/test/working-line.test.ts +386 -18
  991. package/dist/extensions/pi-zentui/test/wrapped-editor-consumers.integration.test.ts +579 -0
  992. package/dist/extensions/pi-zentui/test/wrapped-editor-usage.integration.test.ts +298 -0
  993. package/dist/extensions/pi-zentui/tsconfig.json +1 -1
  994. package/dist/extensions/pi-zentui/vitest.host.config.ts +33 -0
  995. package/dist/extensions/question/index.ts +1 -5
  996. package/dist/extensions/rtk.test.ts +28 -15
  997. package/dist/extensions/rtk.ts +22 -22
  998. package/dist/extensions/skills-index/index.test.ts +99 -0
  999. package/dist/extensions/skills-index/index.ts +105 -0
  1000. package/dist/extensions/skills-index/package.json +9 -0
  1001. package/dist/extensions/tokenin-onboarding.ts +48 -208
  1002. package/dist/extensions/tool-search/index.d.ts +11 -0
  1003. package/dist/extensions/tool-search/index.js +14 -0
  1004. package/dist/extensions/tool-search/tool.d.ts +91 -0
  1005. package/dist/extensions/tool-search/tool.js +214 -0
  1006. package/dist/index.d.ts +17 -9
  1007. package/dist/index.js +11 -5
  1008. package/dist/main.d.ts +4 -0
  1009. package/dist/main.js +106 -42
  1010. package/dist/migrations.js +4 -3
  1011. package/dist/modes/index.d.ts +1 -0
  1012. package/dist/modes/interactive/bug-report.js +4 -0
  1013. package/dist/modes/interactive/components/armin.d.ts +3 -0
  1014. package/dist/modes/interactive/components/armin.js +7 -5
  1015. package/dist/modes/interactive/components/assistant-message.js +1 -1
  1016. package/dist/modes/interactive/components/auth-url.d.ts +13 -0
  1017. package/dist/modes/interactive/components/auth-url.js +36 -0
  1018. package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
  1019. package/dist/modes/interactive/components/bash-execution.js +17 -14
  1020. package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
  1021. package/dist/modes/interactive/components/branch-summary-message.js +5 -2
  1022. package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
  1023. package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
  1024. package/dist/modes/interactive/components/config-selector.js +13 -3
  1025. package/dist/modes/interactive/components/custom-editor.js +7 -0
  1026. package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
  1027. package/dist/modes/interactive/components/custom-entry.js +8 -2
  1028. package/dist/modes/interactive/components/custom-message.js +1 -0
  1029. package/dist/modes/interactive/components/first-time-setup.d.ts +4 -4
  1030. package/dist/modes/interactive/components/first-time-setup.js +8 -2
  1031. package/dist/modes/interactive/components/footer.d.ts +7 -0
  1032. package/dist/modes/interactive/components/footer.js +44 -4
  1033. package/dist/modes/interactive/components/index.d.ts +0 -1
  1034. package/dist/modes/interactive/components/index.js +0 -1
  1035. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  1036. package/dist/modes/interactive/components/login-dialog.js +11 -5
  1037. package/dist/modes/interactive/components/mermaid.d.ts +10 -0
  1038. package/dist/modes/interactive/components/mermaid.js +74 -0
  1039. package/dist/modes/interactive/components/model-selector.d.ts +14 -9
  1040. package/dist/modes/interactive/components/model-selector.js +79 -31
  1041. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  1042. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  1043. package/dist/modes/interactive/components/pi-logo.d.ts +18 -0
  1044. package/dist/modes/interactive/components/pi-logo.js +36 -0
  1045. package/dist/modes/interactive/components/radius-login-selector.d.ts +14 -0
  1046. package/dist/modes/interactive/components/radius-login-selector.js +84 -0
  1047. package/dist/modes/interactive/components/scoped-models-selector.d.ts +4 -0
  1048. package/dist/modes/interactive/components/scoped-models-selector.js +26 -0
  1049. package/dist/modes/interactive/components/settings-selector.d.ts +8 -11
  1050. package/dist/modes/interactive/components/settings-selector.js +60 -102
  1051. package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
  1052. package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
  1053. package/dist/modes/interactive/components/themed-text.d.ts +16 -0
  1054. package/dist/modes/interactive/components/themed-text.js +28 -0
  1055. package/dist/modes/interactive/components/tool-execution.d.ts +11 -18
  1056. package/dist/modes/interactive/components/tool-execution.js +34 -47
  1057. package/dist/modes/interactive/components/tree-selector.js +7 -0
  1058. package/dist/modes/interactive/components/user-message.d.ts +3 -1
  1059. package/dist/modes/interactive/components/user-message.js +14 -6
  1060. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  1061. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  1062. package/dist/modes/interactive/external-editor.js +2 -1
  1063. package/dist/modes/interactive/interactive-mode.d.ts +41 -8
  1064. package/dist/modes/interactive/interactive-mode.js +854 -492
  1065. package/dist/modes/interactive/program-status-reporter.d.ts +33 -0
  1066. package/dist/modes/interactive/program-status-reporter.js +109 -0
  1067. package/dist/modes/interactive/theme/dark.json +59 -72
  1068. package/dist/modes/interactive/theme/light.json +57 -69
  1069. package/dist/modes/interactive/theme/system-theme.d.ts +54 -0
  1070. package/dist/modes/interactive/theme/system-theme.js +545 -0
  1071. package/dist/modes/interactive/theme/theme-controller.d.ts +46 -6
  1072. package/dist/modes/interactive/theme/theme-controller.js +127 -47
  1073. package/dist/modes/interactive/theme/theme-json.d.ts +1 -0
  1074. package/dist/modes/interactive/theme/theme-json.js +3 -1
  1075. package/dist/modes/interactive/theme/theme-schema.json +7 -2
  1076. package/dist/modes/interactive/theme/theme.d.ts +66 -39
  1077. package/dist/modes/interactive/theme/theme.js +243 -320
  1078. package/dist/modes/interactive/tui-renderer.d.ts +2 -1
  1079. package/dist/modes/interactive/tui-renderer.js +1 -0
  1080. package/dist/modes/json-event.d.ts +33 -0
  1081. package/dist/modes/json-event.js +28 -0
  1082. package/dist/modes/print-mode.js +12 -2
  1083. package/dist/modes/rpc/rpc-client.d.ts +11 -19
  1084. package/dist/modes/rpc/rpc-client.js +52 -35
  1085. package/dist/modes/rpc/rpc-mode.js +11 -26
  1086. package/dist/modes/rpc/rpc-types.d.ts +12 -23
  1087. package/dist/package-manager-cli.js +16 -5
  1088. package/dist/rpc-entry.js +1 -0
  1089. package/dist/skills/pi-subagents/SKILL.md +109 -35
  1090. package/dist/skills/pi-subagents/references/constraints-and-recipes.md +38 -238
  1091. package/dist/skills/pi-subagents/references/execution-controls.md +181 -83
  1092. package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -9
  1093. package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +24 -2
  1094. package/dist/skills/pi-subagents/references/prompting-and-roles.md +121 -91
  1095. package/dist/skills/pi-subagents/references/review-and-validation.md +73 -0
  1096. package/dist/utils/ansi.d.ts +8 -0
  1097. package/dist/utils/ansi.js +30 -11
  1098. package/dist/utils/clipboard-image.js +14 -17
  1099. package/dist/utils/clipboard.d.ts +2 -0
  1100. package/dist/utils/clipboard.js +17 -11
  1101. package/dist/utils/frontmatter.js +2 -1
  1102. package/dist/utils/image-convert.d.ts +12 -0
  1103. package/dist/utils/image-convert.js +45 -6
  1104. package/dist/utils/image-resize-core.d.ts +12 -0
  1105. package/dist/utils/image-resize-core.js +5 -0
  1106. package/dist/utils/image-resize-worker.js +3 -2
  1107. package/dist/utils/image-resize.js +9 -10
  1108. package/dist/utils/mime.js +1 -1
  1109. package/dist/utils/output-files.d.ts +14 -0
  1110. package/dist/utils/output-files.js +29 -0
  1111. package/dist/utils/paths.d.ts +6 -3
  1112. package/dist/utils/paths.js +28 -5
  1113. package/dist/utils/shell.d.ts +1 -3
  1114. package/dist/utils/shell.js +3 -30
  1115. package/dist/utils/syntax-highlight.d.ts +1 -0
  1116. package/dist/utils/syntax-highlight.js +68 -2
  1117. package/dist/utils/tool-result-images.d.ts +20 -0
  1118. package/dist/utils/tool-result-images.js +47 -0
  1119. package/dist/utils/tools-manager.d.ts +5 -0
  1120. package/dist/utils/tools-manager.js +6 -6
  1121. package/dist/utils/version-check.d.ts +4 -0
  1122. package/dist/utils/version-check.js +20 -2
  1123. package/docs/cli-integration.md +104 -0
  1124. package/docs/cli.md +333 -0
  1125. package/docs/codemode.md +230 -0
  1126. package/docs/configuration.md +47 -0
  1127. package/docs/environment-variables.md +5 -0
  1128. package/docs/extensions.md +107 -30
  1129. package/docs/json.md +8 -4
  1130. package/docs/keybindings.md +10 -10
  1131. package/docs/mcp.md +262 -0
  1132. package/docs/models.md +104 -3
  1133. package/docs/providers.md +20 -2
  1134. package/docs/rpc.md +13 -12
  1135. package/docs/sdk.md +41 -33
  1136. package/docs/security.md +21 -20
  1137. package/docs/settings.md +18 -46
  1138. package/docs/terminal-setup.md +14 -0
  1139. package/docs/virtual-models.md +114 -0
  1140. package/examples/extensions/jev-router.ts +113 -0
  1141. package/examples/extensions/tokenin-usage-widget.ts +124 -0
  1142. package/examples/rpc-client.ts +35 -0
  1143. package/examples/sdk/14-codemode-mcp.ts +67 -0
  1144. package/package.json +15 -8
  1145. package/dist/core/agent-session-auto-handoff.test.js +0 -195
  1146. package/dist/core/built-in-extensions.d.ts +0 -2
  1147. package/dist/core/built-in-extensions.js +0 -2
  1148. package/dist/core/llama/provider.js +0 -143
  1149. package/dist/core/settings-manager-auto-handoff.test.d.ts +0 -1
  1150. package/dist/core/settings-manager-auto-handoff.test.js +0 -53
  1151. package/dist/extensions/capability-gateway/catalog.ts +0 -177
  1152. package/dist/extensions/capability-gateway/index.test.ts +0 -226
  1153. package/dist/extensions/capability-gateway/index.ts +0 -669
  1154. package/dist/extensions/capability-gateway/integration.test.ts +0 -803
  1155. package/dist/extensions/capability-gateway/package.json +0 -16
  1156. package/dist/extensions/capability-gateway/routing.test.ts +0 -574
  1157. package/dist/extensions/capability-gateway/routing.ts +0 -403
  1158. package/dist/extensions/pi-subagents/runner-server-preload.mjs +0 -13
  1159. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +0 -89
  1160. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +0 -259
  1161. package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +0 -312
  1162. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +0 -374
  1163. package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +0 -69
  1164. package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +0 -307
  1165. package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +0 -211
  1166. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +0 -3
  1167. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +0 -2
  1168. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +0 -17
  1169. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +0 -57
  1170. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +0 -16
  1171. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +0 -15
  1172. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +0 -18
  1173. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +0 -9
  1174. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +0 -10
  1175. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +0 -10
  1176. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +0 -20
  1177. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +0 -3
  1178. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +0 -96
  1179. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +0 -119
  1180. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +0 -85
  1181. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +0 -620
  1182. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +0 -5
  1183. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +0 -56
  1184. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +0 -32
  1185. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +0 -49
  1186. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +0 -93
  1187. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +0 -128
  1188. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +0 -7
  1189. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +0 -38
  1190. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +0 -3
  1191. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +0 -15
  1192. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +0 -9
  1193. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +0 -29
  1194. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +0 -2
  1195. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +0 -22
  1196. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +0 -37
  1197. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +0 -34
  1198. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +0 -12
  1199. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +0 -23
  1200. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +0 -171
  1201. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +0 -1261
  1202. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +0 -20
  1203. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +0 -54
  1204. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +0 -22
  1205. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +0 -13
  1206. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +0 -358
  1207. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +0 -77
  1208. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +0 -512
  1209. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +0 -43
  1210. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +0 -121
  1211. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +0 -82
  1212. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +0 -17
  1213. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +0 -7
  1214. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +0 -210
  1215. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +0 -15
  1216. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +0 -54
  1217. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +0 -4
  1218. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +0 -55
  1219. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +0 -2
  1220. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +0 -5
  1221. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +0 -30
  1222. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +0 -206
  1223. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +0 -15
  1224. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +0 -106
  1225. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +0 -19
  1226. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +0 -356
  1227. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +0 -297
  1228. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +0 -60
  1229. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +0 -15
  1230. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +0 -18
  1231. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +0 -28
  1232. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +0 -3
  1233. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +0 -10
  1234. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +0 -68
  1235. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +0 -106
  1236. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +0 -51
  1237. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +0 -6
  1238. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +0 -35
  1239. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +0 -37
  1240. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +0 -40
  1241. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +0 -37
  1242. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +0 -52
  1243. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +0 -10
  1244. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +0 -35
  1245. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +0 -24
  1246. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +0 -14
  1247. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +0 -70
  1248. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +0 -26
  1249. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +0 -36
  1250. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +0 -19
  1251. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +0 -61
  1252. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +0 -23
  1253. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +0 -3
  1254. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +0 -10
  1255. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +0 -42
  1256. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +0 -35
  1257. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +0 -12
  1258. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +0 -33
  1259. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +0 -9
  1260. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +0 -34
  1261. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +0 -22
  1262. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +0 -34
  1263. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +0 -16
  1264. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +0 -16
  1265. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +0 -16
  1266. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +0 -102
  1267. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +0 -14
  1268. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +0 -21
  1269. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +0 -19
  1270. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +0 -20
  1271. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  1272. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +0 -12
  1273. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +0 -15
  1274. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  1275. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +0 -22
  1276. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +0 -23
  1277. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +0 -26
  1278. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +0 -25
  1279. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +0 -32
  1280. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +0 -34
  1281. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +0 -13
  1282. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +0 -52
  1283. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +0 -54
  1284. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +0 -33
  1285. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +0 -42
  1286. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +0 -23
  1287. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +0 -95
  1288. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +0 -77
  1289. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +0 -10
  1290. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +0 -17
  1291. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +0 -28
  1292. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +0 -11
  1293. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +0 -11
  1294. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +0 -63
  1295. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +0 -94
  1296. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +0 -23
  1297. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +0 -30
  1298. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +0 -14
  1299. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +0 -24
  1300. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +0 -394
  1301. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +0 -12
  1302. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +0 -29
  1303. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +0 -120
  1304. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +0 -28
  1305. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +0 -17
  1306. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +0 -246
  1307. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +0 -20
  1308. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +0 -457
  1309. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +0 -8
  1310. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +0 -3
  1311. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +0 -2
  1312. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +0 -22
  1313. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +0 -18
  1314. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +0 -11
  1315. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +0 -11
  1316. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +0 -4
  1317. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +0 -4
  1318. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +0 -5
  1319. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +0 -8
  1320. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +0 -5
  1321. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +0 -26
  1322. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +0 -7
  1323. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +0 -10
  1324. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +0 -18
  1325. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +0 -30
  1326. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +0 -2
  1327. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +0 -16
  1328. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +0 -3
  1329. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +0 -3
  1330. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +0 -9
  1331. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +0 -31
  1332. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +0 -21
  1333. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +0 -2
  1334. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +0 -31
  1335. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +0 -5
  1336. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +0 -12
  1337. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +0 -3
  1338. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +0 -15
  1339. package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +0 -3
  1340. package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +0 -31
  1341. package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +0 -74
  1342. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +0 -150
  1343. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +0 -766
  1344. package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +0 -327
  1345. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +0 -309
  1346. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +0 -1093
  1347. package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +0 -94
  1348. package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +0 -1329
  1349. package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +0 -153
  1350. package/dist/extensions/pi-zentui/extensions/zentui/accent-rail-layout-patch.ts +0 -457
  1351. package/dist/extensions/pi-zentui/test/accent-rail-layout-patch.test.ts +0 -669
  1352. package/dist/extensions/pi-zentui/test/thinking-experimental-docs.test.ts +0 -51
  1353. package/dist/modes/interactive/components/daxnuts.d.ts +0 -22
  1354. package/dist/modes/interactive/components/daxnuts.js +0 -139
  1355. /package/dist/core/{agent-session-auto-handoff.test.d.ts → agent-session-custom-tools.test.d.ts} +0 -0
  1356. /package/dist/{core → extensions}/llama/huggingface.d.ts +0 -0
  1357. /package/dist/{core → extensions}/llama/huggingface.js +0 -0
  1358. /package/dist/{core → extensions}/llama/index.d.ts +0 -0
  1359. /package/dist/{core → extensions}/llama/ui.d.ts +0 -0
  1360. /package/dist/{core → extensions}/llama/ui.js +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,
@@ -97,10 +80,8 @@ import { applyThinkingSuffix, projectLaunchResolvedChildExtensions, resolvePiLau
97
80
  import type { InheritedChildRuntime } from "../shared/child-launch.ts";
98
81
  import { buildRunnerChildLaunch } from "./runner-child-launch.ts";
99
82
  import { normalizeExtensionBindings } from "../shared/extension-bindings.ts";
100
- import type { ChildSessionFactory } from "../shared/child-session.ts";
101
- import { getSettledReadonlyChild, runChildSession, type ChildEvent, type RunChildSessionInput, type RunChildSessionResult, type StepSteerHandler } from "./run-child-session.ts";
102
- import { planReadonlyModelContinuation, READONLY_CONTINUATION_PROMPT, type LogicalRecoveryState } from "../shared/readonly-model-continuation.ts";
103
- 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";
104
85
  import { loadRunnerChildSessionFactory } from "./runner-child-sessions.ts";
105
86
  import { SUBAGENT_CHILD_ENV } from "../shared/child-runtime-config.ts";
106
87
  import { deriveChildSessionName } from "../../shared/child-session-name.ts";
@@ -113,12 +94,13 @@ import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTr
113
94
  import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
114
95
  import { claimRunFanoutBatch, getRunFanoutBudgetSnapshot } from "../shared/run-fanout-budget.ts";
115
96
  import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
116
- import { formatModelAttemptNote, formatSubagentModelVerificationError, isContextOverflow, isRetryableModelFailureAttempt, recordRetryableModelFailure } from "../shared/model-fallback.ts";
117
- import { markProcessTerminalCandidateLeaseRelease, processTerminalPath, writeProcessTerminalCandidate, type ProcessTerminalCandidate } from "./process-terminal.ts";
118
- import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, updateSteeringTarget } from "./steering.ts";
119
- import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getFinalOutput, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.ts";
120
- import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.ts";
121
- 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";
122
104
  import { planAbortRecovery } from "../shared/abort-recovery.ts";
123
105
  import {
124
106
  createMutatingFailureState,
@@ -148,10 +130,10 @@ import {
148
130
  } from "../shared/worktree.ts";
149
131
  import { findModelInfo, resolveEffectiveThinking, splitKnownThinkingSuffix } from "../../shared/model-info.ts";
150
132
  import { assertThinkingWithinCeiling } from "../../shared/thinking-ceiling.ts";
151
- import { launchBindingDigest } from "../../shared/launch-contract.ts";
133
+ import { resolveLaunchBinding } from "../../shared/launch-contract.ts";
152
134
  import { writeInitialProgressFile } from "../../shared/settings.ts";
153
135
  import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts";
154
- 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";
155
137
  import { attachContractProjections, isAgentContract } from "../shared/agent-contract.ts";
156
138
  import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
157
139
  import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
@@ -161,9 +143,14 @@ import { effectiveToolTimeoutMs, formatToolTimeoutMessage, toolTimeoutCallKey }
161
143
  import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
162
144
  import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup, writeWorktreeSetupHandoff } from "../shared/parallel-handoff.ts";
163
145
  import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
164
- import { acquireSessionLease, type SessionLeaseRequest } from "../shared/session-lease.ts";
146
+ import type { SessionLeaseRequest } from "../shared/session-lease.ts";
165
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";
166
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";
167
154
  import { runExternalJob } from "../shared/external-job-runner.ts";
168
155
  import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-progress-tabs.ts";
169
156
  import type { ResolvedSubagentCapabilityCeiling } from "../shared/capability-ceiling.ts";
@@ -182,7 +169,7 @@ const INTERCOM_DETACH_RECEIPT = "Detached for intercom coordination before task
182
169
  // child host.
183
170
  process.env[SUBAGENT_CHILD_ENV] = "1";
184
171
 
185
- interface SubagentRunConfig {
172
+ export interface SubagentRunConfig {
186
173
  id: string;
187
174
  steps: RunnerStep[];
188
175
  resultPath: string;
@@ -203,6 +190,8 @@ interface SubagentRunConfig {
203
190
  childSessionFactoryModule?: string;
204
191
  /** The launching executor's own child runtime when it was itself an in-process child. */
205
192
  inheritedChildRuntime?: InheritedChildRuntime;
193
+ /** The launching session's project trust; undefined keeps Pi's default for hosts without trust. */
194
+ projectTrusted?: boolean;
206
195
  worktreeSetupHook?: string;
207
196
  worktreeSetupHookTimeoutMs?: number;
208
197
  worktreeBaseDir?: string;
@@ -222,6 +211,8 @@ interface SubagentRunConfig {
222
211
  deadlineAt?: number;
223
212
  /** Resolved configured hard per-tool-call timeout (ms); fast tools still have a default when undefined. */
224
213
  toolTimeoutMs?: number;
214
+ /** Steer the running steps to checkpoint and stop this many ms before `deadlineAt`; absent = no checkpoint steer. */
215
+ checkpointBeforeDeadlineMs?: number;
225
216
  toolBudget?: ResolvedToolBudget;
226
217
  usageBudget?: UsageBudgetConfig;
227
218
  revivalLease?: SessionLeaseRequest;
@@ -230,6 +221,7 @@ interface SubagentRunConfig {
230
221
  globalConcurrencyLimit?: number;
231
222
  capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
232
223
  runFanoutBudget?: RunFanoutBudgetDescriptor;
224
+ /** Builtin tool names the host runtime provides; used to intersect agent-declared tools. */
233
225
  launchContractDigest?: string;
234
226
  launchResolvedExtensions?: LaunchResolvedChildExtensions;
235
227
  runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
@@ -251,6 +243,7 @@ interface StepResult {
251
243
  runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
252
244
  output: string;
253
245
  outputState?: SubagentOutputState;
246
+ outputPartial?: boolean;
254
247
  error?: string;
255
248
  success?: boolean;
256
249
  exitCode: number | null;
@@ -268,14 +261,15 @@ interface StepResult {
268
261
  sessionFile?: string;
269
262
  intercomTarget?: string;
270
263
  model?: string;
264
+ nativeMachine?: import("../../shared/types.ts").SingleResult["nativeMachine"];
271
265
  thinking?: string;
272
- attemptedModels?: string[];
273
- modelAttempts?: ModelAttempt[];
266
+ requestedModel?: string;
274
267
  /** True when the dispatch failed because the input exceeded the model's context window. */
275
268
  contextOverflow?: boolean;
276
269
  totalCost?: CostSummary;
277
270
  artifactPaths?: ArtifactPaths;
278
271
  outputSaveError?: string;
272
+ artifactOutputSaveFailed?: true;
279
273
  metadataSaveError?: string;
280
274
  truncated?: boolean;
281
275
  transcriptPath?: string;
@@ -419,50 +413,22 @@ function emptyUsage(): Usage {
419
413
  return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
420
414
  }
421
415
 
422
- function tokenUsageFromAttempts(attempts: ModelAttempt[] | undefined): TokenUsage | null {
423
- if (!attempts || attempts.length === 0) return null;
424
- let input = 0;
425
- let output = 0;
426
- for (const attempt of attempts) {
427
- input += attempt.usage?.input ?? 0;
428
- output += attempt.usage?.output ?? 0;
429
- }
416
+ function tokenUsageFromUsage(usage: Usage | undefined): TokenUsage | null {
417
+ const input = usage?.input ?? 0;
418
+ const output = usage?.output ?? 0;
430
419
  const total = input + output;
431
420
  return total > 0 ? { input, output, total } : null;
432
421
  }
433
422
 
434
- function costSummaryFromAttempts(attempts: ModelAttempt[] | undefined): CostSummary | undefined {
435
- if (!attempts || attempts.length === 0) return undefined;
436
- let inputTokens = 0;
437
- let outputTokens = 0;
438
- let costUsd = 0;
439
- for (const attempt of attempts) {
440
- inputTokens += attempt.usage?.input ?? 0;
441
- outputTokens += attempt.usage?.output ?? 0;
442
- costUsd += attempt.usage?.cost ?? 0;
443
- }
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;
444
427
  return inputTokens > 0 || outputTokens > 0 || costUsd > 0
445
428
  ? { inputTokens, outputTokens, costUsd }
446
429
  : undefined;
447
430
  }
448
431
 
449
- function usageFromAttempts(attempts: ModelAttempt[] | undefined): Usage | undefined {
450
- if (!attempts || attempts.length === 0) return undefined;
451
- const usage = emptyUsage();
452
- for (const attempt of attempts) {
453
- if (!attempt.usage) continue;
454
- usage.input += attempt.usage.input;
455
- usage.output += attempt.usage.output;
456
- usage.cacheRead += attempt.usage.cacheRead;
457
- usage.cacheWrite += attempt.usage.cacheWrite;
458
- usage.cost += attempt.usage.cost;
459
- usage.turns += attempt.usage.turns;
460
- }
461
- return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0
462
- ? usage
463
- : undefined;
464
- }
465
-
466
432
  function appendRecentStepOutput(step: RunnerStatusStep, lines: string[]): void {
467
433
  const nonEmpty = lines.filter((line) => line.trim());
468
434
  if (nonEmpty.length === 0) return;
@@ -656,6 +622,38 @@ function writeRunLog(
656
622
  write(logPath, lines.join("\n"));
657
623
  }
658
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
+
659
657
  /** Context for running a single step */
660
658
  interface SingleStepContext {
661
659
  previousOutput: string;
@@ -676,11 +674,14 @@ interface SingleStepContext {
676
674
  childSessions: ChildSessionFactory;
677
675
  /** The launching executor's own child runtime; nested route, depth, and ceilings come from here. */
678
676
  inheritedChildRuntime?: InheritedChildRuntime;
677
+ projectTrusted?: boolean;
679
678
  registerInterrupt?: (interrupt: (() => void) | undefined) => void;
680
679
  registerTimeout?: (interrupt: (() => void) | undefined) => void;
681
680
  registerStop?: (stop: (() => void) | undefined) => void;
682
681
  /** Receives the live child's steer handler while its session runs. */
683
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;
684
685
  timeoutSignal?: AbortSignal;
685
686
  stopSignal?: AbortSignal;
686
687
  timeoutMessage?: string;
@@ -697,22 +698,41 @@ interface SingleStepContext {
697
698
  onAttemptStart?: (attempt: { model?: string; thinking?: string; contextLimit?: number }) => void;
698
699
  onChildEvent?: (event: ChildEvent) => void;
699
700
  onExternalProcess?: (process: ExternalProcessStatus) => void;
701
+ prepareExternalActivity?: (cwd: string, signal: AbortSignal) => Promise<void>;
702
+ onExternalStreamActivity?: () => void;
700
703
  onExternalJob?: (status: ExternalJobStatus) => void;
701
704
  skipAcceptance?: () => boolean;
702
705
  /** Authoritative owner decision after event delivery; undefined includes incomplete run-wide usage. */
703
706
  usageBudgetExhausted?: () => boolean | undefined;
704
707
  /** Existing run-owned budget configuration; cost allowance is not settled by the live token ledger. */
705
708
  usageBudget?: UsageBudgetConfig;
706
- /** False when sibling work in the same Git worktree could have caused the tracked diff. */
707
- trackedMutationEvidenceForCompletionGuard?: boolean;
708
709
  orcaProgressTab?: OrcaProgressTab;
709
710
  }
710
711
 
711
- /** 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
+
712
732
  export async function runSingleStepInner(
713
733
  step: SubagentStep,
714
734
  ctx: SingleStepContext,
715
- ): Promise<StepResult & { completionGuardTriggered?: boolean }> {
735
+ ): Promise<StepResult> {
716
736
  if (step.importAsyncRoot) {
717
737
  let importTimedOut = false;
718
738
  let importStopped = false;
@@ -767,8 +787,7 @@ export async function runSingleStepInner(
767
787
  sessionFile: imported.sessionFile,
768
788
  intercomTarget: imported.intercomTarget,
769
789
  model: imported.model,
770
- attemptedModels: imported.attemptedModels,
771
- modelAttempts: imported.modelAttempts,
790
+ requestedModel: imported.requestedModel,
772
791
  contextOverflow: imported.contextOverflow,
773
792
  totalCost: imported.totalCost,
774
793
  usage: imported.usage,
@@ -791,7 +810,6 @@ export async function runSingleStepInner(
791
810
  const placeholderRegex = new RegExp(ctx.placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
792
811
  let task = step.task.replace(placeholderRegex, () => ctx.previousOutput);
793
812
  if (ctx.outputs) task = resolveOutputReferences(task, ctx.outputs);
794
- const taskForCompletionGuard = task;
795
813
  let resolvedTaskToolPlan: ReturnType<typeof resolvePiLaunchToolPlan> | undefined;
796
814
  if (!step.runner) {
797
815
  resolvedTaskToolPlan = resolvePiLaunchToolPlan(omitUndefinedProperties({
@@ -802,37 +820,16 @@ export async function runSingleStepInner(
802
820
  subagentOnlyExtensions: step.subagentOnlyExtensions,
803
821
  fast: step.fast,
804
822
  model: step.model,
805
- modelCandidates: step.modelCandidates,
806
823
  mcpDirectTools: step.mcpDirectTools,
824
+ builtinMcpTools: step.builtinMcpTools,
807
825
  cwd: step.cwd ?? ctx.cwd,
808
826
  requireReadTool: Boolean(step.skills?.length),
809
827
  structuredOutput: Boolean(effectiveStructuredOutput),
810
828
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
811
829
  inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
830
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
812
831
  permissionRules: step.permissionRules,
813
832
  }));
814
- const contractTools = resolvedTaskToolPlan.explicitToolAllowlist ? resolvedTaskToolPlan.effectiveToolAllowlist : undefined;
815
- const contractError = validateImplementationToolContract({
816
- agent: step.agent,
817
- task: taskForCompletionGuard,
818
- tools: contractTools,
819
- mcpDirectTools: resolvedTaskToolPlan.effectiveMcpTools,
820
- configuredExtensions: resolvedTaskToolPlan.configuredExtensions,
821
- requestedTools: resolvedTaskToolPlan.requestedBuiltinTools,
822
- acceptanceRole: step.acceptanceRole,
823
- completionGuard: step.completionGuard,
824
- });
825
- if (contractError) {
826
- return omitUndefinedProperties({
827
- agent: step.agent,
828
- context: step.context,
829
- output: contractError,
830
- error: contractError,
831
- exitCode: 1,
832
- capabilityCeiling: resolvedTaskToolPlan.capabilityCeiling,
833
- capabilityAudit: resolvedTaskToolPlan.capabilityAudit,
834
- });
835
- }
836
833
  }
837
834
  // Derive from the pre-acceptance task so internal acceptance/recovery
838
835
  // instructions never leak into the display name.
@@ -867,24 +864,91 @@ export async function runSingleStepInner(
867
864
  transcriptWriter?.writeInitialUserMessage(`${PROMPT_REDACTED}; live Prompt Audit only.`);
868
865
 
869
866
  if (step.runner?.type === "external-cli") {
870
- const externalCwd = step.cwd ?? ctx.cwd;
871
- 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 } : {}) });
872
922
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
873
- const external = await runExternalCli(omitUndefinedProperties({
874
- command: runner.command,
875
- 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,
876
930
  cwd: externalCwd,
877
931
  prompt: buildExternalCliPrompt(step.systemPrompt ?? "", task),
878
932
  asyncDir: path.dirname(ctx.outputFile),
879
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,
880
940
  registerTimeout: ctx.registerTimeout,
881
941
  registerStop: ctx.registerStop,
882
942
  timeoutMessage: ctx.timeoutMessage,
883
943
  stopMessage: ctx.stopMessage,
884
944
  onProcess: ctx.onExternalProcess,
885
- onStdout: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8")),
886
- onStderr: (chunk) => ctx.orcaProgressTab?.append(chunk.toString("utf-8")),
887
- }));
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;
888
952
  try { fs.writeFileSync(ctx.outputFile, external.output, "utf-8"); } catch { /* Observability output is best-effort. */ }
889
953
  const resolvedOutput = step.outputPath && external.exitCode === 0
890
954
  ? resolveSingleOutput(step.outputPath, external.output, outputSnapshot, step.outputClaimPath)
@@ -908,7 +972,7 @@ export async function runSingleStepInner(
908
972
  artifactPaths,
909
973
  artifactConfig: ctx.artifactConfig,
910
974
  output: formatOutputArtifactContent(omitUndefinedProperties({ output: resolvedOutput.fullOutput, error: external.error, metadataPath: ctx.artifactConfig?.includeMetadata === false ? undefined : artifactPaths.metadataPath })),
911
- 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() },
912
976
  })
913
977
  : {};
914
978
  return omitUndefinedProperties({
@@ -924,9 +988,10 @@ export async function runSingleStepInner(
924
988
  processSignal: external.processSignal,
925
989
  artifactPaths,
926
990
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
991
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
927
992
  metadataSaveError: artifactErrors.metadataSaveError,
928
993
  runner,
929
- externalProcess: external.externalProcess,
994
+ externalProcess: externalProcess,
930
995
  });
931
996
  }
932
997
 
@@ -993,6 +1058,7 @@ export async function runSingleStepInner(
993
1058
  stopped: external.stopped,
994
1059
  artifactPaths,
995
1060
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
1061
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
996
1062
  metadataSaveError: artifactErrors.metadataSaveError,
997
1063
  runner,
998
1064
  externalJob: external.externalJob,
@@ -1006,73 +1072,39 @@ export async function runSingleStepInner(
1006
1072
  alignForkedSessionCwd(step.sessionFile, effectiveCwd);
1007
1073
  }
1008
1074
 
1009
- const candidates = step.modelCandidates !== undefined
1010
- ? step.modelCandidates.length > 0 ? step.modelCandidates : [undefined]
1011
- : step.model
1012
- ? [step.model]
1013
- : [undefined];
1014
- const attemptedModels: string[] = [];
1075
+ const candidate = step.model;
1015
1076
  let capabilityAudit: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit | undefined;
1016
1077
  let launchResolvedExtensions = step.launchResolvedExtensions;
1017
- const modelAttempts: ModelAttempt[] = [];
1018
- const attemptNotes: string[] = [];
1019
- const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
1020
1078
  let finalRequiredOutputMissing: boolean | undefined;
1079
+ const eventsPath = path.join(path.dirname(ctx.outputFile), "events.jsonl");
1021
1080
  let finalResult: RunChildSessionResult | undefined;
1022
1081
  let finalOutputSnapshot: SingleOutputSnapshot | undefined;
1023
1082
  let structuredAcceptanceReport: unknown;
1024
1083
  let structuredAcceptanceReportError: string | undefined;
1025
- let completionGuardTriggeredFinal = false;
1026
1084
  let toolBudget = step.toolBudget ? initialToolBudgetState(step.toolBudget) : undefined;
1027
1085
  let toolBudgetBlocked = false;
1028
1086
  let actualLaunchContractDigest = step.launchContractDigest;
1029
- 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);
1030
1088
  let finalMutationEvidence = collectTrackedMutationEvidence(mutationSnapshot, step.cwd ?? ctx.cwd);
1031
1089
 
1032
- let modelIndex = 0;
1033
1090
  let contextOverflow = false;
1034
1091
  let launchWarningsEmitted = false;
1035
- let recoveryState: LogicalRecoveryState = "unused";
1036
- let readonlyContinuation: RunChildSessionInput["readonlyContinuation"];
1037
- const continuationBudget = () => {
1038
- if (step.toolBudget) return "tool-budget-configured" as const;
1039
- // Refresh the authoritative run ledger, already fed synchronously by onChildEvent.
1040
- const exhausted = ctx.usageBudgetExhausted?.();
1041
- if (exhausted === true) return "exhausted" as const;
1042
- if (!ctx.usageBudget) return "unconfigured" as const;
1043
- if (ctx.usageBudget.costUsd || !ctx.onChildEvent || exhausted !== false) return "unknown" as const;
1044
- return "available" as const;
1045
- };
1046
- const lifecycleAllowsContinuation = () => !ctx.timeoutSignal?.aborted && !ctx.stopSignal?.aborted
1047
- && !ctx.skipAcceptance?.() && (ctx.deadlineAt === undefined || Date.now() < ctx.deadlineAt);
1048
- const canContinue = () => lifecycleAllowsContinuation() && ["available", "unconfigured"].includes(continuationBudget());
1049
- const failContinuationLaunch = (candidate: string | undefined, error: unknown) => {
1050
- const message = error instanceof Error ? error.message : String(error);
1051
- modelAttempts.push({ model: candidate ?? "default", success: false, exitCode: 1, error: message });
1052
- if (candidate) attemptedModels.push(candidate);
1053
- if (finalResult) finalResult = { ...finalResult, exitCode: 1, error: message };
1054
- };
1055
- let nextAttemptTask = task;
1056
- modelAttemptsLoop: while (modelIndex < candidates.length) {
1057
- if (ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break;
1058
- if (readonlyContinuation && !canContinue()) break;
1059
- const recoveringAbort = recoveryState === "abort-recovery";
1060
- const attemptTask = nextAttemptTask;
1061
- const candidate = candidates[modelIndex];
1062
- 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;
1063
1099
  try {
1064
1100
  assertThinkingWithinCeiling({ model: candidate, configThinking: step.thinking, ceiling: step.thinkingCeiling, agent: step.agent, runId: ctx.id });
1065
1101
  } catch (error) {
1066
1102
  const message = error instanceof Error ? error.message : String(error);
1067
- if (readonlyContinuation) {
1068
- failContinuationLaunch(candidate, error);
1069
- break modelAttemptsLoop;
1070
- }
1071
1103
  return omitUndefinedProperties({ agent: step.agent, output: message, error: message, exitCode: 1, context: step.context, thinkingCeiling: step.thinkingCeiling });
1072
1104
  }
1105
+ const attemptModel = omitUndefinedProperties({ model: candidate, thinking: resolveEffectiveThinking(candidate, step.thinking) });
1073
1106
  ctx.onAttemptStart?.(omitUndefinedProperties({
1074
- model: candidate,
1075
- thinking: resolveEffectiveThinking(candidate, step.thinking),
1107
+ ...attemptModel,
1076
1108
  contextLimit: findModelInfo(candidate, step.modelVerificationRegistry)?.contextWindow,
1077
1109
  }));
1078
1110
  const outputSnapshot = captureSingleOutputSnapshot(step.outputPath);
@@ -1104,11 +1136,7 @@ export async function runSingleStepInner(
1104
1136
  childWatchdog,
1105
1137
  watchdogStatus: (event) => watchdogSink?.(event),
1106
1138
  });
1107
- } catch (error) {
1108
- if (!readonlyContinuation) throw error;
1109
- failContinuationLaunch(candidate, error);
1110
- break modelAttemptsLoop;
1111
- }
1139
+ } catch (error) { throw error; }
1112
1140
  if (effectiveStructuredOutput && launch.config.structuredOutput) {
1113
1141
  // The runner reads the value back from the runtime's files after the run.
1114
1142
  launch.config.structuredOutput.capture = createStructuredOutputFileCapture(effectiveStructuredOutput);
@@ -1127,51 +1155,52 @@ export async function runSingleStepInner(
1127
1155
  subagentOnlyExtensions: step.subagentOnlyExtensions,
1128
1156
  fast: step.fast,
1129
1157
  model: step.model,
1130
- modelCandidates: step.modelCandidates,
1131
1158
  mcpDirectTools: step.mcpDirectTools,
1159
+ builtinMcpTools: step.builtinMcpTools,
1132
1160
  cwd: step.cwd ?? ctx.cwd,
1133
1161
  requireReadTool: Boolean(step.skills?.length),
1134
1162
  structuredOutput: Boolean(effectiveStructuredOutput),
1135
1163
  capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
1136
1164
  inheritedCapabilityCeiling: ctx.inheritedChildRuntime?.capabilityCeiling,
1165
+ requiredExtensions: step.requiredExtensions ?? ctx.inheritedChildRuntime?.requiredExtensions,
1137
1166
  permissionRules: step.permissionRules,
1138
1167
  }));
1139
1168
  launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
1140
- actualLaunchContractDigest = launchBindingDigest(omitUndefinedProperties({
1169
+ actualLaunchContractDigest = resolveLaunchBinding({
1141
1170
  definitionDigest: step.definitionDigest,
1142
- task: step.launchBindingTask ?? task,
1143
- ...(candidate ? { model: candidate } : {}),
1144
- modelCandidates: candidates as string[],
1145
- ...(step.fast !== undefined ? { fast: step.fast } : {}),
1146
- ...(resolveEffectiveThinking(candidate, step.thinking) ? { thinking: resolveEffectiveThinking(candidate, step.thinking) } : {}),
1147
- ...(step.thinkingCeiling ? { thinkingCeiling: step.thinkingCeiling } : {}),
1148
- systemPrompt: step.systemPrompt ?? "",
1149
1171
  systemPromptMode: step.systemPromptMode,
1150
1172
  inheritProjectContext: step.inheritProjectContext,
1151
1173
  inheritGlobalContext: step.inheritGlobalContext,
1152
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 ?? "",
1153
1180
  skills: step.skills,
1154
- tools: toolPlan.effectiveToolAllowlist,
1155
- ...(toolPlan.excludeTools.length > 0 ? { excludeTools: toolPlan.excludeTools } : {}),
1156
- extensions: toolPlan.extensionArgs,
1157
- mcpDirectTools: toolPlan.effectiveMcpTools,
1158
- ...(step.outputPath ? { outputPath: step.outputPath } : {}),
1159
- ...(step.outputMode ? { outputMode: step.outputMode } : {}),
1160
- ...(step.structuredOutputSchema ? { structuredOutputSchema: step.structuredOutputSchema } : {}),
1161
- ...(extensionBindings ? { extensionBindings } : {}),
1162
- }));
1181
+ toolPlan,
1182
+ outputPath: step.outputPath,
1183
+ outputMode: step.outputMode,
1184
+ structuredOutputSchema: step.structuredOutputSchema,
1185
+ extensionBindings,
1186
+ }).launchContractDigest;
1163
1187
  }
1164
1188
  capabilityAudit = attemptCapabilityAudit;
1165
1189
  // Each attempt rewrites the step output log; synchronous appends keep a
1166
1190
  // retried attempt from interleaving with the previous attempt's flush.
1167
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
+ }
1168
1200
  const run = await runChildSession(omitUndefinedProperties({
1169
1201
  factory: ctx.childSessions,
1170
1202
  launch,
1171
- collectReadonlyEvidence: true,
1172
- readonlyContinuation,
1173
- canContinue,
1174
- prompt: `Task: ${attemptTask}`,
1203
+ prompt: `Task: ${recoveryTask}`,
1175
1204
  childWatchdog,
1176
1205
  childEventContext: { runId: ctx.id, stepIndex: ctx.flatIndex, agent: step.agent },
1177
1206
  appendChildEvent: (event) => appendDiagnosticJsonl(eventsPath, JSON.stringify(event), typeof event.type === "string" ? event.type : undefined),
@@ -1187,10 +1216,12 @@ export async function runSingleStepInner(
1187
1216
  registerTimeout: ctx.registerTimeout,
1188
1217
  registerStop: ctx.registerStop,
1189
1218
  registerSteer: ctx.registerSteer,
1219
+ onSteerOutcome: ctx.onSteerOutcome,
1190
1220
  registerWatchdogStatus: (sink) => { watchdogSink = sink; },
1191
1221
  timeoutMessage: ctx.timeoutMessage,
1192
1222
  stopMessage: ctx.stopMessage,
1193
1223
  onChildEvent: ctx.onChildEvent,
1224
+ onContextWindow: (contextLimit) => ctx.onAttemptStart?.({ ...attemptModel, contextLimit }),
1194
1225
  transcriptWriter,
1195
1226
  toolTimeoutMs: ctx.toolTimeoutMs,
1196
1227
  runDeadlineAt: ctx.deadlineAt,
@@ -1199,6 +1230,16 @@ export async function runSingleStepInner(
1199
1230
  modelResponseAliases: step.modelResponseAliases,
1200
1231
  mutationTools: step.mutationTools,
1201
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;
1202
1243
  const toolDiagnostic = run.exitCode === 0 && !run.error ? launch.capture.toolDiagnostic() : undefined;
1203
1244
  const toolAvailabilityError = toolDiagnostic ? formatChildToolDiagnostic(toolDiagnostic) : undefined;
1204
1245
  const runtimeAcknowledgedExtensions = launch.capture.runtimeAcknowledgedExtensions();
@@ -1214,17 +1255,23 @@ export async function runSingleStepInner(
1214
1255
  let structuredOutput: unknown;
1215
1256
  let structuredError: string | undefined;
1216
1257
  let validatedStructuredOutput = false;
1217
- if (effectiveStructuredOutput && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError) {
1218
- if (!run.structuredOutputToolInvoked) {
1258
+ if (effectiveStructuredOutput) {
1259
+ const otherwiseSuccessful = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !midToolExitError;
1260
+ if (!run.structuredOutputToolInvoked && otherwiseSuccessful) {
1219
1261
  structuredError = MISSING_STRUCTURED_OUTPUT_CALL_ERROR;
1220
- } else {
1262
+ } else if (run.structuredOutputToolInvoked) {
1221
1263
  const structured = await readStructuredOutput({
1222
1264
  schema: effectiveStructuredOutput.schema,
1223
1265
  schemaPath: effectiveStructuredOutput.schemaPath,
1224
1266
  outputPath: effectiveStructuredOutput.outputPath,
1225
1267
  });
1226
- if (structured.error === MISSING_STRUCTURED_OUTPUT_CALL_ERROR) structuredError = formatStructuredOutputRejectionError(run.messages);
1227
- 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
+ }
1228
1275
  else {
1229
1276
  structuredOutput = structured.value;
1230
1277
  const acceptanceReport = readStructuredOutputAcceptanceReport(effectiveStructuredOutput);
@@ -1237,13 +1284,13 @@ export async function runSingleStepInner(
1237
1284
  const errorMessages = validatedStructuredOutput
1238
1285
  ? run.messages.slice(run.structuredOutputMessageStartIndex ?? run.messages.length)
1239
1286
  : run.messages;
1240
- const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
1287
+ const hiddenError = terminalDiagnosticsEligible && run.exitCode === 0 && !run.error && !toolAvailabilityError && !structuredError && !midToolExitError
1241
1288
  ? detectSubagentError(errorMessages)
1242
1289
  : null;
1243
1290
  const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
1244
1291
  && hasEmptyTerminalAssistantResponse(run.messages)
1245
1292
  && (run.toolCount > 0 || Boolean(run.finalOutput.trim()));
1246
- const emptyOutputError = run.exitCode === 0
1293
+ const emptyOutputError = terminalDiagnosticsEligible && run.exitCode === 0
1247
1294
  && !run.error
1248
1295
  && !toolAvailabilityError
1249
1296
  && !structuredError
@@ -1252,57 +1299,20 @@ export async function runSingleStepInner(
1252
1299
  && (!hiddenError?.hasError || hasEmptyTerminalAssistantResponse(run.messages))
1253
1300
  ? formatEmptyTerminalAssistantResponseError(run.messages)
1254
1301
  : undefined;
1255
- const completionGuardEnabled = isAgentContract(step.agentContract) ? step.completionGuard === true : step.completionGuard !== false;
1256
- const completionToolPlan = resolvedTaskToolPlan;
1257
- const completionTools = completionToolPlan ? (completionToolPlan.explicitToolAllowlist ? completionToolPlan.effectiveToolAllowlist : undefined) : step.tools;
1258
- 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);
1259
1304
  finalMutationEvidence = mutationEvidence;
1260
- const completionMutationEvidence = ctx.trackedMutationEvidenceForCompletionGuard === false ? undefined : mutationEvidence;
1261
- const completionGuard = run.exitCode === 0 && !run.error && !structuredError && !hiddenError?.hasError && !midToolExitError && !emptyOutputError && completionGuardEnabled
1262
- ? evaluateCompletionMutationGuard(omitUndefinedProperties({
1263
- agent: step.agent,
1264
- task: taskForCompletionGuard,
1265
- messages: run.messages,
1266
- tools: completionTools,
1267
- mcpDirectTools: completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools,
1268
- mutationTools: step.mutationTools,
1269
- toolAvailabilityError,
1270
- mutationEvidence: completionMutationEvidence,
1271
- }))
1272
- : undefined;
1273
- const mutationAttemptObserved = run.observedMutationAttempt === true || completionMutationEvidence?.attemptedMutation === true;
1274
- let arbitration = { triggered: completionGuard?.triggered === true && !mutationAttemptObserved, rescued: false };
1275
- if (arbitration.triggered) {
1276
- const modelContext = launch.capture.completionIntentContext?.();
1277
- arbitration = await arbitrateCompletionGuardRescue({
1278
- guardTriggered: true,
1279
- task: taskForCompletionGuard,
1280
- // Construct lazily too: the shared gate refuses overlength tasks before
1281
- // registry/auth/model work. The child has already shut down normally.
1282
- arbiter: modelContext ? async (task) => createTaskMutationArbiter(modelContext)?.(task) ?? "unavailable" : undefined,
1283
- });
1284
- }
1285
- const completionEvidence = planCompletionEvidence({
1286
- guard: completionGuard,
1287
- guardTriggered: arbitration.triggered,
1288
- arbiterRescued: arbitration.rescued,
1289
- completionGuardEnabled,
1290
- mutationCapable: hasMutationToolCapability(completionTools, completionToolPlan?.effectiveMcpTools ?? step.mcpDirectTools),
1291
- implementationMutationExpected: expectsImplementationMutation(step.agent, taskForCompletionGuard),
1292
- mutationAttemptObserved,
1293
- mutationEvidence: completionMutationEvidence,
1294
- agentContractEnabled: isAgentContract(step.agentContract),
1295
- });
1305
+ const mutationAttemptObserved = run.observedMutationAttempt === true || mutationEvidence.attemptedMutation === true;
1296
1306
  const finalOutputHasPersistableFileContent = run.exitCode === 0 && !run.error && !emptyOutputError && Boolean(stripAcceptanceReport(run.finalOutput).trim());
1297
1307
  const requiredOutput = step.outputMode === "file-only" && step.outputPath
1298
1308
  ? { kind: "file-only" as const, path: step.outputPath, missing: !fs.existsSync(step.outputPath) && !finalOutputHasPersistableFileContent }
1299
1309
  : effectiveStructuredOutput
1300
1310
  ? { kind: "structured" as const, path: effectiveStructuredOutput.outputPath, missing: !fs.existsSync(effectiveStructuredOutput.outputPath) }
1301
1311
  : undefined;
1302
- const missingRequiredOutputError = formatRequiredOutputError(requiredOutput);
1303
1312
  finalRequiredOutputMissing = requiredOutput?.missing;
1313
+ const missingRequiredOutputError = terminalDiagnosticsEligible ? formatRequiredOutputError(requiredOutput) : undefined;
1304
1314
  const missingRequiredOutputAfterMutation = Boolean(missingRequiredOutputError) && (mutationAttemptObserved || Boolean(mutationEvidence.changedFiles.length));
1305
- const effectiveExitCode = toolAvailabilityError || completionEvidence.legacyFailureError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
1315
+ const effectiveExitCode = toolAvailabilityError || midToolExitError || structuredError || emptyOutputError || missingRequiredOutputError
1306
1316
  ? 1
1307
1317
  : hiddenError?.hasError
1308
1318
  ? (hiddenError.exitCode ?? 1)
@@ -1320,17 +1330,7 @@ export async function runSingleStepInner(
1320
1330
  ? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
1321
1331
  : `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
1322
1332
  : undefined);
1323
- const error = underlyingError ?? missingRequiredOutputError ?? completionEvidence.legacyFailureError;
1324
- const attempt: ModelAttempt = omitUndefinedProperties({
1325
- model: candidate ?? run.model ?? step.model ?? "default",
1326
- success: effectiveExitCode === 0 && !error,
1327
- exitCode: effectiveExitCode,
1328
- error,
1329
- usage: run.usage,
1330
- });
1331
- modelAttempts.push(attempt);
1332
- if (!recoveringAbort && candidate) attemptedModels.push(candidate);
1333
- completionGuardTriggeredFinal = completionEvidence.guardTriggered && !underlyingError && !missingRequiredOutputError;
1333
+ const error = underlyingError ?? missingRequiredOutputError;
1334
1334
  finalOutputSnapshot = outputSnapshot;
1335
1335
  if (step.toolBudget) {
1336
1336
  const toolMessages = run.messages.filter((message) => message.role === "toolResult");
@@ -1338,20 +1338,21 @@ export async function runSingleStepInner(
1338
1338
  toolBudgetBlocked = Boolean(blockedMessage);
1339
1339
  toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
1340
1340
  }
1341
- const settlementDiagnostic = projectSettlementDiagnostic(completionEvidence, {
1342
- terminalFailed: effectiveExitCode !== 0,
1341
+ const settlementDiagnostic = effectiveExitCode !== 0 ? {
1343
1342
  finalTextPresent: Boolean(stripAcceptanceReport(run.finalOutput).trim()),
1344
- mutationObserved: mutationEvidence.attemptedMutation,
1345
- requiredOutput,
1343
+ mutation: { attempted: mutationAttemptObserved, observed: mutationEvidence.attemptedMutation },
1344
+ ...(requiredOutput ? { requiredOutput } : {}),
1346
1345
  afterCompactionSettlement: run.afterCompactionSettlement === true,
1347
- });
1348
- 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;
1349
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;
1350
- 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({
1351
1352
  messages: run.messages,
1352
1353
  error,
1353
1354
  sessionAvailable: Boolean(step.sessionFile && fs.existsSync(step.sessionFile)),
1354
- alreadyResumed: recoveryState !== "unused",
1355
+ alreadyResumed: attemptIndex > 0,
1355
1356
  stopped: run.stopped || ctx.stopSignal?.aborted || ctx.skipAcceptance?.(),
1356
1357
  interrupted: run.interrupted,
1357
1358
  timedOut: run.timedOut || ctx.timeoutSignal?.aborted,
@@ -1361,86 +1362,30 @@ export async function runSingleStepInner(
1361
1362
  acceptanceFailed: false,
1362
1363
  currentTool: run.currentTool,
1363
1364
  afterCompactionSettlement: run.afterCompactionSettlement,
1364
- }) : undefined;
1365
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) {
1366
- attempt.error = attempt.error
1367
- ? `${abortRecovery.diagnostic}\n${attempt.error.slice(0, 8_000)}`
1368
- : abortRecovery.diagnostic;
1369
- if (finalResult) finalResult.abortRecoveryDiagnostic = abortRecovery.diagnostic;
1365
+ });
1366
+ if (recovery.action === "resume") {
1367
+ recoveryTask = recovery.prompt;
1368
+ continue singleLaunch;
1370
1369
  }
1371
- if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
1372
- if (abortRecovery?.action === "settle" && abortRecovery.diagnostic) break modelAttemptsLoop;
1373
- if (attempt.success) break modelAttemptsLoop;
1374
- // The shared token is consumed before sibling creation; no third dispatch of any kind.
1375
- if (recoveryState === "readonly-continuation") break modelAttemptsLoop;
1376
- if (recoveringAbort) break modelAttemptsLoop;
1377
- if (abortRecovery?.action === "resume") {
1378
- recoveryState = "abort-recovery";
1379
- nextAttemptTask = abortRecovery.prompt;
1380
- attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
1381
- continue;
1370
+ if (recovery.diagnostic) {
1371
+ finalResult.abortRecoveryDiagnostic = recovery.diagnostic;
1382
1372
  }
1383
- if (completionEvidence.guardTriggered) break modelAttemptsLoop;
1384
1373
 
1385
- const source = getSettledReadonlyChild(run);
1386
- if (source) {
1387
- const captured = launch.capture.completionIntentContext?.();
1388
- const sourceModel = captured?.model;
1389
- const retained = getReadonlySessionEvidence(source)!;
1390
- // Modality/capacity assessment, not another history/provenance validator.
1391
- // Images and unknown content have no certified token bound in this host slice.
1392
- const textOnly = (JSON.parse(retained.contextJson) as Message[]).every((message) => typeof message.content === "string"
1393
- || (Array.isArray(message.content) && message.content.every((block) => ["text", "thinking", "toolCall"].includes(block.type))));
1394
- const retainedBytes = Buffer.byteLength(retained.contextJson, "utf8");
1395
- const resolvedCandidates = candidates.map((reference, index) => {
1396
- // Only exact registry identities qualify; aliases/default guesses remain ineligible.
1397
- const base = reference ? splitKnownThinkingSuffix(reference).baseModel : "";
1398
- const slash = base.indexOf("/");
1399
- const model = slash > 0 ? captured?.modelRegistry.find(base.slice(0, slash), base.slice(slash + 1)) : undefined;
1400
- // Reserve the source window for runtime/system/tool overhead, plus a conservative
1401
- // byte bound for the complete retained text and new prompt; never assume a fit
1402
- // merely because a 429 request was sent. Equal/smaller windows remain denied.
1403
- const compatible = textOnly && model && sourceModel && model.input?.includes("text")
1404
- && Number.isFinite(sourceModel.contextWindow) && sourceModel.contextWindow > 0
1405
- && model.contextWindow >= sourceModel.contextWindow + retainedBytes + Buffer.byteLength(READONLY_CONTINUATION_PROMPT, "utf8")
1406
- && model.maxTokens > 0 && model.maxTokens <= sourceModel.maxTokens;
1407
- return { resolved: model ? { provider: model.provider, model: model.id, api: model.api } : undefined,
1408
- tried: index <= modelIndex, compatibility: compatible ? "compatible" as const : "unknown" as const };
1409
- });
1410
- const plan = planReadonlyModelContinuation({ source, recoveryState, candidates: resolvedCandidates, currentIndex: modelIndex,
1411
- lifecycleAllowsContinuation: lifecycleAllowsContinuation() && !run.interrupted && !run.stopped && !run.timedOut,
1412
- effectsAllowContinuation: !run.currentTool && !run.observedMutationAttempt && !mutationEvidence.attemptedMutation
1413
- && !structuredError && !effectiveStructuredOutput && !missingRequiredOutputError && !toolAvailabilityError
1414
- && !completionEvidence.guardTriggered && !midToolExitError && !hiddenError?.hasError,
1415
- budget: continuationBudget(), knownContextOverflow: isContextOverflow(error) });
1416
- if (plan.kind === "continue" && canContinue()) {
1417
- recoveryState = plan.recoveryState;
1418
- const selected = resolvedCandidates[plan.candidateIndex]!.resolved!;
1419
- readonlyContinuation = { source, expected: plan.expected, modelId: `${selected.provider}/${selected.model}` };
1420
- nextAttemptTask = plan.prompt;
1421
- modelIndex = plan.candidateIndex;
1422
- attemptNotes.push(`[readonly-continuation] ${attempt.model} returned HTTP 429 after read-only progress; continuing the retained session once with ${candidates[modelIndex]}.`);
1423
- continue;
1424
- }
1425
- }
1426
-
1427
- const retryableModelFailure = isRetryableModelFailureAttempt({ error, messages: run.messages, toolCount: run.toolCount });
1428
- if (retryableModelFailure) recordRetryableModelFailure(candidate ?? run.model ?? step.model, error);
1429
1374
  if (isContextOverflow(error)) {
1430
1375
  contextOverflow = true;
1431
- 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.`);
1432
- break modelAttemptsLoop;
1376
+ break singleLaunch;
1433
1377
  }
1434
- if (!retryableModelFailure || modelIndex === candidates.length - 1) break modelAttemptsLoop;
1435
- attemptNotes.push(formatModelAttemptNote(attempt, candidates[modelIndex + 1]));
1436
- modelIndex += 1;
1378
+ break singleLaunch;
1437
1379
  }
1438
1380
 
1439
1381
  const rawOutput = finalResult?.finalOutput ?? "";
1440
- 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.
1441
1386
  const resolvedOutput = step.outputPath && finalResult?.exitCode === 0
1442
- ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot, step.outputClaimPath)
1443
- : { fullOutput: outputForPersistence };
1387
+ ? resolveSingleOutput(step.outputPath, structuredText ?? replyOutput, finalOutputSnapshot, step.outputClaimPath)
1388
+ : { fullOutput: replyOutput };
1444
1389
  if (resolvedOutput.fatalError) {
1445
1390
  if (finalResult) {
1446
1391
  finalResult.exitCode = 1;
@@ -1450,13 +1395,11 @@ export async function runSingleStepInner(
1450
1395
  const output = stripAcceptanceReport(resolvedOutput.fullOutput);
1451
1396
  const outputReference = resolvedOutput.savedPath ? formatSavedOutputReference(resolvedOutput.savedPath, output) : undefined;
1452
1397
  let outputForSummary = output;
1453
- if (attemptNotes.length > 0) {
1454
- outputForSummary = `${attemptNotes.join("\n")}\n\n${outputForSummary}`.trim();
1455
- }
1456
1398
  if (finalResult?.stopped && !outputForSummary.trim()) {
1457
1399
  outputForSummary = ctx.stopMessage ?? "Subagent stopped by user.";
1458
1400
  }
1459
- const outputForAcceptance = rawOutput;
1401
+ // Unfinished streamed text never stands in for the child's completed reply.
1402
+ const outputForAcceptance = finalResult?.outputPartial ? "" : rawOutput;
1460
1403
  const childWrittenOutput = step.outputPath
1461
1404
  ? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
1462
1405
  : undefined;
@@ -1503,6 +1446,7 @@ export async function runSingleStepInner(
1503
1446
  ? { content: childWrittenOutput, path: step.outputPath, authoritative: step.outputMode === "file-only", durable: resolvedOutput.savedPath !== undefined }
1504
1447
  : undefined,
1505
1448
  cwd: step.cwd ?? ctx.cwd,
1449
+ stagedIndexBaseline,
1506
1450
  signal: combinedAbortSignal([ctx.timeoutSignal, ctx.stopSignal]),
1507
1451
  abortMessage: ctx.stopSignal?.aborted ? ctx.stopMessage ?? "Subagent stopped by user." : ctx.timeoutMessage ?? "Subagent timed out.",
1508
1452
  reportOptional: isAgentContract(step.agentContract),
@@ -1523,6 +1467,12 @@ export async function runSingleStepInner(
1523
1467
  const acceptanceFailure = effectiveAcceptance ? acceptanceFailureMessage(effectiveAcceptance) : undefined;
1524
1468
  const acceptanceCanFailRun = acceptanceFailure && effectiveAcceptance?.explicit && (finalResult?.exitCode ?? 1) === 0 && !finalResult?.interrupted && !timedOutAfterAcceptance && !stoppedAfterAcceptance && !isAgentContract(step.agentContract);
1525
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
+ }
1526
1476
  const intercomDetachReceipt = finalResult?.finalOutput === INTERCOM_DETACH_RECEIPT;
1527
1477
  const baseFinalError = stoppedAfterAcceptance
1528
1478
  ? ctx.stopMessage ?? "Subagent stopped by user."
@@ -1537,7 +1487,7 @@ export async function runSingleStepInner(
1537
1487
  abortRecoveryDiagnostic: effectiveFinalExitCode !== 0 ? finalResult?.abortRecoveryDiagnostic : undefined,
1538
1488
  requiredOutput: effectiveFinalExitCode !== 0 ? finalResult?.effects?.settlementDiagnostic?.requiredOutput : undefined,
1539
1489
  });
1540
- const usage = usageFromAttempts(modelAttempts);
1490
+ const usage = launched ? aggregateUsage : undefined;
1541
1491
 
1542
1492
  const artifactErrors = artifactPaths && ctx.artifactConfig?.enabled !== false
1543
1493
  ? persistStepArtifacts({
@@ -1555,8 +1505,8 @@ export async function runSingleStepInner(
1555
1505
  task: PROMPT_REDACTED,
1556
1506
  exitCode: effectiveFinalExitCode,
1557
1507
  model: finalResult?.model,
1558
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1559
- modelAttempts,
1508
+ nativeMachine: finalResult?.nativeMachine,
1509
+ requestedModel: step.requestedModel,
1560
1510
  usage,
1561
1511
  error: effectiveFinalError,
1562
1512
  acceptance: effectiveAcceptance,
@@ -1572,7 +1522,7 @@ export async function runSingleStepInner(
1572
1522
  })
1573
1523
  : {};
1574
1524
 
1575
- const result: StepResult & { completionGuardTriggered?: boolean } = omitUndefinedProperties({
1525
+ const result: StepResult = omitUndefinedProperties({
1576
1526
  agent: step.agent,
1577
1527
  ...(childSessionName ? { sessionName: childSessionName } : {}),
1578
1528
  context: step.context,
@@ -1580,20 +1530,22 @@ export async function runSingleStepInner(
1580
1530
  launchContractDigest: actualLaunchContractDigest,
1581
1531
  output: outputForSummary,
1582
1532
  outputState,
1533
+ outputPartial: finalResult?.outputPartial,
1583
1534
  exitCode: effectiveFinalExitCode,
1584
1535
  error: effectiveFinalError,
1585
1536
  sessionFile: step.sessionFile,
1586
1537
  intercomTarget: ctx.childIntercomTarget,
1587
1538
  model: finalResult?.model,
1539
+ nativeMachine: finalResult?.nativeMachine,
1588
1540
  thinking: resolveEffectiveThinking(finalResult?.model, step.thinking),
1589
- attemptedModels: attemptedModels.length > 0 ? attemptedModels : undefined,
1590
- modelAttempts,
1541
+ requestedModel: step.requestedModel,
1591
1542
  contextOverflow: contextOverflow || undefined,
1592
- totalCost: costSummaryFromAttempts(modelAttempts),
1543
+ totalCost: costSummaryFromUsage(usage),
1593
1544
  usage,
1594
1545
  artifactPaths,
1595
1546
  savedOutputPath: finalizedOutput.savedPath,
1596
1547
  outputSaveError: [resolvedOutput.saveError, artifactErrors.outputSaveError].filter(Boolean).join("\n") || undefined,
1548
+ artifactOutputSaveFailed: artifactErrors.outputSaveError ? true : undefined,
1597
1549
  metadataSaveError: artifactErrors.metadataSaveError,
1598
1550
  transcriptPath: transcriptWriter ? artifactPaths?.transcriptPath : undefined,
1599
1551
  transcriptError: transcriptWriter?.getError(),
@@ -1603,7 +1555,6 @@ export async function runSingleStepInner(
1603
1555
  timeoutRecovery,
1604
1556
  toolBudget,
1605
1557
  toolBudgetBlocked: toolBudgetBlocked || undefined,
1606
- completionGuardTriggered: completionGuardTriggeredFinal,
1607
1558
  ...((finalResult as (RunChildSessionResult & { effects?: import("../../shared/types.ts").EffectsProjection }) | undefined)?.effects ? { effects: (finalResult as RunChildSessionResult & { effects?: import("../../shared/types.ts").EffectsProjection }).effects } : {}),
1608
1559
  structuredOutput: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : (finalResult as (RunChildSessionResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput,
1609
1560
  structuredOutputFailed: timedOutAfterAcceptance || stoppedAfterAcceptance ? undefined : finalResult?.structuredOutputFailed,
@@ -1621,7 +1572,7 @@ export async function runSingleStepInner(
1621
1572
  async function runSingleStep(
1622
1573
  step: SubagentStep,
1623
1574
  ctx: SingleStepContext,
1624
- ): Promise<StepResult & { completionGuardTriggered?: boolean }> {
1575
+ ): Promise<StepResult> {
1625
1576
  if (!step.importAsyncRoot) ctx.orcaProgressTab?.section({ agent: step.agent, index: ctx.flatIndex, count: ctx.flatStepCount });
1626
1577
  return runSingleStepInner(step, ctx);
1627
1578
  }
@@ -1708,7 +1659,12 @@ function markParallelGroupSetupFailure(input: {
1708
1659
  if (!task) throw new Error(`Missing parallel task at index ${taskIndex}`);
1709
1660
  const stopped = statusStep.stopped || statusStep.stopRequested || input.statusPayload.stopped;
1710
1661
  const paused = !stopped && input.statusPayload.state === "paused";
1662
+ const timedOut = !stopped && !paused && input.statusPayload.timedOut === true;
1711
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;
1712
1668
  statusStep.startedAt = input.failedAt;
1713
1669
  statusStep.endedAt = input.failedAt;
1714
1670
  statusStep.durationMs = 0;
@@ -1838,8 +1794,12 @@ function missingRequiredOutputAfterUsefulMutation(result: SingleStepResult): boo
1838
1794
  }
1839
1795
 
1840
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;
1841
1801
  const fileMutation = result.effects?.fileMutation;
1842
- return result.execution?.status === "partial" && (fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length));
1802
+ return fileMutation?.attempted === true || Boolean(fileMutation?.evidence?.changedFiles.length);
1843
1803
  }
1844
1804
 
1845
1805
  function partialEvidenceResult(result: SingleStepResult): boolean {
@@ -1921,6 +1881,11 @@ export async function runSubagent(
1921
1881
  let previousOutput = "";
1922
1882
  const outputs: ChainOutputMap = {};
1923
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>();
1924
1889
  const overallStartTime = Date.now();
1925
1890
  const shareEnabled = config.share === true;
1926
1891
  const asyncDir = config.asyncDir;
@@ -1942,6 +1907,7 @@ export async function runSubagent(
1942
1907
  let currentActivityState: ActivityState | undefined;
1943
1908
  let activityTimer: NodeJS.Timeout | undefined;
1944
1909
  let timeoutTimer: NodeJS.Timeout | undefined;
1910
+ let checkpointTimer: NodeJS.Timeout | undefined;
1945
1911
  let timedOut = false;
1946
1912
  let stopped = false;
1947
1913
  let usageBudgetExceeded = false;
@@ -1950,6 +1916,7 @@ export async function runSubagent(
1950
1916
  const timeoutAbortController = new AbortController();
1951
1917
  const stopAbortController = new AbortController();
1952
1918
  const setupInterruptController = new AbortController();
1919
+ const runStopSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal]);
1953
1920
  const setupSignal = AbortSignal.any([timeoutAbortController.signal, stopAbortController.signal, setupInterruptController.signal]);
1954
1921
  let previousCumulativeTokens: TokenUsage = { input: 0, output: 0, total: 0 };
1955
1922
  let latestSessionFile: string | undefined;
@@ -1991,7 +1958,7 @@ export async function runSubagent(
1991
1958
  model: task.model,
1992
1959
  ...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
1993
1960
  thinking: task.thinking,
1994
- attemptedModels: task.modelCandidates && task.modelCandidates.length > 0 ? task.modelCandidates : task.model ? [task.model] : undefined,
1961
+ requestedModel: task.requestedModel,
1995
1962
  recentTools: [],
1996
1963
  recentOutput: [],
1997
1964
  }));
@@ -2045,7 +2012,7 @@ export async function runSubagent(
2045
2012
  model: step.model,
2046
2013
  ...(step.contextLimit !== undefined ? { contextLimit: step.contextLimit } : {}),
2047
2014
  thinking: step.thinking,
2048
- attemptedModels: step.modelCandidates && step.modelCandidates.length > 0 ? step.modelCandidates : step.model ? [step.model] : undefined,
2015
+ requestedModel: step.requestedModel,
2049
2016
  recentTools: [],
2050
2017
  recentOutput: [],
2051
2018
  }));
@@ -2090,6 +2057,7 @@ export async function runSubagent(
2090
2057
  ...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
2091
2058
  ...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
2092
2059
  pid: process.pid,
2060
+ pidNamespaceScope: currentPidNamespaceScope(),
2093
2061
  cwd,
2094
2062
  currentStep: 0,
2095
2063
  chainStepCount: steps.length,
@@ -2272,9 +2240,7 @@ export async function runSubagent(
2272
2240
  sessionFile: step.sessionFile,
2273
2241
  model: step.model,
2274
2242
  thinking: step.thinking,
2275
- attemptedModels: step.attemptedModels,
2276
- modelAttempts: step.modelAttempts,
2277
- usage: usageFromAttempts(step.modelAttempts),
2243
+ requestedModel: step.requestedModel,
2278
2244
  contextOverflow: step.contextOverflow,
2279
2245
  })),
2280
2246
  exitCode: state === "complete" || state === "paused" ? 0 : 1,
@@ -2439,6 +2405,8 @@ export async function runSubagent(
2439
2405
  yield* nestedRuns(child.steps?.flatMap((step) => step.children ?? []));
2440
2406
  }
2441
2407
  };
2408
+ const isNestedControlDescendant = (run: NestedRunSummary): boolean =>
2409
+ !config.nestedSelf || run.path.some((entry) => entry.runId === id);
2442
2410
  const interruptNestedAsyncDescendants = (): void => {
2443
2411
  if (!config.nestedRoute) return;
2444
2412
  let registry: ReturnType<typeof projectNestedEvents>;
@@ -2454,7 +2422,7 @@ export async function runSubagent(
2454
2422
  return;
2455
2423
  }
2456
2424
  for (const run of nestedRuns(registry.children)) {
2457
- if (run.state !== "running" && run.state !== "queued") continue;
2425
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2458
2426
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2459
2427
  if (!nestedAsyncDir) continue;
2460
2428
  try {
@@ -2485,7 +2453,7 @@ export async function runSubagent(
2485
2453
  return;
2486
2454
  }
2487
2455
  for (const run of nestedRuns(registry.children)) {
2488
- if (run.state !== "running" && run.state !== "queued") continue;
2456
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2489
2457
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2490
2458
  if (!nestedAsyncDir) continue;
2491
2459
  try {
@@ -2516,7 +2484,7 @@ export async function runSubagent(
2516
2484
  return;
2517
2485
  }
2518
2486
  for (const run of nestedRuns(registry.children)) {
2519
- if (run.state !== "running" && run.state !== "queued") continue;
2487
+ if (!isNestedControlDescendant(run) || (run.state !== "running" && run.state !== "queued")) continue;
2520
2488
  const nestedAsyncDir = run.asyncDir ?? resolveNestedAsyncDir(config.nestedRoute.rootRunId, run);
2521
2489
  if (!nestedAsyncDir) continue;
2522
2490
  try {
@@ -2572,6 +2540,7 @@ export async function runSubagent(
2572
2540
  }
2573
2541
  const appendedSteps = requests.flatMap((request) => request.steps);
2574
2542
  steps.push(...appendedSteps);
2543
+ flatSteps.push(...flattenSteps(appendedSteps));
2575
2544
  const now = Date.now();
2576
2545
  const pendingAppends = countPendingChainAppendRequests(asyncDir);
2577
2546
  const added = appendRunnerStepsToStatus({
@@ -2605,9 +2574,66 @@ export async function runSubagent(
2605
2574
  setOptionalProperty(groupNode, "acceptanceStatus", acceptance?.status ?? groupNode.acceptanceStatus);
2606
2575
  };
2607
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
+ };
2608
2633
  const stepOutputActivityAt = (index: number): number => {
2609
2634
  const step = statusPayload.steps[index];
2610
2635
  let lastActivityAt = step?.lastActivityAt ?? step?.startedAt ?? overallStartTime;
2636
+ lastActivityAt = Math.max(lastActivityAt, externalActivityEvidence.get(index)?.lastStreamActivityAt ?? 0);
2611
2637
  const outputPath = path.join(asyncDir, `output-${index}.log`);
2612
2638
  try {
2613
2639
  lastActivityAt = Math.max(lastActivityAt, fs.statSync(outputPath).mtimeMs);
@@ -2622,7 +2648,7 @@ export async function runSubagent(
2622
2648
  const activeLongRunningSteps = new Set<number>();
2623
2649
  const mutatingFailureStates = initialStatusSteps.map(() => createMutatingFailureState());
2624
2650
  const pendingToolResults: Array<{ tool: string; path?: string; mutates: boolean; startedAt?: number } | undefined> = initialStatusSteps.map(() => undefined);
2625
- 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 };
2626
2652
  const activeToolCalls = initialStatusSteps.map(() => new Map<string, ActiveToolCall>());
2627
2653
  const activeToolKeysByName = initialStatusSteps.map(() => new Map<string, string[]>());
2628
2654
  const activeToolSequences = initialStatusSteps.map(() => 0);
@@ -2686,8 +2712,11 @@ export async function runSubagent(
2686
2712
  return key ? removeActiveToolCallKey(flatIndex, key) : undefined;
2687
2713
  };
2688
2714
  const openToolAttentionTarget = (flatIndex: number, now: number): ActiveToolCall | undefined => [...(activeToolCalls[flatIndex]?.values() ?? [])]
2689
- .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 }))
2690
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 }));
2691
2720
  const supervisorAttentionSteps = new Map<number, ActivityState | undefined>();
2692
2721
  const mutatingFailureWindowMs = 5 * 60_000;
2693
2722
  const appendControlEvent = (rawEvent: ReturnType<typeof buildControlEvent>) => {
@@ -2785,9 +2814,12 @@ export async function runSubagent(
2785
2814
  };
2786
2815
  const maybeEmitOpenToolAttention = (flatIndex: number, now: number): boolean => {
2787
2816
  const step = statusPayload.steps[flatIndex];
2788
- if (!step || step.status !== "running" || step.activityState === "needs_attention") return false;
2817
+ if (!step || step.status !== "running") return false;
2789
2818
  const target = openToolAttentionTarget(flatIndex, now);
2790
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");
2791
2823
  const previous = step.activityState;
2792
2824
  step.activityState = "needs_attention";
2793
2825
  noteAttentionCause(flatIndex, "tool_open_threshold", previous);
@@ -2807,6 +2839,7 @@ export async function runSubagent(
2807
2839
  tokens: step.tokens?.total,
2808
2840
  toolCount: step.toolCount,
2809
2841
  currentTool: target.tool,
2842
+ toolCallId: target.key.startsWith("id:") ? target.key.slice(3) : undefined,
2810
2843
  currentToolDurationMs: toolDurationMs,
2811
2844
  currentPath: target.path,
2812
2845
  })));
@@ -2950,7 +2983,10 @@ export async function runSubagent(
2950
2983
  const applySteerDelivery = (requestId: string, index: number, delivery: { state: "delivered" | "queued" | "failed"; message: string }): void => {
2951
2984
  const lifecycle = steeringStatus(statusPayload);
2952
2985
  const request = lifecycle.recent.find((candidate) => candidate.id === requestId);
2953
- 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;
2954
2990
  const late = fs.existsSync(steeringMarkerPath(requestId));
2955
2991
  const now = Date.now();
2956
2992
  if (delivery.state === "delivered") {
@@ -3025,7 +3061,7 @@ export async function runSubagent(
3025
3061
  return;
3026
3062
  }
3027
3063
  if (event.type === "message_end") {
3028
- const next = applyChildWatchdogMessage(step.watchdog, event.message, now);
3064
+ const next = applyChildWatchdogMessage(step.watchdog, event.message);
3029
3065
  if (next) step.watchdog = next;
3030
3066
  if (next && (event.message as { role?: unknown } | undefined)?.role === "custom") {
3031
3067
  statusPayload.lastUpdate = now;
@@ -3168,12 +3204,12 @@ export async function runSubagent(
3168
3204
  statusPayload.lastActivityAt = now;
3169
3205
  statusPayload.lastUpdate = now;
3170
3206
  // The open tool that raised `tool_open_threshold` ended (or no remaining open tool is past the threshold): the step recovered.
3171
- if (attentionCauses.get(flatIndex)?.has("tool_open_threshold") && !openToolAttentionTarget(flatIndex, now)) resolveAttentionCause(flatIndex, "tool_open_threshold", now);
3207
+ if (attentionCauses.get(flatIndex)?.has("tool_open_threshold") && !hasOpenToolPastThreshold(flatIndex, now)) resolveAttentionCause(flatIndex, "tool_open_threshold", now);
3172
3208
  maybeEmitActiveLongRunning(flatIndex, now);
3173
3209
  // A sibling may keep aggregate attention unchanged; publish this step's transition.
3174
3210
  writeStatusPayload(step.activityState !== previousActivityState);
3175
3211
  };
3176
- const updateRunnerActivityState = (now: number): boolean => {
3212
+ const updateRunnerActivityState = (now: number, skipExternalProbeIndex?: number): boolean => {
3177
3213
  if (!controlConfig.enabled) return false;
3178
3214
  let changed = false;
3179
3215
  let runLastActivityAt = statusPayload.lastActivityAt ?? overallStartTime;
@@ -3190,12 +3226,35 @@ export async function runSubagent(
3190
3226
  config: controlConfig,
3191
3227
  startedAt: step.startedAt ?? overallStartTime,
3192
3228
  lastActivityAt,
3193
- turnCount: step.turnCount,
3229
+ turnCount: flatSteps[index]?.runner?.type === "external-cli" ? 1 : step.turnCount,
3194
3230
  currentTool: step.currentTool,
3195
3231
  thinking: step.thinking,
3196
3232
  now,
3197
3233
  }));
3198
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
+ }
3199
3258
  const previous = step.activityState;
3200
3259
  step.activityState = "needs_attention";
3201
3260
  noteAttentionCause(index, "idle", previous);
@@ -3259,11 +3318,15 @@ export async function runSubagent(
3259
3318
  };
3260
3319
  const finalizeWorktree = async (setup: WorktreeSetup, stepIndex: number, flatStartIndex: number, action: () => void, deadlineAt?: number): Promise<void> => {
3261
3320
  let admitted = false;
3262
- try { await withWorktreeTransaction(() => {
3263
- if (deadlineAt !== undefined && Date.now() >= deadlineAt) throw new Error("Run deadline expired before worktree cleanup");
3264
- admitted = true;
3265
- action();
3266
- }); }
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
+ }
3267
3330
  catch (error) {
3268
3331
  if (admitted) throw error;
3269
3332
  const reason = `Worktree finalization retained; manual reconciliation required: ${error instanceof Error ? error.message : String(error)}`;
@@ -3318,16 +3381,17 @@ export async function runSubagent(
3318
3381
  interruptActiveChildren();
3319
3382
  };
3320
3383
  const stopRunner = () => {
3321
- if (stopped || timedOut || interrupted || statusPayload.state !== "running") return;
3384
+ if (stopped || timedOut || (statusPayload.state !== "running" && statusPayload.state !== "paused")) return;
3322
3385
  stopped = true;
3386
+ interrupted = false;
3323
3387
  const now = Date.now();
3324
3388
  statusPayload.stopped = true;
3325
3389
  statusPayload.error = stopMessage;
3326
3390
  currentActivityState = undefined;
3327
3391
  delete statusPayload.activityState;
3328
3392
  statusPayload.lastUpdate = now;
3329
- for (const step of statusPayload.steps) {
3330
- 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;
3331
3395
  step.status = "stopped";
3332
3396
  step.error = stopMessage;
3333
3397
  step.exitCode = 1;
@@ -3336,6 +3400,8 @@ export async function runSubagent(
3336
3400
  step.endedAt = now;
3337
3401
  step.durationMs = step.startedAt ? now - step.startedAt : 0;
3338
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 };
3339
3405
  }
3340
3406
  writeStatusPayload();
3341
3407
  appendJsonl(eventsPath, JSON.stringify({
@@ -3407,6 +3473,30 @@ export async function runSubagent(
3407
3473
  const remainingMs = Math.max(0, config.deadlineAt - Date.now());
3408
3474
  timeoutTimer = setTimeout(timeoutRunner, remainingMs);
3409
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
+ }
3410
3500
  }
3411
3501
  appendJsonl(
3412
3502
  eventsPath,
@@ -3452,14 +3542,7 @@ export async function runSubagent(
3452
3542
  const thinkingOverride = step.thinkingOverrides?.[itemIndex];
3453
3543
  const model = thinkingOverride ? applyThinkingSuffix(step.parallel.model, thinkingOverride, true) : step.parallel.model;
3454
3544
  const configThinking = thinkingOverride ? thinkingOverride : step.parallel.thinking;
3455
- const candidates = step.parallel.modelCandidates !== undefined
3456
- ? step.parallel.modelCandidates.length > 0
3457
- ? step.parallel.modelCandidates.map((candidate) => thinkingOverride ? applyThinkingSuffix(candidate, thinkingOverride, true) ?? candidate : candidate)
3458
- : [undefined]
3459
- : model ? [model] : [undefined];
3460
- for (const candidate of candidates) {
3461
- assertThinkingWithinCeiling({ model: candidate, configThinking, ceiling: step.parallel.thinkingCeiling, agent: step.parallel.agent, runId: id });
3462
- }
3545
+ assertThinkingWithinCeiling({ model, configThinking, ceiling: step.parallel.thinkingCeiling, agent: step.parallel.agent, runId: id });
3463
3546
  }
3464
3547
  if (materialized.collectedOnEmpty) await validateDynamicCollection(step.collect.outputSchema, materialized.collectedOnEmpty);
3465
3548
  if (!config.runFanoutBudget) throw new Error("Async runner is missing its run fan-out budget identity.");
@@ -3592,10 +3675,6 @@ export async function runSubagent(
3592
3675
  ...(thinkingOverride ? {
3593
3676
  ...(model ? { model } : {}),
3594
3677
  ...(thinking ? { thinking } : {}),
3595
- ...(step.parallel.modelCandidates ? { modelCandidates: step.parallel.modelCandidates.flatMap((candidate) => {
3596
- const resolved = applyThinkingSuffix(candidate, thinkingOverride, true);
3597
- return resolved ? [resolved] : [];
3598
- }) } : {}),
3599
3678
  } : {}),
3600
3679
  structuredOutputSchema: step.parallel.structuredOutputSchema ?? step.parallel.structuredOutput?.schema,
3601
3680
  });
@@ -3606,6 +3685,7 @@ export async function runSubagent(
3606
3685
  return omitUndefinedProperties({
3607
3686
  agent: task.agent,
3608
3687
  ...(task.sessionName ? { sessionName: task.sessionName } : {}),
3688
+ ...(externalRunnerStatus(task.runner) ? { runner: externalRunnerStatus(task.runner) } : {}),
3609
3689
  ...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
3610
3690
  ...(task.context ? { context: task.context } : {}),
3611
3691
  ...(task.phase ?? step.phase ? { phase: task.phase ?? step.phase } : {}),
@@ -3622,7 +3702,7 @@ export async function runSubagent(
3622
3702
  ...(task.contextLimit !== undefined ? { contextLimit: task.contextLimit } : {}),
3623
3703
  ...(task.thinking ? { thinking: task.thinking } : {}),
3624
3704
  ...(task.thinkingCeiling ? { thinkingCeiling: task.thinkingCeiling } : {}),
3625
- ...(task.modelCandidates && task.modelCandidates.length > 0 ? { attemptedModels: task.modelCandidates } : task.model ? { attemptedModels: [task.model] } : {}),
3705
+ ...(task.requestedModel ? { requestedModel: task.requestedModel } : {}),
3626
3706
  recentTools: [],
3627
3707
  recentOutput: [],
3628
3708
  });
@@ -3708,6 +3788,7 @@ export async function runSubagent(
3708
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 });
3709
3789
  }
3710
3790
  const taskStartTime = Date.now();
3791
+ launchedFlatIndices.add(fi);
3711
3792
  statusPayload.currentStep = fi;
3712
3793
  requiredStatusStep(statusPayload, fi).status = "running";
3713
3794
  delete requiredStatusStep(statusPayload, fi).error;
@@ -3728,6 +3809,7 @@ export async function runSubagent(
3728
3809
  artifactsDir, artifactConfig, id,
3729
3810
  flatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),
3730
3811
  outputFile: path.join(asyncDir, `output-${fi}.log`),
3812
+ projectTrusted: config.projectTrusted,
3731
3813
  piPackageRoot: config.piPackageRoot,
3732
3814
  childSessions,
3733
3815
  inheritedChildRuntime: config.inheritedChildRuntime,
@@ -3740,15 +3822,17 @@ export async function runSubagent(
3740
3822
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
3741
3823
  registerStop: (stop) => registerStepStop(fi, stop),
3742
3824
  registerSteer: (steer) => registerStepSteer(fi, steer),
3825
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
3743
3826
  timeoutSignal: timeoutAbortController.signal,
3744
3827
  stopSignal: stopAbortController.signal,
3745
- trackedMutationEvidenceForCompletionGuard: false,
3746
3828
  timeoutMessage,
3747
3829
  stopMessage,
3748
3830
  toolTimeoutMs: task.toolTimeoutMs ?? config.toolTimeoutMs,
3749
3831
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
3750
3832
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
3751
3833
  onExternalProcess: (process) => updateExternalProcess(fi, process),
3834
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
3835
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
3752
3836
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
3753
3837
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
3754
3838
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -3758,7 +3842,7 @@ export async function runSubagent(
3758
3842
  const taskEndTime = Date.now();
3759
3843
  const childInterrupted = singleResult.interrupted === true;
3760
3844
  const childStopped = singleResult.stopped === true;
3761
- 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";
3762
3846
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
3763
3847
  requiredStatusStep(statusPayload, fi).durationMs = taskEndTime - taskStartTime;
3764
3848
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -3771,8 +3855,7 @@ export async function runSubagent(
3771
3855
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
3772
3856
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
3773
3857
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
3774
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
3775
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
3858
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
3776
3859
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
3777
3860
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
3778
3861
  if (singleResult.totalCost) {
@@ -3828,8 +3911,9 @@ export async function runSubagent(
3828
3911
  runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
3829
3912
  output: pr.output,
3830
3913
  outputState: pr.outputState,
3914
+ outputPartial: pr.outputPartial,
3831
3915
  error: pr.error,
3832
- 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",
3833
3917
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
3834
3918
  skipped: pr.skipped,
3835
3919
  interrupted: pr.interrupted,
@@ -3841,12 +3925,13 @@ export async function runSubagent(
3841
3925
  intercomTarget: pr.intercomTarget,
3842
3926
  model: pr.model,
3843
3927
  thinking: pr.thinking,
3844
- attemptedModels: pr.attemptedModels,
3845
- modelAttempts: pr.modelAttempts,
3928
+ requestedModel: pr.requestedModel,
3846
3929
  contextOverflow: pr.contextOverflow,
3847
3930
  totalCost: pr.totalCost,
3848
3931
  usage: pr.usage,
3849
3932
  artifactPaths: pr.artifactPaths,
3933
+ outputSaveError: pr.outputSaveError,
3934
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
3850
3935
  transcriptPath: pr.transcriptPath,
3851
3936
  transcriptError: pr.transcriptError,
3852
3937
  effects: pr.effects,
@@ -4108,6 +4193,7 @@ export async function runSubagent(
4108
4193
  }
4109
4194
 
4110
4195
  const taskStartTime = Date.now();
4196
+ launchedFlatIndices.add(fi);
4111
4197
  statusPayload.currentStep = fi;
4112
4198
  requiredStatusStep(statusPayload, fi).status = "running";
4113
4199
  delete requiredStatusStep(statusPayload, fi).error;
@@ -4138,6 +4224,7 @@ export async function runSubagent(
4138
4224
  sessionDir: taskSessionDir,
4139
4225
  artifactsDir, artifactConfig, id,
4140
4226
  flatIndex: fi, flatStepCount: Math.max(statusPayload.steps.length, 1),
4227
+ projectTrusted: config.projectTrusted,
4141
4228
  outputFile: path.join(asyncDir, `output-${fi}.log`),
4142
4229
  piPackageRoot: config.piPackageRoot,
4143
4230
  childSessions,
@@ -4151,15 +4238,17 @@ export async function runSubagent(
4151
4238
  registerTimeout: (interrupt) => registerStepTimeout(fi, interrupt),
4152
4239
  registerStop: (stop) => registerStepStop(fi, stop),
4153
4240
  registerSteer: (steer) => registerStepSteer(fi, steer),
4241
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, fi, delivery),
4154
4242
  timeoutSignal: timeoutAbortController.signal,
4155
4243
  stopSignal: stopAbortController.signal,
4156
- trackedMutationEvidenceForCompletionGuard: Boolean(worktreeSetup),
4157
4244
  timeoutMessage,
4158
4245
  stopMessage,
4159
4246
  toolTimeoutMs: taskForRun.toolTimeoutMs ?? config.toolTimeoutMs,
4160
4247
  onAttemptStart: (attempt) => updateStepModel(fi, attempt.model, attempt.thinking, attempt.contextLimit),
4161
4248
  onChildEvent: (event) => updateStepFromChildEvent(fi, event),
4162
4249
  onExternalProcess: (process) => updateExternalProcess(fi, process),
4250
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(fi, externalCwd, signal),
4251
+ onExternalStreamActivity: () => recordExternalStreamActivity(fi),
4163
4252
  onExternalJob: (externalJob) => updateExternalJob(fi, externalJob),
4164
4253
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(fi),
4165
4254
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -4175,7 +4264,7 @@ export async function runSubagent(
4175
4264
  const childInterrupted = singleResult.interrupted === true;
4176
4265
  const childStopped = singleResult.stopped === true;
4177
4266
 
4178
- 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";
4179
4268
  requiredStatusStep(statusPayload, fi).endedAt = taskEndTime;
4180
4269
  requiredStatusStep(statusPayload, fi).durationMs = taskDuration;
4181
4270
  requiredStatusStep(statusPayload, fi).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4188,8 +4277,7 @@ export async function runSubagent(
4188
4277
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "sessionName", singleResult.sessionName);
4189
4278
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "model", singleResult.model);
4190
4279
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, fi).thinking));
4191
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "attemptedModels", singleResult.attemptedModels);
4192
- setOptionalProperty(requiredStatusStep(statusPayload, fi), "modelAttempts", singleResult.modelAttempts);
4280
+ setOptionalProperty(requiredStatusStep(statusPayload, fi), "requestedModel", singleResult.requestedModel);
4193
4281
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "contextOverflow", singleResult.contextOverflow);
4194
4282
  setOptionalProperty(requiredStatusStep(statusPayload, fi), "totalCost", singleResult.totalCost);
4195
4283
  if (singleResult.totalCost) {
@@ -4229,20 +4317,6 @@ export async function runSubagent(
4229
4317
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode, durationMs: taskDuration,
4230
4318
  }));
4231
4319
  if (stopped || childStopped) appendTerminalChildStatusEvent(fi, taskEndTime);
4232
- if (singleResult.completionGuardTriggered) {
4233
- const event = buildControlEvent(omitUndefinedProperties({
4234
- from: requiredStatusStep(statusPayload, fi).activityState,
4235
- to: "needs_attention",
4236
- runId: id,
4237
- agent: task.agent,
4238
- index: fi,
4239
- ts: taskEndTime,
4240
- message: `${task.agent} completed without making edits for an implementation task`,
4241
- reason: "completion_guard",
4242
- }));
4243
- appendControlEvent(event);
4244
- }
4245
-
4246
4320
  if (singleResult.exitCode !== 0 && failFast && !childStopped) aborted = true;
4247
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 };
4248
4322
  },
@@ -4256,7 +4330,7 @@ export async function runSubagent(
4256
4330
  const sessionTokens = config.sessionDir
4257
4331
  ? parseSessionTokens(path.join(config.sessionDir, `parallel-${t}`))
4258
4332
  : null;
4259
- const fallbackTokens = tokenUsageFromAttempts(parallelResults[t]?.modelAttempts);
4333
+ const fallbackTokens = tokenUsageFromUsage(parallelResults[t]?.usage);
4260
4334
  const observedTokens = requiredStatusStep(statusPayload, fi).tokens;
4261
4335
  const taskTokens = sessionTokens ?? (fallbackTokens
4262
4336
  ? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
@@ -4286,8 +4360,9 @@ export async function runSubagent(
4286
4360
  launchResolvedExtensions: pr.launchResolvedExtensions,
4287
4361
  output: pr.output,
4288
4362
  outputState: pr.outputState,
4363
+ outputPartial: pr.outputPartial,
4289
4364
  error: pr.error,
4290
- 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",
4291
4366
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
4292
4367
  skipped: pr.skipped,
4293
4368
  interrupted: pr.interrupted,
@@ -4299,20 +4374,21 @@ export async function runSubagent(
4299
4374
  intercomTarget: pr.intercomTarget,
4300
4375
  model: pr.model,
4301
4376
  thinking: pr.thinking,
4302
- attemptedModels: pr.attemptedModels,
4303
- modelAttempts: pr.modelAttempts,
4377
+ requestedModel: pr.requestedModel,
4304
4378
  contextOverflow: pr.contextOverflow,
4305
4379
  totalCost: pr.totalCost,
4306
4380
  usage: pr.usage,
4307
4381
  artifactPaths: pr.artifactPaths,
4382
+ outputSaveError: pr.outputSaveError,
4383
+ artifactOutputSaveFailed: pr.artifactOutputSaveFailed,
4308
4384
  transcriptPath: pr.transcriptPath,
4309
4385
  transcriptError: pr.transcriptError,
4310
- effects: pr.effects,
4311
- execution: pr.execution,
4312
- review: pr.review,
4313
- timeoutRecovery: pr.timeoutRecovery,
4314
- structuredOutput: pr.structuredOutput,
4315
- 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,
4316
4392
  structuredOutputPath: pr.structuredOutputPath,
4317
4393
  structuredOutputSchemaPath: pr.structuredOutputSchemaPath,
4318
4394
  acceptance: pr.acceptance,
@@ -4338,7 +4414,7 @@ export async function runSubagent(
4338
4414
  exitCode: r.exitCode,
4339
4415
  error: r.error,
4340
4416
  model: r.model,
4341
- attemptedModels: r.attemptedModels,
4417
+ requestedModel: r.requestedModel,
4342
4418
  })),
4343
4419
  );
4344
4420
  if (worktreeSetup) {
@@ -4506,6 +4582,7 @@ export async function runSubagent(
4506
4582
  }
4507
4583
  const singleCwd = singleWorktreeSetup?.worktrees[0]?.agentCwd ?? cwd;
4508
4584
  const stepStartTime = Date.now();
4585
+ launchedFlatIndices.add(flatIndex);
4509
4586
  statusPayload.currentStep = flatIndex;
4510
4587
  requiredStatusStep(statusPayload, flatIndex).status = "running";
4511
4588
  delete requiredStatusStep(statusPayload, flatIndex).activityState;
@@ -4538,6 +4615,7 @@ export async function runSubagent(
4538
4615
  outputs: statusPayload.mode === "single" ? undefined : outputs,
4539
4616
  sessionDir: config.sessionDir,
4540
4617
  artifactsDir, artifactConfig, id,
4618
+ projectTrusted: config.projectTrusted,
4541
4619
  flatIndex, flatStepCount: Math.max(statusPayload.steps.length, 1),
4542
4620
  outputFile: path.join(asyncDir, `output-${flatIndex}.log`),
4543
4621
  piPackageRoot: config.piPackageRoot,
@@ -4552,6 +4630,7 @@ export async function runSubagent(
4552
4630
  registerTimeout: (interrupt) => registerStepTimeout(flatIndex, interrupt),
4553
4631
  registerStop: (stop) => registerStepStop(flatIndex, stop),
4554
4632
  registerSteer: (steer) => registerStepSteer(flatIndex, steer),
4633
+ onSteerOutcome: (request, delivery) => applySteerDelivery(request.id, flatIndex, delivery),
4555
4634
  timeoutSignal: timeoutAbortController.signal,
4556
4635
  stopSignal: stopAbortController.signal,
4557
4636
  timeoutMessage,
@@ -4560,6 +4639,8 @@ export async function runSubagent(
4560
4639
  onAttemptStart: (attempt) => updateStepModel(flatIndex, attempt.model, attempt.thinking, attempt.contextLimit),
4561
4640
  onChildEvent: (event) => updateStepFromChildEvent(flatIndex, event),
4562
4641
  onExternalProcess: (process) => updateExternalProcess(flatIndex, process),
4642
+ prepareExternalActivity: (externalCwd, signal) => prepareExternalActivity(flatIndex, externalCwd, signal),
4643
+ onExternalStreamActivity: () => recordExternalStreamActivity(flatIndex),
4563
4644
  onExternalJob: (externalJob) => updateExternalJob(flatIndex, externalJob),
4564
4645
  skipAcceptance: () => timedOut || stopped || childStopRequests.has(flatIndex),
4565
4646
  usageBudgetExhausted: continuationUsageBudgetExhausted,
@@ -4586,20 +4667,22 @@ export async function runSubagent(
4586
4667
  runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
4587
4668
  output: stopped || childStopped ? stopMessage : timedOut ? singleResult.output || (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
4588
4669
  outputState: singleResult.outputState,
4670
+ outputPartial: singleResult.outputPartial,
4589
4671
  error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
4590
- 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",
4591
4673
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,
4592
4674
  sessionFile: singleResult.sessionFile,
4593
4675
  intercomTarget: singleResult.intercomTarget,
4594
4676
  model: singleResult.model,
4595
4677
  thinking: singleResult.thinking,
4596
- attemptedModels: singleResult.attemptedModels,
4597
- modelAttempts: singleResult.modelAttempts,
4678
+ requestedModel: singleResult.requestedModel,
4598
4679
  contextOverflow: singleResult.contextOverflow,
4599
4680
  totalCost: singleResult.totalCost,
4600
4681
  usage: singleResult.usage,
4601
4682
  artifactPaths: singleResult.artifactPaths,
4602
4683
  savedOutputPath: singleResult.savedOutputPath,
4684
+ outputSaveError: singleResult.outputSaveError,
4685
+ artifactOutputSaveFailed: singleResult.artifactOutputSaveFailed,
4603
4686
  transcriptPath: singleResult.transcriptPath,
4604
4687
  transcriptError: singleResult.transcriptError,
4605
4688
  effects: singleResult.effects,
@@ -4645,7 +4728,7 @@ export async function runSubagent(
4645
4728
  if (cumulativeTokens) {
4646
4729
  previousCumulativeTokens = cumulativeTokens;
4647
4730
  } else {
4648
- const fallbackTokens = tokenUsageFromAttempts(singleResult.modelAttempts);
4731
+ const fallbackTokens = tokenUsageFromUsage(singleResult.usage);
4649
4732
  const observedTokens = requiredStatusStep(statusPayload, flatIndex).tokens;
4650
4733
  stepTokens = fallbackTokens
4651
4734
  ? { ...fallbackTokens, ...(observedTokens?.window !== undefined ? { window: observedTokens.window } : {}), ...(observedTokens?.windowPeak !== undefined ? { windowPeak: observedTokens.windowPeak } : {}) }
@@ -4665,7 +4748,7 @@ export async function runSubagent(
4665
4748
 
4666
4749
  const stepEndTime = Date.now();
4667
4750
  const childInterrupted = singleResult.interrupted === true;
4668
- 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";
4669
4752
  requiredStatusStep(statusPayload, flatIndex).endedAt = stepEndTime;
4670
4753
  requiredStatusStep(statusPayload, flatIndex).durationMs = stepEndTime - stepStartTime;
4671
4754
  requiredStatusStep(statusPayload, flatIndex).exitCode = stopped || childStopped ? 1 : timedOut ? 1 : childInterrupted ? 0 : singleResult.exitCode;
@@ -4678,8 +4761,7 @@ export async function runSubagent(
4678
4761
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "sessionName", singleResult.sessionName);
4679
4762
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "model", singleResult.model);
4680
4763
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "thinking", resolveEffectiveThinking(singleResult.model, requiredStatusStep(statusPayload, flatIndex).thinking));
4681
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "attemptedModels", singleResult.attemptedModels);
4682
- setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "modelAttempts", singleResult.modelAttempts);
4764
+ setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "requestedModel", singleResult.requestedModel);
4683
4765
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "contextOverflow", singleResult.contextOverflow);
4684
4766
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "totalCost", singleResult.totalCost);
4685
4767
  setOptionalProperty(requiredStatusStep(statusPayload, flatIndex), "error", stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error);
@@ -4768,20 +4850,6 @@ export async function runSubagent(
4768
4850
  });
4769
4851
  }
4770
4852
 
4771
- if (singleResult.completionGuardTriggered) {
4772
- const event = buildControlEvent(omitUndefinedProperties({
4773
- from: requiredStatusStep(statusPayload, flatIndex).activityState,
4774
- to: "needs_attention",
4775
- runId: id,
4776
- agent: seqStep.agent,
4777
- index: flatIndex,
4778
- ts: stepEndTime,
4779
- message: `${seqStep.agent} completed without making edits for an implementation task`,
4780
- reason: "completion_guard",
4781
- }));
4782
- appendControlEvent(event);
4783
- }
4784
-
4785
4853
  flatIndex++;
4786
4854
  if (isAgentContract(seqStep.agentContract) && seqStep.gateOn === "acceptance" && singleResult.acceptance?.status === "rejected") {
4787
4855
  statusPayload.error = acceptanceFailureMessage(singleResult.acceptance) ?? "Chain acceptance gate rejected the step.";
@@ -4794,6 +4862,34 @@ export async function runSubagent(
4794
4862
  }
4795
4863
  }
4796
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
+
4797
4893
  let summary = results.map((r) => `${r.agent}:\n${r.output || (r.exitCode !== 0 ? r.error : undefined) || "(no output)"}`).join("\n\n");
4798
4894
  let truncated = false;
4799
4895
 
@@ -4859,9 +4955,21 @@ export async function runSubagent(
4859
4955
  clearTimeout(timeoutTimer);
4860
4956
  timeoutTimer = undefined;
4861
4957
  }
4958
+ if (checkpointTimer) {
4959
+ clearTimeout(checkpointTimer);
4960
+ checkpointTimer = undefined;
4961
+ }
4862
4962
  if (!timedOut && !stopped && !interrupted && config.timeoutMs !== undefined && timeoutMessage !== undefined && results.some((result) => result.timedOut === true && result.error?.startsWith(timeoutMessage))) {
4863
4963
  timedOut = true;
4864
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);
4865
4973
  const signalTerminated = !stopped && !timedOut && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal(omitUndefinedProperties({
4866
4974
  processSignal: result.processSignal,
4867
4975
  interrupted: result.interrupted,
@@ -4876,7 +4984,6 @@ export async function runSubagent(
4876
4984
  });
4877
4985
  statusPayload.state = stopped || signalTerminated ? "stopped" : timedOut || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : partialWithEvidence ? "partial" : "failed";
4878
4986
  closeSteerInbox(asyncDir, statusPayload.state, (filePath, payload) => runPersistence.write(filePath, payload));
4879
- disposeControlInbox();
4880
4987
  for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
4881
4988
  const effectiveSessionFile = sessionFile ?? latestSessionFile;
4882
4989
  const steeringLifecycle = steeringStatus(statusPayload);
@@ -4885,7 +4992,7 @@ export async function runSubagent(
4885
4992
  for (const target of request.targets) {
4886
4993
  if (target.state !== "scheduled" && target.state !== "routed" && target.state !== "queued") continue;
4887
4994
  changed = true;
4888
- 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";
4889
4996
  updateSteeringLifecycleTarget(request.id, target.index, "failed", Date.now(), { reason });
4890
4997
  markSteeringAttention(target.index);
4891
4998
  emitSteeringEvent("subagent.steer.failed", { type: "steer", id: request.id, ts: request.requestedAt, message: reason }, target.index, { reason });
@@ -4912,7 +5019,7 @@ export async function runSubagent(
4912
5019
  statusPayload.activityState = "needs_attention";
4913
5020
  statusPayload.error = partialResult?.error ?? statusPayload.error;
4914
5021
  for (const step of statusPayload.steps) {
4915
- if (step.status === "failed") step.activityState = "needs_attention";
5022
+ if (step.status === "failed" || step.status === "partial") step.activityState = "needs_attention";
4916
5023
  }
4917
5024
  }
4918
5025
  statusPayload.endedAt = runEndedAt;
@@ -4956,6 +5063,7 @@ export async function runSubagent(
4956
5063
  context: r.context,
4957
5064
  output: r.output,
4958
5065
  outputState: r.outputState,
5066
+ outputPartial: r.outputPartial,
4959
5067
  error: r.error,
4960
5068
  success: r.success,
4961
5069
  skipped: r.skipped || undefined,
@@ -4969,14 +5077,14 @@ export async function runSubagent(
4969
5077
  intercomTarget: r.intercomTarget,
4970
5078
  model: r.model,
4971
5079
  thinking: r.thinking,
4972
- attemptedModels: r.attemptedModels,
4973
- modelAttempts: r.modelAttempts,
5080
+ requestedModel: r.requestedModel,
4974
5081
  contextOverflow: r.contextOverflow,
4975
5082
  totalCost: r.totalCost,
4976
5083
  usage: r.usage,
4977
5084
  artifactPaths: r.artifactPaths,
4978
5085
  savedOutputPath: r.savedOutputPath,
4979
5086
  outputSaveError: r.outputSaveError,
5087
+ artifactOutputSaveFailed: r.artifactOutputSaveFailed,
4980
5088
  metadataSaveError: r.metadataSaveError,
4981
5089
  truncated: r.truncated,
4982
5090
  transcriptPath: r.transcriptPath,
@@ -5058,6 +5166,26 @@ export async function runSubagent(
5058
5166
  usageBudget: statusPayload.usageBudget,
5059
5167
  }),
5060
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
+ }
5061
5189
  writeRunLog(logPath, omitUndefinedProperties({
5062
5190
  id,
5063
5191
  mode: statusPayload.mode,
@@ -5110,149 +5238,40 @@ export async function runSubagent(
5110
5238
  }
5111
5239
  }
5112
5240
 
5113
- async function waitForStartupControl(
5114
- controlPath: string,
5115
- token: string,
5116
- action: "ack" | "proceed",
5117
- timeoutMs = 30_000,
5118
- ): Promise<void> {
5119
- const deadline = Date.now() + timeoutMs;
5120
- while (Date.now() <= deadline) {
5121
- if (fs.existsSync(controlPath)) {
5122
- let payload: { action?: unknown; token?: unknown };
5123
- try {
5124
- payload = JSON.parse(fs.readFileSync(controlPath, "utf-8")) as { action?: unknown; token?: unknown };
5125
- } catch (error) {
5126
- throw new Error(`Failed to read runner startup control '${controlPath}': ${error instanceof Error ? error.message : String(error)}`);
5127
- }
5128
- if (payload.token !== token) throw new Error("Runner startup control token does not match.");
5129
- if (payload.action === action) return;
5130
- if (payload.action !== "ack" && payload.action !== "proceed") throw new Error("Runner startup control action is invalid.");
5131
- }
5132
- await new Promise((resolve) => setTimeout(resolve, 20));
5133
- }
5134
- throw new Error(`Timed out after ${timeoutMs}ms waiting for runner startup control '${action}'.`);
5135
- }
5136
-
5137
- async function runConfiguredSubagent(config: SubagentRunConfig): Promise<void> {
5138
- let lease: ReturnType<typeof acquireSessionLease> | undefined;
5139
- let startupCommitted = config.revivalLease === undefined && config.launchBarrierToken === undefined;
5140
- const startupPath = path.join(config.asyncDir, "runner-startup.json");
5141
- const startupAckPath = path.join(config.asyncDir, "runner-startup-ack.json");
5142
- const startupProceedPath = path.join(config.asyncDir, "runner-startup-proceed.json");
5143
- const releaseOnExit = (): void => {
5144
- try {
5145
- lease?.release();
5146
- } catch {
5147
- // Exit cleanup is best effort; a dead-owner lease is reclaimed on the next revival.
5148
- }
5149
- };
5150
- 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;
5151
5244
  try {
5152
- if (config.launchBarrierToken) {
5153
- await waitForStartupControl(startupProceedPath, config.launchBarrierToken, "proceed");
5154
- startupCommitted = true;
5155
- try {
5156
- fs.rmSync(startupProceedPath, { force: true });
5157
- } catch {
5158
- // Startup control cleanup is best effort after the parent commits the run.
5159
- }
5160
- } else if (config.revivalLease) {
5161
- lease = acquireSessionLease(config.revivalLease);
5162
- config.revivalLeaseToken = lease.owner.token;
5163
- writeAtomicJson(startupPath, { state: "ready", token: lease.owner.token, pid: process.pid, owner: lease.owner });
5164
- await waitForStartupControl(startupAckPath, lease.owner.token, "ack");
5165
- writeAtomicJson(startupPath, { state: "acknowledged", token: lease.owner.token, pid: process.pid });
5166
- await waitForStartupControl(startupProceedPath, lease.owner.token, "proceed");
5167
- startupCommitted = true;
5168
- for (const controlPath of [startupAckPath, startupProceedPath]) {
5169
- try {
5170
- fs.rmSync(controlPath, { force: true });
5171
- } catch {
5172
- // Startup control cleanup is best effort after the parent commits the run.
5173
- }
5174
- }
5175
- }
5176
- const childSessions = await loadRunnerChildSessionFactory(config);
5177
- try {
5178
- await runSubagent(config, childSessions);
5179
- } finally {
5180
- try {
5181
- await childSessions.dispose();
5182
- } catch (error) {
5183
- console.error("Failed to dispose runner child sessions:", error);
5184
- }
5185
- }
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);
5186
5249
  } catch (error) {
5187
- if (!startupCommitted) {
5188
- try {
5189
- writeAtomicJson(startupPath, { state: "error", pid: process.pid, error: error instanceof Error ? error.message : String(error) });
5190
- } catch {
5191
- // The parent will time out and terminate this runner if the handshake cannot be written.
5192
- }
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);
5193
5265
  }
5194
5266
  throw error;
5195
- } finally {
5196
- process.off("exit", releaseOnExit);
5197
- if (lease) {
5198
- let acknowledged = false;
5199
- try {
5200
- acknowledged = lease.release();
5201
- } catch (error) {
5202
- console.error("Failed to release session revival lease:", error);
5203
- }
5204
- try {
5205
- markProcessTerminalCandidateLeaseRelease(config.asyncDir, lease.owner.token, acknowledged);
5206
- } catch (error) {
5207
- console.error("Failed to record session revival lease release:", error);
5208
- }
5209
- }
5210
5267
  }
5211
- }
5212
-
5213
- function startConfiguredSubagent(config: SubagentRunConfig): void {
5214
- // Child sessions and the extensions loaded into them may leave handles
5215
- // behind even after shutdown; the run is fully persisted by now, so exit
5216
- // explicitly instead of waiting for the event loop to drain.
5217
- runConfiguredSubagent(config).then(
5218
- () => process.exit(0),
5219
- (runErr) => {
5220
- console.error("Subagent runner error:", runErr);
5221
- process.exit(1);
5222
- },
5223
- );
5224
- }
5225
-
5226
- if (isRunnerEntrypoint) {
5227
- const configArg = process.argv[2];
5228
- if (configArg) {
5229
5268
  try {
5230
- const configJson = fs.readFileSync(configArg, "utf-8");
5231
- const config = JSON.parse(configJson) as SubagentRunConfig;
5269
+ await runSubagent(config, childSessions);
5270
+ } finally {
5232
5271
  try {
5233
- fs.unlinkSync(configArg);
5234
- } catch {
5235
- // Temp config cleanup is best effort.
5272
+ await childSessions.dispose();
5273
+ } catch (error) {
5274
+ console.error("Failed to dispose runner child sessions:", error);
5236
5275
  }
5237
- startConfiguredSubagent(config);
5238
- } catch (err) {
5239
- console.error("Subagent runner error:", err);
5240
- process.exit(1);
5241
5276
  }
5242
- } else {
5243
- let input = "";
5244
- process.stdin.setEncoding("utf-8");
5245
- process.stdin.on("data", (chunk) => {
5246
- input += chunk;
5247
- });
5248
- process.stdin.on("end", () => {
5249
- try {
5250
- const config = JSON.parse(input) as SubagentRunConfig;
5251
- startConfiguredSubagent(config);
5252
- } catch (err) {
5253
- console.error("Subagent runner error:", err);
5254
- process.exit(1);
5255
- }
5256
- });
5257
- }
5258
5277
  }