@bastani/atomic 0.9.12 → 0.9.13-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/README.md +5 -12
  4. package/dist/builtin/intercom/broker/client.ts +11 -2
  5. package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
  6. package/dist/builtin/intercom/index-heavy.ts +13 -3
  7. package/dist/builtin/intercom/index.ts +43 -19
  8. package/dist/builtin/intercom/intercom-utils.ts +15 -29
  9. package/dist/builtin/intercom/package.json +1 -1
  10. package/dist/builtin/intercom/source-ownership.ts +9 -12
  11. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  12. package/dist/builtin/mcp/README.md +3 -1
  13. package/dist/builtin/mcp/index.ts +10 -16
  14. package/dist/builtin/mcp/package.json +1 -1
  15. package/dist/builtin/mcp/startup-warmup.ts +20 -8
  16. package/dist/builtin/subagents/CHANGELOG.md +30 -0
  17. package/dist/builtin/subagents/README.md +22 -30
  18. package/dist/builtin/subagents/package.json +1 -1
  19. package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
  20. package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
  21. package/dist/builtin/subagents/src/extension/index.ts +23 -32
  22. package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
  23. package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
  24. package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
  25. package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
  26. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
  27. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
  28. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
  29. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
  30. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
  31. package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
  32. package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
  33. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
  34. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
  35. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
  36. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
  37. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
  38. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
  39. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
  40. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
  41. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
  42. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
  43. package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
  44. package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
  45. package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
  46. package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
  47. package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
  48. package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
  49. package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
  50. package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
  51. package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
  52. package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
  53. package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
  54. package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
  55. package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
  56. package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
  57. package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
  58. package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
  59. package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
  60. package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
  61. package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
  62. package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
  63. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
  64. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
  65. package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
  66. package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
  67. package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
  68. package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
  69. package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
  70. package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
  71. package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
  72. package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
  73. package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
  74. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
  75. package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
  76. package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
  77. package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
  78. package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
  79. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
  80. package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
  81. package/dist/builtin/web-access/package.json +1 -1
  82. package/dist/builtin/workflows/CHANGELOG.md +25 -0
  83. package/dist/builtin/workflows/README.md +13 -3
  84. package/dist/builtin/workflows/package.json +1 -1
  85. package/dist/builtin/workflows/src/durable/backend.ts +7 -0
  86. package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
  87. package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
  88. package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
  89. package/dist/builtin/workflows/src/durable/types.ts +5 -0
  90. package/dist/builtin/workflows/src/engine/run.ts +17 -1
  91. package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
  92. package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
  93. package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
  94. package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
  95. package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
  96. package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
  97. package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
  98. package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
  99. package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
  100. package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
  101. package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
  102. package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
  103. package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
  104. package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
  105. package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
  106. package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
  107. package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
  108. package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
  109. package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
  110. package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
  111. package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
  112. package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
  113. package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
  114. package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
  115. package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
  116. package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
  117. package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
  118. package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
  119. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
  120. package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
  121. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
  122. package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
  123. package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
  124. package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
  125. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
  126. package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
  127. package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
  128. package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
  129. package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
  130. package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
  131. package/dist/builtin/workflows/src/shared/timing.ts +10 -0
  132. package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
  133. package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
  134. package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
  135. package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
  136. package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
  137. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
  138. package/dist/builtin/workflows/src/tui/widget.ts +16 -46
  139. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  140. package/dist/core/agent-session-auto-compaction.js +54 -11
  141. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  142. package/dist/core/agent-session-events.d.ts.map +1 -1
  143. package/dist/core/agent-session-events.js +49 -14
  144. package/dist/core/agent-session-events.js.map +1 -1
  145. package/dist/core/agent-session-methods.d.ts +13 -0
  146. package/dist/core/agent-session-methods.d.ts.map +1 -1
  147. package/dist/core/agent-session-methods.js.map +1 -1
  148. package/dist/core/agent-session-models.d.ts.map +1 -1
  149. package/dist/core/agent-session-models.js +12 -1
  150. package/dist/core/agent-session-models.js.map +1 -1
  151. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  152. package/dist/core/agent-session-prompt.js +4 -0
  153. package/dist/core/agent-session-prompt.js.map +1 -1
  154. package/dist/core/agent-session-retry.d.ts +21 -4
  155. package/dist/core/agent-session-retry.d.ts.map +1 -1
  156. package/dist/core/agent-session-retry.js +232 -106
  157. package/dist/core/agent-session-retry.js.map +1 -1
  158. package/dist/core/agent-session-state.d.ts.map +1 -1
  159. package/dist/core/agent-session-state.js +2 -1
  160. package/dist/core/agent-session-state.js.map +1 -1
  161. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  162. package/dist/core/agent-session-tool-hooks.js +12 -0
  163. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  164. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  165. package/dist/core/agent-session-tool-registry.js +1 -1
  166. package/dist/core/agent-session-tool-registry.js.map +1 -1
  167. package/dist/core/agent-session-types.d.ts +3 -1
  168. package/dist/core/agent-session-types.d.ts.map +1 -1
  169. package/dist/core/agent-session-types.js.map +1 -1
  170. package/dist/core/agent-session.d.ts +12 -1
  171. package/dist/core/agent-session.d.ts.map +1 -1
  172. package/dist/core/agent-session.js +7 -0
  173. package/dist/core/agent-session.js.map +1 -1
  174. package/dist/core/extensions/context-types.d.ts +25 -0
  175. package/dist/core/extensions/context-types.d.ts.map +1 -1
  176. package/dist/core/extensions/context-types.js.map +1 -1
  177. package/dist/core/extensions/index.d.ts +1 -1
  178. package/dist/core/extensions/index.d.ts.map +1 -1
  179. package/dist/core/extensions/index.js.map +1 -1
  180. package/dist/core/extensions/runner-context.d.ts +2 -1
  181. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  182. package/dist/core/extensions/runner-context.js +4 -0
  183. package/dist/core/extensions/runner-context.js.map +1 -1
  184. package/dist/core/extensions/runner.d.ts +3 -2
  185. package/dist/core/extensions/runner.d.ts.map +1 -1
  186. package/dist/core/extensions/runner.js +3 -1
  187. package/dist/core/extensions/runner.js.map +1 -1
  188. package/dist/core/model-fallback-failures.d.ts +30 -0
  189. package/dist/core/model-fallback-failures.d.ts.map +1 -0
  190. package/dist/core/model-fallback-failures.js +610 -0
  191. package/dist/core/model-fallback-failures.js.map +1 -0
  192. package/dist/core/retry-policy.d.ts +30 -0
  193. package/dist/core/retry-policy.d.ts.map +1 -0
  194. package/dist/core/retry-policy.js +25 -0
  195. package/dist/core/retry-policy.js.map +1 -0
  196. package/dist/core/sdk-types.d.ts +8 -2
  197. package/dist/core/sdk-types.d.ts.map +1 -1
  198. package/dist/core/sdk-types.js.map +1 -1
  199. package/dist/core/sdk.d.ts.map +1 -1
  200. package/dist/core/sdk.js +6 -1
  201. package/dist/core/sdk.js.map +1 -1
  202. package/dist/core/session-manager-core.d.ts +2 -0
  203. package/dist/core/session-manager-core.d.ts.map +1 -1
  204. package/dist/core/session-manager-core.js +7 -0
  205. package/dist/core/session-manager-core.js.map +1 -1
  206. package/dist/index-extensions.d.ts +1 -1
  207. package/dist/index-extensions.d.ts.map +1 -1
  208. package/dist/index-extensions.js.map +1 -1
  209. package/dist/index.d.ts +3 -0
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/index.js +2 -0
  212. package/dist/index.js.map +1 -1
  213. package/docs/intercom.md +5 -10
  214. package/docs/settings.md +7 -1
  215. package/docs/subagents.md +19 -19
  216. package/docs/workflows.md +21 -5
  217. package/examples/extensions/gondolin/package-lock.json +3 -3
  218. package/npm-shrinkwrap.json +29 -29
  219. package/package.json +2 -2
  220. package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
  221. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
  222. package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
  223. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
  224. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
  225. package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
  226. package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
  227. package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
  228. package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
  229. package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
  230. package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
  231. package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
  232. package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
  233. package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
  234. package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
  235. package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
  236. package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
  237. package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
  238. package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
  239. package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
  240. package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
  241. package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
  242. package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
  243. package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
  244. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
  245. package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
  246. package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
  247. package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
  248. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
  249. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
  250. package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
  251. package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
  252. package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
  253. package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
  254. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
  255. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
  256. package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
  257. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
  258. package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
  259. package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
  260. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
  261. package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
  262. package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
  263. package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
  264. /package/dist/builtin/subagents/src/runs/{shared/nested-path.ts → inprocess/runtime-support/nested-paths.ts} +0 -0
