@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
@@ -1,411 +0,0 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
3
- import { formatDuration, formatModelThinking, formatTokens, shortenPath } from "../../shared/formatters.ts";
4
- import { formatActivityLabel, formatParallelOutcome } from "../../shared/status-format.ts";
5
- import type {
6
- ActivityState,
7
- AsyncJobStep,
8
- AsyncParallelGroupStatus,
9
- AsyncStatus,
10
- NestedRunSummary,
11
- SubagentRunMode,
12
- TokenUsage,
13
- } from "../../shared/types.ts";
14
- import { readStatus } from "../../shared/utils.ts";
15
- import {
16
- attachRootChildrenToSteps,
17
- findNestedRouteForRootId,
18
- projectNestedRegistryForRoot,
19
- } from "../shared/nested-events.ts";
20
- import { formatNestedRunStatusLines } from "../shared/nested-render.ts";
21
- import { flatToLogicalStepIndex, normalizeParallelGroups } from "./parallel-groups.ts";
22
- import { reconcileAsyncRun, reconcileNestedAsyncDescendants } from "./stale-run-reconciler.ts";
23
-
24
- interface AsyncRunStepSummary {
25
- index: number;
26
- agent: string;
27
- label?: string;
28
- phase?: string;
29
- outputName?: string;
30
- structured?: boolean;
31
- status: AsyncJobStep["status"];
32
- activityState?: ActivityState;
33
- lastActivityAt?: number;
34
- currentTool?: string;
35
- currentToolArgs?: string;
36
- currentToolStartedAt?: number;
37
- currentPath?: string;
38
- recentTools?: Array<{ tool: string; args: string; endMs: number }>;
39
- recentOutput?: string[];
40
- turnCount?: number;
41
- toolCount?: number;
42
- durationMs?: number;
43
- tokens?: TokenUsage;
44
- skills?: string[];
45
- model?: string;
46
- thinking?: string;
47
- fastMode?: boolean;
48
- attemptedModels?: string[];
49
- error?: string;
50
- children?: NestedRunSummary[];
51
- }
52
-
53
- export interface AsyncRunSummary {
54
- id: string;
55
- asyncDir: string;
56
- sessionId?: string;
57
- state: "queued" | "running" | "complete" | "failed" | "paused";
58
- activityState?: ActivityState;
59
- lastActivityAt?: number;
60
- currentTool?: string;
61
- currentToolStartedAt?: number;
62
- currentPath?: string;
63
- turnCount?: number;
64
- toolCount?: number;
65
- mode: SubagentRunMode;
66
- cwd?: string;
67
- startedAt: number;
68
- lastUpdate?: number;
69
- endedAt?: number;
70
- currentStep?: number;
71
- chainStepCount?: number;
72
- parallelGroups?: AsyncParallelGroupStatus[];
73
- steps: AsyncRunStepSummary[];
74
- sessionDir?: string;
75
- outputFile?: string;
76
- totalTokens?: TokenUsage;
77
- sessionFile?: string;
78
- nestedChildren?: NestedRunSummary[];
79
- nestedWarnings?: string[];
80
- }
81
-
82
- interface AsyncRunListOptions {
83
- states?: Array<AsyncRunSummary["state"]>;
84
- sessionId?: string;
85
- limit?: number;
86
- resultsDir?: string;
87
- kill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;
88
- now?: () => number;
89
- reconcile?: boolean;
90
- /** Only consider run dirs whose dir or status.json changed within this window. */
91
- maxAgeMs?: number;
92
- }
93
-
94
- function getErrorMessage(error: unknown): string {
95
- return error instanceof Error ? error.message : String(error);
96
- }
97
-
98
- function isNotFoundError(error: unknown): boolean {
99
- return (
100
- typeof error === "object" &&
101
- error !== null &&
102
- "code" in error &&
103
- (error as NodeJS.ErrnoException).code === "ENOENT"
104
- );
105
- }
106
-
107
- function isAsyncRunDir(root: string, entry: string): boolean {
108
- const entryPath = path.join(root, entry);
109
- try {
110
- return fs.statSync(entryPath).isDirectory();
111
- } catch (error) {
112
- if (isNotFoundError(error)) return false;
113
- throw new Error(`Failed to inspect async run path '${entryPath}': ${getErrorMessage(error)}`, {
114
- cause: error instanceof Error ? error : undefined,
115
- });
116
- }
117
- }
118
-
119
- function runDirTouchedSince(asyncDir: string, cutoffMs: number): boolean {
120
- try {
121
- if (fs.statSync(asyncDir).mtimeMs >= cutoffMs) return true;
122
- } catch {
123
- return false;
124
- }
125
- try {
126
- return fs.statSync(path.join(asyncDir, "status.json")).mtimeMs >= cutoffMs;
127
- } catch {
128
- return false;
129
- }
130
- }
131
-
132
- function outputFileMtime(outputFile: string | undefined): number | undefined {
133
- if (!outputFile) return undefined;
134
- try {
135
- return fs.statSync(outputFile).mtimeMs;
136
- } catch (error) {
137
- if (isNotFoundError(error)) return undefined;
138
- throw new Error(`Failed to inspect async output file '${outputFile}': ${getErrorMessage(error)}`, {
139
- cause: error instanceof Error ? error : undefined,
140
- });
141
- }
142
- }
143
-
144
- function deriveAsyncActivityState(
145
- asyncDir: string,
146
- status: AsyncStatus,
147
- ): { activityState?: ActivityState; lastActivityAt?: number } {
148
- if (status.state !== "running")
149
- return { activityState: status.activityState, lastActivityAt: status.lastActivityAt };
150
- const outputPath = status.outputFile
151
- ? path.isAbsolute(status.outputFile)
152
- ? status.outputFile
153
- : path.join(asyncDir, status.outputFile)
154
- : undefined;
155
- const currentStep = typeof status.currentStep === "number" ? status.steps?.[status.currentStep] : undefined;
156
- return {
157
- activityState: status.activityState,
158
- lastActivityAt:
159
- status.lastActivityAt ??
160
- outputFileMtime(outputPath) ??
161
- currentStep?.lastActivityAt ??
162
- currentStep?.startedAt ??
163
- status.startedAt,
164
- };
165
- }
166
-
167
- function statusToSummary(
168
- asyncDir: string,
169
- status: AsyncStatus & { cwd?: string },
170
- nestedWarnings: string[] = [],
171
- ): AsyncRunSummary {
172
- if (status.sessionId !== undefined && typeof status.sessionId !== "string") {
173
- throw new Error(`Invalid async status '${path.join(asyncDir, "status.json")}': sessionId must be a string.`);
174
- }
175
- const { activityState, lastActivityAt } = deriveAsyncActivityState(asyncDir, status);
176
- const steps = status.steps ?? [];
177
- const chainStepCount = status.chainStepCount ?? steps.length;
178
- const parallelGroups = normalizeParallelGroups(status.parallelGroups, steps.length, chainStepCount);
179
- let nestedChildren: NestedRunSummary[] = [];
180
- if (nestedWarnings.length === 0) {
181
- try {
182
- nestedChildren = projectNestedRegistryForRoot(status.runId || path.basename(asyncDir))?.children ?? [];
183
- } catch (error) {
184
- nestedWarnings.push(`Nested status unavailable: ${getErrorMessage(error)}`);
185
- }
186
- }
187
- const summarizedSteps = steps.map((step, index) => {
188
- const stepActivityState = step.activityState;
189
- const stepLastActivityAt = step.lastActivityAt;
190
- return {
191
- index,
192
- agent: step.agent,
193
- ...(step.label ? { label: step.label } : {}),
194
- ...(step.phase ? { phase: step.phase } : {}),
195
- ...(step.outputName ? { outputName: step.outputName } : {}),
196
- ...(step.structured ? { structured: step.structured } : {}),
197
- status: step.status,
198
- ...(stepActivityState ? { activityState: stepActivityState } : {}),
199
- ...(stepLastActivityAt ? { lastActivityAt: stepLastActivityAt } : {}),
200
- ...(step.currentTool ? { currentTool: step.currentTool } : {}),
201
- ...(step.currentToolArgs ? { currentToolArgs: step.currentToolArgs } : {}),
202
- ...(step.currentToolStartedAt ? { currentToolStartedAt: step.currentToolStartedAt } : {}),
203
- ...(step.currentPath ? { currentPath: step.currentPath } : {}),
204
- ...(step.recentTools ? { recentTools: step.recentTools.map((tool) => ({ ...tool })) } : {}),
205
- ...(step.recentOutput ? { recentOutput: [...step.recentOutput] } : {}),
206
- ...(step.turnCount !== undefined ? { turnCount: step.turnCount } : {}),
207
- ...(step.toolCount !== undefined ? { toolCount: step.toolCount } : {}),
208
- ...(step.durationMs !== undefined ? { durationMs: step.durationMs } : {}),
209
- ...(step.tokens ? { tokens: step.tokens } : {}),
210
- ...(step.skills ? { skills: step.skills } : {}),
211
- ...(step.model ? { model: step.model } : {}),
212
- ...(step.thinking ? { thinking: step.thinking } : {}),
213
- ...(step.fastMode !== undefined ? { fastMode: step.fastMode } : {}),
214
- ...(step.attemptedModels ? { attemptedModels: step.attemptedModels } : {}),
215
- ...(step.error ? { error: step.error } : {}),
216
- ...(step.children?.length ? { children: step.children } : {}),
217
- };
218
- });
219
- attachRootChildrenToSteps(status.runId || path.basename(asyncDir), summarizedSteps, nestedChildren);
220
- return {
221
- id: status.runId || path.basename(asyncDir),
222
- asyncDir,
223
- ...(status.sessionId ? { sessionId: status.sessionId } : {}),
224
- state: status.state,
225
- activityState,
226
- lastActivityAt,
227
- currentTool: status.currentTool,
228
- currentToolStartedAt: status.currentToolStartedAt,
229
- currentPath: status.currentPath,
230
- turnCount: status.turnCount,
231
- toolCount: status.toolCount,
232
- mode: status.mode,
233
- cwd: status.cwd,
234
- startedAt: status.startedAt,
235
- lastUpdate: status.lastUpdate,
236
- endedAt: status.endedAt,
237
- currentStep: status.currentStep,
238
- ...(status.chainStepCount !== undefined ? { chainStepCount: status.chainStepCount } : {}),
239
- ...(parallelGroups.length ? { parallelGroups } : {}),
240
- steps: summarizedSteps,
241
- ...(nestedChildren.length ? { nestedChildren } : {}),
242
- ...(nestedWarnings.length ? { nestedWarnings } : {}),
243
- ...(status.sessionDir ? { sessionDir: status.sessionDir } : {}),
244
- ...(status.outputFile ? { outputFile: status.outputFile } : {}),
245
- ...(status.totalTokens ? { totalTokens: status.totalTokens } : {}),
246
- ...(status.sessionFile ? { sessionFile: status.sessionFile } : {}),
247
- };
248
- }
249
-
250
- function sortRuns(runs: AsyncRunSummary[]): AsyncRunSummary[] {
251
- const rank = (state: AsyncRunSummary["state"]): number => {
252
- switch (state) {
253
- case "running":
254
- return 0;
255
- case "queued":
256
- return 1;
257
- case "failed":
258
- return 2;
259
- case "paused":
260
- return 2;
261
- case "complete":
262
- return 3;
263
- }
264
- };
265
- return [...runs].sort((a, b) => {
266
- const byState = rank(a.state) - rank(b.state);
267
- if (byState !== 0) return byState;
268
- const aTime = a.lastUpdate ?? a.endedAt ?? a.startedAt;
269
- const bTime = b.lastUpdate ?? b.endedAt ?? b.startedAt;
270
- return bTime - aTime;
271
- });
272
- }
273
-
274
- export function listAsyncRuns(asyncDirRoot: string, options: AsyncRunListOptions = {}): AsyncRunSummary[] {
275
- let entries: string[];
276
- try {
277
- entries = fs.readdirSync(asyncDirRoot).filter((entry) => isAsyncRunDir(asyncDirRoot, entry));
278
- } catch (error) {
279
- if (isNotFoundError(error)) return [];
280
- throw new Error(`Failed to list async runs in '${asyncDirRoot}': ${getErrorMessage(error)}`, {
281
- cause: error instanceof Error ? error : undefined,
282
- });
283
- }
284
-
285
- const allowedStates = options.states ? new Set(options.states) : undefined;
286
- const cutoff = options.maxAgeMs !== undefined ? (options.now?.() ?? Date.now()) - options.maxAgeMs : undefined;
287
- const runs: AsyncRunSummary[] = [];
288
- for (const entry of entries) {
289
- const asyncDir = path.join(asyncDirRoot, entry);
290
- // Recency cutoff: skip reconcile/read/parse work for long-untouched runs
291
- // (two stats instead of a full per-run reconciliation at startup).
292
- if (cutoff !== undefined && !runDirTouchedSince(asyncDir, cutoff)) continue;
293
- const reconciliation =
294
- options.reconcile === false
295
- ? undefined
296
- : reconcileAsyncRun(asyncDir, { resultsDir: options.resultsDir, kill: options.kill, now: options.now });
297
- const status = (reconciliation?.status ?? readStatus(asyncDir)) as (AsyncStatus & { cwd?: string }) | null;
298
- if (!status) continue;
299
- const nestedWarnings: string[] = [];
300
- try {
301
- const nestedRoute = findNestedRouteForRootId(status.runId || path.basename(asyncDir));
302
- if (nestedRoute)
303
- reconcileNestedAsyncDescendants(nestedRoute, {
304
- resultsDir: options.resultsDir,
305
- kill: options.kill,
306
- now: options.now,
307
- });
308
- } catch (error) {
309
- nestedWarnings.push(`Nested status unavailable: ${getErrorMessage(error)}`);
310
- }
311
- const summary = statusToSummary(asyncDir, status, nestedWarnings);
312
- if (allowedStates && !allowedStates.has(summary.state)) continue;
313
- if (options.sessionId && summary.sessionId !== options.sessionId) continue;
314
- runs.push(summary);
315
- }
316
-
317
- const sorted = sortRuns(runs);
318
- return options.limit !== undefined ? sorted.slice(0, options.limit) : sorted;
319
- }
320
-
321
- function formatActivityFacts(input: {
322
- activityState?: ActivityState;
323
- lastActivityAt?: number;
324
- currentTool?: string;
325
- currentToolStartedAt?: number;
326
- currentPath?: string;
327
- turnCount?: number;
328
- toolCount?: number;
329
- }): string | undefined {
330
- const facts: string[] = [];
331
- if (input.currentTool && input.currentToolStartedAt !== undefined)
332
- facts.push(`tool ${input.currentTool} ${formatDuration(Math.max(0, Date.now() - input.currentToolStartedAt))}`);
333
- else if (input.currentTool) facts.push(`tool ${input.currentTool}`);
334
- if (input.currentPath) facts.push(shortenPath(input.currentPath));
335
- if (input.turnCount !== undefined) facts.push(`${input.turnCount} turns`);
336
- if (input.toolCount !== undefined) facts.push(`${input.toolCount} tools`);
337
- const activity = formatActivityLabel(input.lastActivityAt, input.activityState);
338
- return activity || facts.length ? [activity, ...facts].filter(Boolean).join(" | ") : undefined;
339
- }
340
-
341
- function formatStepLine(step: AsyncRunStepSummary): string {
342
- const display = step.label ? `${step.label} (${step.agent})` : step.agent;
343
- const phase = step.phase ? `[${step.phase}] ` : "";
344
- const parts = [`${step.index + 1}. ${phase}${display}`, step.status];
345
- const activity = formatActivityFacts(step);
346
- if (activity) parts.push(activity);
347
- const modelThinking = formatModelThinking(step.model, step.thinking, step.fastMode);
348
- if (modelThinking) parts.push(modelThinking);
349
- if (step.durationMs !== undefined) parts.push(formatDuration(step.durationMs));
350
- if (step.tokens) parts.push(`${formatTokens(step.tokens.total)} tok`);
351
- return parts.join(" | ");
352
- }
353
-
354
- export function formatAsyncRunOutputPath(run: Pick<AsyncRunSummary, "asyncDir" | "outputFile">): string | undefined {
355
- if (!run.outputFile) return undefined;
356
- return path.isAbsolute(run.outputFile) ? run.outputFile : path.join(run.asyncDir, run.outputFile);
357
- }
358
-
359
- export function formatAsyncRunProgressLabel(
360
- run: Pick<AsyncRunSummary, "mode" | "state" | "currentStep" | "chainStepCount" | "parallelGroups" | "steps">,
361
- ): string {
362
- const stepCount = run.steps.length || 1;
363
- const chainStepCount = run.chainStepCount ?? stepCount;
364
- const groups = normalizeParallelGroups(run.parallelGroups, run.steps.length, chainStepCount);
365
- const activeGroup =
366
- run.currentStep !== undefined
367
- ? groups.find((group) => run.currentStep! >= group.start && run.currentStep! < group.start + group.count)
368
- : undefined;
369
- if (activeGroup) {
370
- const groupSteps = run.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count);
371
- const groupLabel = formatParallelOutcome(groupSteps, activeGroup.count, { showRunning: run.state === "running" });
372
- if (run.mode === "parallel") return groupLabel;
373
- return `step ${activeGroup.stepIndex + 1}/${chainStepCount} · parallel group: ${groupLabel}`;
374
- }
375
- if (run.mode === "parallel")
376
- return formatParallelOutcome(run.steps, stepCount, { showRunning: run.state === "running" });
377
- if (run.mode === "chain" && run.currentStep !== undefined && groups.length > 0) {
378
- const logicalStep = flatToLogicalStepIndex(run.currentStep, chainStepCount, groups);
379
- return `step ${logicalStep + 1}/${chainStepCount}`;
380
- }
381
- return run.currentStep !== undefined ? `step ${run.currentStep + 1}/${stepCount}` : `steps ${stepCount}`;
382
- }
383
-
384
- function formatRunHeader(run: AsyncRunSummary): string {
385
- const stepLabel = formatAsyncRunProgressLabel(run);
386
- const cwd = run.cwd ? shortenPath(run.cwd) : shortenPath(run.asyncDir);
387
- const activity = formatActivityFacts(run);
388
- return `${run.id} | ${run.state}${activity ? ` | ${activity}` : ""} | ${run.mode} | ${stepLabel} | ${cwd}`;
389
- }
390
-
391
- export function formatAsyncRunList(runs: AsyncRunSummary[], heading = "Active async runs"): string {
392
- if (runs.length === 0) return `No ${heading.toLowerCase()}.`;
393
-
394
- const lines = [`${heading}: ${runs.length}`, ""];
395
- for (const run of runs) {
396
- lines.push(`- ${formatRunHeader(run)}`);
397
- for (const step of run.steps) {
398
- lines.push(` ${formatStepLine(step)}`);
399
- lines.push(...formatNestedRunStatusLines(step.children, { indent: " ", maxLines: 12 }));
400
- }
401
- const attached = new Set(run.steps.flatMap((step) => step.children?.map((child) => child.id) ?? []));
402
- const unattached = run.nestedChildren?.filter((child) => !attached.has(child.id)) ?? [];
403
- lines.push(...formatNestedRunStatusLines(unattached, { indent: " ", maxLines: 12 }));
404
- for (const warning of run.nestedWarnings ?? []) lines.push(` Warning: ${warning}`);
405
- const outputPath = formatAsyncRunOutputPath(run);
406
- if (outputPath) lines.push(` output: ${shortenPath(outputPath)}`);
407
- if (run.sessionFile) lines.push(` session: ${shortenPath(run.sessionFile)}`);
408
- lines.push("");
409
- }
410
- return lines.join("\n").trimEnd();
411
- }
@@ -1,196 +0,0 @@
1
- import type { FrozenCompletionEnvelope } from "./result-file-claims.js";
2
-
3
- type CompletionClaimStatus = "delivered" | "retry" | "exhausted" | "conflict" | "released";
4
- type TerminalStatus = Extract<CompletionClaimStatus, "delivered" | "exhausted">;
5
-
6
- interface CompletionAttempt {
7
- status: CompletionClaimStatus;
8
- noProgressFailures: number;
9
- }
10
-
11
- interface CompletionFlight {
12
- promise: Promise<CompletionAttempt>;
13
- }
14
-
15
- export interface CompletionClaimSnapshot {
16
- intercomDelivered: boolean;
17
- localDelivered: boolean;
18
- noProgressFailures: number;
19
- terminalStatus?: TerminalStatus;
20
- envelope: FrozenCompletionEnvelope;
21
- }
22
-
23
- interface CompletionClaim extends CompletionClaimSnapshot {
24
- signature: string;
25
- inFlight?: CompletionFlight;
26
- completedAt?: number;
27
- lastTouchedAt: number;
28
- }
29
-
30
- export interface CompletionClaimResult extends CompletionAttempt {
31
- owner: boolean;
32
- }
33
-
34
- export interface CompletionDeliveryPhases {
35
- intercom?: (envelope: FrozenCompletionEnvelope) => Promise<boolean> | boolean;
36
- local?: (envelope: FrozenCompletionEnvelope) => Promise<boolean> | boolean;
37
- isOwned?: () => boolean;
38
- onState?: (snapshot: CompletionClaimSnapshot) => void;
39
- }
40
-
41
- export interface CompletionClaimInitial {
42
- intercomDelivered?: boolean;
43
- localDelivered?: boolean;
44
- noProgressFailures?: number;
45
- terminalStatus?: TerminalStatus;
46
- envelope?: FrozenCompletionEnvelope;
47
- }
48
-
49
- const STORE_KEY = "__atomicSubagentCompletionClaims";
50
- const DEFAULT_MAX_NO_PROGRESS_FAILURES = 8;
51
- const MAX_CLAIMS = 2048;
52
-
53
- function cloneEnvelope(envelope: FrozenCompletionEnvelope): FrozenCompletionEnvelope {
54
- return JSON.parse(JSON.stringify(envelope)) as FrozenCompletionEnvelope;
55
- }
56
-
57
- function claims(): Map<string, CompletionClaim> {
58
- const globalStore = globalThis as Record<string, unknown>;
59
- const existing = globalStore[STORE_KEY];
60
- if (existing instanceof Map) return existing as Map<string, CompletionClaim>;
61
- const created = new Map<string, CompletionClaim>();
62
- globalStore[STORE_KEY] = created;
63
- return created;
64
- }
65
-
66
- function prune(store: Map<string, CompletionClaim>, now: number, ttlMs: number): void {
67
- for (const [key, claim] of store) {
68
- if (claim.completedAt !== undefined && now - claim.completedAt > ttlMs) store.delete(key);
69
- }
70
- if (store.size <= MAX_CLAIMS) return;
71
- const disposable = [...store.entries()]
72
- .filter(([, claim]) => !claim.inFlight && !claim.intercomDelivered && !claim.localDelivered)
73
- .sort((a, b) => a[1].lastTouchedAt - b[1].lastTouchedAt);
74
- for (const [key] of disposable) {
75
- if (store.size <= MAX_CLAIMS) break;
76
- store.delete(key);
77
- }
78
- }
79
-
80
- function snapshot(claim: CompletionClaim): CompletionClaimSnapshot {
81
- return {
82
- intercomDelivered: claim.intercomDelivered,
83
- localDelivered: claim.localDelivered,
84
- noProgressFailures: claim.noProgressFailures,
85
- terminalStatus: claim.terminalStatus,
86
- envelope: cloneEnvelope(claim.envelope),
87
- };
88
- }
89
-
90
- function persist(claim: CompletionClaim, callback: CompletionDeliveryPhases["onState"]): void {
91
- claim.lastTouchedAt = Date.now();
92
- callback?.(snapshot(claim));
93
- }
94
-
95
- /** Atomically owns and advances one completion across aliases and watcher replacements. */
96
- export async function deliverClaimedCompletion(
97
- key: string,
98
- signature: string,
99
- ttlMs: number,
100
- phases: CompletionDeliveryPhases,
101
- maxNoProgressFailures = DEFAULT_MAX_NO_PROGRESS_FAILURES,
102
- initial: CompletionClaimInitial = {},
103
- envelope: FrozenCompletionEnvelope = { local: {} },
104
- ): Promise<CompletionClaimResult> {
105
- const store = claims();
106
- const now = Date.now();
107
- prune(store, now, ttlMs);
108
- let claim = store.get(key);
109
- if (!claim) {
110
- claim = {
111
- signature,
112
- envelope: cloneEnvelope(initial.envelope ?? envelope),
113
- intercomDelivered: initial.intercomDelivered === true,
114
- localDelivered: initial.localDelivered === true,
115
- noProgressFailures: initial.noProgressFailures ?? 0,
116
- terminalStatus: initial.terminalStatus,
117
- completedAt: initial.terminalStatus ? now : undefined,
118
- lastTouchedAt: now,
119
- };
120
- store.set(key, claim);
121
- persist(claim, phases.onState);
122
- } else if (claim.signature !== signature) {
123
- return { owner: false, status: "conflict", noProgressFailures: claim.noProgressFailures };
124
- }
125
- claim.lastTouchedAt = now;
126
- if (claim.terminalStatus)
127
- return { owner: false, status: claim.terminalStatus, noProgressFailures: claim.noProgressFailures };
128
- if (claim.inFlight) return { owner: false, ...(await claim.inFlight.promise) };
129
-
130
- const ownedClaim = claim;
131
- const hasVisibleProgress = () => ownedClaim.intercomDelivered || ownedClaim.localDelivered;
132
- const retireForOwnershipLoss = (): CompletionAttempt => {
133
- if (!hasVisibleProgress()) {
134
- store.delete(key);
135
- return { status: "released", noProgressFailures: ownedClaim.noProgressFailures };
136
- }
137
- persist(ownedClaim, phases.onState);
138
- return { status: "released", noProgressFailures: ownedClaim.noProgressFailures };
139
- };
140
- const attempt = (async (): Promise<CompletionAttempt> => {
141
- let progressed = false;
142
- const failed = (): CompletionAttempt => {
143
- if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
144
- ownedClaim.noProgressFailures = progressed ? 0 : ownedClaim.noProgressFailures + 1;
145
- if (ownedClaim.noProgressFailures >= Math.max(1, maxNoProgressFailures)) {
146
- ownedClaim.terminalStatus = "exhausted";
147
- ownedClaim.completedAt = Date.now();
148
- persist(ownedClaim, phases.onState);
149
- return { status: "exhausted", noProgressFailures: ownedClaim.noProgressFailures };
150
- }
151
- persist(ownedClaim, phases.onState);
152
- return { status: "retry", noProgressFailures: ownedClaim.noProgressFailures };
153
- };
154
- const runPhase = async (
155
- phase: ((value: FrozenCompletionEnvelope) => Promise<boolean> | boolean) | undefined,
156
- ): Promise<boolean | undefined> => {
157
- if (!phase) return undefined;
158
- if (phases.isOwned && !phases.isOwned()) return false;
159
- try {
160
- return await phase(cloneEnvelope(ownedClaim.envelope));
161
- } catch {
162
- return false;
163
- }
164
- };
165
- if (!ownedClaim.intercomDelivered && phases.intercom) {
166
- const delivered = await runPhase(phases.intercom);
167
- if (!delivered) return failed();
168
- ownedClaim.intercomDelivered = true;
169
- progressed = true;
170
- persist(ownedClaim, phases.onState);
171
- if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
172
- }
173
- if (!ownedClaim.localDelivered && phases.local) {
174
- const delivered = await runPhase(phases.local);
175
- if (!delivered) return failed();
176
- ownedClaim.localDelivered = true;
177
- progressed = true;
178
- persist(ownedClaim, phases.onState);
179
- if (phases.isOwned && !phases.isOwned()) return retireForOwnershipLoss();
180
- }
181
- ownedClaim.noProgressFailures = 0;
182
- ownedClaim.terminalStatus = "delivered";
183
- ownedClaim.completedAt = Date.now();
184
- persist(ownedClaim, phases.onState);
185
- return { status: "delivered", noProgressFailures: 0 };
186
- })();
187
- const flight: CompletionFlight = { promise: attempt };
188
- ownedClaim.inFlight = flight;
189
- try {
190
- return { owner: true, ...(await flight.promise) };
191
- } finally {
192
- // The explicit flight handle is the ownership token; comparing resolved
193
- // values would let an older attempt clear a newer in-flight claim.
194
- if (ownedClaim.inFlight === flight) ownedClaim.inFlight = undefined;
195
- }
196
- }