pi-subagents 0.74.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/docs/agents.md +15 -5
  3. package/docs/configuration.md +14 -2
  4. package/docs/extension-api.md +2 -2
  5. package/docs/missions.md +27 -3
  6. package/docs/models.md +6 -2
  7. package/docs/observability.md +8 -3
  8. package/docs/tool-reference.md +48 -8
  9. package/docs/workflows.md +3 -3
  10. package/package.json +2 -1
  11. package/src/agents/agent-memory.js +3 -3
  12. package/src/agents/agent-memory.js.map +1 -1
  13. package/src/agents/agent-serializer.d.ts.map +1 -1
  14. package/src/agents/agent-serializer.js +8 -1
  15. package/src/agents/agent-serializer.js.map +1 -1
  16. package/src/agents/agents.d.ts +1 -0
  17. package/src/agents/agents.d.ts.map +1 -1
  18. package/src/agents/agents.js +137 -95
  19. package/src/agents/agents.js.map +1 -1
  20. package/src/api/preflight.d.ts +1 -1
  21. package/src/api/preflight.d.ts.map +1 -1
  22. package/src/api/preflight.js +44 -1
  23. package/src/api/preflight.js.map +1 -1
  24. package/src/extension/config.d.ts.map +1 -1
  25. package/src/extension/config.js +4 -1
  26. package/src/extension/config.js.map +1 -1
  27. package/src/extension/index.d.ts.map +1 -1
  28. package/src/extension/index.js +62 -22
  29. package/src/extension/index.js.map +1 -1
  30. package/src/extension/public-execution.d.ts.map +1 -1
  31. package/src/extension/public-execution.js +4 -0
  32. package/src/extension/public-execution.js.map +1 -1
  33. package/src/extension/reply-workflow-script.d.ts.map +1 -1
  34. package/src/extension/reply-workflow-script.js +21 -12
  35. package/src/extension/reply-workflow-script.js.map +1 -1
  36. package/src/extension/rpc.js +1 -1
  37. package/src/extension/rpc.js.map +1 -1
  38. package/src/extension/schemas.d.ts +2 -1
  39. package/src/extension/schemas.d.ts.map +1 -1
  40. package/src/extension/schemas.js +13 -11
  41. package/src/extension/schemas.js.map +1 -1
  42. package/src/extension/tool-description.js +2 -2
  43. package/src/extension/tool-description.js.map +1 -1
  44. package/src/intercom/result-intercom.d.ts.map +1 -1
  45. package/src/intercom/result-intercom.js +2 -1
  46. package/src/intercom/result-intercom.js.map +1 -1
  47. package/src/missions/goal-driver.d.ts +1 -0
  48. package/src/missions/goal-driver.d.ts.map +1 -1
  49. package/src/missions/goal-driver.js +49 -34
  50. package/src/missions/goal-driver.js.map +1 -1
  51. package/src/missions/store.d.ts.map +1 -1
  52. package/src/missions/store.js +11 -1
  53. package/src/missions/store.js.map +1 -1
  54. package/src/profiles/profiles.d.ts +1 -1
  55. package/src/profiles/profiles.d.ts.map +1 -1
  56. package/src/profiles/profiles.js +29 -22
  57. package/src/profiles/profiles.js.map +1 -1
  58. package/src/runs/background/active-async-capacity.d.ts +15 -1
  59. package/src/runs/background/active-async-capacity.d.ts.map +1 -1
  60. package/src/runs/background/active-async-capacity.js +51 -6
  61. package/src/runs/background/active-async-capacity.js.map +1 -1
  62. package/src/runs/background/async-execution.d.ts +13 -0
  63. package/src/runs/background/async-execution.d.ts.map +1 -1
  64. package/src/runs/background/async-execution.js +89 -6
  65. package/src/runs/background/async-execution.js.map +1 -1
  66. package/src/runs/background/async-job-tracker.d.ts +4 -2
  67. package/src/runs/background/async-job-tracker.d.ts.map +1 -1
  68. package/src/runs/background/async-job-tracker.js +4 -3
  69. package/src/runs/background/async-job-tracker.js.map +1 -1
  70. package/src/runs/background/await-async-run.d.ts.map +1 -1
  71. package/src/runs/background/await-async-run.js +4 -2
  72. package/src/runs/background/await-async-run.js.map +1 -1
  73. package/src/runs/background/calendar-schedule.d.ts +27 -0
  74. package/src/runs/background/calendar-schedule.d.ts.map +1 -0
  75. package/src/runs/background/calendar-schedule.js +94 -0
  76. package/src/runs/background/calendar-schedule.js.map +1 -0
  77. package/src/runs/background/control-channel.d.ts +10 -0
  78. package/src/runs/background/control-channel.d.ts.map +1 -1
  79. package/src/runs/background/control-channel.js +51 -0
  80. package/src/runs/background/control-channel.js.map +1 -1
  81. package/src/runs/background/notify.d.ts +6 -0
  82. package/src/runs/background/notify.d.ts.map +1 -1
  83. package/src/runs/background/notify.js +24 -4
  84. package/src/runs/background/notify.js.map +1 -1
  85. package/src/runs/background/result-watcher.d.ts +5 -1
  86. package/src/runs/background/result-watcher.d.ts.map +1 -1
  87. package/src/runs/background/result-watcher.js +44 -7
  88. package/src/runs/background/result-watcher.js.map +1 -1
  89. package/src/runs/background/run-child-session.d.ts +2 -0
  90. package/src/runs/background/run-child-session.d.ts.map +1 -1
  91. package/src/runs/background/run-child-session.js +32 -7
  92. package/src/runs/background/run-child-session.js.map +1 -1
  93. package/src/runs/background/runner-aliases.d.ts +1 -0
  94. package/src/runs/background/runner-aliases.d.ts.map +1 -1
  95. package/src/runs/background/runner-aliases.js +6 -2
  96. package/src/runs/background/runner-aliases.js.map +1 -1
  97. package/src/runs/background/scheduled-runs.d.ts +5 -2
  98. package/src/runs/background/scheduled-runs.d.ts.map +1 -1
  99. package/src/runs/background/scheduled-runs.js +210 -56
  100. package/src/runs/background/scheduled-runs.js.map +1 -1
  101. package/src/runs/background/stale-run-reconciler.d.ts +1 -1
  102. package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
  103. package/src/runs/background/stale-run-reconciler.js +15 -2
  104. package/src/runs/background/stale-run-reconciler.js.map +1 -1
  105. package/src/runs/background/subagent-runner.d.ts +1 -0
  106. package/src/runs/background/subagent-runner.d.ts.map +1 -1
  107. package/src/runs/background/subagent-runner.js +58 -9
  108. package/src/runs/background/subagent-runner.js.map +1 -1
  109. package/src/runs/background/wait-completions.d.ts.map +1 -1
  110. package/src/runs/background/wait-completions.js +1 -0
  111. package/src/runs/background/wait-completions.js.map +1 -1
  112. package/src/runs/background/workflow-terminal-proof.d.ts +14 -1
  113. package/src/runs/background/workflow-terminal-proof.d.ts.map +1 -1
  114. package/src/runs/background/workflow-terminal-proof.js +41 -28
  115. package/src/runs/background/workflow-terminal-proof.js.map +1 -1
  116. package/src/runs/foreground/command-action.d.ts +13 -0
  117. package/src/runs/foreground/command-action.d.ts.map +1 -0
  118. package/src/runs/foreground/command-action.js +38 -0
  119. package/src/runs/foreground/command-action.js.map +1 -0
  120. package/src/runs/foreground/execution.d.ts.map +1 -1
  121. package/src/runs/foreground/execution.js +42 -8
  122. package/src/runs/foreground/execution.js.map +1 -1
  123. package/src/runs/foreground/foreground-history.d.ts.map +1 -1
  124. package/src/runs/foreground/foreground-history.js +1 -0
  125. package/src/runs/foreground/foreground-history.js.map +1 -1
  126. package/src/runs/foreground/subagent-executor.d.ts +2 -1
  127. package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  128. package/src/runs/foreground/subagent-executor.js +108 -17
  129. package/src/runs/foreground/subagent-executor.js.map +1 -1
  130. package/src/runs/shared/child-commands.d.ts +28 -0
  131. package/src/runs/shared/child-commands.d.ts.map +1 -0
  132. package/src/runs/shared/child-commands.js +250 -0
  133. package/src/runs/shared/child-commands.js.map +1 -0
  134. package/src/runs/shared/child-session.d.ts +4 -0
  135. package/src/runs/shared/child-session.d.ts.map +1 -1
  136. package/src/runs/shared/child-session.js +107 -22
  137. package/src/runs/shared/child-session.js.map +1 -1
  138. package/src/runs/shared/child-tool-plan.js +1 -1
  139. package/src/runs/shared/child-tool-plan.js.map +1 -1
  140. package/src/runs/shared/claude-code-adapter.d.ts +56 -0
  141. package/src/runs/shared/claude-code-adapter.d.ts.map +1 -1
  142. package/src/runs/shared/claude-code-adapter.js +138 -2
  143. package/src/runs/shared/claude-code-adapter.js.map +1 -1
  144. package/src/runs/shared/dynamic-fanout.js +1 -1
  145. package/src/runs/shared/dynamic-fanout.js.map +1 -1
  146. package/src/runs/shared/external-cli-preflight.d.ts +10 -0
  147. package/src/runs/shared/external-cli-preflight.d.ts.map +1 -1
  148. package/src/runs/shared/external-cli-preflight.js +50 -6
  149. package/src/runs/shared/external-cli-preflight.js.map +1 -1
  150. package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
  151. package/src/runs/shared/external-cli-runner.js +4 -2
  152. package/src/runs/shared/external-cli-runner.js.map +1 -1
  153. package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
  154. package/src/runs/shared/mcp-direct-tool-allowlist.js +8 -5
  155. package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
  156. package/src/runs/shared/model-resolution.d.ts +6 -2
  157. package/src/runs/shared/model-resolution.d.ts.map +1 -1
  158. package/src/runs/shared/model-resolution.js +9 -2
  159. package/src/runs/shared/model-resolution.js.map +1 -1
  160. package/src/runs/shared/parallel-handoff.d.ts +10 -4
  161. package/src/runs/shared/parallel-handoff.d.ts.map +1 -1
  162. package/src/runs/shared/parallel-handoff.js +53 -6
  163. package/src/runs/shared/parallel-handoff.js.map +1 -1
  164. package/src/runs/shared/parallel-utils.d.ts +2 -0
  165. package/src/runs/shared/parallel-utils.d.ts.map +1 -1
  166. package/src/runs/shared/parallel-utils.js.map +1 -1
  167. package/src/runs/shared/partial-output.d.ts +18 -0
  168. package/src/runs/shared/partial-output.d.ts.map +1 -0
  169. package/src/runs/shared/partial-output.js +29 -0
  170. package/src/runs/shared/partial-output.js.map +1 -0
  171. package/src/runs/shared/run-history.d.ts +47 -0
  172. package/src/runs/shared/run-history.d.ts.map +1 -1
  173. package/src/runs/shared/run-history.js +70 -0
  174. package/src/runs/shared/run-history.js.map +1 -1
  175. package/src/runs/shared/subagent-control.d.ts.map +1 -1
  176. package/src/runs/shared/subagent-control.js +30 -17
  177. package/src/runs/shared/subagent-control.js.map +1 -1
  178. package/src/runs/shared/subagent-prompt-runtime.d.ts +1 -0
  179. package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  180. package/src/runs/shared/subagent-prompt-runtime.js +12 -5
  181. package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  182. package/src/runs/shared/worktree-cleanup-apply.d.ts +37 -0
  183. package/src/runs/shared/worktree-cleanup-apply.d.ts.map +1 -0
  184. package/src/runs/shared/worktree-cleanup-apply.js +179 -0
  185. package/src/runs/shared/worktree-cleanup-apply.js.map +1 -0
  186. package/src/runs/shared/worktree-cleanup-plan.d.ts +7 -0
  187. package/src/runs/shared/worktree-cleanup-plan.d.ts.map +1 -1
  188. package/src/runs/shared/worktree-cleanup-plan.js +41 -19
  189. package/src/runs/shared/worktree-cleanup-plan.js.map +1 -1
  190. package/src/runs/shared/worktree-lock.d.ts +6 -0
  191. package/src/runs/shared/worktree-lock.d.ts.map +1 -0
  192. package/src/runs/shared/worktree-lock.js +41 -0
  193. package/src/runs/shared/worktree-lock.js.map +1 -0
  194. package/src/runs/shared/worktree.d.ts +3 -0
  195. package/src/runs/shared/worktree.d.ts.map +1 -1
  196. package/src/runs/shared/worktree.js +9 -1
  197. package/src/runs/shared/worktree.js.map +1 -1
  198. package/src/shared/file-lease.d.ts +5 -0
  199. package/src/shared/file-lease.d.ts.map +1 -0
  200. package/src/shared/file-lease.js +101 -0
  201. package/src/shared/file-lease.js.map +1 -0
  202. package/src/shared/required-child-extensions.d.ts +16 -1
  203. package/src/shared/required-child-extensions.d.ts.map +1 -1
  204. package/src/shared/required-child-extensions.js +37 -5
  205. package/src/shared/required-child-extensions.js.map +1 -1
  206. package/src/shared/settings-file-lease.d.ts +5 -0
  207. package/src/shared/settings-file-lease.d.ts.map +1 -0
  208. package/src/shared/settings-file-lease.js +39 -0
  209. package/src/shared/settings-file-lease.js.map +1 -0
  210. package/src/shared/types.d.ts +16 -1
  211. package/src/shared/types.d.ts.map +1 -1
  212. package/src/shared/types.js +1 -1
  213. package/src/shared/types.js.map +1 -1
  214. package/src/slash/subagent-cost.d.ts.map +1 -1
  215. package/src/slash/subagent-cost.js +8 -4
  216. package/src/slash/subagent-cost.js.map +1 -1
  217. package/src/tui/render.d.ts +1 -1
  218. package/src/tui/render.d.ts.map +1 -1
  219. package/src/tui/render.js +11 -6
  220. package/src/tui/render.js.map +1 -1
  221. package/src/watchdog/diff-tool.js +2 -2
  222. package/src/watchdog/diff-tool.js.map +1 -1
  223. package/src/watchdog/register-main.js +1 -2
  224. package/src/watchdog/register-main.js.map +1 -1
  225. package/src/watchdog/runtime.d.ts +3 -3
  226. package/src/watchdog/runtime.d.ts.map +1 -1
  227. package/src/watchdog/runtime.js +7 -3
  228. package/src/watchdog/runtime.js.map +1 -1
  229. package/src/watchdog/settings.d.ts.map +1 -1
  230. package/src/watchdog/settings.js +22 -17
  231. package/src/watchdog/settings.js.map +1 -1
  232. package/src/workflows/workflow-receipt.js +2 -2
  233. package/src/workflows/workflow-receipt.js.map +1 -1
  234. package/src/workflows/workflow-resources.d.ts +4 -0
  235. package/src/workflows/workflow-resources.d.ts.map +1 -1
  236. package/src/workflows/workflow-resources.js +7 -4
  237. package/src/workflows/workflow-resources.js.map +1 -1
