@bastani/atomic 0.9.19-alpha.5 → 0.9.19-alpha.7

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 (209) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  4. package/dist/builtin/intercom/broker/client.ts +19 -1
  5. package/dist/builtin/intercom/index.bundle.mjs +8 -1
  6. package/dist/builtin/intercom/package.json +1 -1
  7. package/dist/builtin/mcp/package.json +1 -1
  8. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  9. package/dist/builtin/subagents/README.md +3 -1
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +7 -7
  11. package/dist/builtin/subagents/package.json +1 -1
  12. package/dist/builtin/subagents/skills/subagent/SKILL.md +3 -1
  13. package/dist/builtin/subagents/src/extension/index.bundle.mjs +2 -1
  14. package/dist/builtin/web-access/CHANGELOG.md +13 -0
  15. package/dist/builtin/web-access/README.md +31 -24
  16. package/dist/builtin/web-access/index.bundle.mjs +16121 -80
  17. package/dist/builtin/web-access/package.json +2 -1
  18. package/dist/builtin/workflows/CHANGELOG.md +15 -0
  19. package/dist/builtin/workflows/README.md +1 -1
  20. package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
  21. package/dist/builtin/workflows/builtin/{chunk-vhmnzdj9.js → chunk-1jth021m.js} +1 -1
  22. package/dist/builtin/workflows/builtin/{chunk-p8jjwfg6.js → chunk-2377r57g.js} +4 -2
  23. package/dist/builtin/workflows/builtin/{chunk-hbnwv56f.js → chunk-31j2gs7h.js} +2 -2
  24. package/dist/builtin/workflows/builtin/{chunk-n8zysf1t.js → chunk-ngkqkzej.js} +1 -1
  25. package/dist/builtin/workflows/builtin/{chunk-1nbq96fh.js → chunk-nkrafh9s.js} +1 -1
  26. package/dist/builtin/workflows/builtin/{chunk-1kx4aggw.js → chunk-wf741bv3.js} +2 -2
  27. package/dist/builtin/workflows/builtin/{chunk-t6x2d78s.js → chunk-z29qbehr.js} +1 -1
  28. package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
  29. package/dist/builtin/workflows/builtin/goal.js +3 -3
  30. package/dist/builtin/workflows/builtin/index.js +7 -7
  31. package/dist/builtin/workflows/builtin/ralph.js +3 -3
  32. package/dist/builtin/workflows/builtin/tournament.js +2 -2
  33. package/dist/builtin/workflows/package.json +1 -1
  34. package/dist/builtin/workflows/src/extension/index.bundle.mjs +339 -31
  35. package/dist/builtin/workflows/src/index.js +67 -19
  36. package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -0
  37. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  38. package/dist/core/agent-session-tool-registry.js +10 -0
  39. package/dist/core/agent-session-tool-registry.js.map +1 -1
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/tools/bash.d.ts +1 -1
  42. package/dist/core/tools/bash.d.ts.map +1 -1
  43. package/dist/core/tools/bash.js +3 -2
  44. package/dist/core/tools/bash.js.map +1 -1
  45. package/dist/core/tools/edit.d.ts +3 -0
  46. package/dist/core/tools/edit.d.ts.map +1 -1
  47. package/dist/core/tools/edit.js +91 -12
  48. package/dist/core/tools/edit.js.map +1 -1
  49. package/dist/core/tools/file-mutation-coordinator.d.ts +255 -0
  50. package/dist/core/tools/file-mutation-coordinator.d.ts.map +1 -0
  51. package/dist/core/tools/file-mutation-coordinator.js +300 -0
  52. package/dist/core/tools/file-mutation-coordinator.js.map +1 -0
  53. package/dist/core/tools/file-mutation-queue.d.ts +14 -1
  54. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  55. package/dist/core/tools/file-mutation-queue.js +15 -3
  56. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  57. package/dist/core/tools/hashline.d.ts +9 -0
  58. package/dist/core/tools/hashline.d.ts.map +1 -1
  59. package/dist/core/tools/hashline.js +12 -1
  60. package/dist/core/tools/hashline.js.map +1 -1
  61. package/dist/core/tools/index.d.ts +9 -1
  62. package/dist/core/tools/index.d.ts.map +1 -1
  63. package/dist/core/tools/index.js +67 -12
  64. package/dist/core/tools/index.js.map +1 -1
  65. package/dist/core/tools/non-minting-snapshot-store.d.ts +49 -0
  66. package/dist/core/tools/non-minting-snapshot-store.d.ts.map +1 -0
  67. package/dist/core/tools/non-minting-snapshot-store.js +64 -0
  68. package/dist/core/tools/non-minting-snapshot-store.js.map +1 -0
  69. package/dist/core/tools/powershell.d.ts +2 -2
  70. package/dist/core/tools/powershell.d.ts.map +1 -1
  71. package/dist/core/tools/powershell.js +2 -5
  72. package/dist/core/tools/powershell.js.map +1 -1
  73. package/dist/core/tools/read-document-extract.js.map +1 -1
  74. package/dist/core/tools/render-utils.js.map +1 -1
  75. package/dist/core/tools/write.d.ts +30 -1
  76. package/dist/core/tools/write.d.ts.map +1 -1
  77. package/dist/core/tools/write.js +97 -8
  78. package/dist/core/tools/write.js.map +1 -1
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js.map +1 -1
  82. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  83. package/dist/modes/interactive/components/task-live-transcript.d.ts +1 -1
  84. package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -1
  85. package/dist/modes/interactive/components/task-live-transcript.js +19 -11
  86. package/dist/modes/interactive/components/task-live-transcript.js.map +1 -1
  87. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  88. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  89. package/dist/modes/interactive/interactive-mode-base.js +3 -1
  90. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  91. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -1
  92. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  93. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  94. package/dist/modes/interactive/interactive-render-chat.js +28 -4
  95. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  96. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  97. package/dist/modes/interactive/interactive-startup.js +3 -0
  98. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  99. package/dist/modes/interactive-engine/activity-watchdog.d.ts +2 -2
  100. package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -1
  101. package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -1
  102. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts +3 -1
  103. package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts.map +1 -1
  104. package/dist/modes/interactive-engine/engine-diagnostic-view.js +11 -0
  105. package/dist/modes/interactive-engine/engine-diagnostic-view.js.map +1 -1
  106. package/dist/modes/interactive-engine/isolated-runtime.js +2 -1
  107. package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
  108. package/dist/modes/rpc/rpc-client-process.d.ts +2 -0
  109. package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
  110. package/dist/modes/rpc/rpc-client-process.js +23 -1
  111. package/dist/modes/rpc/rpc-client-process.js.map +1 -1
  112. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  113. package/dist/modes/rpc/rpc-client.js +20 -3
  114. package/dist/modes/rpc/rpc-client.js.map +1 -1
  115. package/dist/utils/markit.d.ts +2 -0
  116. package/dist/utils/markit.d.ts.map +1 -1
  117. package/dist/utils/markit.js +65 -5
  118. package/dist/utils/markit.js.map +1 -1
  119. package/docs/background-tasks.md +15 -11
  120. package/docs/build.md +51 -0
  121. package/docs/changelog.mdx +8 -8
  122. package/docs/compaction/reference.md +267 -0
  123. package/docs/compaction.md +36 -219
  124. package/docs/computer-use.md +35 -0
  125. package/docs/containerization.md +9 -5
  126. package/docs/custom-provider/api-reference.md +145 -0
  127. package/docs/custom-provider/oauth.md +131 -0
  128. package/docs/custom-provider/override.md +34 -0
  129. package/docs/custom-provider/registration.md +163 -0
  130. package/docs/custom-provider/streaming.md +214 -0
  131. package/docs/custom-provider.md +43 -607
  132. package/docs/development.md +87 -0
  133. package/docs/docs.json +199 -76
  134. package/docs/environment-variables.md +1 -1
  135. package/docs/extensions/api-reference.md +1001 -0
  136. package/docs/extensions/authoring.md +676 -0
  137. package/docs/extensions/events.md +793 -0
  138. package/docs/extensions/examples.md +94 -0
  139. package/docs/extensions/ui.md +470 -0
  140. package/docs/extensions.md +270 -2768
  141. package/docs/getting-started/authentication.md +55 -0
  142. package/docs/getting-started/first-session.md +172 -0
  143. package/docs/getting-started/installation.md +154 -0
  144. package/docs/getting-started/project-instructions.md +43 -0
  145. package/docs/guides/configuration.md +65 -0
  146. package/docs/guides/intercom.md +24 -0
  147. package/docs/guides/non-interactive.md +33 -0
  148. package/docs/guides/subagents.md +24 -0
  149. package/docs/guides/workflows.md +27 -0
  150. package/docs/guides.md +41 -0
  151. package/docs/index.md +13 -45
  152. package/docs/intercom/operations.md +178 -0
  153. package/docs/intercom/reference.md +146 -0
  154. package/docs/intercom.md +54 -259
  155. package/docs/json.md +17 -0
  156. package/docs/llama-cpp.md +5 -0
  157. package/docs/models/artificial-analysis-index.md +89 -0
  158. package/docs/models/evals.md +2 -2
  159. package/docs/models/model-selection.md +3 -3
  160. package/docs/models/pareto-efficiency.md +2 -2
  161. package/docs/models/reference.md +601 -0
  162. package/docs/models.md +45 -550
  163. package/docs/packages/authoring.md +88 -0
  164. package/docs/packages/reference.md +43 -0
  165. package/docs/packages.md +28 -107
  166. package/docs/programmatic.md +29 -0
  167. package/docs/prompt-templates.md +11 -0
  168. package/docs/providers/reference.md +23 -0
  169. package/docs/providers.md +10 -15
  170. package/docs/quickstart.md +44 -238
  171. package/docs/reference/cli.md +252 -0
  172. package/docs/reference.md +52 -0
  173. package/docs/rpc/examples.md +64 -0
  174. package/docs/rpc/extension-ui.md +198 -0
  175. package/docs/rpc/protocol.md +1341 -0
  176. package/docs/rpc.md +109 -1346
  177. package/docs/sdk/reference.md +1090 -0
  178. package/docs/sdk.md +56 -1002
  179. package/docs/session-format.md +2 -0
  180. package/docs/sessions.md +6 -10
  181. package/docs/settings.md +6 -45
  182. package/docs/skills/authoring.md +95 -0
  183. package/docs/skills/reference.md +60 -0
  184. package/docs/skills.md +20 -122
  185. package/docs/subagents/authoring.md +37 -0
  186. package/docs/subagents/reference.md +60 -0
  187. package/docs/subagents.md +42 -96
  188. package/docs/terminal-setup.md +1 -1
  189. package/docs/themes/reference.md +176 -0
  190. package/docs/themes.md +21 -135
  191. package/docs/tmux.md +5 -0
  192. package/docs/tools/edit.md +5 -0
  193. package/docs/tools.md +31 -0
  194. package/docs/tui/reference.md +343 -0
  195. package/docs/tui.md +23 -286
  196. package/docs/usage.md +26 -209
  197. package/docs/web-access.md +40 -0
  198. package/docs/windows.md +2 -1
  199. package/docs/workflows/api-reference.md +11 -4
  200. package/docs/workflows/authoring.md +4 -2
  201. package/docs/workflows/builtins.md +2 -2
  202. package/docs/workflows/operations.md +11 -7
  203. package/docs/workflows/reliable-design.md +21 -3
  204. package/docs/workflows/verification.md +8 -0
  205. package/examples/extensions/gondolin/index.ts +116 -148
  206. package/examples/extensions/gondolin/package.json +1 -1
  207. package/examples/extensions/ssh.ts +56 -34
  208. package/npm-shrinkwrap.json +33 -33
  209. package/package.json +4 -4
