@selesai/code 0.13.0 → 0.13.2

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 (463) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/core/agent-session.d.ts +1 -1
  3. package/dist/core/agent-session.js +1 -1
  4. package/dist/core/sdk.d.ts +2 -2
  5. package/dist/core/sdk.js +1 -1
  6. package/dist/core/system-prompt.d.ts +1 -1
  7. package/dist/core/system-prompt.js +1 -1
  8. package/dist/extensions/package.json +1 -2
  9. package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
  10. package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
  11. package/dist/extensions/pi-hermes-memory/README.md +643 -0
  12. package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
  13. package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
  14. package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
  15. package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
  16. package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
  17. package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
  18. package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
  19. package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
  20. package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
  21. package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
  22. package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
  23. package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
  24. package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
  25. package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
  26. package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
  27. package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
  28. package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
  29. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
  30. package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
  31. package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
  32. package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
  33. package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
  34. package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
  35. package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
  36. package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
  37. package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
  38. package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
  39. package/dist/extensions/pi-hermes-memory/package.json +66 -0
  40. package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
  41. package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
  42. package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
  43. package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
  44. package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
  45. package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
  46. package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
  47. package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
  48. package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
  49. package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
  50. package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
  51. package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
  52. package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
  53. package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
  54. package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
  55. package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
  56. package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
  57. package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
  58. package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
  59. package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
  60. package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
  61. package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
  62. package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
  63. package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
  64. package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
  65. package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
  66. package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
  67. package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
  68. package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
  69. package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
  70. package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
  71. package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
  72. package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
  73. package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
  74. package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
  75. package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
  76. package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
  77. package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
  78. package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
  79. package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
  80. package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
  81. package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
  82. package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
  83. package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
  84. package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
  85. package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
  86. package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
  87. package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
  88. package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
  89. package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
  90. package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
  91. package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
  92. package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
  93. package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
  94. package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
  95. package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
  96. package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
  97. package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
  98. package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
  99. package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
  100. package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
  101. package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
  102. package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
  103. package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
  104. package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
  105. package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
  106. package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
  107. package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
  108. package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
  109. package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
  110. package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
  111. package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
  112. package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
  113. package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
  114. package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
  115. package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
  116. package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
  117. package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
  118. package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
  119. package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
  120. package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
  121. package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
  122. package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
  123. package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
  124. package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
  125. package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
  126. package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
  127. package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
  128. package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
  129. package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
  130. package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
  131. package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
  132. package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
  133. package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
  134. package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
  135. package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
  136. package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
  137. package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
  138. package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
  139. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
  140. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
  141. package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
  142. package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
  143. package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
  144. package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
  145. package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
  146. package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
  147. package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
  148. package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
  149. package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
  150. package/dist/extensions/pi-rewind-hook/README.md +4 -1
  151. package/dist/extensions/pi-rewind-hook/index.ts +151 -21
  152. package/dist/extensions/pi-rewind-hook/package.json +5 -3
  153. package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
  154. package/dist/extensions/pi-subagents/AGENTS.md +5 -0
  155. package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
  156. package/dist/extensions/pi-subagents/README.md +12 -6
  157. package/dist/extensions/pi-subagents/VISION.md +81 -0
  158. package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
  159. package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
  160. package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
  161. package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
  162. package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
  163. package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
  164. package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
  165. package/dist/extensions/pi-subagents/docs/agents.md +488 -0
  166. package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
  167. package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
  168. package/dist/extensions/pi-subagents/docs/models.md +27 -4
  169. package/dist/extensions/pi-subagents/docs/observability.md +10 -9
  170. package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
  171. package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
  172. package/dist/extensions/pi-subagents/package-lock.json +389 -2
  173. package/dist/extensions/pi-subagents/package.json +3 -1
  174. package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
  175. package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
  176. package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
  177. package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
  178. package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
  179. package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
  180. package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
  181. package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
  182. package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
  183. package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
  184. package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
  185. package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
  186. package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
  187. package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
  188. package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
  189. package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
  190. package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
  191. package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
  192. package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
  193. package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
  194. package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
  195. package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
  196. package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
  197. package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
  198. package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
  199. package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
  200. package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
  201. package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
  202. package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -7
  203. package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
  204. package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
  205. package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
  206. package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
  207. package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
  208. package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
  209. package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
  210. package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
  211. package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
  212. package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
  213. package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
  214. package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
  215. package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
  216. package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
  217. package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
  218. package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
  219. package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
  220. package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
  221. package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
  222. package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
  223. package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
  224. package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
  225. package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
  226. package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
  227. package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
  228. package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
  229. package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
  230. package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
  231. package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
  232. package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
  233. package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
  234. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
  235. package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
  236. package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
  237. package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
  238. package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
  239. package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
  240. package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
  241. package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
  242. package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
  243. package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
  244. package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
  245. package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
  246. package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
  247. package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
  248. package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
  249. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
  250. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
  251. package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
  252. package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
  253. package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
  254. package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
  255. package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
  256. package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
  257. package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
  258. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
  259. package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
  260. package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
  261. package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
  262. package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
  263. package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
  264. package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
  265. package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
  266. package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
  267. package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
  268. package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
  269. package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
  270. package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
  271. package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
  272. package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
  273. package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
  274. package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
  275. package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
  276. package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
  277. package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
  278. package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
  279. package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
  280. package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
  281. package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
  282. package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
  283. package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
  284. package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
  285. package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
  286. package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
  287. package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
  288. package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
  289. package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
  290. package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
  291. package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
  292. package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
  293. package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
  294. package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
  295. package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
  296. package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
  297. package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
  298. package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
  299. package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
  300. package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
  301. package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
  302. package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
  303. package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
  304. package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
  305. package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
  306. package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
  307. package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
  308. package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
  309. package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
  310. package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
  311. package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
  312. package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
  313. package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
  314. package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
  315. package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
  316. package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
  317. package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
  318. package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
  319. package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
  320. package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
  321. package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
  322. package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
  323. package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
  324. package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
  325. package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
  326. package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
  327. package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
  328. package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
  329. package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
  330. package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
  331. package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
  332. package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
  333. package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
  334. package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
  335. package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
  336. package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
  337. package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
  338. package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
  339. package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
  340. package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
  341. package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
  342. package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
  343. package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
  344. package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
  345. package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
  346. package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
  347. package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
  348. package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
  349. package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
  350. package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
  351. package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
  352. package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
  353. package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
  354. package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
  355. package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
  356. package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
  357. package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
  358. package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
  359. package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
  360. package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
  361. package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
  362. package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
  363. package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
  364. package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
  365. package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
  366. package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
  367. package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
  368. package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
  369. package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
  370. package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
  371. package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
  372. package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
  373. package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +136 -6
  374. package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
  375. package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
  376. package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
  377. package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
  378. package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
  379. package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
  380. package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
  381. package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
  382. package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
  383. package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
  384. package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
  385. package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
  386. package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
  387. package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
  388. package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
  389. package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
  390. package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
  391. package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
  392. package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
  393. package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
  394. package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
  395. package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
  396. package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
  397. package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
  398. package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
  399. package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
  400. package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
  401. package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
  402. package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
  403. package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
  404. package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
  405. package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
  406. package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
  407. package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
  408. package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
  409. package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
  410. package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
  411. package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
  412. package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
  413. package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
  414. package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
  415. package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
  416. package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
  417. package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
  418. package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
  419. package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
  420. package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
  421. package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
  422. package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
  423. package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
  424. package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
  425. package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
  426. package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
  427. package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
  428. package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
  429. package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
  430. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
  431. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
  432. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
  433. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
  434. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
  435. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
  436. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
  437. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
  438. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
  439. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
  440. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
  441. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
  442. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
  443. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
  444. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
  445. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
  446. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
  447. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
  448. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
  449. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
  450. package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
  451. package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
  452. package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
  453. package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
  454. package/dist/modes/interactive/interactive-mode.js +7 -7
  455. package/dist/skills/workflow/SKILL.md +65 -50
  456. package/package.json +112 -110
  457. package/dist/extensions/enable-readonly-tools.test.ts +0 -63
  458. package/dist/extensions/enable-readonly-tools.ts +0 -24
  459. package/dist/extensions/model-prompt-injector/config.json +0 -16
  460. package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
  461. package/dist/extensions/model-prompt-injector/index.ts +0 -148
  462. package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
  463. package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