@@ -50,6 +50,7 @@ import { persistRunnerStartupFailure } from "./runner-startup-failure.js";
50
50
  import { currentPidNamespaceScope } from "./pid-namespace.js";
51
51
  import { createSteeringStatus, recordSteeringRequest, steeringStatus, terminalSteeringNoticeState, unconsumedSteerReason, updateSteeringTarget } from "./steering.js";
52
52
  import { PROMPT_REDACTED, detectSubagentError, extractTextFromContent, extractToolArgsPreview, formatEmptyTerminalAssistantResponseError, getAgentDir, hasEmptyTerminalAssistantResponse, readStatus } from "../../shared/utils.js";
53
+ import { planBackgroundRunHistory, recordRun } from "../shared/run-history.js";
53
54
  import { planAbortRecovery } from "../shared/abort-recovery.js";
54
55
  import { createMutatingFailureState, didMutatingToolFail, isMutatingTool, nextLongRunningTrigger, recordMutatingFailure, resetMutatingFailureState, resolveCurrentPath, shouldEscalateMutatingFailures, summarizeRecentMutatingFailures, } from "../shared/long-running-guard.js";
55
56
  import { parseSessionTokens } from "../../shared/session-tokens.js";
@@ -618,7 +619,7 @@ export async function runSingleStepInner(step, ctx) {
618
619
  const adapterLaunch = step.runner.adapter === "codex-exec" || step.runner.adapter === "codex-exec-writer"
619
620
  ? resolveCodexExecLaunch({ adapter: step.runner.adapter, command: step.runner.command, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
620
621
  : step.runner.adapter === "claude-code" || step.runner.adapter === "claude-code-writer"
621
- ? resolveClaudeCodeLaunch({ adapter: step.runner.adapter, command: step.runner.command })
622
+ ? resolveClaudeCodeLaunch({ adapter: step.runner.adapter, command: step.runner.command, overrideArgs: step.claudeCodeOverrideArgs })
622
623
  : step.runner.adapter === "cursor-agent" || step.runner.adapter === "cursor-agent-writer"
623
624
  ? resolveCursorAgentLaunch({ adapter: step.runner.adapter, command: step.runner.command, cwd: externalCwd, asyncDir: path.dirname(ctx.outputFile), stepIndex: ctx.flatIndex })
624
625
  : undefined;
@@ -1095,12 +1096,14 @@ export async function runSingleStepInner(step, ctx) {
1095
1096
  break singleLaunch;
1096
1097
  }
1097
1098
  const rawOutput = finalResult?.finalOutput ?? "";
1098
- let outputForPersistence = stripAcceptanceReport(rawOutput);
1099
- if (!outputForPersistence.trim() && finalResult?.structuredOutput !== undefined)
1100
- outputForPersistence = JSON.stringify(finalResult.structuredOutput, null, 2);
1099
+ const structuredText = finalResult?.structuredOutput === undefined ? undefined : JSON.stringify(finalResult.structuredOutput, null, 2);
1100
+ let replyOutput = stripAcceptanceReport(rawOutput);
1101
+ if (!replyOutput.trim() && structuredText !== undefined)
1102
+ replyOutput = structuredText;
1103
+ // The schema is the caller's contract: a bound output file holds the structured result, not closing prose.
1101
1104
  const resolvedOutput = step.outputPath && finalResult?.exitCode === 0
1102
- ? resolveSingleOutput(step.outputPath, outputForPersistence, finalOutputSnapshot, step.outputClaimPath)
1103
- : { fullOutput: outputForPersistence };
1105
+ ? resolveSingleOutput(step.outputPath, structuredText ?? replyOutput, finalOutputSnapshot, step.outputClaimPath)
1106
+ : { fullOutput: replyOutput };
1104
1107
  if (resolvedOutput.fatalError) {
1105
1108
  if (finalResult) {
1106
1109
  finalResult.exitCode = 1;
@@ -1113,7 +1116,8 @@ export async function runSingleStepInner(step, ctx) {
1113
1116
  if (finalResult?.stopped && !outputForSummary.trim()) {
1114
1117
  outputForSummary = ctx.stopMessage ?? "Subagent stopped by user.";
1115
1118
  }
1116
- const outputForAcceptance = rawOutput;
1119
+ // Unfinished streamed text never stands in for the child's completed reply.
1120
+ const outputForAcceptance = finalResult?.outputPartial ? "" : rawOutput;
1117
1121
  const childWrittenOutput = step.outputPath
1118
1122
  ? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
1119
1123
  : undefined;
@@ -1243,6 +1247,7 @@ export async function runSingleStepInner(step, ctx) {
1243
1247
  launchContractDigest: actualLaunchContractDigest,
1244
1248
  output: outputForSummary,
1245
1249
  outputState,
1250
+ outputPartial: finalResult?.outputPartial,
1246
1251
  exitCode: effectiveFinalExitCode,
1247
1252
  error: effectiveFinalError,
1248
1253
  sessionFile: step.sessionFile,
@@ -1335,7 +1340,13 @@ function markParallelGroupSetupFailure(input) {
1335
1340
  throw new Error(`Missing parallel task at index ${taskIndex}`);
1336
1341
  const stopped = statusStep.stopped || statusStep.stopRequested || input.statusPayload.stopped;
1337
1342
  const paused = !stopped && input.statusPayload.state === "paused";
1343
+ const timedOut = !stopped && !paused && input.statusPayload.timedOut === true;
1338
1344
  statusStep.status = stopped ? "stopped" : paused ? "paused" : "failed";
1345
+ // Mirror the run-level timeout onto the step so consumers (status readers,
1346
+ // run-history recording) see timed_out rather than a bare failure — the
1347
+ // StepResult below already carries it, the status step must too.
1348
+ if (timedOut)
1349
+ statusStep.timedOut = true;
1339
1350
  statusStep.startedAt = input.failedAt;
1340
1351
  statusStep.endedAt = input.failedAt;
1341
1352
  statusStep.durationMs = 0;
@@ -1506,6 +1517,11 @@ export async function runSubagent(config, childSessions) {
1506
1517
  let previousOutput = "";
1507
1518
  const outputs = {};
1508
1519
  const results = [];
1520
+ // Flat indices of steps a child session was actually dispatched for — the
1521
+ // ground truth for run-history: stopRunner/timeoutRunner/fail-fast/budget
1522
+ // skips relabel never-launched steps to terminal statuses, so status alone
1523
+ // cannot distinguish them from steps that really ran.
1524
+ const launchedFlatIndices = new Set();
1509
1525
  const overallStartTime = Date.now();
1510
1526
  const shareEnabled = config.share === true;
1511
1527
  const asyncDir = config.asyncDir;
@@ -2392,7 +2408,7 @@ export async function runSubagent(config, childSessions) {
2392
2408
  return key ? removeActiveToolCallKey(flatIndex, key) : undefined;
2393
2409
  };
2394
2410
  const openToolAttentionTarget = (flatIndex, now) => [...(activeToolCalls[flatIndex]?.values() ?? [])]
2395
- .filter((active) => shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }))
2411
+ .filter((active) => !active.attentionEmitted && shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }))
2396
2412
  .sort((left, right) => left.startedAt - right.startedAt)[0];
2397
2413
  const supervisorAttentionSteps = new Map();
2398
2414
  const mutatingFailureWindowMs = 5 * 60_000;
@@ -2446,11 +2462,15 @@ export async function runSubagent(config, childSessions) {
2446
2462
  };
2447
2463
  const maybeEmitOpenToolAttention = (flatIndex, now) => {
2448
2464
  const step = statusPayload.steps[flatIndex];
2449
- if (!step || step.status !== "running" || step.activityState === "needs_attention")
2465
+ if (!step || step.status !== "running")
2450
2466
  return false;
2451
2467
  const target = openToolAttentionTarget(flatIndex, now);
2452
2468
  if (!target)
2453
2469
  return false;
2470
+ target.attentionEmitted = true;
2471
+ // Keep this attention when a concurrent supervisor request ends and restores its saved state.
2472
+ if (supervisorAttentionSteps.has(flatIndex))
2473
+ supervisorAttentionSteps.set(flatIndex, "needs_attention");
2454
2474
  const previous = step.activityState;
2455
2475
  step.activityState = "needs_attention";
2456
2476
  statusPayload.activityState = "needs_attention";
@@ -2469,6 +2489,7 @@ export async function runSubagent(config, childSessions) {
2469
2489
  tokens: step.tokens?.total,
2470
2490
  toolCount: step.toolCount,
2471
2491
  currentTool: target.tool,
2492
+ toolCallId: target.key.startsWith("id:") ? target.key.slice(3) : undefined,
2472
2493
  currentToolDurationMs: toolDurationMs,
2473
2494
  currentPath: target.path,
2474
2495
  })));
@@ -3342,6 +3363,7 @@ export async function runSubagent(config, childSessions) {
3342
3363
  return omitUndefinedProperties({
3343
3364
  agent: task.agent,
3344
3365
  ...(task.sessionName ? { sessionName: task.sessionName } : {}),
3366
+ ...(externalRunnerStatus(task.runner) ? { runner: externalRunnerStatus(task.runner) } : {}),
3345
3367
  ...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
3346
3368
  ...(task.context ? { context: task.context } : {}),
3347
3369
  ...(task.phase ?? step.phase ? { phase: task.phase ?? step.phase } : {}),
@@ -3449,6 +3471,7 @@ export async function runSubagent(config, childSessions) {
3449
3471
  return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: "(skipped — fail-fast)", exitCode: -1, skipped: true });
3450
3472
  }
3451
3473
  const taskStartTime = Date.now();
3474
+ launchedFlatIndices.add(fi);
3452
3475
  statusPayload.currentStep = fi;
3453
3476
  requiredStatusStep(statusPayload, fi).status = "running";
3454
3477
  delete requiredStatusStep(statusPayload, fi).error;
@@ -3576,6 +3599,7 @@ export async function runSubagent(config, childSessions) {
3576
3599
  runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
3577
3600
  output: pr.output,
3578
3601
  outputState: pr.outputState,
3602
+ outputPartial: pr.outputPartial,
3579
3603
  error: pr.error,
3580
3604
  success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
3581
3605
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
@@ -3865,6 +3889,7 @@ export async function runSubagent(config, childSessions) {
3865
3889
  return omitUndefinedProperties({ agent: task.agent, ...(task.sessionName ? { sessionName: task.sessionName } : {}), context: task.context, output: "(skipped — fail-fast)", exitCode: -1, skipped: true });
3866
3890
  }
3867
3891
  const taskStartTime = Date.now();
3892
+ launchedFlatIndices.add(fi);
3868
3893
  statusPayload.currentStep = fi;
3869
3894
  requiredStatusStep(statusPayload, fi).status = "running";
3870
3895
  delete requiredStatusStep(statusPayload, fi).error;
@@ -4027,6 +4052,7 @@ export async function runSubagent(config, childSessions) {
4027
4052
  launchResolvedExtensions: pr.launchResolvedExtensions,
4028
4053
  output: pr.output,
4029
4054
  outputState: pr.outputState,
4055
+ outputPartial: pr.outputPartial,
4030
4056
  error: pr.error,
4031
4057
  success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0 && pr.execution?.status !== "partial",
4032
4058
  exitCode: pr.interrupted === true ? 0 : pr.exitCode,
@@ -4256,6 +4282,7 @@ export async function runSubagent(config, childSessions) {
4256
4282
  }
4257
4283
  const singleCwd = singleWorktreeSetup?.worktrees[0]?.agentCwd ?? cwd;
4258
4284
  const stepStartTime = Date.now();
4285
+ launchedFlatIndices.add(flatIndex);
4259
4286
  statusPayload.currentStep = flatIndex;
4260
4287
  requiredStatusStep(statusPayload, flatIndex).status = "running";
4261
4288
  delete requiredStatusStep(statusPayload, flatIndex).activityState;
@@ -4339,6 +4366,7 @@ export async function runSubagent(config, childSessions) {
4339
4366
  runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
4340
4367
  output: stopped || childStopped ? stopMessage : timedOut ? singleResult.output || (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
4341
4368
  outputState: singleResult.outputState,
4369
+ outputPartial: singleResult.outputPartial,
4342
4370
  error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
4343
4371
  success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0 && singleResult.execution?.status !== "partial",
4344
4372
  exitCode: stopped || childStopped ? 1 : timedOut ? 1 : singleResult.interrupted === true ? 0 : singleResult.exitCode,
@@ -4743,6 +4771,7 @@ export async function runSubagent(config, childSessions) {
4743
4771
  context: r.context,
4744
4772
  output: r.output,
4745
4773
  outputState: r.outputState,
4774
+ outputPartial: r.outputPartial,
4746
4775
  error: r.error,
4747
4776
  success: r.success,
4748
4777
  skipped: r.skipped || undefined,
@@ -4845,6 +4874,26 @@ export async function runSubagent(config, childSessions) {
4845
4874
  totalCost: finalTotalCost,
4846
4875
  usageBudget: statusPayload.usageBudget,
4847
4876
  }));
4877
+ // Paused runs record an interrupted attempt; a later resume records another.
4878
+ for (const historyEntry of planBackgroundRunHistory({
4879
+ steps,
4880
+ resultMode,
4881
+ statusSteps: statusPayload.steps.map((step, index) => ({
4882
+ agent: step.agent,
4883
+ status: step.status,
4884
+ durationMs: step.durationMs,
4885
+ timedOut: step.timedOut,
4886
+ stopped: step.stopped,
4887
+ launched: launchedFlatIndices.has(index),
4888
+ })),
4889
+ stepResults: results,
4890
+ runDurationMs: runEndedAt - overallStartTime,
4891
+ stopped,
4892
+ interrupted,
4893
+ timedOut,
4894
+ })) {
4895
+ recordRun(historyEntry.agent, historyEntry.task, historyEntry.exitCode, historyEntry.durationMs, historyEntry.terminal);
4896
+ }
4848
4897
  writeRunLog(logPath, omitUndefinedProperties({
4849
4898
  id,
4850
4899
  mode: statusPayload.mode,