@@ -76420,6 +76420,7 @@ class StageUiBroker {
76420
76420
  };
76421
76421
  }
76422
76422
  requestCustomUi(runId, stageId, factory, options, signal) {
76423
+ signal = options?.signal ? signal ? AbortSignal.any([signal, options.signal]) : options.signal : signal;
76423
76424
  if (signal?.aborted) {
76424
76425
  return Promise.reject(signal.reason ?? new Error("atomic-workflows: stage UI request aborted"));
76425
76426
  }
@@ -82123,6 +82124,108 @@ function collectDefinitionName(tokens, localValues, workflowNames) {
82123
82124
  }
82124
82125
  return;
82125
82126
  }
82127
+ function discoveryField(object) {
82128
+ if (object?.[0]?.value !== "{" || object.at(-1)?.value !== "}")
82129
+ return;
82130
+ let value2;
82131
+ for (const field of arrayElements(object)) {
82132
+ let key = field;
82133
+ while (["get", "set", "async", "*"].includes(key[0]?.value ?? ""))
82134
+ key = key.slice(1);
82135
+ if (key[0]?.value === "[" || key !== field && key[0]?.value === "possibleStageNames")
82136
+ return;
82137
+ if (field[0]?.value === ".") {
82138
+ if (value2 !== undefined)
82139
+ return;
82140
+ continue;
82141
+ }
82142
+ if (field[0]?.value !== "possibleStageNames")
82143
+ continue;
82144
+ if (value2 !== undefined || field[1]?.value !== ":")
82145
+ return;
82146
+ value2 = field.slice(2);
82147
+ }
82148
+ return value2;
82149
+ }
82150
+ function literalDiscoveryNames(value2) {
82151
+ if (value2?.[0]?.value !== "[" || value2.at(-1)?.value !== "]")
82152
+ return;
82153
+ const names = [];
82154
+ for (const element of arrayElements(value2)) {
82155
+ if (element.length !== 1 || element[0]?.kind !== "string")
82156
+ return;
82157
+ names.push(element[0].value);
82158
+ }
82159
+ return names.length > 0 ? names : undefined;
82160
+ }
82161
+ function discoveryHelpers(tokens) {
82162
+ const helpers = [];
82163
+ for (let index = 0;index < tokens.length; index += 1) {
82164
+ if (tokens[index]?.value !== "function" || tokens[index + 1]?.kind !== "ident")
82165
+ continue;
82166
+ let open = index + 2;
82167
+ if (tokens[open]?.value === "<")
82168
+ open = (matchBracket(tokens, open, "<", ">") ?? tokens.length) + 1;
82169
+ if (tokens[open]?.value !== "(")
82170
+ continue;
82171
+ const close = matchBracket(tokens, open, "(", ")");
82172
+ if (close === undefined)
82173
+ continue;
82174
+ let bodyOpen = close + 1;
82175
+ while (bodyOpen < tokens.length && tokens[bodyOpen]?.value !== "{")
82176
+ bodyOpen += 1;
82177
+ const bodyClose = matchBracket(tokens, bodyOpen, "{", "}");
82178
+ if (bodyClose === undefined)
82179
+ continue;
82180
+ const preceding = tokens[index - (tokens[index - 1]?.value === "async" ? 2 : 1)]?.value;
82181
+ helpers.push({
82182
+ name: tokens[index + 1].value,
82183
+ nameIndex: index + 1,
82184
+ params: splitTopLevelArguments({ method: "parallel", argsOpen: open }, tokens),
82185
+ bodyOpen,
82186
+ bodyClose,
82187
+ declaration: preceding === undefined || ["export", ";", "{", "}"].includes(preceding)
82188
+ });
82189
+ }
82190
+ return helpers;
82191
+ }
82192
+ function hasDiscoveryDestructuringWrite(tokens, parameter) {
82193
+ for (let index = 0;index < tokens.length; index += 1) {
82194
+ const open = tokens[index]?.value;
82195
+ if (open !== "[" && open !== "{")
82196
+ continue;
82197
+ const close = matchBracket(tokens, index, open, open === "[" ? "]" : "}");
82198
+ if (close === undefined || !["=", "of", "in"].includes(tokens[close + 1]?.value ?? ""))
82199
+ continue;
82200
+ if (tokens.slice(index + 1, close).some((token) => token.kind === "ident" && token.value === parameter))
82201
+ return true;
82202
+ }
82203
+ return false;
82204
+ }
82205
+ function discoveryCalls(tokens, name, declaration) {
82206
+ const calls = [];
82207
+ for (let index = 0;index < tokens.length; index += 1) {
82208
+ if (tokens[index]?.value === "import") {
82209
+ while (index < tokens.length && tokens[index]?.kind !== "string")
82210
+ index += 1;
82211
+ continue;
82212
+ }
82213
+ if (tokens[index]?.value === "export" && tokens[index + 1]?.value === "{") {
82214
+ const close = matchBracket(tokens, index + 1, "{", "}") ?? tokens.length;
82215
+ const exported = tokens.slice(index + 2, close);
82216
+ if (exported.some((token, offset) => token.value === name && (declaration === undefined || exported[offset + 1]?.value === "as")))
82217
+ return;
82218
+ index = close;
82219
+ continue;
82220
+ }
82221
+ if (tokens[index]?.kind !== "ident" || tokens[index]?.value !== name || index === declaration)
82222
+ continue;
82223
+ if (tokens[index + 1]?.value !== "(" || [".", "?.", "function"].includes(tokens[index - 1]?.value ?? ""))
82224
+ return;
82225
+ calls.push(index + 1);
82226
+ }
82227
+ return calls;
82228
+ }
82126
82229
 