@@ -129,7 +129,7 @@ export async function handleRunControlCommand(
129
129
  return true;
130
130
  }
131
131
  }
132
- const results = action === "quit" ? await quitAllRuns() : await interruptAllRuns();
132
+ const results = action === "quit" ? await quitAllRuns({ actor: "user" }) : await interruptAllRuns();
133
133
  const successes = results.filter((result) => result.ok);
134
134
  const changed = successes.length;
135
135
  const failures = results.filter((result) => !result.ok);
@@ -171,7 +171,7 @@ export async function handleRunControlCommand(
171
171
  return true;
172
172
  }
173
173
  try {
174
- const result = await quitRun(resolved.runId);
174
+ const result = await quitRun(resolved.runId, { actor: "user" });
175
175
  if (result.ok) print(`Run ${result.runId} quit and can be resumed with /workflow resume.`);
176
176
  else if (result.reason === "already_ended") print(`Run ${result.runId} already ended.`);
177
177
  else if (result.reason === "no_active_stages") {
@@ -284,11 +284,11 @@ export async function handleRunControlCommand(
284
284
  await ensureWorkflowResourcesVisible();
285
285
  const continuation = await deps
286
286
  .runtimeForContext(ctx)
287
- .resumeFailedRun(resolved.runId, undefined, { policy });
287
+ .resumeFailedRun(resolved.runId, undefined, { policy, actor: "user" });
288
288
  continuation.ok ? print(continuation.message) : fail(continuation.message);
289
289
  } else {
290
290
  try {
291
- const result = await resumeRun(resolved.runId, {});
291
+ const result = await resumeRun(resolved.runId, { actor: "user" });
292
292
  if (result.ok && !isPaused && result.mode === "snapshot" && run?.exitReason === "quit") {
293
293
  return await handleDurableResume(resolved.runId, ctx, reporter, deps);
294
294
  }
@@ -443,7 +443,7 @@ export async function handleRunControlCommand(
443
443
  const stageRunId = resolvedStage.runId ?? runId;
444
444
  if (action === "pause") {
445
445
  try {
446
- const result = await pauseRun(stageRunId, { stageId });
446
+ const result = await pauseRun(stageRunId, { stageId, actor: "user" });
447
447
  if (!result.ok) {
448
448
  fail(
449
449
  result.reason === "not_found"
@@ -495,7 +495,9 @@ export async function handleRunControlCommand(
495
495
  }
496
496
  if (isResumableContinuation) {
497
497
  await ensureWorkflowResourcesVisible();
498
- const continuation = await deps.runtimeForContext(ctx).resumeFailedRun(stageRunId, stageId, { policy });
498
+ const continuation = await deps
499
+ .runtimeForContext(ctx)
500
+ .resumeFailedRun(stageRunId, stageId, { policy, actor: "user" });
499
501
  continuation.ok ? print(continuation.message) : fail(continuation.message);
500
502
  return true;
501
503
  }
@@ -507,7 +509,7 @@ export async function handleRunControlCommand(
507
509
  }
508
510
  let result: Awaited<ReturnType<typeof resumeRun>>;
509
511
  try {
510
- result = await resumeRun(stageRunId, { stageId, message });
512
+ result = await resumeRun(stageRunId, { stageId, message, actor: "user" });
511
513
  } catch (error) {
512
514
  fail(`Failed to resume run ${stageRunId}: ${error instanceof Error ? error.message : String(error)}`);
513
515
  return true;
@@ -102,6 +102,17 @@ export interface WorkflowStatusListing {
102
102
  readonly snapshots: RunSnapshot[];
103
103
  }
104
104
 
105
+ const workflowStatusRenderRuns = new WeakMap<object, readonly RunSnapshot[]>();
106
+
107
+ /** Keep the full point-in-time run collection out of agent-facing result JSON. */
108
+ export function setWorkflowStatusRenderRuns(result: object, runs: readonly RunSnapshot[]): void {
109
+ workflowStatusRenderRuns.set(result, runs);
110
+ }
111
+
112
+ export function getWorkflowStatusRenderRuns(result: object): readonly RunSnapshot[] | undefined {
113
+ return workflowStatusRenderRuns.get(result);
114
+ }
115
+
105
116
  function stageIsActive(stage: StageSnapshot): boolean {
106
117
  return stage.status === "running" || stage.status === "awaiting_input";
107
118
  }
@@ -1,10 +1,13 @@
1
+ import { runIndicatorStatus } from "../shared/run-indicator-status.js";
1
2
  import { deriveInputFields } from "../shared/schema-introspection.js";
3
+ import type { RunSnapshot } from "../shared/store-types.js";
2
4
  import type { WorkflowSerializableValue } from "../shared/types.js";
3
- import { fmtDuration } from "../tui/status-helpers.js";
5
+ import { fmtDuration, statusIcon } from "../tui/status-helpers.js";
4
6
  import type { WorkflowToolArgs } from "./public-types.js";
5
7
  import type { WorkflowToolResult } from "./render-result.js";
6
8
  import type { ExtensionRuntime } from "./runtime.js";
7
9
  import type { WorkflowRunStatusSummary, WorkflowStatusAwaitingInput } from "./workflow-status-summary.js";
10
+ import { getWorkflowStatusRenderRuns } from "./workflow-status-summary.js";
8
11
 
9
12
  function stringifyWorkflowToolResult(result: WorkflowToolResult): string {
10
13
  return JSON.stringify(result, null, 2);
@@ -69,7 +72,20 @@ function statusAwaitingInputLine(entry: WorkflowStatusAwaitingInput): string {
69
72
  return ` awaiting input: ${target}${prompt}${message}`;
70
73
  }
71
74
 
75
+ function statusRunIcon(
76
+ run: WorkflowRunStatusSummary,
77
+ snapshot: RunSnapshot | undefined,
78
+ allRuns: readonly RunSnapshot[],
79
+ ): string {
80
+ if (snapshot === undefined) return statusIcon(run.status);
81
+ const indicatorStatus = runIndicatorStatus(snapshot, allRuns);
82
+ if (snapshot.endedAt === undefined && snapshot.status === "paused" && snapshot.exitReason === "quit") {
83
+ return statusIcon("pending");
84
+ }
85
+ return statusIcon(indicatorStatus);
86
+ }
72
87
  function renderStatusToolContent(result: Extract<WorkflowToolResult, { action: "status" }>): string {
88
+ const allRuns = getWorkflowStatusRenderRuns(result) ?? result.snapshots;
73
89
  const lines = ["action: status", `filter: ${result.filter}`];
74
90
  if (result.runs.length === 0) {
75
91
  lines.push(result.filter === "all" ? "runs: none" : `runs: none (statusFilter: ${result.filter})`);
@@ -81,6 +97,7 @@ function renderStatusToolContent(result: Extract<WorkflowToolResult, { action: "
81
97
  const hint = statusRunHint(run);
82
98
  const summaryLine = [
83
99
  `[${index + 1}]`,
100
+ statusRunIcon(run, result.snapshots[index], allRuns),
84
101
  run.runId,
85
102
  run.name,
86
103
  run.status,
@@ -70,7 +70,7 @@ export async function workflowPauseAction(args: WorkflowToolArgs): Promise<Workf
70
70
  return { action, runId: "--all", status: "noop", message: allStageConflictMessage("pause") };
71
71
  }
72
72
  try {
73
- const results = await pauseAllRuns();
73
+ const results = await pauseAllRuns({ actor: "agent" });
74
74
  const paused = results.filter((result) => result.ok).length;
75
75
  return {
76
76
  action,
@@ -100,7 +100,7 @@ export async function workflowPauseAction(args: WorkflowToolArgs): Promise<Workf
100
100
  if (!stage.ok) return { action, runId: target.runId, status: "noop", message: stage.message };
101
101
  const stageRunId = stage.runId ?? target.runId;
102
102
  try {
103
- const result = await pauseRun(stageRunId, { stageId: stage.stageId });
103
+ const result = await pauseRun(stageRunId, { stageId: stage.stageId, actor: "agent" });
104
104
  return result.ok
105
105
  ? {
106
106
  action,
@@ -241,7 +241,7 @@ export async function workflowQuitAction(args: WorkflowToolArgs): Promise<Workfl
241
241
  if (args.stageId !== undefined && args.stageId.length > 0) {
242
242
  return { action, runId: "--all", status: "noop", message: allStageConflictMessage("quit") };
243
243
  }
244
- const results = await quitAllRuns();
244
+ const results = await quitAllRuns({ actor: "agent" });
245
245
  const successes = results.filter((result) => result.ok);
246
246
  const quitCount = successes.length;
247
247
  const failures = results.filter((result) => !result.ok);
@@ -264,7 +264,7 @@ export async function workflowQuitAction(args: WorkflowToolArgs): Promise<Workfl
264
264
  if (!controlNode.ok) return { action, runId: target.runId, status: "noop", message: controlNode.message };
265
265
  if (controlNode.kind === "tool") return quitToolNodeAction(controlNode.runId, controlNode.nodeId, action);
266
266
  try {
267
- const result = await quitRun(target.runId);
267
+ const result = await quitRun(target.runId, { actor: "agent" });
268
268
  if (result.ok) {
269
269
  return {
270
270
  action,
@@ -354,7 +354,7 @@ async function resumeDurableShadow(
354
354
  } catch (error) {
355
355
  warning = formatWorkflowResourceLoadWarning(error);
356
356
  }
357
- const resumed = await runtime.resumeDurableWorkflow(runId, { policy: deps.policy });
357
+ const resumed = await runtime.resumeDurableWorkflow(runId, { policy: deps.policy, actor: "agent" });
358
358
  const message = warning === undefined ? resumed.message : `${warning}\n\n${resumed.message}`;
359
359
  return {
360
360
  action: "resume",
@@ -369,7 +369,7 @@ async function resumePreparedDurableTarget(
369
369
  deps: Pick<WorkflowControlActionDeps, "getRuntime" | "policy">,
370
370
  ): Promise<WorkflowToolResult> {
371
371
  try {
372
- const resumed = await deps.getRuntime().resumeDurableWorkflow(runId, { policy: deps.policy });
372
+ const resumed = await deps.getRuntime().resumeDurableWorkflow(runId, { policy: deps.policy, actor: "agent" });
373
373
  return {
374
374
  action: "resume",
375
375
  runId: resumed.ok ? resumed.runId : runId,
@@ -493,7 +493,9 @@ export async function workflowResumeAction(
493
493
  } catch (error) {
494
494
  warning = formatWorkflowResourceLoadWarning(error);
495
495
  }
496
- const continuation = await deps.getRuntime().resumeFailedRun(stageRunId, stage.stageId, { policy: deps.policy });
496
+ const continuation = await deps
497
+ .getRuntime()
498
+ .resumeFailedRun(stageRunId, stage.stageId, { policy: deps.policy, actor: "agent" });
497
499
  const message = warning === undefined ? continuation.message : `${warning}\n\n${continuation.message}`;
498
500
  return {
499
501
  action: "resume",
@@ -503,7 +505,7 @@ export async function workflowResumeAction(
503
505
  };
504
506
  }
505
507
  try {
506
- const result = await resumeRun(stageRunId, { stageId: stage.stageId, message: args.message });
508
+ const result = await resumeRun(stageRunId, { stageId: stage.stageId, message: args.message, actor: "agent" });
507
509
  if (result.ok) {
508
510
  const runLevelResumed =
509
511
  hadPausedRunState &&
@@ -1,5 +1,6 @@
1
1
  import { getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
2
2
  import { inspectRun } from "../runs/background/status.js";
3
+ import { store } from "../shared/store.js";
3
4
  import type { WorkflowExecutionPolicy } from "../shared/types.js";
4
5
  import type { PiExecuteContext, WorkflowToolArgs } from "./public-types.js";
5
6
  import type { WorkflowToolResult } from "./render-result.js";
@@ -7,7 +8,7 @@ import type { ExtensionRuntime } from "./runtime.js";
7
8
  import { formatWorkflowResourceLoadWarning } from "./workflow-command-surfaces.js";
8
9
  import { workflowPolicyFromContext } from "./workflow-policy.js";
9
10
  import type { WorkflowReloadReport } from "./workflow-reload-report.js";
10
- import { buildWorkflowStatusListing } from "./workflow-status-summary.js";
11
+ import { buildWorkflowStatusListing, setWorkflowStatusRenderRuns } from "./workflow-status-summary.js";
11
12
  import { isWorkflowStageToolContext, resolveRunId, topLevelExpandedSnapshots } from "./workflow-targets.js";
12
13
  import { workflowGetResult } from "./workflow-tool-content.js";
13
14
  import {
@@ -74,7 +75,9 @@ export function makeExecuteWorkflowTool(
74
75
  }
75
76
  case "run": {
76
77
  await ensureWorkflowResourcesVisible();
77
- return getRuntime().dispatch(args, { policy });
78
+ // A tool launch is the agent's own action: it is attributed as such and
79
+ // the tool result already reports the run, so it raises no chat notice.
80
+ return getRuntime().dispatch(args, { policy, origin: "agent" });
78
81
  }
79
82
  case "status": {
80
83
  const target = args.runId;
@@ -92,12 +95,14 @@ export function makeExecuteWorkflowTool(
92
95
  : { action: "statusDetail", runId: target, error: `run not found: ${target}` };
93
96
  }
94
97
  const listing = buildWorkflowStatusListing(topLevelExpandedSnapshots(), args.statusFilter ?? "all");
95
- return {
96
- action: "status",
98
+ const result = {
99
+ action: "status" as const,
97
100
  filter: listing.filter,
98
101
  runs: listing.runs,
99
102
  snapshots: listing.snapshots,
100
103
  };
104
+ setWorkflowStatusRenderRuns(result, store.graphSnapshot().runs);
105
+ return result;
101
106
  }
102
107
  case "stages":
103
108
  return workflowStagesResult(args);
@@ -20,7 +20,7 @@ import { topLevelWorkflowRuns } from "../../shared/run-visibility.js";
20
20
  import { store as defaultStore } from "../../shared/store.js";
21
21
  import { readGraphStoreSnapshot } from "../../shared/store-observation.js";
22
22
  import type { Store } from "../../shared/store-public-types.js";
23
- import type { RunSnapshot, StageSnapshot } from "../../shared/store-types.js";
23
+ import type { RunSnapshot, StageSnapshot, WorkflowActor } from "../../shared/store-types.js";
24
24
  import type { WorkflowCancelledToolNode, WorkflowToolNodeIdentity } from "../../shared/types.js";
25
25
  import {
26
26
  stageControlRegistry as defaultStageControlRegistry,
@@ -83,6 +83,12 @@ type QuitAllRunResult =
83
83
  * It deliberately does NOT abort through the cancellation registry or append a
84
84
  * terminal `workflow.run.end` entry. Destructive cancellation remains an
85
85
  * internal lifecycle mechanism.
86
+ *
87
+ * A quit publishes its stage pauses in step 1, long before step 5 can record the
88
+ * quit itself, so the run passes through an ordinary paused state on the way.
89
+ * Only step 5 carries the caller's `actor`, so an observer that reports deliberate
90
+ * control actions sees one quit rather than a pause followed by a quit — and
91
+ * still sees nothing at all when a quit never publishes.
86
92
  */
87
93
  export async function quitRun(
88
94
  runId: string,
@@ -91,6 +97,8 @@ export async function quitRun(
91
97
  stageControlRegistry?: StageControlRegistry;
92
98
  toolControlRegistry?: ToolControlRegistry;
93
99
  jobs?: JobTracker;
100
+ /** Who requested this quit. Omitted for internal callers. */
101
+ actor?: WorkflowActor;
94
102
  },
95
103
  ): Promise<QuitRunResult> {
96
104
  const activeStore = opts?.store ?? defaultStore;
@@ -170,7 +178,7 @@ export async function quitRun(
170
178
  // record, and only the publication below can report that the run stopped.
171
179
  const suspendedByAbort = toolHandles.length > 0;
172
180
  const publish = (resumable: boolean): void => {
173
- publishLocalQuit(activeStore, runId, pausedRunIds, resumable);
181
+ publishLocalQuit(activeStore, runId, pausedRunIds, resumable, opts?.actor);
174
182
  // An abandoned callback keeps its executor alive, but that executor is no
175
183
  // longer authoritative for this run id: detach it so `/workflow resume`
176
184
  // relaunches a fresh executor instead of adopting the stale job and
@@ -202,15 +210,28 @@ export async function quitRun(
202
210
  * process could resume from it, so it is not advertised as resumable. Recording
203
211
  * it keeps the run controllable, so a later `/workflow quit` re-attempts the
204
212
  * transition and upgrades the record.
213
+ *
214
+ * The boundary run is deliberately excluded from the descendant loop: a bare
215
+ * `recordRunPaused(runId)` first would publish a plain paused state, and a
216
+ * lifecycle observer would report this quit as a pause followed by a quit. The
217
+ * single metadata-carrying call below records the same end state in one step.
205
218
  */
206
219
  function publishLocalQuit(
207
220
  activeStore: Store,
208
221
  runId: string,
209
222
  pausedRunIds: ReadonlySet<string>,
210
223
  resumable: boolean,
224
+ actor?: WorkflowActor,
211
225
  ): void {
212
- for (const pausedRunId of pausedRunIds) activeStore.recordRunPaused(pausedRunId);
213
- activeStore.recordRunPaused(runId, undefined, { exitReason: "quit", resumable });
226
+ for (const pausedRunId of pausedRunIds) {
227
+ if (pausedRunId === runId) continue;
228
+ activeStore.recordRunPaused(pausedRunId);
229
+ }
230
+ activeStore.recordRunPaused(runId, undefined, {
231
+ exitReason: "quit",
232
+ resumable,
233
+ ...(actor === undefined ? {} : { actor }),
234
+ });
214
235
  }
215
236
 
216
237
  /**
@@ -368,6 +389,8 @@ export async function quitAllRuns(opts?: {
368
389
  stageControlRegistry?: StageControlRegistry;
369
390
  toolControlRegistry?: ToolControlRegistry;
370
391
  jobs?: JobTracker;
392
+ /** Who requested these quits. Omitted for internal callers. */
393
+ actor?: WorkflowActor;
371
394
  }): Promise<QuitAllRunResult[]> {
372
395
  const activeStore = opts?.store ?? defaultStore;
373
396
  const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((run) => run.endedAt === undefined);
@@ -377,6 +400,7 @@ export async function quitAllRuns(opts?: {
377
400
  stageControlRegistry: opts?.stageControlRegistry,
378
401
  toolControlRegistry: opts?.toolControlRegistry,
379
402
  jobs: opts?.jobs,
403
+ ...(opts?.actor === undefined ? {} : { actor: opts.actor }),
380
404
  }),
381
405
  );
382
406
  const settled = await Promise.allSettled(attempts);
@@ -75,7 +75,8 @@ export async function settleResumeAcknowledgements(
75
75
  if (visiblyRunning) lateFailures.push(qualified);
76
76
  else if (controlRun?.endedAt === undefined && targetIsActuallyPaused(store, target)) failures.push(qualified);
77
77
  });
78
- for (const controlRunId of resumedRunIds) store.recordRunResumed(controlRunId);
78
+ for (const controlRunId of resumedRunIds)
79
+ store.recordRunResumed(controlRunId, undefined, { source: "acknowledgement" });
79
80
  return { resumed, acknowledged, failures, lateFailures };
80
81
  }
81
82
 
@@ -16,7 +16,7 @@ import { topLevelWorkflowRuns } from "../../shared/run-visibility.js";
16
16
  import type { Store } from "../../shared/store.js";
17
17
  import { store as defaultStore } from "../../shared/store.js";
18
18
  import { readGraphStoreSnapshot } from "../../shared/store-observation.js";
19
- import type { RunSnapshot, RunStatus, StageSnapshot } from "../../shared/store-types.js";
19
+ import type { RunSnapshot, RunStatus, StageSnapshot, WorkflowActor } from "../../shared/store-types.js";
20
20
  import type { WorkflowPersistencePort } from "../../shared/types.js";
21
21
  import type { StageControlRegistry } from "../foreground/stage-control-registry.js";
22
22
  import { stageControlRegistry as defaultStageControlRegistry } from "../foreground/stage-control-registry.js";
@@ -204,6 +204,8 @@ export async function resumeRun(
204
204
  stageId?: string;
205
205
  /** Optional resume message forwarded to each resumed stage. */
206
206
  message?: string;
207
+ /** Who requested this resume. Omitted for internal callers. */
208
+ actor?: WorkflowActor;
207
209
  },
208
210
  ): Promise<ResumeResult> {
209
211
  const activeStore = opts?.store ?? defaultStore;
@@ -250,8 +252,29 @@ export async function resumeRun(
250
252
  !hasPausedDescendant &&
251
253
  currentRun?.status === "paused")
252
254
  ) {
253
- activeStore.recordRunResumed(runId);
254
- if (aggregateRootRunId !== runId) activeStore.recordRunResumed(aggregateRootRunId);
255
+ // One scope carries the actor, mirroring pauseRun: the stage when a
256
+ // stage-scoped resume leaves siblings paused, the run otherwise. The
257
+ // aggregate root is reconciled without attribution so one request never
258
+ // reports twice.
259
+ //
260
+ // A run only carries the actor when it has a resume transition to attach
261
+ // it to. A stage-scoped resume of a run that never paused — because a
262
+ // sibling stage kept it running — leaves `resumedAt` unset, and
263
+ // `recordRunResumed` refuses an attribution-only claim against a run that
264
+ // never resumed. Attributing the run there would report nothing at all,
265
+ // so the stage carries it instead.
266
+ const attributeStage =
267
+ opts?.stageId !== undefined && (hasPausedDescendant || currentRun?.resumedAt === undefined);
268
+ activeStore.recordRunResumed(runId, undefined, {
269
+ source: "run_control",
270
+ ...(opts?.actor === undefined || attributeStage ? {} : { actor: opts.actor }),
271
+ });
272
+ if (aggregateRootRunId !== runId) {
273
+ activeStore.recordRunResumed(aggregateRootRunId, undefined, { source: "run_control" });
274
+ }
275
+ if (attributeStage && opts?.actor !== undefined && opts.stageId !== undefined) {
276
+ activeStore.recordStageResumed(runId, opts.stageId, undefined, { actor: opts.actor });
277
+ }
255
278
  }
256
279
  const reconciledRoot = activeStore.runs().find((candidate) => candidate.id === runId);
257
280
  if (acknowledgements.failures.length > 0) {
@@ -346,7 +369,15 @@ export async function resumeRun(
346
369
  }
347
370
 
348
371
  // pauseRun
349
- /** Pause a run only after its live stage controls acknowledge the request. */
372
+ /**
373
+ * Pause a run only after its live stage controls acknowledge the request.
374
+ *
375
+ * `actor` attributes the pause to whoever asked for it. Exactly one scope carries
376
+ * it: a whole-run pause attributes the run, and a stage-scoped pause attributes
377
+ * the run when it stops the last active stage and the stage otherwise. An
378
+ * observer therefore reports one event per request, never a stage and a run
379
+ * event for the same one.
380
+ */
350
381
  export async function pauseRun(
351
382
  runId: string,
352
383
  opts?: {
@@ -354,11 +385,14 @@ export async function pauseRun(
354
385
  stageControlRegistry?: StageControlRegistry;
355
386
  /** Pause only this stage. */
356
387
  stageId?: string;
388
+ /** Who requested this pause. Omitted for internal callers. */
389
+ actor?: WorkflowActor;
357
390
  },
358
391
  ): Promise<PauseResult> {
359
392
  const activeStore = opts?.store ?? defaultStore;
360
393
  const registry = opts?.stageControlRegistry ?? defaultStageControlRegistry;
361
394
  const run = activeStore.runs().find((candidate) => candidate.id === runId);
395
+ const actorMetadata = opts?.actor === undefined ? undefined : { actor: opts.actor };
362
396
 
363
397
  if (!run) return { ok: false, runId, reason: "not_found" };
364
398
  if (run.endedAt !== undefined) return { ok: false, runId, reason: "already_ended" };
@@ -379,7 +413,9 @@ export async function pauseRun(
379
413
  (candidate) =>
380
414
  candidate.id !== opts.stageId && (candidate.status === "running" || candidate.status === "pending"),
381
415
  ) ?? false;
382
- if (!stillActive) activeStore.recordRunPaused(runId);
416
+ if (!stillActive) activeStore.recordRunPaused(runId, undefined, actorMetadata);
417
+ else if (actorMetadata !== undefined)
418
+ activeStore.recordStagePaused(runId, opts.stageId, undefined, actorMetadata);
383
419
  return { ok: true, runId, paused };
384
420
  }
385
421
 
@@ -403,19 +439,30 @@ export async function pauseRun(
403
439
  const stage = controlRun?.stages.find((candidate) => candidate.id === handle.stageId);
404
440
  if (stage !== undefined) paused.push(structuredClone(stage));
405
441
  }
406
- for (const pausedRunId of pausedRunIds) activeStore.recordRunPaused(pausedRunId);
407
- activeStore.recordRunPaused(runId);
442
+ for (const pausedRunId of pausedRunIds) {
443
+ if (pausedRunId === runId) continue;
444
+ activeStore.recordRunPaused(pausedRunId);
445
+ }
446
+ activeStore.recordRunPaused(runId, undefined, actorMetadata);
408
447
  return { ok: true, runId, paused };
409
448
  }
410
449
 
411
450
  export async function pauseAllRuns(opts?: {
412
451
  store?: Store;
413
452
  stageControlRegistry?: StageControlRegistry;
453
+ /** Who requested these pauses. Omitted for internal callers. */
454
+ actor?: WorkflowActor;
414
455
  }): Promise<PauseResult[]> {
415
456
  const activeStore = opts?.store ?? defaultStore;
416
457
  const inFlight = topLevelWorkflowRuns(activeStore.runs()).filter((run) => run.endedAt === undefined);
417
458
  return Promise.all(
418
- inFlight.map((run) => pauseRun(run.id, { store: activeStore, stageControlRegistry: opts?.stageControlRegistry })),
459
+ inFlight.map((run) =>
460
+ pauseRun(run.id, {
461
+ store: activeStore,
462
+ stageControlRegistry: opts?.stageControlRegistry,
463
+ ...(opts?.actor === undefined ? {} : { actor: opts.actor }),
464
+ }),
465
+ ),
419
466
  );
420
467
  }
421
468
  // ---------------------------------------------------------------------------
@@ -1,5 +1,6 @@
1
1
  import { isAbsolute, join, resolve } from "node:path";
2
2
  import { CONFIG_DIR_NAME, isCodexFastModeCandidateModelId } from "@bastani/atomic";
3
+ import type { WorkflowActor } from "../../shared/store-types.js";
3
4
  import type { StageOptions, WorkflowArtifact, WorkflowTaskOptions, WorkflowTaskStep } from "../../shared/types.js";
4
5
  import { workflowArtifactRunPath } from "../../shared/workflow-artifacts.js";
5
6
  import { buildModelCandidatesFromCatalog, workflowModelId } from "../shared/model-fallback.js";
@@ -178,11 +179,13 @@ export function workflowInvocationMetadata(
178
179
  inputDefaults: Partial<StageOptions>,
179
180
  workflowInvocationCwd: string,
180
181
  cache?: GitWorktreeSetupCache,
182
+ origin?: WorkflowActor,
181
183
  ): {
182
184
  readonly invocationCwd: string;
183
185
  readonly workflowCwd?: string;
184
186
  readonly repositoryRoot?: string;
185
187
  readonly gitWorktreeRoot?: string;
188
+ readonly origin?: WorkflowActor;
186
189
  } {
187
190
  const setup = setupWorkflowInputGitWorktree(inputDefaults, workflowInvocationCwd, cache);
188
191
  return {
@@ -190,6 +193,7 @@ export function workflowInvocationMetadata(
190
193
  ...(setup !== undefined
191
194
  ? { workflowCwd: setup.cwd, repositoryRoot: setup.repositoryRoot, gitWorktreeRoot: setup.worktreeRoot }
192
195
  : {}),
196
+ ...(origin !== undefined ? { origin } : {}),
193
197
  };
194
198
  }
195
199
 
@@ -182,7 +182,9 @@ export function buildPromptNodeUiAdapter(input: {
182
182
  },
183
183
  async resume() {
184
184
  input.activeStore.recordStageResumed(input.runId, stageId);
185
- input.activeStore.recordRunResumed(input.runId);
185
+ // Answering a human-in-the-loop prompt continues work already in flight.
186
+ // It is not a control action and must never reach the main chat.
187
+ input.activeStore.recordRunResumed(input.runId, undefined, { source: "prompt_answer" });
186
188
  const currentPauseGate = pauseGate;
187
189
  pauseGate = undefined;
188
190
  currentPauseGate?.resolve();
@@ -193,7 +193,7 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
193
193
  await runtime.scheduler.cascadeResumeFrom(runtime.stageId);
194
194
  // Preserve manual per-stage semantics: once this acknowledged
195
195
  // resume succeeds, the run is active even if sibling stages remain paused.
196
- runtime.activeStore.recordRunResumed(runtime.runId);
196
+ runtime.activeStore.recordRunResumed(runtime.runId, undefined, { source: "stage_control" });
197
197
  }
198
198
  if (wakeReleasedIdleStageChat) runtime.state.wakeWaitingForStageChatTurn?.();
199
199
  if (resumesIdleStageChat && hasMessage) {
@@ -233,7 +233,7 @@ export function createStageContext(opts: StageRunnerOpts): InternalStageContext
233
233
  },
234
234
 
235
235
  async abort() {
236
- await controller.currentSession?.abort();
236
+ await controller.abort();
237
237
  },
238
238
 
239
239
  async __dispose() {