@@ -6,7 +6,7 @@ import { spawn } from "node:child_process";
6
6
  import { existsSync, unlinkSync } from "node:fs";
7
7
  import * as path from "node:path";
8
8
  import type { Message } from "@earendil-works/pi-ai";
9
- import type { AgentConfig } from "../../agents/agents.ts";
9
+ import { discoverAgents, formatUnknownAgentError, unknownAgentDiagnosticContext, type AgentConfig } from "../../agents/agents.ts";
10
10
  import { appendAgentRefinementOverlay } from "../../agents/agent-refinements.ts";
11
11
  import { alignForkedSessionCwd } from "../../shared/fork-context.ts";
12
12
  import {
@@ -46,6 +46,7 @@ import {
46
46
  findLatestSessionFile,
47
47
  detectSubagentError,
48
48
  hasEmptyTerminalAssistantResponse,
49
+ formatEmptyTerminalAssistantResponseError,
49
50
  extractToolArgsPreview,
50
51
  extractTextFromContent,
51
52
  boundStreamedRecentTools,
@@ -55,20 +56,24 @@ import {
55
56
  import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
56
57
  import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
57
58
  import { effectiveToolTimeoutMs, formatToolTimeoutMessage, resolveToolTimeoutMs, toolTimeoutCallKey, toolTimeoutFromEnv } from "../shared/tool-timeout.ts";
58
- import { evaluateCompletionMutationGuard, validateImplementationToolContract } from "../shared/completion-guard.ts";
59
+ import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.ts";
60
+ import { planCompletionEvidence } from "../shared/completion-evidence.ts";
61
+ import { planAbortRecovery } from "../shared/abort-recovery.ts";
59
62
  import { arbitrateCompletionGuardRescue } from "../shared/llm-intent-arbiter.ts";
60
63
  import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
64
+ import { preflightLaunchCwd } from "../shared/launch-cwd.ts";
61
65
  import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
62
66
  import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-progress-tabs.ts";
63
67
  import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
64
68
  import { resolvePermissionRules } from "../shared/permissions.ts";
65
69
  import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan, type SubagentTaskDelivery } from "../shared/pi-args.ts";
70
+ import { deriveChildSessionName } from "../../shared/child-session-name.ts";
66
71
  import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
67
72
  import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.ts";
68
73
  import { resolveEffectiveThinking } from "../../shared/model-info.ts";
69
74
  import { assertThinkingWithinCeiling, decodeThinkingCeiling, intersectThinkingCeilings, SUBAGENT_THINKING_CEILING_ENV } from "../../shared/thinking-ceiling.ts";
70
75
  import { MISSING_STRUCTURED_OUTPUT_CALL_ERROR, readStructuredOutput, readStructuredOutputAcceptanceReport } from "../shared/structured-output.ts";
71
- import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
76
+ import { formatMidToolExitError, formatProcessSignalError, isOrdinaryToolForMidToolExit, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
72
77
  import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
73
78
  import { buildTimeoutRecoverySummary, collectTrackedMutationEvidence, snapshotTrackedMutations } from "../shared/mutation-evidence.ts";
74
79
  import { captureSingleOutputSnapshot, extractChildWrittenOutput, finalizeSingleOutput, formatSavedOutputReference, injectOutputPathSystemPrompt, resolveSingleOutput, validateFileOnlyOutputMode, type SingleOutputSnapshot } from "../shared/single-output.ts";
@@ -77,7 +82,7 @@ import {
77
82
  formatSubagentModelVerificationError,
78
83
  formatModelAttemptNote,
79
84
  isContextOverflow,
80
- isRetryableModelFailure,
85
+ isRetryableModelFailureAttempt,
81
86
  recordRetryableModelFailure,
82
87
  } from "../shared/model-fallback.ts";
83
88
  import {
@@ -102,11 +107,11 @@ import {
102
107
  import { acceptanceFailureMessage, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport, validateAcceptanceInput } from "../shared/acceptance.ts";
103
108
  import { PROMPT_REDACTED } from "../../shared/utils.ts";
104
109
  import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
105
- import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
106
110
  import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
107
111
  import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
108
112
  import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
109
- import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, PI_AGGREGATE_EVENT_PROJECTOR, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
113
+ import { consumeWorkflowChildPermit } from "../../shared/workflow-child-permit.ts";
114
+ import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, PI_AGGREGATE_EVENT_PROJECTOR, projectChildLifecycle, type ChildLifecycleAction, type ChildLifecycleState, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
110
115
  import {
111
116
  acceptChildWatchdogEvent,
112
117
  childWatchdogIsActive,
@@ -292,6 +297,9 @@ function snapshotStreamResult(result: SingleResult, progress: AgentProgress): Si
292
297
  return snapshot;
293
298
  }
294
299
 
300
+ const AFTER_COMPACTION_SETTLEMENT = Symbol("afterCompactionSettlement");
301
+ type AbortRecoverySingleResult = SingleResult & { [AFTER_COMPACTION_SETTLEMENT]?: true };
302
+
295
303
  async function runSingleAttempt(
296
304
  runtimeCwd: string,
297
305
  agent: AgentConfig,
@@ -321,6 +329,10 @@ async function runSingleAttempt(
321
329
  assertThinkingWithinCeiling({ model: modelArg, configThinking: effectiveThinking, ceiling: options.thinkingCeiling, agent: agent.name, runId: options.runId });
322
330
  const expectedModelForVerification = shared.verifyModel ? modelArg : undefined;
323
331
  const resolvedThinking = resolveEffectiveThinking(modelArg, effectiveThinking);
332
+ // Display name for the child session: applied inside the child via
333
+ // PI_SUBAGENT_SESSION_NAME and echoed back on the result payload so hosts
334
+ // can label this run without reading the child's session file.
335
+ const childSessionName = deriveChildSessionName({ agent: agent.name, task: shared.originalTask ?? task });
324
336
  const watchdogConfig = resolveWatchdogConfig(options.cwd ?? runtimeCwd);
325
337
  const childWatchdog = watchdogConfig.ok
326
338
  ? resolveChildWatchdogConfig({
@@ -345,16 +357,19 @@ async function runSingleAttempt(
345
357
  thinking: effectiveThinking,
346
358
  systemPromptMode: agent.systemPromptMode,
347
359
  inheritProjectContext: agent.inheritProjectContext,
360
+ inheritGlobalContext: agent.inheritGlobalContext,
348
361
  inheritSkills: agent.inheritSkills,
349
362
  requireReadTool: Boolean(shared.resolvedSkillNames?.length),
350
363
  tools: agent.tools,
364
+ allowNestedSubagents: agent.allowNestedSubagents,
351
365
  extensions: agent.extensions,
352
366
  subagentOnlyExtensions: agent.subagentOnlyExtensions,
353
- systemPrompt: appendTurnBudgetSystemPrompt(shared.systemPrompt, options.turnBudget),
367
+ systemPrompt: shared.systemPrompt,
354
368
  mcpDirectTools: agent.mcpDirectTools,
355
369
  cwd: options.cwd ?? runtimeCwd,
356
370
  promptFileStem: agent.name,
357
371
  intercomSessionName: options.intercomSessionName,
372
+ sessionName: childSessionName,
358
373
  orchestratorIntercomTarget: options.orchestratorIntercomTarget,
359
374
  runId: options.runId,
360
375
  childAgentName: agent.name,
@@ -377,18 +392,21 @@ async function runSingleAttempt(
377
392
  permissionAuditPath,
378
393
  childWatchdog,
379
394
  waitToolEnabled: options.waitToolEnabled,
395
+ waitToolDefaultTimeoutMs: options.waitToolDefaultTimeoutMs,
380
396
  capabilityCeiling: options.capabilityCeiling,
381
397
  thinkingCeiling: options.thinkingCeiling,
382
398
  extensionBindings: options.extensionBindings,
399
+ runtimeSnapshotHost: options.runtimeSnapshotHost,
383
400
  });
384
401
  if (!shared.launchWarnings.emitted && warnings.length > 0) {
385
402
  for (const warning of warnings) console.warn(`[pi-subagents] ${warning}`);
386
403
  shared.launchWarnings.emitted = true;
387
404
  }
388
405
 
389
- const effectiveSystemPrompt = appendTurnBudgetSystemPrompt(shared.systemPrompt, options.turnBudget);
406
+ const effectiveSystemPrompt = shared.systemPrompt;
390
407
  const toolPlan = resolvePiLaunchToolPlan({
391
408
  tools: agent.tools,
409
+ allowNestedSubagents: agent.allowNestedSubagents,
392
410
  extensions: agent.extensions,
393
411
  subagentOnlyExtensions: agent.subagentOnlyExtensions,
394
412
  mcpDirectTools: agent.mcpDirectTools,
@@ -402,6 +420,7 @@ async function runSingleAttempt(
402
420
  inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
403
421
  agentName: agent.name,
404
422
  permissionRules,
423
+ runtimeSnapshotHost: options.runtimeSnapshotHost,
405
424
  });
406
425
  const contractTools = toolPlan.explicitToolAllowlist ? toolPlan.effectiveToolAllowlist : undefined;
407
426
  const contractError = validateImplementationToolContract({
@@ -420,6 +439,7 @@ async function runSingleAttempt(
420
439
  index: options.index ?? 0,
421
440
  agent: agent.name,
422
441
  task,
442
+ ...(childSessionName ? { sessionName: childSessionName } : {}),
423
443
  messages: [],
424
444
  finalOutput: "",
425
445
  exitCode: 1,
@@ -445,6 +465,7 @@ async function runSingleAttempt(
445
465
  systemPrompt: effectiveSystemPrompt,
446
466
  systemPromptMode: agent.systemPromptMode,
447
467
  inheritProjectContext: agent.inheritProjectContext,
468
+ inheritGlobalContext: agent.inheritGlobalContext,
448
469
  inheritSkills: agent.inheritSkills,
449
470
  skills: shared.resolvedSkillNames ?? [],
450
471
  tools: toolPlan.effectiveToolAllowlist,
@@ -459,6 +480,7 @@ async function runSingleAttempt(
459
480
  index: options.index ?? 0,
460
481
  agent: agent.name,
461
482
  task: shared.originalTask ?? task,
483
+ ...(childSessionName ? { sessionName: childSessionName } : {}),
462
484
  ...(options.agentContract ? { agentContract: options.agentContract } : {}),
463
485
  launchContractDigest,
464
486
  launchResolvedExtensions,
@@ -472,7 +494,6 @@ async function runSingleAttempt(
472
494
  transcriptPath: shared.transcriptWriter ? shared.artifactPaths?.transcriptPath : undefined,
473
495
  skills: shared.resolvedSkillNames,
474
496
  skillsWarning: shared.skillsWarning,
475
- ...(options.turnBudget ? { turnBudget: initialTurnBudgetState(options.turnBudget) } : {}),
476
497
  ...(options.toolBudget ? { toolBudget: initialToolBudgetState(options.toolBudget) } : {}),
477
498
  ...(options.capabilityCeiling ? { capabilityCeiling: options.capabilityCeiling } : {}),
478
499
  ...(capabilityAudit ? { capabilityAudit } : {}),
@@ -501,6 +522,7 @@ async function runSingleAttempt(
501
522
  const progress: AgentProgress = {
502
523
  index: options.index ?? 0,
503
524
  agent: agent.name,
525
+ ...(childSessionName ? { sessionName: childSessionName } : {}),
504
526
  status: "running",
505
527
  task,
506
528
  skills: shared.resolvedSkillNames,
@@ -538,9 +560,30 @@ async function runSingleAttempt(
538
560
  let structuredOutputToolInvoked = false;
539
561
  let structuredOutputMessageStartIndex: number | undefined;
540
562
  let toolAvailabilityError: string | undefined;
563
+ let abortedBySignal = options.signal?.aborted === true;
541
564
 
565
+ const spawnSpec = getPiSpawnCommand(args);
566
+ if (options.workflowChildPermitLaunch) {
567
+ const permitError = consumeWorkflowChildPermit(options.workflowChildPermitLaunch.permit, {
568
+ workflowRunId: options.workflowChildPermitLaunch.workflowRunId,
569
+ childKey: options.workflowChildPermitLaunch.childKey,
570
+ agent: agent.name,
571
+ launchContractDigest,
572
+ context: options.context ?? "fresh",
573
+ runner: "pi",
574
+ });
575
+ if (permitError) {
576
+ cleanupTempDir(tempDir);
577
+ result.exitCode = 1;
578
+ result.error = permitError;
579
+ result.finalOutput = permitError;
580
+ progress.status = "failed";
581
+ progress.error = permitError;
582
+ return result;
583
+ }
584
+ }
585
+ let afterCompactionSettlement = false;
542
586
  const exitCode = await new Promise<number>((resolve) => {
543
- const spawnSpec = getPiSpawnCommand(args);
544
587
  const proc = spawn(spawnSpec.command, spawnSpec.args, {
545
588
  cwd: options.cwd ?? runtimeCwd,
546
589
  env: spawnEnv,
@@ -559,20 +602,7 @@ async function runSingleAttempt(
559
602
  let timeoutTimer: NodeJS.Timeout | undefined;
560
603
  let timeoutTerminationTimer: NodeJS.Timeout | undefined;
561
604
  let timeoutHardKillTimer: NodeJS.Timeout | undefined;
562
- let turnBudgetSoftReached = false;
563
- let turnBudgetTerminationTimer: NodeJS.Timeout | undefined;
564
- let turnBudgetHardKillTimer: NodeJS.Timeout | undefined;
565
605
  let protocolHardKillTimer: NodeJS.Timeout | undefined;
566
- const clearTurnBudgetTimers = () => {
567
- if (turnBudgetTerminationTimer) {
568
- clearTimeout(turnBudgetTerminationTimer);
569
- turnBudgetTerminationTimer = undefined;
570
- }
571
- if (turnBudgetHardKillTimer) {
572
- clearTimeout(turnBudgetHardKillTimer);
573
- turnBudgetHardKillTimer = undefined;
574
- }
575
- };
576
606
  const clearTimeoutTimers = () => {
577
607
  if (timeoutTimer) {
578
608
  clearTimeout(timeoutTimer);
@@ -635,6 +665,7 @@ async function runSingleAttempt(
635
665
  let forcedTerminationSignal = false;
636
666
  let cleanTerminalAssistantStopReceived = false;
637
667
  let agentSettledReceived = false;
668
+ let compactionStartedReceived = false;
638
669
  let finalDrainTimer: NodeJS.Timeout | undefined;
639
670
  let finalHardKillTimer: NodeJS.Timeout | undefined;
640
671
  let watchdogTailTimer: NodeJS.Timeout | undefined;
@@ -707,6 +738,7 @@ async function runSingleAttempt(
707
738
  }
708
739
  if (action === "start-drain") startFinalDrain();
709
740
  };
741
+ const childLifecycleState: ChildLifecycleState = { compactionRetryActive: false };
710
742
 
711
743
  const unsubscribeIntercomDetach = options.intercomEvents?.on?.(INTERCOM_DETACH_REQUEST_EVENT, (payload) => {
712
744
  if (!options.allowIntercomDetach || processClosed) return;
@@ -732,7 +764,6 @@ async function runSingleAttempt(
732
764
  clearStdioGuard();
733
765
  clearTimeoutTimers();
734
766
  clearAllToolTimeouts();
735
- clearTurnBudgetTimers();
736
767
  if (protocolHardKillTimer) {
737
768
  clearTimeout(protocolHardKillTimer);
738
769
  protocolHardKillTimer = undefined;
@@ -870,57 +901,6 @@ async function runSingleAttempt(
870
901
  }));
871
902
  return true;
872
903
  };
873
- const requestTurnBudgetAbort = (turnCount: number) => {
874
- const budget = options.turnBudget;
875
- if (!budget || result.timedOut || result.turnBudgetExceeded || interruptedByControl || processClosed || lifecycleFinished) return;
876
- const message = turnBudgetExceededMessage(budget, turnCount);
877
- result.turnBudgetExceeded = true;
878
- result.wrapUpRequested = true;
879
- result.turnBudget = turnBudgetState(budget, turnCount, true);
880
- result.error = message;
881
- result.finalOutput = message;
882
- progress.status = "failed";
883
- progress.error = message;
884
- progress.durationMs = Date.now() - startTime;
885
- fireUpdate();
886
- trySignalChild(proc, "SIGINT");
887
- turnBudgetTerminationTimer = setTimeout(() => {
888
- if (processClosed || lifecycleFinished || result.timedOut) return;
889
- trySignalChild(proc, "SIGTERM");
890
- }, 1000);
891
- turnBudgetTerminationTimer.unref?.();
892
- turnBudgetHardKillTimer = setTimeout(() => {
893
- if (processClosed || lifecycleFinished || result.timedOut) return;
894
- trySignalChild(proc, "SIGKILL");
895
- }, 4000);
896
- turnBudgetHardKillTimer.unref?.();
897
- };
898
-
899
- const updateTurnBudget = (turnCount: number, terminalAssistantStop: boolean, toolWorkActiveOrStarting: boolean) => {
900
- const budget = options.turnBudget;
901
- if (!budget || result.timedOut || result.turnBudgetExceeded) return;
902
- if (turnCount < budget.maxTurns) {
903
- result.turnBudget = { ...budget, outcome: "within-budget", turnCount };
904
- return;
905
- }
906
- if (!turnBudgetSoftReached) {
907
- turnBudgetSoftReached = true;
908
- result.wrapUpRequested = true;
909
- appendRecentOutput(progress, [turnBudgetSoftNote(budget, turnCount)]);
910
- }
911
- const decision = turnBudgetDecision(budget, turnCount, terminalAssistantStop, toolWorkActiveOrStarting, options.enforceHardTurnLimit);
912
- if (decision === "defer") {
913
- result.turnBudget = turnBudgetDeferredState(
914
- budget,
915
- turnCount,
916
- result.turnBudget?.terminationDeferredAtTurn,
917
- );
918
- return;
919
- }
920
- result.turnBudget = turnBudgetState(budget, turnCount, false);
921
- if (decision === "abort") requestTurnBudgetAbort(turnCount);
922
- };
923
-
924
904
  const updateActivityState = (now: number): boolean => {
925
905
  if (!controlConfig.enabled) return false;
926
906
  const idleState = deriveActivityState({
@@ -974,7 +954,7 @@ async function runSingleAttempt(
974
954
  const fireUpdate = () => {
975
955
  if (!options.onUpdate || processClosed) return;
976
956
  progress.durationMs = Date.now() - startTime;
977
- const output = (result.timedOut || result.turnBudgetExceeded) && result.finalOutput ? result.finalOutput : getFinalOutput(result.messages ?? []);
957
+ const output = result.timedOut && result.finalOutput ? result.finalOutput : getFinalOutput(result.messages ?? []);
978
958
  emitUpdateSnapshot(output || "(running...)");
979
959
  };
980
960
 
@@ -994,8 +974,21 @@ async function runSingleAttempt(
994
974
  }
995
975
  shared.transcriptWriter?.writeChildEvent(evt);
996
976
  shared.orcaProgressTab?.event(evt);
997
- if (evt.type === "agent_settled") agentSettledReceived = true;
998
- applyChildLifecycle(projectChildLifecycle(evt));
977
+ if (evt.type === "compaction_start") compactionStartedReceived = true;
978
+ if (evt.type === "compaction_end" && evt.willRetry === true) {
979
+ compactionStartedReceived = false;
980
+ afterCompactionSettlement = false;
981
+ }
982
+ if (evt.type === "agent_start" || evt.type === "auto_retry_start") {
983
+ compactionStartedReceived = false;
984
+ afterCompactionSettlement = false;
985
+ }
986
+ const lifecycleAction = projectChildLifecycle(evt, false, childLifecycleState);
987
+ if (evt.type === "agent_settled" && lifecycleAction === "start-drain") {
988
+ agentSettledReceived = true;
989
+ afterCompactionSettlement = compactionStartedReceived;
990
+ }
991
+ applyChildLifecycle(lifecycleAction);
999
992
 
1000
993
  if (isChildWatchdogStatusEvent(evt)) {
1001
994
  if (!childWatchdog) return;
@@ -1041,7 +1034,7 @@ async function runSingleAttempt(
1041
1034
  if (options.toolBudget) {
1042
1035
  result.toolBudget = toolBudgetState(options.toolBudget, progress.toolCount);
1043
1036
  }
1044
- const mutates = isMutatingTool(evt.toolName, toolArgs);
1037
+ const mutates = isMutatingTool(evt.toolName, toolArgs, agent.mutationTools);
1045
1038
  observedMutationAttempt = observedMutationAttempt || mutates;
1046
1039
  pendingToolResult = { tool: evt.toolName ?? "tool", path: activeTool?.path, mutates, startedAt: now };
1047
1040
  fireUpdate();
@@ -1066,18 +1059,14 @@ async function runSingleAttempt(
1066
1059
  if (evt.message.role === "assistant") {
1067
1060
  result.usage.turns++;
1068
1061
  progress.turnCount = result.usage.turns;
1069
- const stopReason = (evt.message as { stopReason?: string }).stopReason;
1070
1062
  const toolCalls = Array.isArray(evt.message.content)
1071
1063
  ? evt.message.content.filter((part) => (part as { type?: string }).type === "toolCall")
1072
1064
  : [];
1073
1065
  const hasToolCall = toolCalls.length > 0;
1074
- const terminalAssistantStop = stopReason === "stop" && !hasToolCall;
1075
- const terminalStructuredOutputCall = Boolean(options.structuredOutput)
1076
- && toolCalls.length === 1
1077
- && (toolCalls[0] as { name?: string }).name === "structured_output";
1078
- updateTurnBudget(result.usage.turns, terminalAssistantStop || terminalStructuredOutputCall, hasToolCall || Boolean(progress.currentTool));
1066
+ const terminalAssistantStop = (evt.message as { stopReason?: string }).stopReason === "stop" && !hasToolCall;
1079
1067
  const u = evt.message.usage;
1080
1068
  if (u) {
1069
+ const window = (u.input || 0) + (u.cacheRead || 0);
1081
1070
  result.usage.input += u.input || 0;
1082
1071
  result.usage.output += u.output || 0;
1083
1072
  result.usage.cacheRead += u.cacheRead || 0;
@@ -1086,6 +1075,8 @@ async function runSingleAttempt(
1086
1075
  progress.tokens = result.usage.input + result.usage.output;
1087
1076
  progress.inputTokens = result.usage.input;
1088
1077
  progress.outputTokens = result.usage.output;
1078
+ progress.window = window;
1079
+ progress.windowPeak = Math.max(progress.windowPeak ?? 0, window);
1089
1080
  }
1090
1081
  if (evt.message.model) {
1091
1082
  progress.model = evt.message.model;
@@ -1102,7 +1093,11 @@ async function runSingleAttempt(
1102
1093
  if (terminalAssistantStop) {
1103
1094
  if (!evt.message.errorMessage && assistantText.trim()) assistantError = undefined;
1104
1095
  cleanTerminalAssistantStopReceived ||= !evt.message.errorMessage;
1105
- applyChildLifecycle(projectChildLifecycle(evt, true));
1096
+ clearAllToolTimeouts();
1097
+ activeToolCalls.clear();
1098
+ activeToolKeysByName.clear();
1099
+ refreshCurrentTool();
1100
+ applyChildLifecycle(projectChildLifecycle(evt, true, childLifecycleState));
1106
1101
  }
1107
1102
  }
1108
1103
  updateActivityState(now);
@@ -1328,14 +1323,17 @@ async function runSingleAttempt(
1328
1323
  const rawStdout = rawStdoutTail.text();
1329
1324
  let closeError = result.error ?? toolDiagnosticError ?? assistantError;
1330
1325
  const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !closeError;
1326
+ const forcedDrainAfterEmptyTerminal = forcedDrainAfterFinalSuccess && hasEmptyTerminalAssistantResponse(result.messages ?? []);
1331
1327
  if (signal) result.processSignal = signal;
1328
+ if (!closeError && forcedDrainAfterEmptyTerminal && stderr.trim()) {
1329
+ closeError = stderr.trim();
1330
+ }
1332
1331
  if (!closeError && isUnexplainedProcessSignal({
1333
1332
  processSignal: signal,
1334
1333
  interrupted: result.interrupted,
1335
1334
  timedOut: result.timedOut,
1336
1335
  stopped: result.stopped,
1337
- turnBudgetExceeded: result.turnBudgetExceeded,
1338
- forcedDrainAfterFinalSuccess,
1336
+ forcedDrainAfterFinalSuccess: forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal,
1339
1337
  })) {
1340
1338
  closeError = formatProcessSignalError(signal!);
1341
1339
  }
@@ -1345,7 +1343,7 @@ async function runSingleAttempt(
1345
1343
  if (code !== 0 && stderr.trim() && !closeError && !forcedDrainAfterFinalSuccess) {
1346
1344
  closeError = stderr.trim();
1347
1345
  }
1348
- const finalCode = forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (code ?? 1) : (code ?? 0);
1346
+ const finalCode = forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal ? 0 : forcedTerminationSignal || signal ? (code ?? 1) : (code ?? 0);
1349
1347
  if (!result.error && closeError) result.error = closeError;
1350
1348
  finish(finalCode);
1351
1349
  });
@@ -1369,6 +1367,7 @@ async function runSingleAttempt(
1369
1367
  if (options.signal) {
1370
1368
  const kill = () => {
1371
1369
  if (processClosed || lifecycleFinished) return;
1370
+ abortedBySignal = true;
1372
1371
  proc.kill("SIGTERM");
1373
1372
  setTimeout(() => !proc.killed && proc.kill("SIGKILL"), 3000);
1374
1373
  };
@@ -1416,6 +1415,9 @@ async function runSingleAttempt(
1416
1415
  }
1417
1416
  });
1418
1417
  result.exitCode = exitCode;
1418
+ if (afterCompactionSettlement) {
1419
+ (result as AbortRecoverySingleResult)[AFTER_COMPACTION_SETTLEMENT] = true;
1420
+ }
1419
1421
  if (interruptedByControl) {
1420
1422
  result.exitCode = 0;
1421
1423
  result.interrupted = true;
@@ -1431,6 +1433,21 @@ async function runSingleAttempt(
1431
1433
  };
1432
1434
  return result;
1433
1435
  }
1436
+ if (progress.currentTool
1437
+ && isOrdinaryToolForMidToolExit(progress.currentTool)
1438
+ && !abortedBySignal
1439
+ && !result.timedOut
1440
+ && !result.stopped
1441
+ && !result.protocolError
1442
+ && !toolAvailabilityError) {
1443
+ const processExitCode = result.exitCode;
1444
+ result.exitCode = 1;
1445
+ result.error = formatMidToolExitError({
1446
+ toolName: progress.currentTool,
1447
+ exitCode: processExitCode,
1448
+ processSignal: result.processSignal,
1449
+ });
1450
+ }
1434
1451
  result.error = formatSubagentExtensionConflictError(result.error, {
1435
1452
  agent: agent.name,
1436
1453
  ambientExtensionsEnabled: !launchResolvedExtensions.disableAmbientExtensions,
@@ -1473,9 +1490,12 @@ async function runSingleAttempt(
1473
1490
  : messages;
1474
1491
  const errInfo = detectSubagentError(errorMessages);
1475
1492
  const missingOutput = !finalText?.trim() && !validatedStructuredOutput;
1476
- if (missingOutput && (!errInfo.hasError || hasEmptyTerminalAssistantResponse(messages))) {
1493
+ const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
1494
+ && hasEmptyTerminalAssistantResponse(messages)
1495
+ && (progress.toolCount > 0 || Boolean(finalText?.trim()));
1496
+ if ((missingOutput || terminalEmptyAfterUsefulWork) && (!errInfo.hasError || hasEmptyTerminalAssistantResponse(messages))) {
1477
1497
  result.exitCode = 1;
1478
- result.error = "Subagent produced no output (possible model cold-start or empty response).";
1498
+ result.error = formatEmptyTerminalAssistantResponseError(messages);
1479
1499
  } else if (errInfo.hasError) {
1480
1500
  result.exitCode = errInfo.exitCode ?? 1;
1481
1501
  result.error = errInfo.details
@@ -1494,6 +1514,7 @@ async function runSingleAttempt(
1494
1514
  }
1495
1515
 
1496
1516
  result.progressSummary = {
1517
+ ...(childSessionName ? { sessionName: childSessionName } : {}),
1497
1518
  toolCount: progress.toolCount,
1498
1519
  tokens: progress.tokens,
1499
1520
  durationMs: progress.durationMs,
@@ -1519,14 +1540,6 @@ async function runSingleAttempt(
1519
1540
  fullOutput = fullOutput.trim()
1520
1541
  ? `${timeoutMessage}\n\n${result.timeoutRecovery.message}\n\nPartial output before timeout:\n${fullOutput}`
1521
1542
  : `${timeoutMessage}\n\n${result.timeoutRecovery.message}`;
1522
- } else if (result.turnBudgetExceeded && result.turnBudget) {
1523
- fullOutput = formatTurnBudgetOutput(turnBudgetExceededMessage(result.turnBudget, result.turnBudget.turnCount), fullOutput);
1524
- } else if (result.turnBudget?.outcome === "termination-deferred") {
1525
- const note = turnBudgetDeferredNote(result.turnBudget, result.turnBudget.terminationDeferredAtTurn ?? result.turnBudget.turnCount);
1526
- fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
1527
- } else if (result.wrapUpRequested && result.turnBudget?.outcome === "wrap-up-requested") {
1528
- const note = turnBudgetSoftNote(result.turnBudget, result.turnBudget.wrapUpRequestedAtTurn ?? result.turnBudget.turnCount);
1529
- fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
1530
1543
  }
1531
1544
  const completionGuardEnabled = isAgentContractV1(options.agentContract) ? agent.completionGuard === true : agent.completionGuard !== false;
1532
1545
  const completionGuard = ((result.exitCode === 0 && !result.error) || toolAvailabilityError) && completionGuardEnabled
@@ -1536,13 +1549,13 @@ async function runSingleAttempt(
1536
1549
  messages: result.messages ?? [],
1537
1550
  tools: contractTools,
1538
1551
  mcpDirectTools: toolPlan.effectiveMcpTools,
1552
+ mutationTools: agent.mutationTools,
1539
1553
  toolAvailabilityError,
1540
1554
  mutationEvidence,
1541
1555
  })
1542
1556
  : undefined;
1543
1557
  const mutationAttemptObserved = observedMutationAttempt || mutationEvidence.attemptedMutation;
1544
1558
  let completionGuardTriggered = completionGuard?.triggered === true && !mutationAttemptObserved;
1545
- const completionGuardBlocked = completionGuard?.blocked === true;
1546
1559
  // The classifier is deliberately narrow, so a read-only review task can
1547
1560
  // still be misread as implementation. Arbitrate BEFORE any failure side
1548
1561
  // effect is published (effects, exit code, progress, notifications,
@@ -1559,31 +1572,26 @@ async function runSingleAttempt(
1559
1572
  completionGuardTriggered = arbitration.triggered;
1560
1573
  arbiterRescued = arbitration.rescued;
1561
1574
  }
1562
- if (completionGuard) {
1575
+ const completionEvidence = planCompletionEvidence({
1576
+ guard: completionGuard,
1577
+ guardTriggered: completionGuardTriggered,
1578
+ completionGuardEnabled,
1579
+ mutationCapable: hasMutationToolCapability(contractTools, toolPlan.effectiveMcpTools),
1580
+ implementationMutationExpected: expectsImplementationMutation(agent.name, shared.originalTask ?? task),
1581
+ mutationAttemptObserved,
1582
+ mutationEvidence,
1583
+ arbiterRescued,
1584
+ agentContractV1: isAgentContractV1(options.agentContract),
1585
+ });
1586
+ if (completionEvidence.fileMutation) {
1563
1587
  result.effects = {
1564
1588
  ...(result.effects ?? {}),
1565
- fileMutation: {
1566
- status: completionGuardBlocked
1567
- ? "blocked"
1568
- : completionGuard.expectedMutation
1569
- ? completionGuardTriggered
1570
- ? "missing"
1571
- : arbiterRescued
1572
- ? "not-applicable"
1573
- : "observed"
1574
- : "not-applicable",
1575
- expected: completionGuard.expectedMutation,
1576
- attempted: completionGuardBlocked ? false : completionGuard.attemptedMutation || mutationAttemptObserved,
1577
- evidence: mutationEvidence,
1578
- ...(completionGuardBlocked && completionGuard.message ? { message: completionGuard.message } : {}),
1579
- ...(completionGuardTriggered ? { message: "Subagent completed without making edits for an implementation task." } : {}),
1580
- ...(arbiterRescued ? { resolvedBy: "llm-intent-arbiter" } : {}),
1581
- },
1589
+ fileMutation: completionEvidence.fileMutation,
1582
1590
  };
1583
1591
  }
1584
- if (completionGuardTriggered && !isAgentContractV1(options.agentContract)) {
1592
+ if (completionEvidence.legacyFailureError) {
1585
1593
  result.exitCode = 1;
1586
- result.error = "Subagent completed without making edits for an implementation task.\nIt appears to have returned planning or scratchpad output instead of applying changes.";
1594
+ result.error = completionEvidence.legacyFailureError;
1587
1595
  progress.status = "failed";
1588
1596
  progress.error = result.error;
1589
1597
  emitControlEvent(buildControlEvent({
@@ -1598,10 +1606,14 @@ async function runSingleAttempt(
1598
1606
  }));
1599
1607
  }
1600
1608
  if (options.outputPath && result.exitCode === 0) {
1601
- const resolvedOutput = resolveSingleOutput(options.outputPath, fullOutput, shared.outputSnapshot);
1609
+ const resolvedOutput = resolveSingleOutput(options.outputPath, fullOutput, shared.outputSnapshot, options.outputClaimPath);
1602
1610
  fullOutput = stripAcceptanceReport(resolvedOutput.fullOutput);
1603
1611
  result.savedOutputPath = resolvedOutput.savedPath;
1604
1612
  result.outputSaveError = resolvedOutput.saveError;
1613
+ if (resolvedOutput.fatalError) {
1614
+ result.exitCode = 1;
1615
+ result.error = result.error ? `${result.error}\n${resolvedOutput.saveError}` : resolvedOutput.saveError;
1616
+ }
1605
1617
  if (resolvedOutput.savedPath) {
1606
1618
  result.outputReference = formatSavedOutputReference(resolvedOutput.savedPath, fullOutput);
1607
1619
  if (result.outputState === "absent") result.outputState = "unknown";
@@ -1641,12 +1653,28 @@ async function runSyncCompletionInner(
1641
1653
  task: string,
1642
1654
  options: RunSyncOptions,
1643
1655
  ): Promise<SingleResult> {
1656
+ const effectiveCwd = options.cwd ?? runtimeCwd;
1657
+ const cwdError = preflightLaunchCwd(options.requestedCwd ?? effectiveCwd, effectiveCwd);
1658
+ if (cwdError) {
1659
+ return redactResultPrompt(withRunContext({
1660
+ index: options.index ?? 0,
1661
+ agent: agentName,
1662
+ task,
1663
+ exitCode: 1,
1664
+ messages: [],
1665
+ usage: emptyUsage(),
1666
+ error: cwdError,
1667
+ }, options.context));
1668
+ }
1644
1669
  options = {
1645
1670
  ...options,
1646
1671
  capabilityCeiling: intersectSubagentCapabilityCeilings(options.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(options.parentSessionId), decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV])),
1647
1672
  };
1673
+ const childSessionName = deriveChildSessionName({ agent: agentName, task });
1648
1674
  const agent = agents.find((a) => a.name === agentName);
1649
1675
  if (!agent) {
1676
+ const diagnosticContext = options.unknownAgentDiagnosticContext
1677
+ ?? unknownAgentDiagnosticContext(discoverAgents(path.resolve(options.cwd ?? runtimeCwd), "both"));
1650
1678
  return redactResultPrompt(withRunContext({
1651
1679
  index: options.index ?? 0,
1652
1680
  agent: agentName,
@@ -1654,7 +1682,7 @@ async function runSyncCompletionInner(
1654
1682
  exitCode: 1,
1655
1683
  messages: [],
1656
1684
  usage: emptyUsage(),
1657
- error: `Unknown agent: ${agentName}`,
1685
+ error: formatUnknownAgentError(agentName, diagnosticContext),
1658
1686
  }, options.context));
1659
1687
  }
1660
1688
  options = {
@@ -1781,6 +1809,18 @@ async function runSyncCompletionInner(
1781
1809
  agent.modelProvider ?? options.preferredModelProvider,
1782
1810
  { scope: options.modelScope, primaryModelFromParent: options.modelOverrideFromParent },
1783
1811
  );
1812
+ if (options.workflowChildPermitLaunch && candidates.length > 1) {
1813
+ const error = "Workflow child permit does not support model fallback.";
1814
+ return redactResultPrompt(withRunContext({
1815
+ index: options.index ?? 0,
1816
+ agent: agent.name,
1817
+ task,
1818
+ exitCode: 1,
1819
+ messages: [],
1820
+ usage: emptyUsage(),
1821
+ error,
1822
+ }, options.context));
1823
+ }
1784
1824
  try {
1785
1825
  for (const candidate of candidates) {
1786
1826
  const model = applyThinkingSuffix(candidate, options.thinkingOverride ?? agent.thinking, options.thinkingOverride !== undefined);
@@ -1873,12 +1913,16 @@ async function runSyncCompletionInner(
1873
1913
  // Escalated to "file" after an unexplained zero-activity startup failure so
1874
1914
  // retries keep the task text out of argv (endpoint pre-exec scans may deny it).
1875
1915
  let taskDeliveryOverride: SubagentTaskDelivery | undefined;
1916
+ let abortRecoveryAttempted = false;
1917
+ let nextAttemptTask = taskWithAcceptance;
1876
1918
  modelAttemptsLoop: for (let modelIndex = 0; modelIndex < modelsToTry.length; modelIndex++) {
1877
1919
  const candidate = modelsToTry[modelIndex];
1878
1920
  for (let startupAttemptIndex = 0; ; startupAttemptIndex++) {
1921
+ const recoveringAbort = abortRecoveryAttempted;
1922
+ const attemptTask = nextAttemptTask;
1879
1923
  const verifyModel = Boolean(candidate) && !(options.modelOverrideFromParent && modelIndex === 0);
1880
1924
  const outputSnapshot = captureSingleOutputSnapshot(options.outputPath);
1881
- const result = await runSingleAttempt(runtimeCwd, agent, taskWithAcceptance, candidate, attemptOptions, {
1925
+ const result = await runSingleAttempt(runtimeCwd, agent, attemptTask, candidate, attemptOptions, {
1882
1926
  sessionEnabled,
1883
1927
  systemPrompt,
1884
1928
  resolvedSkillNames: resolvedSkills.length > 0 ? resolvedSkills.map((skill) => skill.name) : undefined,
@@ -1898,7 +1942,7 @@ async function runSyncCompletionInner(
1898
1942
  verifyModel,
1899
1943
  });
1900
1944
  lastResult = result;
1901
- if (startupAttemptIndex === 0) {
1945
+ if (!recoveringAbort && startupAttemptIndex === 0) {
1902
1946
  if (result.model) attemptedModels.push(result.model);
1903
1947
  else if (candidate) attemptedModels.push(candidate);
1904
1948
  }
@@ -1914,10 +1958,42 @@ async function runSyncCompletionInner(
1914
1958
  usage: { ...result.usage },
1915
1959
  };
1916
1960
  modelAttempts.push(attempt);
1961
+ if (!attemptSucceeded) {
1962
+ const afterCompactionSettlement = (result as AbortRecoverySingleResult)[AFTER_COMPACTION_SETTLEMENT];
1963
+ const abortRecovery = planAbortRecovery({
1964
+ messages: result.messages ?? [],
1965
+ error: result.error,
1966
+ processSignal: result.processSignal,
1967
+ sessionAvailable: Boolean(options.sessionFile && existsSync(options.sessionFile)),
1968
+ alreadyResumed: abortRecoveryAttempted,
1969
+ stopped: result.stopped || result.detached || options.signal?.aborted,
1970
+ interrupted: result.interrupted || intercomDetached || options.interruptSignal?.aborted,
1971
+ timedOut: result.timedOut,
1972
+ toolBudgetExhausted: result.toolBudgetBlocked,
1973
+ usageBudgetExhausted: false,
1974
+ structuredOutputFailed: result.structuredOutputFailed,
1975
+ acceptanceFailed: false,
1976
+ currentTool: result.progress?.currentTool,
1977
+ afterCompactionSettlement,
1978
+ });
1979
+ if (abortRecovery.action === "resume") {
1980
+ abortRecoveryAttempted = true;
1981
+ nextAttemptTask = abortRecovery.prompt;
1982
+ attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
1983
+ continue;
1984
+ }
1985
+ if (abortRecovery.diagnostic) {
1986
+ result.error = result.error ? `${result.error}\n${abortRecovery.diagnostic}` : abortRecovery.diagnostic;
1987
+ attempt.error = result.error;
1988
+ break modelAttemptsLoop;
1989
+ }
1990
+ }
1991
+ if (recoveringAbort && !attemptSucceeded) break modelAttemptsLoop;
1992
+ if (options.workflowChildPermitLaunch && !attemptSucceeded) break modelAttemptsLoop;
1917
1993
  // Preserve the legacy intercom handoff contract: once this logical run has
1918
1994
  // been handed to a supervisor, terminating that attempt must not launch a
1919
1995
  // startup retry or model fallback. Explicit user detach retains fallback.
1920
- if (intercomDetached || result.timedOut || result.turnBudgetExceeded) break modelAttemptsLoop;
1996
+ if (intercomDetached || result.timedOut) break modelAttemptsLoop;
1921
1997
  if (attemptSucceeded) break modelAttemptsLoop;
1922
1998
 
1923
1999
  const startupFailure = isRetryableSubagentStartupFailure({
@@ -1934,7 +2010,6 @@ async function runSyncCompletionInner(
1934
2010
  interrupted: result.interrupted,
1935
2011
  timedOut: result.timedOut,
1936
2012
  stopped: result.stopped,
1937
- turnBudgetExceeded: result.turnBudgetExceeded,
1938
2013
  });
1939
2014
  const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
1940
2015
  if (startupFailure && retryDelayMs !== undefined) {
@@ -1986,7 +2061,7 @@ async function runSyncCompletionInner(
1986
2061
  attempt.error = startupError;
1987
2062
  break modelAttemptsLoop;
1988
2063
  }
1989
- const retryableModelFailure = isRetryableModelFailure(result.error);
2064
+ const retryableModelFailure = isRetryableModelFailureAttempt({ error: result.error, messages: result.messages, toolCount: result.progressSummary?.toolCount });
1990
2065
  if (retryableModelFailure) recordRetryableModelFailure(result.model ?? candidate, result.error);
1991
2066
  if (isContextOverflow(result.error)) {
1992
2067
  result.contextOverflow = true;
@@ -2008,11 +2083,13 @@ async function runSyncCompletionInner(
2008
2083
  usage: emptyUsage(),
2009
2084
  error: "Subagent did not produce a result.",
2010
2085
  } satisfies SingleResult, options.context);
2086
+ result.task = task;
2011
2087
 
2012
2088
  result.usage = aggregateUsage;
2013
2089
  result.attemptedModels = attemptedModels.length > 0 ? attemptedModels : undefined;
2014
2090
  result.modelAttempts = modelAttempts.length > 0 ? modelAttempts : undefined;
2015
2091
  result.progressSummary = {
2092
+ ...(childSessionName ? { sessionName: childSessionName } : {}),
2016
2093
  toolCount: totalToolCount,
2017
2094
  tokens: aggregateUsage.input + aggregateUsage.output,
2018
2095
  durationMs: totalDurationMs,
@@ -2066,8 +2143,6 @@ async function runSyncCompletionInner(
2066
2143
  result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "stopped", message: "Acceptance was not evaluated because the subagent was stopped." });
2067
2144
  } else if (result.timedOut) {
2068
2145
  result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "timeout", message: "Acceptance was not evaluated because the subagent timed out." });
2069
- } else if (result.turnBudgetExceeded) {
2070
- result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "turn-budget", message: "Acceptance was not evaluated because the subagent exceeded its turn budget." });
2071
2146
  } else {
2072
2147
  result.acceptance = await evaluateAcceptance({
2073
2148
  acceptance: effectiveAcceptance,