82127
82230
  class PossibleStagesScanner {
82128
82231
  stages = new Set;
@@ -82131,6 +82234,7 @@ class PossibleStagesScanner {
82131
82234
  maxDepth;
82132
82235
  units = new Map;
82133
82236
  aliasPool = new Set;
82237
+ closure = [];
82134
82238
  constructor(maxDepth) {
82135
82239
  this.maxDepth = maxDepth;
82136
82240
  }
@@ -82166,11 +82270,17 @@ class PossibleStagesScanner {
82166
82270
  this.aliasPool.add(alias);
82167
82271
  }
82168
82272
  }
82169
- for (const path of ordered) {
82170
- const unit = this.units.get(path);
82171
- if (unit === undefined)
82172
- continue;
82173
- this.scanUnit(unit, path, boundaryPrefix, depth, ancestorStack);
82273
+ const previousClosure = this.closure;
82274
+ this.closure = ordered;
82275
+ try {
82276
+ for (const path of ordered) {
82277
+ const unit = this.units.get(path);
82278
+ if (unit === undefined)
82279
+ continue;
82280
+ this.scanUnit(unit, path, boundaryPrefix, depth, ancestorStack);
82281
+ }
82282
+ } finally {
82283
+ this.closure = previousClosure;
82174
82284
  }
82175
82285
  }
82176
82286
  unitFor(path) {
@@ -82284,7 +82394,127 @@ class PossibleStagesScanner {
82284
82394
  }
82285
82395
  return resolveRelativeSpecifier(specifier, importingFile);
82286
82396
  }
82397
+ hasDataOnlyDiscoveryOptions(argument) {
82398
+ if (argument?.[0]?.value !== "{" || argument.at(-1)?.value !== "}")
82399
+ return false;
82400
+ return arrayElements(argument).every((field) => (field[0]?.kind === "ident" || field[0]?.kind === "string") && field[0].value !== "__proto__" && field[1]?.value === ":");
82401
+ }
82402
+ discoveryNames(call, unit, path) {
82403
+ if (call.method !== "parallel")
82404
+ return;
82405
+ const value2 = discoveryField(splitTopLevelArguments(call, unit.tokens)[1]);
82406
+ const literal = literalDiscoveryNames(value2);
82407
+ if (literal !== undefined)
82408
+ return literal;
82409
+ if (value2?.length !== 3 || value2[0]?.kind !== "ident" || value2[1]?.value !== "." || value2[2]?.value !== "possibleStageNames")
82410
+ return;
82411
+ const owner = discoveryHelpers(unit.tokens).filter((helper) => helper.bodyOpen < call.argsOpen && helper.bodyClose > call.argsOpen).at(-1);
82412
+ if (owner === undefined || !owner.declaration)
82413
+ return;
82414
+ const parameter = owner.params.findIndex((param) => param[0]?.value === value2[0]?.value);
82415
+ if (parameter < 0)
82416
+ return;
82417
+ for (const param of owner.params) {
82418
+ if (param[0]?.kind !== "ident")
82419
+ return;
82420
+ const assignment = param.findIndex((token) => token.value === "=");
82421
+ if (assignment < 0)
82422
+ continue;
82423
+ const initial = param.slice(assignment + 1);
82424
+ const emptyObject = initial.length === 2 && initial[0]?.value === "{" && initial[1]?.value === "}";
82425
+ const scalar = initial.length === 1 && (initial[0]?.kind === "string" || ["true", "false", "null", "undefined"].includes(initial[0]?.value ?? ""));
82426
+ if (!emptyObject && !scalar)
82427
+ return;
82428
+ }
82429
+ const body = unit.tokens.slice(owner.bodyOpen, owner.bodyClose);
82430
+ if (body.some((token) => token.kind === "ident" && token.value === "arguments"))
82431
+ return;
82432
+ if (hasDiscoveryDestructuringWrite(body, value2[0].value))
82433
+ return;
82434
+ const forwarded = new Set;
82435
+ const spreadOptions = new Set;
82436
+ for (let index = 0;index < body.length; index += 1) {
82437
+ const parallel = matchCtxCall(body, index, this.aliasPool);
82438
+ if (parallel?.method !== "parallel")
82439
+ continue;
82440
+ const parallelOptions = splitTopLevelArguments(parallel, body)[1];
82441
+ const field = discoveryField(parallelOptions);
82442
+ if (parallelOptions?.[0]?.value === "{") {
82443
+ for (const entry of arrayElements(parallelOptions)) {
82444
+ if (entry.length === 4 && entry.slice(0, 3).every((token) => token.value === "."))
82445
+ spreadOptions.add(entry[3]);
82446
+ }
82447
+ }
82448
+ if (field?.length === 3 && field[0]?.value === value2[0].value && field[1]?.value === "." && field[2]?.value === "possibleStageNames")
82449
+ forwarded.add(field[0]);
82450
+ }
82451
+ for (let index = 0;index < body.length; index += 1) {
82452
+ if (body[index]?.value !== value2[0]?.value)
82453
+ continue;
82454
+ if (body[index + 2]?.value === "possibleStageNames" && !forwarded.has(body[index]))
82455
+ return;
82456
+ const destructured = body[index - 2]?.value === "}" && body[index - 1]?.value === "=" && body[index + 1]?.value === ";";
82457
+ if (destructured) {
82458
+ let matched = false;
82459
+ for (let open = 0;open < index - 2; open += 1) {
82460
+ if (body[open]?.value !== "{" || matchBracket(body, open, "{", "}") !== index - 2)
82461
+ continue;
82462
+ if (body[open - 1]?.value !== "const")
82463
+ return;
82464
+ matched = true;
82465
+ for (const entry of arrayElements(body.slice(open, index - 1))) {
82466
+ if (entry.length === 1 && entry[0]?.kind === "ident" && entry[0].value !== "possibleStageNames")
82467
+ continue;
82468
+ if (entry.length !== 4 || !entry.slice(0, 3).every((token) => token.value === ".") || entry[3]?.kind !== "ident")
82469
+ return;
82470
+ const rest = entry[3];
82471
+ for (let use = 0;use < body.length; use += 1) {
82472
+ const token = body[use];
82473
+ if (token?.kind !== "ident" || token.value !== rest.value || token === rest)
82474
+ continue;
82475
+ if (spreadOptions.has(token))
82476
+ continue;
82477
+ if (body[use - 3]?.value === "const" && body[use - 2]?.kind === "ident" && body[use - 1]?.value === "=" && body[use + 1]?.value === "." && body[use + 2]?.value === "concurrency" && body[use + 3]?.value === ";")
82478
+ continue;
82479
+ return;
82480
+ }
82481
+ }
82482
+ }
82483
+ if (!matched)
82484
+ return;
82485
+ }
82486
+ if (!destructured && !forwarded.has(body[index]))
82487
+ return;
82488
+ }
82489
+ const names = [];
82490
+ for (const callerPath of this.closure) {
82491
+ const caller = this.units.get(callerPath);
82492
+ if (caller === undefined)
82493
+ continue;
82494
+ if ([...caller.imports.values()].some((binding) => binding.importedName === undefined && resolveRelativeSpecifier(binding.specifier, callerPath) === path))
82495
+ return;
82496
+ const references = callerPath === path ? [owner.name] : [...caller.imports].filter(([, binding]) => binding.importedName === owner.name && resolveRelativeSpecifier(binding.specifier, callerPath) === path).map(([local]) => local);
82497
+ for (const reference of references) {
82498
+ const calls = discoveryCalls(caller.tokens, reference, callerPath === path ? owner.nameIndex : undefined);
82499
+ if (calls === undefined)
82500
+ return;
82501
+ for (const argsOpen of calls) {
82502
+ const argument = splitTopLevelArguments({ method: "parallel", argsOpen }, caller.tokens)[parameter];
82503
+ if (!this.hasDataOnlyDiscoveryOptions(argument))
82504
+ return;
82505
+ const declared = literalDiscoveryNames(discoveryField(argument));
82506
+ if (declared === undefined)
82507
+ return;
82508
+ names.push(...declared);
82509
+ }
82510
+ }
82511
+ }
82512
+ return names.length > 0 || this.closure[0] !== path ? names : undefined;
82513
+ }
82287
82514
  stepNamesForStepsCall(call, unit, path) {
82515
+ const declared = this.discoveryNames(call, unit, path);
82516
+ if (declared !== undefined)
82517
+ return declared;
82288
82518
  const first = firstArgumentTokens(call, unit.tokens);
82289
82519
  if (first === undefined || first.length === 0)
82290
82520
  return [];
@@ -90858,7 +91088,8 @@ async function warm_first_fan_out(ctx, steps, prefixKeyOf, options = {}) {
90858
91088
  const warmResults = await ctx.parallel(warmSteps, {
90859
91089
  ...parallelOptions,
90860
91090
  concurrency: boundedConcurrency(warmSteps.length, warmConcurrency ?? DEFAULT_WARM_CONCURRENCY, inheritedConcurrency),
90861
- failFast: false
91091
+ failFast: false,
91092
+ possibleStageNames: options.possibleStageNames
90862
91093
  });
90863
91094
  for (const [resultIndex, result] of warmResults.entries()) {
90864
91095
  const originalIndex = warmIndices[resultIndex];
@@ -90873,7 +91104,8 @@ async function warm_first_fan_out(ctx, steps, prefixKeyOf, options = {}) {
90873
91104
  const restSteps = restIndices.map((index) => steps[index]);
90874
91105
  const restResults = await ctx.parallel(restSteps, {
90875
91106
  ...parallelOptions,
90876
- concurrency: boundedConcurrency(restSteps.length, undefined, inheritedConcurrency)
91107
+ concurrency: boundedConcurrency(restSteps.length, undefined, inheritedConcurrency),
91108
+ possibleStageNames: options.possibleStageNames
90877
91109
  });
90878
91110
  for (const [resultIndex, result] of restResults.entries()) {
90879
91111
  const originalIndex = restIndices[resultIndex];
@@ -91082,7 +91314,7 @@ async function runAdversarialVerification(ctx) {
91082
91314
  const runWave = async (pending, reaskWave) => {
91083
91315
  if (pending.length === 0)
91084
91316
  return { valid: [], invalid: [], results: [] };
91085
- const reports = await warm_first_fan_out(ctx, pending.map((cell) => scoreStep(cell, reaskWave, scoringHead, criteriaPath)), () => scoringHead, { concurrency: Math.min(pending.length, 4), failFast: false });
91317
+ const reports = await warm_first_fan_out(ctx, pending.map((cell) => scoreStep(cell, reaskWave, scoringHead, criteriaPath)), () => scoringHead, { concurrency: Math.min(pending.length, 4), failFast: false, possibleStageNames: ["verifier-*-*-*", "verifier-*-*-*-reask-*"] });
91086
91318
  const byName = new Map;
91087
91319
  for (const report of reports) {
91088
91320
  const name = report.name ?? report.stageName;
@@ -96470,7 +96702,7 @@ async function runTournament(ctx) {
96470
96702
  if (stages.length === 0)
96471
96703
  return { preferences: [], results: [] };
96472
96704
  executed += stages.length;
96473
- const results = await warm_first_fan_out(ctx, stages.map((stage) => stage.step), (_step, index) => `${stages[index].slot1}:${stages[index].slot2}`, { concurrency: maxConcurrency, failFast: false });
96705
+ const results = await warm_first_fan_out(ctx, stages.map((stage) => stage.step), (_step, index) => `${stages[index].slot1}:${stages[index].slot2}`, { concurrency: maxConcurrency, failFast: false, possibleStageNames: ["judge-*-*-*-r*"] });
96474
96706
  const phaseResults = [...results];
96475
96707
  for (const stage of stages) {
96476
96708
  let report = judgeReport(resultFor(results, stage.name)?.structured);
@@ -104255,21 +104487,17 @@ function throwFinalizationError(error) {
104255
104487
  function createTrackedStageCaller(input) {
104256
104488
  const { runtime } = input;
104257
104489
  const readinessGateEnabled = runtime.opts.confirmStageReadiness !== undefined || runtime.opts.usePromptNodesForUi === true;
104258
- const confirmReadiness = async () => {
104259
- try {
104260
- if (runtime.opts.confirmStageReadiness !== undefined) {
104261
- const ready = await runtime.opts.confirmStageReadiness({
104262
- runId: runtime.runId,
104263
- stageId: runtime.stageId,
104264
- stageName: runtime.name,
104265
- signal: runtime.signal
104266
- });
104267
- return ready ? { action: "advance" } : { action: "stay" };
104268
- }
104269
- return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, runtime.signal);
104270
- } catch {
104271
- return { action: "advance" };
104272
- }
104490
+ const confirmReadiness = async (signal) => {
104491
+ if (runtime.opts.confirmStageReadiness !== undefined) {
104492
+ const ready = await raceAbort(runtime.opts.confirmStageReadiness({
104493
+ runId: runtime.runId,
104494
+ stageId: runtime.stageId,
104495
+ stageName: runtime.name,
104496
+ signal
104497
+ }), signal);
104498
+ return ready ? { action: "advance" } : { action: "stay" };
104499
+ }
104500
+ return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, signal);
104273
104501
  };
104274
104502
  const suppressReadinessForCurrentTurn = () => {
104275
104503
  runtime.state.askUserQuestionObservedThisTurn = false;
@@ -104423,9 +104651,35 @@ function createTrackedStageCaller(input) {
104423
104651
  });
104424
104652
  try {
104425
104653
  while (runtime.state.askUserQuestionObservedThisTurn || repeatReadinessAfterChatTurn) {
104426
- const decision = await confirmReadiness();
104654
+ runtime.signal.throwIfAborted();
104655
+ if (runtime.stageSnapshot.status === "paused" || runtime.stageSnapshot.status === "blocked") {
104656
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
104657
+ continue;
104658
+ }
104659
+ const controller = new AbortController;
104660
+ runtime.state.readinessController = controller;
104661
+ let decision;
104662
+ try {
104663
+ decision = await confirmReadiness(AbortSignal.any([runtime.signal, controller.signal]));
104664
+ if (decision.action === "advance" || decision.message !== undefined) {
104665
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
104666
+ }
104667
+ runtime.signal.throwIfAborted();
104668
+ if (controller.signal.aborted) {
104669
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
104670
+ continue;
104671
+ }
104672
+ } catch (error) {
104673
+ runtime.signal.throwIfAborted();
104674
+ if (controller.signal.aborted) {
104675
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
104676
+ continue;
104677
+ }
104678
+ throw error;
104679
+ }
104427
104680
  if (decision.action === "advance")
104428
104681
  break;
104682
+ delete runtime.state.readinessController;
104429
104683
  if (runtime.signal.aborted)
104430
104684
  break;
104431
104685
  runtime.state.askUserQuestionObservedThisTurn = false;
@@ -104568,9 +104822,17 @@ function createTrackedStageCaller(input) {
104568
104822
  const failure = runtime.classifyExecutorFailure(durableCheckpointError.error);
104569
104823
  applyTerminalStageState = () => applyFailureToStage(runtime.stageSnapshot, failure);
104570
104824
  }
104571
- if (!runtime.state.stageFinalized)
104572
- applyTerminalStageState?.();
104573
104825
  try {
104826
+ if (terminalStateIsSuccess && runtime.state.readinessController !== undefined) {
104827
+ let pauseVersion;
104828
+ do {
104829
+ pauseVersion = runtime.state.readinessPauseVersion;
104830
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
104831
+ } while (pauseVersion !== runtime.state.readinessPauseVersion);
104832
+ runtime.signal.throwIfAborted();
104833
+ }
104834
+ if (!runtime.state.stageFinalized)
104835
+ applyTerminalStageState?.();
104574
104836
  await runtime.finalizeStageSnapshot();
104575
104837
  } catch (err) {
104576
104838
  finalizationError ??= { thrown: true, error: err };
@@ -104588,6 +104850,9 @@ function createTrackedStageCaller(input) {
104588
104850
  input.limiter.release();
104589
104851
  if (finalizationError !== undefined)
104590
104852
  throwFinalizationError(finalizationError.error);
104853
+ delete runtime.state.readinessController;
104854
+ if (terminalStateIsSuccess && readinessGateEnabled)
104855
+ runtime.signal.throwIfAborted();
104591
104856
  }
104592
104857
  };
104593
104858
  }
@@ -104908,12 +105173,26 @@ function createStageControlHandle(runtime) {
104908
105173
  async pause() {
104909
105174
  runtime.throwIfStageMutationBlocked();
104910
105175
  const statusBeforePause = runtime.stageSnapshot.status;
105176
+ let readinessPauseVersion;
105177
+ if (runtime.state.readinessController !== undefined) {
105178
+ runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
105179
+ readinessPauseVersion = (runtime.state.readinessPauseVersion ?? 0) + 1;
105180
+ runtime.state.readinessPauseVersion = readinessPauseVersion;
105181
+ }
104911
105182
  if (statusBeforePause === "pending" || statusBeforePause === "running" || runtime.innerCtx.isStreaming) {
104912
- await runtime.innerCtx.__requestPause();
105183
+ try {
105184
+ await runtime.innerCtx.__requestPause();
105185
+ } catch (error) {
105186
+ if (readinessPauseVersion !== undefined && runtime.state.readinessPauseVersion === readinessPauseVersion && runtime.stageSnapshot.status !== "paused" && runtime.stageSnapshot.status !== "blocked" && !runtime.scheduler.hasCascadePauseOwners(runtime.stageId)) {
105187
+ runtime.scheduler.releaseStageBarrier(runtime.stageId);
105188
+ }
105189
+ throw error;
105190
+ }
104913
105191
  }
104914
105192
  const changed = runtime.activeStore.recordStagePaused(runtime.runId, runtime.stageId);
104915
105193
  if (changed) {
104916
105194
  runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
105195
+ runtime.state.readinessController?.abort(new Error("atomic-workflows: readiness paused"));
104917
105196
  await runtime.scheduler.cascadePauseFrom(runtime.stageId);
104918
105197
  const run = runtime.activeStore.runs().find((candidate) => candidate.id === runtime.runId);
104919
105198
  const stillActive = run?.stages.some((stage) => stage.status === "running" && stage.id !== runtime.stageId) ?? false;
@@ -112462,21 +112741,24 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
112462
112741
  pi.events?.emit?.(PENDING_STAGE_UNDELIVERABLE_EVENT, payload);
112463
112742
  return payload.handled && await payload.completion === true;
112464
112743
  };
112744
+ const announcedRoutes = new Map;
112465
112745
  const announceRoutes = () => {
112466
112746
  if (disposed)
112467
112747
  return;
112748
+ const ownedRunIds = new Set;
112468
112749
  const runs = activeStore.runs();
112469
112750
  for (const run of runs) {
112470
112751
  const rootRunId = durableRootRunIdForRun(runs, run.id);
112471
112752
  if (rootRunId === undefined)
112472
112753
  continue;
112754
+ ownedRunIds.add(run.id);
112473
112755
  const parentRun = runs.find((candidate) => candidate.id === run.parentRunId);
112474
112756
  const boundary = parentRun?.stages.find((stage) => stage.id === run.parentStageId);
112475
112757
  const parent = parentRun === undefined || boundary === undefined ? undefined : {
112476
112758
  runId: parentRun.id,
112477
112759
  stageKeys: [boundary.id, boundary.name].filter((key) => resolveChildRun(runs, parentRun, key)?.id === run.id)
112478
112760
  };
112479
- pi.events?.emit?.(PENDING_STAGE_ROUTE_EVENT, {
112761
+ const announcement = {
112480
112762
  runId: run.id,
112481
112763
  group: workflowInvocationIntercomGroup(rootRunId),
112482
112764
  capability: workflowPendingStageRouteCapability(activeStore, run.id),
@@ -112501,7 +112783,32 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
112501
112783
  }))
112502
112784
  ],
112503
112785
  ...run.id === rootRunId ? { possibleStages: possibleStageRows(runs, rootRunId, run) } : {}
112504
- });
112786
+ };
112787
+ const signature = JSON.stringify(announcement);
112788
+ if (announcedRoutes.get(run.id)?.signature === signature)
112789
+ continue;
112790
+ const entry = { signature };
112791
+ announcedRoutes.set(run.id, entry);
112792
+ try {
112793
+ pi.events?.emit?.(PENDING_STAGE_ROUTE_EVENT, announcement);
112794
+ } catch (error) {
112795
+ if (announcedRoutes.get(run.id) === entry)
112796
+ announcedRoutes.delete(run.id);
112797
+ throw error;
112798
+ }
112799
+ const completion = announcement.completion;
112800
+ if (completion === undefined) {
112801
+ announcedRoutes.delete(run.id);
112802
+ } else {
112803
+ completion.catch(() => {
112804
+ if (announcedRoutes.get(run.id) === entry)
112805
+ announcedRoutes.delete(run.id);
112806
+ });
112807
+ }
112808
+ }
112809
+ for (const runId of announcedRoutes.keys()) {
112810
+ if (!ownedRunIds.has(runId))
112811
+ announcedRoutes.delete(runId);
112505
112812
  }
112506
112813
  sweepPromise = sweepPromise.then(() => settleUndeliverablePendingStageMessages(activeStore, notifyUndeliverable)).then(() => {
112507
112814
  return;
@@ -112586,6 +112893,7 @@ function registerPendingStageIntercomBridge(pi, activeStore) {
112586
112893
  subscription();
112587
112894
  if (typeof stickySubscription === "function")
112588
112895
  stickySubscription();
112896
+ announcedRoutes.clear();
112589
112897
  };
112590
112898
  pi.on?.("session_shutdown", dispose);
112591
112899
  return dispose;
@@ -117150,7 +117458,7 @@ var DEFAULT_PROMPT_GUIDANCE = [
117150
117458
  - After creating and reloading a newly authored custom workflow, close the loop by stating the folder containing the workflow file just written, for example \`.atomic/workflows/\`, in this shape: \`Custom workflow created. You can inspect its code at: <workflow-folder-path>\`. Do this only for newly created custom workflows, never builtin or pre-existing workflows.
117151
117459
  - Keep a small, readable workflow in one entry file and write it for human maintainers. Keep the graph and control flow visible in the top-level workflow entry file, use stage names that state each stage's responsibility, and make its inputs, outputs, evidence, and success contract explicit. A developer reading the entry file from top to bottom should be able to identify the graph, branches, gates, artifacts, and stop conditions. Avoid both monolithic prompt blobs and gratuitous fragmentation. Do not split short one-use prompts, create one file per stage, add wrapper-only modules, hide the graph across files, or use line counts alone as a module boundary.
117152
117460
  - When a meaningful source boundary improves clarity, reuse, ownership, or testability, keep the graph and control flow in the top-level workflow entry file and extract cohesive concerns such as long or reused prompt builders, shared TypeBox schemas and workflow-specific types, model-policy constants shared by several stages, deterministic helpers with their own testable behavior, or reusable child workflow definitions into a subdirectory below the top-level discovery directory — either one owned by a single workflow or a shared support directory. Project and user discovery scans only top-level \`.ts\`/\`.js\`/\`.mjs\`/\`.cjs\` files in the workflow directory, so those support modules are not scanned as extra top-level workflow candidates; use \`.js\` import extensions from TypeScript source.
117153
- - Evaluate Atomic extension hooks when a workflow needs fine-grained, cross-cutting tool or session event control. Workflow TypeScript owns the inspectable DAG, stages, handoffs, durable \`ctx.tool\` side effects, and gates; extension hooks own cross-cutting session and model-tool policy such as \`tool_call\` interception, input mutation, or blocking, \`tool_result\` transformation, context and provider hooks, lifecycle observation, or reusable custom tools. Use hooks only when cross-stage or cross-workflow event control is materially clearer than embedding the policy in each stage; do not prescribe a companion extension for ordinary workflow logic. Consult \`packages/coding-agent/docs/extensions.md#events\` for the authoritative hook contracts.
117461
+ - Evaluate Atomic extension hooks when a workflow needs fine-grained, cross-cutting tool or session event control. Workflow TypeScript owns the inspectable DAG, stages, handoffs, durable \`ctx.tool\` side effects, and gates; extension hooks own cross-cutting session and model-tool policy such as \`tool_call\` interception, input mutation, or blocking, \`tool_result\` transformation, context and provider hooks, lifecycle observation, or reusable custom tools. Use hooks only when cross-stage or cross-workflow event control is materially clearer than embedding the policy in each stage; do not prescribe a companion extension for ordinary workflow logic. Consult \`packages/coding-agent/docs/extensions/events.md#events\` for the authoritative hook contracts.
117154
117462
  - When a workflow depends on a companion extension, make the dependency explicit, package and document it with the workflow, include any extension-provided custom tools in stage \`tools\` allowlists, and document hook-driven behavior so the workflow remains inspectable.
117155
117463
  - When creating or editing a workflow that pins an explicit stage \`model\` or \`fallbackModels\`, consult \`packages/coding-agent/docs/models/model-selection.md\` for role-based recommendations and \`packages/coding-agent/docs/models/evals.md\` for the measured per-evaluation scores behind them (its task-type picker maps each stage type to the eval that measures it), treating benchmark thinking levels as measurement configurations rather than universal workflow defaults, then call \`workflow({ action: "models" })\` to see the models actually present in the user's configured catalog. Use only the catalog's returned \`fullId\` values as model strings, and append a thinking suffix only when that exact level appears in the entry's \`availableThinkingLevels\`; apply the stage role and failure-cost policy independently to the primary and every fallback; treat an absent or empty \`availableThinkingLevels\` as no suffix support rather than inferring one. If a guide-recommended model for the role is unavailable, try another guide-recommended model that is present in the catalog. If the selected model does not support the role's level, choose another catalog model that does or leave the stage unpinned rather than inventing or silently promoting a level. An explicit user request for a level overrides the role default, but never fabricate an unsupported catalog level. If no recommendation intersects with the catalog, leave the stage unpinned rather than inventing a substitute, and mention the limitation, asking the user only if the workflow requires an explicit model choice. If the catalog is empty, continue with unpinned stages, state that no configured models were returned, and do not fabricate model IDs. Do not inspect or infer credentials, environment variables, auth files, token validity, entitlements, or the reason a model is absent; \`isCurrent\` marks the active selection, not a quality recommendation.
117156
117464
  - Consult docs/workflows/reliable-design.md and its starter patterns (Classify-and-act, Fan-out-and-synthesize, Adversarial verification, Generate-and-filter, Tournament, Loop until done, and Stacked implementation slices) when designing a stage graph.
@@ -3156,6 +3156,7 @@ class StageUiBroker {
3156
3156
  };
3157
3157
  }
3158
3158
  requestCustomUi(runId, stageId, factory, options, signal) {
3159
+ signal = options?.signal ? signal ? AbortSignal.any([signal, options.signal]) : options.signal : signal;
3159
3160
  if (signal?.aborted) {
3160
3161
  return Promise.reject(signal.reason ?? new Error("atomic-workflows: stage UI request aborted"));
3161
3162
  }
@@ -13429,21 +13430,17 @@ function throwFinalizationError(error) {
13429
13430
  function createTrackedStageCaller(input) {
13430
13431
  const { runtime } = input;
13431
13432
  const readinessGateEnabled = runtime.opts.confirmStageReadiness !== undefined || runtime.opts.usePromptNodesForUi === true;
13432
- const confirmReadiness = async () => {
13433
- try {
13434
- if (runtime.opts.confirmStageReadiness !== undefined) {
13435
- const ready = await runtime.opts.confirmStageReadiness({
13436
- runId: runtime.runId,
13437
- stageId: runtime.stageId,
13438
- stageName: runtime.name,
13439
- signal: runtime.signal
13440
- });
13441
- return ready ? { action: "advance" } : { action: "stay" };
13442
- }
13443
- return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, runtime.signal);
13444
- } catch {
13445
- return { action: "advance" };
13446
- }
13433
+ const confirmReadiness = async (signal) => {
13434
+ if (runtime.opts.confirmStageReadiness !== undefined) {
13435
+ const ready = await raceAbort(runtime.opts.confirmStageReadiness({
13436
+ runId: runtime.runId,
13437
+ stageId: runtime.stageId,
13438
+ stageName: runtime.name,
13439
+ signal
13440
+ }), signal);
13441
+ return ready ? { action: "advance" } : { action: "stay" };
13442
+ }
13443
+ return await askReadinessViaStageBroker(runtime.runId, runtime.stageId, signal);
13447
13444
  };
13448
13445
  const suppressReadinessForCurrentTurn = () => {
13449
13446
  runtime.state.askUserQuestionObservedThisTurn = false;
@@ -13597,9 +13594,35 @@ function createTrackedStageCaller(input) {
13597
13594
  });
13598
13595
  try {
13599
13596
  while (runtime.state.askUserQuestionObservedThisTurn || repeatReadinessAfterChatTurn) {
13600
- const decision = await confirmReadiness();
13597
+ runtime.signal.throwIfAborted();
13598
+ if (runtime.stageSnapshot.status === "paused" || runtime.stageSnapshot.status === "blocked") {
13599
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
13600
+ continue;
13601
+ }
13602
+ const controller = new AbortController;
13603
+ runtime.state.readinessController = controller;
13604
+ let decision;
13605
+ try {
13606
+ decision = await confirmReadiness(AbortSignal.any([runtime.signal, controller.signal]));
13607
+ if (decision.action === "advance" || decision.message !== undefined) {
13608
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
13609
+ }
13610
+ runtime.signal.throwIfAborted();
13611
+ if (controller.signal.aborted) {
13612
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
13613
+ continue;
13614
+ }
13615
+ } catch (error) {
13616
+ runtime.signal.throwIfAborted();
13617
+ if (controller.signal.aborted) {
13618
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
13619
+ continue;
13620
+ }
13621
+ throw error;
13622
+ }
13601
13623
  if (decision.action === "advance")
13602
13624
  break;
13625
+ delete runtime.state.readinessController;
13603
13626
  if (runtime.signal.aborted)
13604
13627
  break;
13605
13628
  runtime.state.askUserQuestionObservedThisTurn = false;
@@ -13742,9 +13765,17 @@ function createTrackedStageCaller(input) {
13742
13765
  const failure = runtime.classifyExecutorFailure(durableCheckpointError.error);
13743
13766
  applyTerminalStageState = () => applyFailureToStage(runtime.stageSnapshot, failure);
13744
13767
  }
13745
- if (!runtime.state.stageFinalized)
13746
- applyTerminalStageState?.();
13747
13768
  try {
13769
+ if (terminalStateIsSuccess && runtime.state.readinessController !== undefined) {
13770
+ let pauseVersion;
13771
+ do {
13772
+ pauseVersion = runtime.state.readinessPauseVersion;
13773
+ await runtime.scheduler.waitForStageRelease(runtime.stageId, runtime.releaseLiveHandle);
13774
+ } while (pauseVersion !== runtime.state.readinessPauseVersion);
13775
+ runtime.signal.throwIfAborted();
13776
+ }
13777
+ if (!runtime.state.stageFinalized)
13778
+ applyTerminalStageState?.();
13748
13779
  await runtime.finalizeStageSnapshot();
13749
13780
  } catch (err) {
13750
13781
  finalizationError ??= { thrown: true, error: err };
@@ -13762,6 +13793,9 @@ function createTrackedStageCaller(input) {
13762
13793
  input.limiter.release();
13763
13794
  if (finalizationError !== undefined)
13764
13795
  throwFinalizationError(finalizationError.error);
13796
+ delete runtime.state.readinessController;
13797
+ if (terminalStateIsSuccess && readinessGateEnabled)
13798
+ runtime.signal.throwIfAborted();
13765
13799
  }
13766
13800
  };
13767
13801
  }
@@ -14122,12 +14156,26 @@ function createStageControlHandle(runtime) {
14122
14156
  async pause() {
14123
14157
  runtime.throwIfStageMutationBlocked();
14124
14158
  const statusBeforePause = runtime.stageSnapshot.status;
14159
+ let readinessPauseVersion;
14160
+ if (runtime.state.readinessController !== undefined) {
14161
+ runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
14162
+ readinessPauseVersion = (runtime.state.readinessPauseVersion ?? 0) + 1;
14163
+ runtime.state.readinessPauseVersion = readinessPauseVersion;
14164
+ }
14125
14165
  if (statusBeforePause === "pending" || statusBeforePause === "running" || runtime.innerCtx.isStreaming) {
14126
- await runtime.innerCtx.__requestPause();
14166
+ try {
14167
+ await runtime.innerCtx.__requestPause();
14168
+ } catch (error) {
14169
+ if (readinessPauseVersion !== undefined && runtime.state.readinessPauseVersion === readinessPauseVersion && runtime.stageSnapshot.status !== "paused" && runtime.stageSnapshot.status !== "blocked" && !runtime.scheduler.hasCascadePauseOwners(runtime.stageId)) {
14170
+ runtime.scheduler.releaseStageBarrier(runtime.stageId);
14171
+ }
14172
+ throw error;
14173
+ }
14127
14174
  }
14128
14175
  const changed = runtime.activeStore.recordStagePaused(runtime.runId, runtime.stageId);
14129
14176
  if (changed) {
14130
14177
  runtime.scheduler.ensureReleaseBarrier(runtime.stageId);
14178
+ runtime.state.readinessController?.abort(new Error("atomic-workflows: readiness paused"));
14131
14179
  await runtime.scheduler.cascadePauseFrom(runtime.stageId);
14132
14180
  const run = runtime.activeStore.runs().find((candidate) => candidate.id === runtime.runId);
14133
14181
  const stillActive = run?.stages.some((stage) => stage.status === "running" && stage.id !== runtime.stageId) ?? false;
@@ -358,6 +358,8 @@ export interface WorkflowChainOptions extends WorkflowSharedTaskDefaults {
358
358
  export interface WorkflowParallelOptions extends WorkflowSharedTaskDefaults {
359
359
  readonly concurrency?: number;
360
360
  readonly failFast?: boolean;
361
+ /** Static discovery only: literal conservative stage names/globs for an otherwise opaque step array. */
362
+ readonly possibleStageNames?: readonly string[];
361
363
  }
362
364
  export type WorkflowTaskSessionOptions = StageOptions & WorkflowTaskSessionFields;
363
365
  export interface WorkflowRunChildOptions<TInputs extends WorkflowInputValues = WorkflowInputValues> {