tubeless 0.2.11 → 0.2.13

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 (196) hide show
  1. package/dist/core/child-execution.d.ts +1 -24
  2. package/dist/core/child-execution.js +11 -13
  3. package/dist/core/child-execution.js.map +1 -1
  4. package/dist/core/child-progress.js +7 -2
  5. package/dist/core/child-progress.js.map +1 -1
  6. package/dist/core/iteration.d.ts +27 -0
  7. package/dist/core/iteration.js +111 -0
  8. package/dist/core/iteration.js.map +1 -0
  9. package/dist/core/lifecycle.d.ts +7 -5
  10. package/dist/core/lifecycle.js +36 -4
  11. package/dist/core/lifecycle.js.map +1 -1
  12. package/dist/core/pipeline-artifacts.d.ts +11 -0
  13. package/dist/core/pipeline-artifacts.js +2 -0
  14. package/dist/core/pipeline-artifacts.js.map +1 -0
  15. package/dist/core/pipeline-compiler.d.ts +1 -0
  16. package/dist/core/pipeline-compiler.js +1 -0
  17. package/dist/core/pipeline-compiler.js.map +1 -1
  18. package/dist/core/pipeline-definition-identity.d.ts +2 -2
  19. package/dist/core/pipeline-definition-identity.js +28 -5
  20. package/dist/core/pipeline-definition-identity.js.map +1 -1
  21. package/dist/core/pipeline-execute.d.ts +1 -6
  22. package/dist/core/pipeline-execute.js +28 -215
  23. package/dist/core/pipeline-execute.js.map +1 -1
  24. package/dist/core/pipeline-execution-error.d.ts +35 -0
  25. package/dist/core/pipeline-execution-error.js +195 -0
  26. package/dist/core/pipeline-execution-error.js.map +1 -0
  27. package/dist/core/pipeline-identity.d.ts +1 -0
  28. package/dist/core/pipeline-identity.js +1 -0
  29. package/dist/core/pipeline-identity.js.map +1 -1
  30. package/dist/core/pipeline-mermaid.js +4 -1
  31. package/dist/core/pipeline-mermaid.js.map +1 -1
  32. package/dist/core/pipeline-run-state.d.ts +4 -4
  33. package/dist/core/pipeline-run-state.js +10 -16
  34. package/dist/core/pipeline-run-state.js.map +1 -1
  35. package/dist/core/pipeline-step-executor.d.ts +2 -0
  36. package/dist/core/pipeline-step-executor.js +11 -3
  37. package/dist/core/pipeline-step-executor.js.map +1 -1
  38. package/dist/core/pipeline-steps.d.ts +24 -1
  39. package/dist/core/pipeline-steps.js +62 -0
  40. package/dist/core/pipeline-steps.js.map +1 -1
  41. package/dist/core/pipeline-types.d.ts +28 -3
  42. package/dist/core/pipeline-types.js.map +1 -1
  43. package/dist/core/pipeline.d.ts +4 -1
  44. package/dist/core/pipeline.js +22 -4
  45. package/dist/core/pipeline.js.map +1 -1
  46. package/dist/project/project-compiler.d.ts +3 -31
  47. package/dist/project/project-compiler.js +11 -180
  48. package/dist/project/project-compiler.js.map +1 -1
  49. package/dist/project/project-registry.d.ts +44 -0
  50. package/dist/project/project-registry.js +107 -0
  51. package/dist/project/project-registry.js.map +1 -0
  52. package/dist/project/project-step-graph.d.ts +9 -0
  53. package/dist/project/project-step-graph.js +99 -0
  54. package/dist/project/project-step-graph.js.map +1 -0
  55. package/dist/render/render.js +1 -1
  56. package/dist/render/render.js.map +1 -1
  57. package/dist/reporter/interactive-reporter.js +6 -3
  58. package/dist/reporter/interactive-reporter.js.map +1 -1
  59. package/dist/reporter/live-ticker-frame.d.ts +21 -0
  60. package/dist/reporter/live-ticker-frame.js +196 -0
  61. package/dist/reporter/live-ticker-frame.js.map +1 -0
  62. package/dist/reporter/live-ticker-protocol.d.ts +41 -0
  63. package/dist/reporter/live-ticker-protocol.js +59 -0
  64. package/dist/reporter/live-ticker-protocol.js.map +1 -0
  65. package/dist/reporter/live-ticker-worker.js +11 -25
  66. package/dist/reporter/live-ticker-worker.js.map +1 -1
  67. package/dist/reporter/live-ticker.d.ts +0 -15
  68. package/dist/reporter/live-ticker.js +11 -216
  69. package/dist/reporter/live-ticker.js.map +1 -1
  70. package/dist/reporter/reporter.js +7 -6
  71. package/dist/reporter/reporter.js.map +1 -1
  72. package/dist/run-store/definition-projection.d.ts +8 -0
  73. package/dist/run-store/definition-projection.js +89 -0
  74. package/dist/run-store/definition-projection.js.map +1 -0
  75. package/dist/run-store/run-projection.d.ts +15 -0
  76. package/dist/run-store/run-projection.js +203 -0
  77. package/dist/run-store/run-projection.js.map +1 -0
  78. package/dist/run-store/run-store-codec.d.ts +2 -0
  79. package/dist/run-store/run-store-codec.js +11 -0
  80. package/dist/run-store/run-store-codec.js.map +1 -1
  81. package/dist/run-store/run-store-event-decoder.js +3 -0
  82. package/dist/run-store/run-store-event-decoder.js.map +1 -1
  83. package/dist/run-store/run-store-reader.d.ts +7 -0
  84. package/dist/run-store/run-store-reader.js +31 -0
  85. package/dist/run-store/run-store-reader.js.map +1 -0
  86. package/dist/run-store/run-store-sqlite.js +23 -7
  87. package/dist/run-store/run-store-sqlite.js.map +1 -1
  88. package/dist/run-store/run-store.d.ts +16 -4
  89. package/dist/run-store/run-store.js +14 -263
  90. package/dist/run-store/run-store.js.map +1 -1
  91. package/dist/studio/run-store-ui-api.d.ts +13 -0
  92. package/dist/studio/run-store-ui-api.js +163 -0
  93. package/dist/studio/run-store-ui-api.js.map +1 -0
  94. package/dist/studio/run-store-ui-client-browser.js +2 -2
  95. package/dist/studio/run-store-ui-client-transport.js +28 -3
  96. package/dist/studio/run-store-ui-client-transport.js.map +1 -1
  97. package/dist/studio/run-store-ui-client.d.ts +2 -1
  98. package/dist/studio/run-store-ui-client.js +15 -9
  99. package/dist/studio/run-store-ui-client.js.map +1 -1
  100. package/dist/studio/run-store-ui-http.d.ts +11 -0
  101. package/dist/studio/run-store-ui-http.js +52 -0
  102. package/dist/studio/run-store-ui-http.js.map +1 -1
  103. package/dist/studio/run-store-ui-state.d.ts +1 -1
  104. package/dist/studio/run-store-ui-state.js +10 -28
  105. package/dist/studio/run-store-ui-state.js.map +1 -1
  106. package/dist/studio/run-store-ui.d.ts +5 -11
  107. package/dist/studio/run-store-ui.js +5 -203
  108. package/dist/studio/run-store-ui.js.map +1 -1
  109. package/dist/testing/testing.d.ts +18 -2
  110. package/dist/testing/testing.js +35 -2
  111. package/dist/testing/testing.js.map +1 -1
  112. package/dist/tracing/artifact-metadata.d.ts +28 -0
  113. package/dist/tracing/artifact-metadata.js +105 -0
  114. package/dist/tracing/artifact-metadata.js.map +1 -0
  115. package/dist/tracing/tracing-codec.d.ts +1 -1
  116. package/dist/tracing/tracing-codec.js +1 -1
  117. package/dist/tracing/tracing-codec.js.map +1 -1
  118. package/dist/tracing/tracing-constants.d.ts +1 -1
  119. package/dist/tracing/tracing-constants.js +1 -1
  120. package/dist/tracing/tracing-constants.js.map +1 -1
  121. package/dist/tracing/tracing-contracts.d.ts +3 -1
  122. package/dist/tracing/tracing-contracts.js.map +1 -1
  123. package/dist/tracing/tracing-internal.d.ts +2 -0
  124. package/dist/tracing/tracing-internal.js +36 -13
  125. package/dist/tracing/tracing-internal.js.map +1 -1
  126. package/dist/tracing/tracing-schema.d.ts +330 -49
  127. package/dist/tracing/tracing-schema.js +102 -10
  128. package/dist/tracing/tracing-schema.js.map +1 -1
  129. package/dist/workbench/workbench-command-execution.d.ts +6 -0
  130. package/dist/workbench/workbench-command-execution.js +48 -0
  131. package/dist/workbench/workbench-command-execution.js.map +1 -0
  132. package/dist/workbench/workbench-history.js +11 -18
  133. package/dist/workbench/workbench-history.js.map +1 -1
  134. package/dist/workbench/workbench-launch-session.d.ts +2 -2
  135. package/dist/workbench/workbench-launch-session.js.map +1 -1
  136. package/dist/workbench/workbench-run.d.ts +0 -4
  137. package/dist/workbench/workbench-run.js +3 -47
  138. package/dist/workbench/workbench-run.js.map +1 -1
  139. package/dist/workbench/workbench-studio-launcher.d.ts +27 -0
  140. package/dist/workbench/workbench-studio-launcher.js +95 -0
  141. package/dist/workbench/workbench-studio-launcher.js.map +1 -0
  142. package/dist/workbench/workbench-ui.js +10 -83
  143. package/dist/workbench/workbench-ui.js.map +1 -1
  144. package/docs/README.md +13 -7
  145. package/docs/agent-guide.md +75 -6
  146. package/docs/airflow.md +187 -0
  147. package/docs/api-reference.md +87 -76
  148. package/docs/api-report.json +17 -6
  149. package/docs/artifacts.md +173 -0
  150. package/docs/child-pipeline-composition.md +87 -8
  151. package/docs/comparison.md +20 -0
  152. package/docs/concepts.md +79 -2
  153. package/docs/dagster.md +161 -0
  154. package/docs/inngest.md +163 -0
  155. package/docs/llms.txt +30 -1
  156. package/docs/recipes.md +82 -32
  157. package/docs/remote-step-composition.md +6 -0
  158. package/docs/step-functions.md +190 -0
  159. package/docs/studio.md +31 -12
  160. package/docs/temporal.md +183 -0
  161. package/examples/airflow/contract.ts +46 -0
  162. package/examples/airflow/hosted.ts +70 -0
  163. package/examples/airflow/remote.ts +175 -0
  164. package/examples/airflow/tubeless_example.py +49 -0
  165. package/examples/airflow/worker.ts +24 -0
  166. package/examples/artifact-lineage.ts +70 -0
  167. package/examples/dagster/definitions.py +59 -0
  168. package/examples/dagster/hosted.ts +78 -0
  169. package/examples/dagster/pipeline.ts +62 -0
  170. package/examples/dagster/test_definitions.py +47 -0
  171. package/examples/dagster/tsconfig.build.json +10 -0
  172. package/examples/dagster/worker.ts +22 -0
  173. package/examples/inherited-inputs.ts +28 -0
  174. package/examples/inngest/client.ts +4 -0
  175. package/examples/inngest/functions.ts +65 -0
  176. package/examples/inngest/pipeline.ts +41 -0
  177. package/examples/inngest/send.ts +11 -0
  178. package/examples/inngest/server.ts +17 -0
  179. package/examples/inngest/tsconfig.build.json +10 -0
  180. package/examples/iteration.ts +52 -0
  181. package/examples/parameterized-steps.ts +96 -0
  182. package/examples/project/tubeless.project.ts +50 -0
  183. package/examples/step-functions/handler.ts +110 -0
  184. package/examples/step-functions/input.json +1 -0
  185. package/examples/step-functions/pipeline.ts +41 -0
  186. package/examples/step-functions/state-machine.asl.json +41 -0
  187. package/examples/step-functions/template.json +42 -0
  188. package/examples/step-output-overrides.ts +41 -0
  189. package/examples/temporal/activities.ts +94 -0
  190. package/examples/temporal/client.ts +19 -0
  191. package/examples/temporal/pipeline.ts +41 -0
  192. package/examples/temporal/tsconfig.build.json +10 -0
  193. package/examples/temporal/worker.ts +21 -0
  194. package/examples/temporal/workflows.ts +16 -0
  195. package/package.json +13 -4
  196. package/skills/tubeless/SKILL.md +37 -4
@@ -0,0 +1,195 @@
1
+ import { isAbortError } from "../utilities/abort.js";
2
+ import { brandTubelessError } from "../utilities/tubeless-error.js";
3
+ import { formatPipelineError } from "./pipeline-diagnostics.js";
4
+ import { PIPELINE_FINALIZE_STEP_ID } from "./pipeline-step-metadata.js";
5
+ import { PipelineBoundaryValidationError } from "./pipeline-validation.js";
6
+ export function isCancellationOnly(errors) {
7
+ return errors.length > 0 && errors.every(({ kind }) => kind === "cancellation");
8
+ }
9
+ export class PipelineChildError extends Error {
10
+ cancelled;
11
+ fanOut;
12
+ constructor(message, cancelled = false, cause, fanOut) {
13
+ super(message, cause === undefined ? undefined : { cause });
14
+ this.cancelled = cancelled;
15
+ this.fanOut = fanOut;
16
+ this.name = "PipelineChildError";
17
+ }
18
+ }
19
+ const originalPipelineErrors = new WeakMap();
20
+ function defaultExecutionErrorMessage(result) {
21
+ const firstError = result.errors[0];
22
+ const disposition = isCancellationOnly(result.errors) ? "cancelled" : "failed";
23
+ return firstError
24
+ ? `Pipeline ${result.pipelineId} ${disposition}: ${formatPipelineError(firstError)}`
25
+ : `Pipeline ${result.pipelineId} ${disposition}`;
26
+ }
27
+ function firstOriginalPipelineError(errors) {
28
+ for (const error of errors) {
29
+ if (originalPipelineErrors.has(error))
30
+ return originalPipelineErrors.get(error);
31
+ }
32
+ return undefined;
33
+ }
34
+ /** Error thrown by `runOrThrow` when a pipeline run does not complete successfully. */
35
+ export class PipelineExecutionError extends Error {
36
+ result;
37
+ constructor(result, message = defaultExecutionErrorMessage(result)) {
38
+ const cause = firstOriginalPipelineError(result.errors);
39
+ super(message, cause === undefined ? undefined : { cause });
40
+ this.result = result;
41
+ this.name = "PipelineExecutionError";
42
+ brandTubelessError(this, "pipeline-execution");
43
+ }
44
+ }
45
+ const MAX_PIPELINE_CAUSE_DEPTH = 8;
46
+ function readErrorField(value, field) {
47
+ try {
48
+ // SAFETY: any object may be probed for an optional string-keyed field; a
49
+ // getter that throws is caught below, so the cast only enables the lookup.
50
+ return value[field];
51
+ }
52
+ catch {
53
+ return undefined;
54
+ }
55
+ }
56
+ function safeErrorMessage(value) {
57
+ try {
58
+ return String(value);
59
+ }
60
+ catch {
61
+ return "Unknown thrown value";
62
+ }
63
+ }
64
+ function normalizePipelineCause(value, seen, depth = 0) {
65
+ if (depth >= MAX_PIPELINE_CAUSE_DEPTH) {
66
+ return { message: "Cause chain truncated" };
67
+ }
68
+ if (typeof value !== "object" || value === null) {
69
+ return { message: safeErrorMessage(value) };
70
+ }
71
+ if (seen.has(value)) {
72
+ return { message: "Circular cause" };
73
+ }
74
+ seen.add(value);
75
+ const message = readErrorField(value, "message");
76
+ const name = readErrorField(value, "name");
77
+ const sourceCode = readErrorField(value, "code");
78
+ const nested = readErrorField(value, "cause");
79
+ const cause = {
80
+ message: typeof message === "string" ? message : safeErrorMessage(value),
81
+ };
82
+ if (typeof name === "string")
83
+ cause.name = name;
84
+ if (typeof sourceCode === "string")
85
+ cause.sourceCode = sourceCode;
86
+ if (nested !== undefined)
87
+ cause.cause = normalizePipelineCause(nested, seen, depth + 1);
88
+ return cause;
89
+ }
90
+ // Fan-out snapshots bound every string as well as cause depth and item count.
91
+ function fanOutCause(error) {
92
+ const cause = normalizePipelineCause(error, new WeakSet());
93
+ let current = cause;
94
+ while (current) {
95
+ current.message = current.message.slice(0, 1024);
96
+ if (current.name)
97
+ current.name = current.name.slice(0, 1024);
98
+ if (current.sourceCode)
99
+ current.sourceCode = current.sourceCode.slice(0, 1024);
100
+ current = current.cause;
101
+ }
102
+ return cause;
103
+ }
104
+ function normalizedNestedCause(error) {
105
+ if (typeof error !== "object" || error === null)
106
+ return undefined;
107
+ const cause = readErrorField(error, "cause");
108
+ if (cause === undefined)
109
+ return undefined;
110
+ const seen = new WeakSet();
111
+ seen.add(error);
112
+ return normalizePipelineCause(cause, seen);
113
+ }
114
+ export function toPipelineError(error, classification) {
115
+ const sourceCode = typeof error === "object" && error !== null ? readErrorField(error, "code") : undefined;
116
+ const cause = normalizedNestedCause(error);
117
+ const pipelineError = {
118
+ ...classification,
119
+ message: error instanceof Error ? error.message : safeErrorMessage(error),
120
+ };
121
+ if (error instanceof Error && error.stack)
122
+ pipelineError.stack = error.stack;
123
+ if (typeof sourceCode === "string")
124
+ pipelineError.sourceCode = sourceCode;
125
+ if (cause)
126
+ pipelineError.cause = cause;
127
+ if (error instanceof PipelineBoundaryValidationError)
128
+ pipelineError.issues = error.issues;
129
+ if (error instanceof PipelineChildError && error.fanOut) {
130
+ const { failures, failureCount, schedulerError } = error.fanOut;
131
+ pipelineError.fanOut = {
132
+ failures: failures.map(({ error: itemError, key, index, cancelled }) => ({
133
+ index,
134
+ key: key.slice(0, 1024),
135
+ keyTruncated: key.length > 1024,
136
+ cancelled,
137
+ error: fanOutCause(itemError),
138
+ })),
139
+ failureCount,
140
+ omittedFailureCount: failureCount - failures.length,
141
+ };
142
+ if (schedulerError !== undefined)
143
+ pipelineError.fanOut.schedulerError = fanOutCause(schedulerError);
144
+ }
145
+ originalPipelineErrors.set(pipelineError, error);
146
+ return pipelineError;
147
+ }
148
+ export function isPipelineCancellation(error, runtime) {
149
+ if (isAbortError(error))
150
+ return true;
151
+ if (runtime.signal?.aborted === true && error === runtime.signal.reason)
152
+ return true;
153
+ if (error instanceof PipelineChildError)
154
+ return error.cancelled;
155
+ return error instanceof PipelineExecutionError && error.result.status === "cancelled";
156
+ }
157
+ /** Classify a failed attempt without exposing error subclasses to execution. */
158
+ export function stepExecutionError(error, runtime, stepId) {
159
+ const cancelled = isPipelineCancellation(error, runtime);
160
+ const childFailure = error instanceof PipelineExecutionError || error instanceof PipelineChildError;
161
+ const validationFailure = error instanceof PipelineBoundaryValidationError;
162
+ return toPipelineError(error, {
163
+ code: cancelled
164
+ ? "TUBELESS_RUN_CANCELLED"
165
+ : validationFailure
166
+ ? "TUBELESS_STEP_OUTPUT_VALIDATION_FAILED"
167
+ : childFailure
168
+ ? "TUBELESS_CHILD_FAILED"
169
+ : "TUBELESS_STEP_FAILED",
170
+ kind: cancelled
171
+ ? "cancellation"
172
+ : validationFailure
173
+ ? "validation"
174
+ : childFailure
175
+ ? "child"
176
+ : "step",
177
+ phase: "execution",
178
+ stepId: stepId,
179
+ });
180
+ }
181
+ export function finalizationError(error, runtime) {
182
+ const cancelled = isPipelineCancellation(error, runtime);
183
+ const validationFailure = error instanceof PipelineBoundaryValidationError;
184
+ return toPipelineError(error, {
185
+ code: cancelled
186
+ ? "TUBELESS_FINALIZATION_CANCELLED"
187
+ : validationFailure
188
+ ? "TUBELESS_FINAL_RESULT_VALIDATION_FAILED"
189
+ : "TUBELESS_FINALIZATION_FAILED",
190
+ kind: cancelled ? "cancellation" : validationFailure ? "validation" : "finalization",
191
+ phase: "finalization",
192
+ stepId: PIPELINE_FINALIZE_STEP_ID,
193
+ });
194
+ }
195
+ //# sourceMappingURL=pipeline-execution-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-execution-error.js","sourceRoot":"","sources":["../../src/core/pipeline-execution-error.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbortError } from \"../utilities/abort.js\";\nimport { brandTubelessError } from \"../utilities/tubeless-error.js\";\nimport { formatPipelineError } from \"./pipeline-diagnostics.js\";\nimport { PIPELINE_FINALIZE_STEP_ID } from \"./pipeline-step-metadata.js\";\nimport type {\n PipelineError,\n PipelineErrorCause,\n PipelineRun,\n PipelineRuntime,\n} from \"./pipeline-types.js\";\nimport { PipelineBoundaryValidationError } from \"./pipeline-validation.js\";\n\nexport function isCancellationOnly(errors: readonly PipelineError[]): boolean {\n return errors.length > 0 && errors.every(({ kind }) => kind === \"cancellation\");\n}\n\nexport class PipelineChildError extends Error {\n constructor(\n message: string,\n readonly cancelled = false,\n cause?: unknown,\n readonly fanOut?: {\n failures: readonly { error: Error; key: string; index: number; cancelled: boolean }[];\n failureCount: number;\n schedulerError?: Error;\n }\n ) {\n super(message, cause === undefined ? undefined : { cause });\n this.name = \"PipelineChildError\";\n }\n}\n\nconst originalPipelineErrors = new WeakMap<PipelineError, unknown>();\n\nfunction defaultExecutionErrorMessage(result: PipelineRun<unknown>): string {\n const firstError = result.errors[0];\n const disposition = isCancellationOnly(result.errors) ? \"cancelled\" : \"failed\";\n return firstError\n ? `Pipeline ${result.pipelineId} ${disposition}: ${formatPipelineError(firstError)}`\n : `Pipeline ${result.pipelineId} ${disposition}`;\n}\n\nfunction firstOriginalPipelineError(errors: readonly PipelineError[]): unknown {\n for (const error of errors) {\n if (originalPipelineErrors.has(error)) return originalPipelineErrors.get(error);\n }\n return undefined;\n}\n\n/** Error thrown by `runOrThrow` when a pipeline run does not complete successfully. */\nexport class PipelineExecutionError extends Error {\n constructor(\n readonly result: PipelineRun<unknown>,\n message = defaultExecutionErrorMessage(result)\n ) {\n const cause = firstOriginalPipelineError(result.errors);\n super(message, cause === undefined ? undefined : { cause });\n this.name = \"PipelineExecutionError\";\n brandTubelessError(this, \"pipeline-execution\");\n }\n}\n\nconst MAX_PIPELINE_CAUSE_DEPTH = 8;\n\nfunction readErrorField(value: object, field: \"cause\" | \"code\" | \"message\" | \"name\"): unknown {\n try {\n // SAFETY: any object may be probed for an optional string-keyed field; a\n // getter that throws is caught below, so the cast only enables the lookup.\n return (value as Record<string, unknown>)[field];\n } catch {\n return undefined;\n }\n}\n\nfunction safeErrorMessage(value: unknown): string {\n try {\n return String(value);\n } catch {\n return \"Unknown thrown value\";\n }\n}\n\nfunction normalizePipelineCause(\n value: unknown,\n seen: WeakSet<object>,\n depth = 0\n): PipelineErrorCause {\n if (depth >= MAX_PIPELINE_CAUSE_DEPTH) {\n return { message: \"Cause chain truncated\" };\n }\n if (typeof value !== \"object\" || value === null) {\n return { message: safeErrorMessage(value) };\n }\n if (seen.has(value)) {\n return { message: \"Circular cause\" };\n }\n seen.add(value);\n\n const message = readErrorField(value, \"message\");\n const name = readErrorField(value, \"name\");\n const sourceCode = readErrorField(value, \"code\");\n const nested = readErrorField(value, \"cause\");\n const cause: PipelineErrorCause = {\n message: typeof message === \"string\" ? message : safeErrorMessage(value),\n };\n if (typeof name === \"string\") cause.name = name;\n if (typeof sourceCode === \"string\") cause.sourceCode = sourceCode;\n if (nested !== undefined) cause.cause = normalizePipelineCause(nested, seen, depth + 1);\n return cause;\n}\n\n// Fan-out snapshots bound every string as well as cause depth and item count.\nfunction fanOutCause(error: unknown): PipelineErrorCause {\n const cause = normalizePipelineCause(error, new WeakSet<object>());\n let current: PipelineErrorCause | undefined = cause;\n while (current) {\n current.message = current.message.slice(0, 1024);\n if (current.name) current.name = current.name.slice(0, 1024);\n if (current.sourceCode) current.sourceCode = current.sourceCode.slice(0, 1024);\n current = current.cause;\n }\n return cause;\n}\n\nfunction normalizedNestedCause(error: unknown): PipelineErrorCause | undefined {\n if (typeof error !== \"object\" || error === null) return undefined;\n const cause = readErrorField(error, \"cause\");\n if (cause === undefined) return undefined;\n const seen = new WeakSet<object>();\n seen.add(error);\n return normalizePipelineCause(cause, seen);\n}\n\nexport function toPipelineError(\n error: unknown,\n classification: Omit<PipelineError, \"cause\" | \"message\" | \"sourceCode\" | \"stack\">\n): PipelineError {\n const sourceCode =\n typeof error === \"object\" && error !== null ? readErrorField(error, \"code\") : undefined;\n const cause = normalizedNestedCause(error);\n const pipelineError: PipelineError = {\n ...classification,\n message: error instanceof Error ? error.message : safeErrorMessage(error),\n };\n if (error instanceof Error && error.stack) pipelineError.stack = error.stack;\n if (typeof sourceCode === \"string\") pipelineError.sourceCode = sourceCode;\n if (cause) pipelineError.cause = cause;\n if (error instanceof PipelineBoundaryValidationError) pipelineError.issues = error.issues;\n if (error instanceof PipelineChildError && error.fanOut) {\n const { failures, failureCount, schedulerError } = error.fanOut;\n pipelineError.fanOut = {\n failures: failures.map(({ error: itemError, key, index, cancelled }) => ({\n index,\n key: key.slice(0, 1024),\n keyTruncated: key.length > 1024,\n cancelled,\n error: fanOutCause(itemError),\n })),\n failureCount,\n omittedFailureCount: failureCount - failures.length,\n };\n if (schedulerError !== undefined)\n pipelineError.fanOut.schedulerError = fanOutCause(schedulerError);\n }\n originalPipelineErrors.set(pipelineError, error);\n return pipelineError;\n}\n\nexport function isPipelineCancellation(\n error: unknown,\n runtime: Pick<PipelineRuntime, \"signal\">\n): boolean {\n if (isAbortError(error)) return true;\n if (runtime.signal?.aborted === true && error === runtime.signal.reason) return true;\n if (error instanceof PipelineChildError) return error.cancelled;\n return error instanceof PipelineExecutionError && error.result.status === \"cancelled\";\n}\n\n/** Classify a failed attempt without exposing error subclasses to execution. */\nexport function stepExecutionError(\n error: unknown,\n runtime: Pick<PipelineRuntime, \"signal\">,\n stepId: string\n): PipelineError {\n const cancelled = isPipelineCancellation(error, runtime);\n const childFailure =\n error instanceof PipelineExecutionError || error instanceof PipelineChildError;\n const validationFailure = error instanceof PipelineBoundaryValidationError;\n return toPipelineError(error, {\n code: cancelled\n ? \"TUBELESS_RUN_CANCELLED\"\n : validationFailure\n ? \"TUBELESS_STEP_OUTPUT_VALIDATION_FAILED\"\n : childFailure\n ? \"TUBELESS_CHILD_FAILED\"\n : \"TUBELESS_STEP_FAILED\",\n kind: cancelled\n ? \"cancellation\"\n : validationFailure\n ? \"validation\"\n : childFailure\n ? \"child\"\n : \"step\",\n phase: \"execution\",\n stepId: stepId,\n });\n}\n\nexport function finalizationError(\n error: unknown,\n runtime: Pick<PipelineRuntime, \"signal\">\n): PipelineError {\n const cancelled = isPipelineCancellation(error, runtime);\n const validationFailure = error instanceof PipelineBoundaryValidationError;\n return toPipelineError(error, {\n code: cancelled\n ? \"TUBELESS_FINALIZATION_CANCELLED\"\n : validationFailure\n ? \"TUBELESS_FINAL_RESULT_VALIDATION_FAILED\"\n : \"TUBELESS_FINALIZATION_FAILED\",\n kind: cancelled ? \"cancellation\" : validationFailure ? \"validation\" : \"finalization\",\n phase: \"finalization\",\n stepId: PIPELINE_FINALIZE_STEP_ID,\n });\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export declare const EXECUTE_COMPILED_RUN: unique symbol;
2
+ export declare const EXECUTE_TEST_RUN: unique symbol;
2
3
  /** Marks the exact object returned by `definePipeline` as a compiled pipeline. */
3
4
  export declare function brandCompiledPipeline(pipeline: object): void;
4
5
  /** True only for the object `definePipeline` returned, not `Object.create` wrappers. */
@@ -1,4 +1,5 @@
1
1
  export const EXECUTE_COMPILED_RUN = Symbol("tubeless.executeCompiledRun");
2
+ export const EXECUTE_TEST_RUN = Symbol("tubeless.executeTestRun");
2
3
  const compiledPipelines = new WeakSet();
3
4
  /** Marks the exact object returned by `definePipeline` as a compiled pipeline. */
4
5
  export function brandCompiledPipeline(pipeline) {
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-identity.js","sourceRoot":"","sources":["../../src/core/pipeline-identity.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAkB,MAAM,CAAC,6BAA6B,CAAC,CAAC;AAEzF,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAAU,CAAC;AAEhD,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC","sourcesContent":["export const EXECUTE_COMPILED_RUN: unique symbol = Symbol(\"tubeless.executeCompiledRun\");\n\nconst compiledPipelines = new WeakSet<object>();\n\n/** Marks the exact object returned by `definePipeline` as a compiled pipeline. */\nexport function brandCompiledPipeline(pipeline: object): void {\n compiledPipelines.add(pipeline);\n}\n\n/** True only for the object `definePipeline` returned, not `Object.create` wrappers. */\nexport function isCompiledPipeline(pipeline: object): boolean {\n return compiledPipelines.has(pipeline);\n}\n"]}
1
+ {"version":3,"file":"pipeline-identity.js","sourceRoot":"","sources":["../../src/core/pipeline-identity.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAkB,MAAM,CAAC,6BAA6B,CAAC,CAAC;AACzF,MAAM,CAAC,MAAM,gBAAgB,GAAkB,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAEjF,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAAU,CAAC;AAEhD,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACzC,CAAC","sourcesContent":["export const EXECUTE_COMPILED_RUN: unique symbol = Symbol(\"tubeless.executeCompiledRun\");\nexport const EXECUTE_TEST_RUN: unique symbol = Symbol(\"tubeless.executeTestRun\");\n\nconst compiledPipelines = new WeakSet<object>();\n\n/** Marks the exact object returned by `definePipeline` as a compiled pipeline. */\nexport function brandCompiledPipeline(pipeline: object): void {\n compiledPipelines.add(pipeline);\n}\n\n/** True only for the object `definePipeline` returned, not `Object.create` wrappers. */\nexport function isCompiledPipeline(pipeline: object): boolean {\n return compiledPipelines.has(pipeline);\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { liveStepGraph, stepEdges } from "./pipeline-graph.js";
2
+ import { STEP_NESTED_PIPELINE } from "./pipeline-step-metadata.js";
2
3
  import { PIPELINE_MERMAID_DIRECTIONS } from "./pipeline-types.js";
3
4
  function escapeMermaidLabel(value) {
4
5
  return value
@@ -23,7 +24,9 @@ export function renderPipelineMermaid(steps, options, stepGraph) {
23
24
  const label = options.includeDescriptions && step.description
24
25
  ? `${displayName} — ${step.description}`
25
26
  : displayName;
26
- lines.push(` ${nodeId}["${escapeMermaidLabel(label)}"]`);
27
+ const nested = step[STEP_NESTED_PIPELINE];
28
+ const iteration = nested?.mode === "iterate" ? ` (at most ${nested.maxIterations} iterations)` : "";
29
+ lines.push(` ${nodeId}["${escapeMermaidLabel(label + iteration)}"]`);
27
30
  }
28
31
  const edgeLines = [];
29
32
  for (const step of steps) {
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-mermaid.js","sourceRoot":"","sources":["../../src/core/pipeline-mermaid.ts"],"names":[],"mappings":"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","sourcesContent":["import { liveStepGraph, stepEdges, type CompiledStepGraph } from \"./pipeline-graph.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport { PIPELINE_MERMAID_DIRECTIONS, type PipelineMermaidOptions } from \"./pipeline-types.js\";\n\nfunction escapeMermaidLabel(value: string): string {\n return value\n .replace(/\\r\\n?|\\n/g, \" \")\n .replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, \" \")\n .replace(/#/g, \"#35;\")\n .replace(/&/g, \"#38;\")\n .replace(/\"/g, \"#quot;\")\n .replace(/</g, \"#60;\")\n .replace(/>/g, \"#62;\");\n}\n\nexport function renderPipelineMermaid<TOptions extends object>(\n steps: readonly AnyStep<TOptions>[],\n options: PipelineMermaidOptions,\n stepGraph?: ReadonlyMap<AnyStep, CompiledStepGraph>\n): string {\n const direction = options.direction ?? \"TD\";\n if (!PIPELINE_MERMAID_DIRECTIONS.includes(direction)) {\n throw new Error(`Invalid Mermaid flowchart direction: ${direction}`);\n }\n const nodeIdByStep = new Map(steps.map((step, index) => [step, `step${index}`]));\n const lines = [`flowchart ${direction}`];\n\n for (const step of steps) {\n const nodeId = nodeIdByStep.get(step)!;\n const displayName = step.name ?? step.id;\n const label =\n options.includeDescriptions && step.description\n ? `${displayName} — ${step.description}`\n : displayName;\n lines.push(` ${nodeId}[\"${escapeMermaidLabel(label)}\"]`);\n }\n\n const edgeLines: string[] = [];\n for (const step of steps) {\n const graph = stepGraph?.get(step) ?? liveStepGraph(step);\n const targetId = nodeIdByStep.get(step)!;\n const required = new Set(graph.dependsOn);\n const optional = new Set(graph.optionalDependsOn);\n const failureGates = new Set(graph.skipAfterFailureOf);\n\n for (const dependency of stepEdges(step, graph)) {\n const sourceId = nodeIdByStep.get(dependency)!;\n if (required.has(dependency)) {\n edgeLines.push(` ${sourceId} --> ${targetId}`);\n continue;\n }\n if (optional.has(dependency) && failureGates.has(dependency)) {\n edgeLines.push(` ${sourceId} -. optional input + failure gate .-> ${targetId}`);\n continue;\n }\n if (optional.has(dependency)) {\n edgeLines.push(` ${sourceId} -. optional input .-> ${targetId}`);\n continue;\n }\n edgeLines.push(` ${sourceId} -. failure gate .-> ${targetId}`);\n }\n }\n\n if (edgeLines.length > 0) lines.push(\"\", ...edgeLines);\n return `${lines.join(\"\\n\")}\\n`;\n}\n"]}
1
+ {"version":3,"file":"pipeline-mermaid.js","sourceRoot":"","sources":["../../src/core/pipeline-mermaid.ts"],"names":[],"mappings":"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","sourcesContent":["import { liveStepGraph, stepEdges, type CompiledStepGraph } from \"./pipeline-graph.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport { STEP_NESTED_PIPELINE } from \"./pipeline-step-metadata.js\";\nimport { PIPELINE_MERMAID_DIRECTIONS, type PipelineMermaidOptions } from \"./pipeline-types.js\";\n\nfunction escapeMermaidLabel(value: string): string {\n return value\n .replace(/\\r\\n?|\\n/g, \" \")\n .replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, \" \")\n .replace(/#/g, \"#35;\")\n .replace(/&/g, \"#38;\")\n .replace(/\"/g, \"#quot;\")\n .replace(/</g, \"#60;\")\n .replace(/>/g, \"#62;\");\n}\n\nexport function renderPipelineMermaid<TOptions extends object>(\n steps: readonly AnyStep<TOptions>[],\n options: PipelineMermaidOptions,\n stepGraph?: ReadonlyMap<AnyStep, CompiledStepGraph>\n): string {\n const direction = options.direction ?? \"TD\";\n if (!PIPELINE_MERMAID_DIRECTIONS.includes(direction)) {\n throw new Error(`Invalid Mermaid flowchart direction: ${direction}`);\n }\n const nodeIdByStep = new Map(steps.map((step, index) => [step, `step${index}`]));\n const lines = [`flowchart ${direction}`];\n\n for (const step of steps) {\n const nodeId = nodeIdByStep.get(step)!;\n const displayName = step.name ?? step.id;\n const label =\n options.includeDescriptions && step.description\n ? `${displayName} — ${step.description}`\n : displayName;\n const nested = step[STEP_NESTED_PIPELINE];\n const iteration =\n nested?.mode === \"iterate\" ? ` (at most ${nested.maxIterations} iterations)` : \"\";\n lines.push(` ${nodeId}[\"${escapeMermaidLabel(label + iteration)}\"]`);\n }\n\n const edgeLines: string[] = [];\n for (const step of steps) {\n const graph = stepGraph?.get(step) ?? liveStepGraph(step);\n const targetId = nodeIdByStep.get(step)!;\n const required = new Set(graph.dependsOn);\n const optional = new Set(graph.optionalDependsOn);\n const failureGates = new Set(graph.skipAfterFailureOf);\n\n for (const dependency of stepEdges(step, graph)) {\n const sourceId = nodeIdByStep.get(dependency)!;\n if (required.has(dependency)) {\n edgeLines.push(` ${sourceId} --> ${targetId}`);\n continue;\n }\n if (optional.has(dependency) && failureGates.has(dependency)) {\n edgeLines.push(` ${sourceId} -. optional input + failure gate .-> ${targetId}`);\n continue;\n }\n if (optional.has(dependency)) {\n edgeLines.push(` ${sourceId} -. optional input .-> ${targetId}`);\n continue;\n }\n edgeLines.push(` ${sourceId} -. failure gate .-> ${targetId}`);\n }\n }\n\n if (edgeLines.length > 0) lines.push(\"\", ...edgeLines);\n return `${lines.join(\"\\n\")}\\n`;\n}\n"]}
@@ -1,10 +1,10 @@
1
1
  import type { PipelineLifecycleObserver } from "./lifecycle.js";
2
2
  import type { PipelineError, PipelinePlan, PipelinePlanStep, PipelineRun, PipelineStepProgress, PipelineStepReport, PipelineStepSkipReason } from "./pipeline-types.js";
3
3
  export interface PipelineStepAttempt {
4
+ outputSource?: "override";
4
5
  attemptId: string;
5
6
  startedAtMs: number;
6
7
  }
7
- export declare function isCancellationOnly(errors: readonly PipelineError[]): boolean;
8
8
  export declare class PipelineRunState<TResult> {
9
9
  #private;
10
10
  readonly pipelineId: string;
@@ -16,18 +16,18 @@ export declare class PipelineRunState<TResult> {
16
16
  runId: string;
17
17
  };
18
18
  readonly now: () => number;
19
- readonly lifecycle: PipelineLifecycleObserver;
19
+ readonly lifecycle: Pick<PipelineLifecycleObserver, "pipelineStart" | "stepStatus" | "finalizeStart" | "finalizeComplete" | "finalizeError" | "pipelineComplete" | "flush">;
20
20
  constructor(pipelineId: string, dryRun: boolean, startedAtMs: number, identity: {
21
21
  correlationId?: string;
22
22
  parentRunId?: string;
23
23
  runId: string;
24
- }, now: () => number, lifecycle: PipelineLifecycleObserver);
24
+ }, now: () => number, lifecycle: Pick<PipelineLifecycleObserver, "pipelineStart" | "stepStatus" | "finalizeStart" | "finalizeComplete" | "finalizeError" | "pipelineComplete" | "flush">);
25
25
  get errors(): readonly PipelineError[];
26
26
  get outputs(): ReadonlyMap<string, unknown>;
27
27
  get reportsByStepId(): ReadonlyMap<string, PipelineStepReport>;
28
28
  start(plan: PipelinePlan, targetIds: readonly string[]): void;
29
29
  planStep(step: PipelinePlanStep): void;
30
- beginAttempt(step: PipelinePlanStep, startedAtMs?: number): PipelineStepAttempt;
30
+ beginAttempt(step: PipelinePlanStep, startedAtMs?: number, outputSource?: "override"): PipelineStepAttempt;
31
31
  reportProgress(step: PipelinePlanStep, attempt: PipelineStepAttempt, progress: PipelineStepProgress): void;
32
32
  completeStep(step: PipelinePlanStep, attempt: PipelineStepAttempt, value: unknown): void;
33
33
  skipStep(step: PipelinePlanStep, input: {
@@ -1,7 +1,5 @@
1
+ import { isCancellationOnly } from "./pipeline-execution-error.js";
1
2
  import { RUN_MODEL_VERSION } from "./pipeline-ids.js";
2
- export function isCancellationOnly(errors) {
3
- return errors.length > 0 && errors.every(({ kind }) => kind === "cancellation");
4
- }
5
3
  function terminalRunStatus(errors) {
6
4
  if (errors.length === 0)
7
5
  return "completed";
@@ -13,6 +11,7 @@ function stepReportFromStatus(event) {
13
11
  name: event.name,
14
12
  description: event.description,
15
13
  finishedAtMs: event.finishedAtMs,
14
+ ...(event.outputSource ? { outputSource: event.outputSource } : {}),
16
15
  };
17
16
  switch (event.status) {
18
17
  case "completed":
@@ -105,13 +104,15 @@ export class PipelineRunState {
105
104
  planStep(step) {
106
105
  this.#applyStepStatus({ pipelineId: this.pipelineId, status: "planned", step });
107
106
  }
108
- beginAttempt(step, startedAtMs = this.now()) {
107
+ beginAttempt(step, startedAtMs = this.now(), outputSource) {
109
108
  const attempt = {
110
109
  attemptId: `${this.identity.runId}:attempt:${(this.#nextAttemptSequence += 1).toString(36)}`,
111
110
  startedAtMs,
111
+ ...(outputSource ? { outputSource } : {}),
112
112
  };
113
113
  this.#applyStepStatus({
114
114
  attemptId: attempt.attemptId,
115
+ ...(attempt.outputSource ? { outputSource: attempt.outputSource } : {}),
115
116
  pipelineId: this.pipelineId,
116
117
  status: "running",
117
118
  step,
@@ -121,6 +122,7 @@ export class PipelineRunState {
121
122
  reportProgress(step, attempt, progress) {
122
123
  this.#applyStepStatus({
123
124
  attemptId: attempt.attemptId,
125
+ ...(attempt.outputSource ? { outputSource: attempt.outputSource } : {}),
124
126
  pipelineId: this.pipelineId,
125
127
  progress,
126
128
  status: "running",
@@ -129,18 +131,18 @@ export class PipelineRunState {
129
131
  }
130
132
  completeStep(step, attempt, value) {
131
133
  const report = {
132
- attemptId: attempt.attemptId,
134
+ ...attempt,
133
135
  id: step.id,
134
136
  name: step.name,
135
137
  description: step.description,
136
138
  finishedAtMs: this.now(),
137
- startedAtMs: attempt.startedAtMs,
138
139
  status: "completed",
139
140
  };
140
141
  this.#applyStepStatus({ ...report, pipelineId: this.pipelineId, step }, { output: { value } });
141
142
  }
142
143
  skipStep(step, input) {
143
144
  const report = {
145
+ ...input.attempt,
144
146
  id: step.id,
145
147
  name: step.name,
146
148
  description: step.description,
@@ -148,10 +150,6 @@ export class PipelineRunState {
148
150
  reason: input.reason,
149
151
  status: "skipped",
150
152
  };
151
- if (input.attempt) {
152
- report.attemptId = input.attempt.attemptId;
153
- report.startedAtMs = input.attempt.startedAtMs;
154
- }
155
153
  if (input.dependencyId)
156
154
  report.dependencyId = input.dependencyId;
157
155
  if (input.message)
@@ -164,19 +162,19 @@ export class PipelineRunState {
164
162
  return;
165
163
  }
166
164
  const report = {
167
- attemptId: attempt.attemptId,
165
+ ...attempt,
168
166
  id: step.id,
169
167
  name: step.name,
170
168
  description: step.description,
171
169
  error,
172
170
  finishedAtMs: this.now(),
173
- startedAtMs: attempt.startedAtMs,
174
171
  status: "failed",
175
172
  };
176
173
  this.#applyStepStatus({ ...report, pipelineId: this.pipelineId, step }, { error: { record: true, value: error } });
177
174
  }
178
175
  cancelStep(step, error, recordError, attempt) {
179
176
  const report = {
177
+ ...attempt,
180
178
  id: step.id,
181
179
  name: step.name,
182
180
  description: step.description,
@@ -184,10 +182,6 @@ export class PipelineRunState {
184
182
  finishedAtMs: this.now(),
185
183
  status: "cancelled",
186
184
  };
187
- if (attempt) {
188
- report.attemptId = attempt.attemptId;
189
- report.startedAtMs = attempt.startedAtMs;
190
- }
191
185
  this.#applyStepStatus({ ...report, pipelineId: this.pipelineId, step }, { error: { record: recordError, value: error } });
192
186
  }
193
187
  recordRunErrors(errors) {
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-run-state.js","sourceRoot":"","sources":["../../src/core/pipeline-run-state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAiCtD,MAAM,UAAU,kBAAkB,CAAC,MAAgC;IACjE,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAgC;IACzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,WAAW,CAAC;IAC5C,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC7D,CAAC;AAED,SAAS,oBAAoB,CAC3B,KAAqE;IAErE,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC;IACF,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,WAAW;YACd,OAAO;gBACL,GAAG,IAAI;gBACP,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,WAAW;aACpB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO;gBACL,GAAG,IAAI;gBACP,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,QAAQ;aACjB,CAAC;QACJ,KAAK,WAAW,EAAE,CAAC;YACjB,MAAM,MAAM,GAAgC;gBAC1C,GAAG,IAAI;gBACP,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM,EAAE,WAAW;aACpB,CAAC;YACF,IAAI,KAAK,CAAC,SAAS;gBAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YACxD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;gBAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;YAC5E,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,SAAS,EAAE,CAAC;YACf,MAAM,MAAM,GAA8B;gBACxC,GAAG,IAAI;gBACP,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,MAAM,EAAE,SAAS;aAClB,CAAC;YACF,IAAI,KAAK,CAAC,SAAS;gBAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YACxD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;gBAAE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;YAC5E,IAAI,KAAK,CAAC,YAAY;gBAAE,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;YACjE,IAAI,KAAK,CAAC,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,OAAO,gBAAgB;IAchB,UAAU;IACV,MAAM;IACN,WAAW;IACX,QAAQ;IACR,GAAG;IACH,SAAS;IAlBX,oBAAoB,GAAG,IAAI,GAAG,EAAwC,CAAC;IACvE,OAAO,GAAoB,EAAE,CAAC;IAC9B,UAAU,GAAG,IAAI,GAAG,EAAiB,CAAC;IACtC,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IACtC,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,gBAAgB,GAAG,IAAI,GAAG,EAA8B,CAAC;IAClE,mBAAmB,CAAoC;IACvD,sBAAsB,GAAG,KAAK,CAAC;IAC/B,aAAa,GAAkC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACtF,oBAAoB,GAAG,CAAC,CAAC;IACzB,MAAM,GAAa,SAAS,CAAC;IAE7B,YACW,UAAkB,EAClB,MAAe,EACf,WAAmB,EACnB,QAAyE,EACzE,GAAiB,EACjB,SAAoC;0BALpC,UAAU;sBACV,MAAM;2BACN,WAAW;wBACX,QAAQ;mBACR,GAAG;yBACH,SAAS;IACjB,CAAC;IAEJ,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,IAAkB,EAAE,SAA4B;QACpD,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC;IAED,QAAQ,CAAC,IAAsB;QAC7B,IAAI,CAAC,gBAAgB,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,YAAY,CAAC,IAAsB,EAAE,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;YAC5F,WAAW;SACZ,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,SAAS;YACjB,IAAI;SACL,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,cAAc,CACZ,IAAsB,EACtB,OAA4B,EAC5B,QAA8B;QAE9B,IAAI,CAAC,gBAAgB,CAAC;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ;YACR,MAAM,EAAE,SAAS;YACjB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,IAAsB,EAAE,OAA4B,EAAE,KAAc;QAC/E,MAAM,MAAM,GAA+B;YACzC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,WAAW;SACpB,CAAC;QACF,IAAI,CAAC,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,QAAQ,CACN,IAAsB,EACtB,KAMC;QAED,MAAM,MAAM,GAA8B;YACxC,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,SAAS;SAClB,CAAC;QACF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3C,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QACjD,CAAC;QACD,IAAI,KAAK,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACjE,IAAI,KAAK,CAAC,OAAO;YAAE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAClD,IAAI,CAAC,gBAAgB,CACnB,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAChD,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CACpD,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,IAAsB,EAAE,OAA4B,EAAE,KAAoB;QACjF,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAClC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAA6B;YACvC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,KAAK;YACL,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,MAAM,EAAE,QAAQ;SACjB,CAAC;QACF,IAAI,CAAC,gBAAgB,CACnB,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAChD,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAC1C,CAAC;IACJ,CAAC;IAED,UAAU,CACR,IAAsB,EACtB,KAAoB,EACpB,WAAoB,EACpB,OAA6B;QAE7B,MAAM,MAAM,GAAgC;YAC1C,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,KAAK;YACL,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,MAAM,EAAE,WAAW;SACpB,CAAC;QACF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;YACrC,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC,gBAAgB,CACnB,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAChD,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CACjD,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,MAAgC;QAC9C,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,sBAAsB;YAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC5F,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC;IACjC,CAAC;IAED,oBAAoB,CAAC,KAAc,EAAE,UAAkB;QACrD,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,gBAAgB,CAAC,KAAoB,EAAE,UAAkB;QACvD,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;QACzB,MAAM,UAAU,GAAG,CAAC,KAAoB,EAAU,EAAE;YAClD,8EAA8E;YAC9E,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC;YAC1C,IAAI,KAAK,CAAC,KAAK,KAAK,cAAc;gBAAE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAChE,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC,CAAC;QACF,qFAAqF;QACrF,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACpD,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAE,CAChF,CAAC;QACF,MAAM,MAAM,GAAyB;YACnC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM;YACN,YAAY,EAAE,IAAI,CAAC,GAAG,EAAE;YACxB,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK;YAC1B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC;YACvC,KAAK;YACL,OAAO,EAAE,iBAAiB;YAC1B,GAAG,IAAI,CAAC,aAAa;SACtB,CAAC;QACF,IAAI,IAAI,CAAC,mBAAmB;YAAE,MAAM,CAAC,kBAAkB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACnF,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YAC9C,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;QACrD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW;YAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC9E,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,gBAAgB,CAAC,KAAyB,EAAE,OAAO,GAA0B,EAAE;QAC7E,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,KAAK,GACT,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;YACtD,CAAC,QAAQ,KAAK,SAAS;gBACrB,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;oBACzB,KAAK,CAAC,MAAM,KAAK,SAAS;oBAC1B,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;YAClC,CAAC,QAAQ,KAAK,SAAS;gBACrB,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS;oBACzB,KAAK,CAAC,MAAM,KAAK,WAAW;oBAC5B,KAAK,CAAC,MAAM,KAAK,SAAS;oBAC1B,KAAK,CAAC,MAAM,KAAK,WAAW;oBAC5B,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,sCAAsC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,YAAY,OAAO,KAAK,CAAC,MAAM,EAAE,CACtG,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,YAAY,CAAC,QAAkB;QAC7B,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,6CAA6C,QAAQ,WAAW,IAAI,CAAC,MAAM,EAAE,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,uBAAuB;QACrB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACzD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC;YAClF,CAAC;QACH,CAAC;IACH,CAAC;CACF","sourcesContent":["import type { PipelineLifecycleObserver } from \"./lifecycle.js\";\nimport { RUN_MODEL_VERSION } from \"./pipeline-ids.js\";\nimport type {\n PipelineError,\n PipelinePlan,\n PipelinePlanStep,\n PipelineRun,\n PipelineRunStatus,\n PipelineStepCancelledReport,\n PipelineStepCompleteReport,\n PipelineStepFailedReport,\n PipelineStepProgress,\n PipelineStepReport,\n PipelineStepSkipReason,\n PipelineStepSkippedReport,\n PipelineStepStatus,\n} from \"./pipeline-types.js\";\n\nexport interface PipelineStepAttempt {\n attemptId: string;\n startedAtMs: number;\n}\n\ntype RunPhase = \"created\" | \"finalizing\" | \"finished\" | \"running\";\n\ntype StepTransitionEffects = {\n error?: { record: boolean; value: PipelineError };\n output?: { value: unknown };\n};\n\ntype PipelineFinalization<TResult> =\n | { finalized: false; value: undefined }\n | { finalized: true; value: TResult };\n\nexport function isCancellationOnly(errors: readonly PipelineError[]): boolean {\n return errors.length > 0 && errors.every(({ kind }) => kind === \"cancellation\");\n}\n\nfunction terminalRunStatus(errors: readonly PipelineError[]): PipelineRunStatus {\n if (errors.length === 0) return \"completed\";\n return isCancellationOnly(errors) ? \"cancelled\" : \"failed\";\n}\n\nfunction stepReportFromStatus(\n event: Exclude<PipelineStepStatus, { status: \"planned\" | \"running\" }>\n): PipelineStepReport {\n const base = {\n id: event.id,\n name: event.name,\n description: event.description,\n finishedAtMs: event.finishedAtMs,\n };\n switch (event.status) {\n case \"completed\":\n return {\n ...base,\n attemptId: event.attemptId,\n startedAtMs: event.startedAtMs,\n status: \"completed\",\n };\n case \"failed\":\n return {\n ...base,\n attemptId: event.attemptId,\n error: event.error,\n startedAtMs: event.startedAtMs,\n status: \"failed\",\n };\n case \"cancelled\": {\n const report: PipelineStepCancelledReport = {\n ...base,\n error: event.error,\n status: \"cancelled\",\n };\n if (event.attemptId) report.attemptId = event.attemptId;\n if (event.startedAtMs !== undefined) report.startedAtMs = event.startedAtMs;\n return report;\n }\n case \"skipped\": {\n const report: PipelineStepSkippedReport = {\n ...base,\n reason: event.reason,\n status: \"skipped\",\n };\n if (event.attemptId) report.attemptId = event.attemptId;\n if (event.startedAtMs !== undefined) report.startedAtMs = event.startedAtMs;\n if (event.dependencyId) report.dependencyId = event.dependencyId;\n if (event.message) report.message = event.message;\n return report;\n }\n }\n}\n\nexport class PipelineRunState<TResult> {\n readonly #currentStepStatuses = new Map<string, PipelineStepStatus[\"status\"]>();\n readonly #errors: PipelineError[] = [];\n readonly #runErrors = new Set<PipelineError>();\n readonly #outputs = new Map<string, unknown>();\n readonly #stepOrder = new Map<string, number>();\n readonly #reportsByStepId = new Map<string, PipelineStepReport>();\n #definitionIdentity: PipelineRun[\"definitionIdentity\"];\n #finalizationAttempted = false;\n #finalization: PipelineFinalization<TResult> = { finalized: false, value: undefined };\n #nextAttemptSequence = 0;\n #phase: RunPhase = \"created\";\n\n constructor(\n readonly pipelineId: string,\n readonly dryRun: boolean,\n readonly startedAtMs: number,\n readonly identity: { correlationId?: string; parentRunId?: string; runId: string },\n readonly now: () => number,\n readonly lifecycle: PipelineLifecycleObserver\n ) {}\n\n get errors(): readonly PipelineError[] {\n return this.#errors;\n }\n\n get outputs(): ReadonlyMap<string, unknown> {\n return this.#outputs;\n }\n\n get reportsByStepId(): ReadonlyMap<string, PipelineStepReport> {\n return this.#reportsByStepId;\n }\n\n start(plan: PipelinePlan, targetIds: readonly string[]): void {\n this.#expectPhase(\"created\");\n this.#phase = \"running\";\n this.#definitionIdentity = plan.definition?.identity;\n plan.steps.forEach((step, index) => this.#stepOrder.set(step.id, index));\n this.lifecycle.pipelineStart(plan, targetIds);\n }\n\n planStep(step: PipelinePlanStep): void {\n this.#applyStepStatus({ pipelineId: this.pipelineId, status: \"planned\", step });\n }\n\n beginAttempt(step: PipelinePlanStep, startedAtMs = this.now()): PipelineStepAttempt {\n const attempt = {\n attemptId: `${this.identity.runId}:attempt:${(this.#nextAttemptSequence += 1).toString(36)}`,\n startedAtMs,\n };\n this.#applyStepStatus({\n attemptId: attempt.attemptId,\n pipelineId: this.pipelineId,\n status: \"running\",\n step,\n });\n return attempt;\n }\n\n reportProgress(\n step: PipelinePlanStep,\n attempt: PipelineStepAttempt,\n progress: PipelineStepProgress\n ): void {\n this.#applyStepStatus({\n attemptId: attempt.attemptId,\n pipelineId: this.pipelineId,\n progress,\n status: \"running\",\n step,\n });\n }\n\n completeStep(step: PipelinePlanStep, attempt: PipelineStepAttempt, value: unknown): void {\n const report: PipelineStepCompleteReport = {\n attemptId: attempt.attemptId,\n id: step.id,\n name: step.name,\n description: step.description,\n finishedAtMs: this.now(),\n startedAtMs: attempt.startedAtMs,\n status: \"completed\",\n };\n this.#applyStepStatus({ ...report, pipelineId: this.pipelineId, step }, { output: { value } });\n }\n\n skipStep(\n step: PipelinePlanStep,\n input: {\n attempt?: PipelineStepAttempt;\n dependencyId?: string;\n message?: string;\n output?: { value: unknown };\n reason: PipelineStepSkipReason;\n }\n ): void {\n const report: PipelineStepSkippedReport = {\n id: step.id,\n name: step.name,\n description: step.description,\n finishedAtMs: this.now(),\n reason: input.reason,\n status: \"skipped\",\n };\n if (input.attempt) {\n report.attemptId = input.attempt.attemptId;\n report.startedAtMs = input.attempt.startedAtMs;\n }\n if (input.dependencyId) report.dependencyId = input.dependencyId;\n if (input.message) report.message = input.message;\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n input.output ? { output: input.output } : undefined\n );\n }\n\n failStep(step: PipelinePlanStep, attempt: PipelineStepAttempt, error: PipelineError): void {\n if (error.kind === \"cancellation\") {\n this.cancelStep(step, error, true, attempt);\n return;\n }\n const report: PipelineStepFailedReport = {\n attemptId: attempt.attemptId,\n id: step.id,\n name: step.name,\n description: step.description,\n error,\n finishedAtMs: this.now(),\n startedAtMs: attempt.startedAtMs,\n status: \"failed\",\n };\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n { error: { record: true, value: error } }\n );\n }\n\n cancelStep(\n step: PipelinePlanStep,\n error: PipelineError,\n recordError: boolean,\n attempt?: PipelineStepAttempt\n ): void {\n const report: PipelineStepCancelledReport = {\n id: step.id,\n name: step.name,\n description: step.description,\n error,\n finishedAtMs: this.now(),\n status: \"cancelled\",\n };\n if (attempt) {\n report.attemptId = attempt.attemptId;\n report.startedAtMs = attempt.startedAtMs;\n }\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n { error: { record: recordError, value: error } }\n );\n }\n\n recordRunErrors(errors: readonly PipelineError[]): void {\n this.#expectPhase(\"running\");\n for (const error of errors) this.#runErrors.add(error);\n this.#errors.push(...errors);\n }\n\n beginFinalization(): void {\n this.#expectPhase(\"running\");\n this.#expectAllStepsTerminal();\n if (this.#finalizationAttempted) throw new Error(\"Pipeline finalization already attempted\");\n this.#finalizationAttempted = true;\n this.#phase = \"finalizing\";\n this.lifecycle.finalizeStart();\n }\n\n completeFinalization(value: TResult, durationMs: number): void {\n this.#expectPhase(\"finalizing\");\n this.#finalization = { finalized: true, value };\n this.#phase = \"running\";\n this.lifecycle.finalizeComplete(durationMs, value);\n }\n\n failFinalization(error: PipelineError, durationMs: number): void {\n this.#expectPhase(\"finalizing\");\n this.#errors.push(error);\n this.#phase = \"running\";\n this.lifecycle.finalizeError(error, durationMs);\n }\n\n async finish(): Promise<PipelineRun<TResult>> {\n this.#expectPhase(\"running\");\n this.#expectAllStepsTerminal();\n this.#phase = \"finished\";\n const errorOrder = (error: PipelineError): number => {\n // A run-level diagnostic may identify a step without becoming a step failure.\n if (this.#runErrors.has(error)) return -1;\n if (error.phase === \"finalization\") return this.#stepOrder.size;\n return error.stepId === undefined ? -1 : (this.#stepOrder.get(error.stepId) ?? -1);\n };\n // Live observations retain event order; only the finished record is ordered by plan.\n const errors = [...this.#errors].sort((left, right) => errorOrder(left) - errorOrder(right));\n const steps = [...this.#reportsByStepId.values()].sort(\n (left, right) => this.#stepOrder.get(left.id)! - this.#stepOrder.get(right.id)!\n );\n const result: PipelineRun<TResult> = {\n pipelineId: this.pipelineId,\n dryRun: this.dryRun,\n errors,\n finishedAtMs: this.now(),\n runId: this.identity.runId,\n startedAtMs: this.startedAtMs,\n status: terminalRunStatus(this.#errors),\n steps,\n version: RUN_MODEL_VERSION,\n ...this.#finalization,\n };\n if (this.#definitionIdentity) result.definitionIdentity = this.#definitionIdentity;\n if (this.identity.correlationId !== undefined) {\n result.correlationId = this.identity.correlationId;\n }\n if (this.identity.parentRunId) result.parentRunId = this.identity.parentRunId;\n this.lifecycle.pipelineComplete(result);\n await this.lifecycle.flush();\n return result;\n }\n\n #applyStepStatus(event: PipelineStepStatus, effects: StepTransitionEffects = {}): void {\n this.#expectPhase(\"running\");\n const previous = this.#currentStepStatuses.get(event.step.id);\n const valid =\n (previous === undefined && event.status === \"planned\") ||\n (previous === \"planned\" &&\n (event.status === \"running\" ||\n event.status === \"skipped\" ||\n event.status === \"cancelled\")) ||\n (previous === \"running\" &&\n (event.status === \"running\" ||\n event.status === \"completed\" ||\n event.status === \"skipped\" ||\n event.status === \"cancelled\" ||\n event.status === \"failed\"));\n if (!valid) {\n throw new Error(\n `Invalid step status transition for ${event.step.id}: ${previous ?? \"unobserved\"} -> ${event.status}`\n );\n }\n\n this.#currentStepStatuses.set(event.step.id, event.status);\n if (event.status !== \"planned\" && event.status !== \"running\") {\n const report = stepReportFromStatus(event);\n this.#reportsByStepId.set(event.step.id, report);\n }\n if (effects.output) this.#outputs.set(event.step.id, effects.output.value);\n if (effects.error?.record) this.#errors.push(effects.error.value);\n this.lifecycle.stepStatus(event);\n }\n\n #expectPhase(expected: RunPhase): void {\n if (this.#phase !== expected) {\n throw new Error(\n `Invalid pipeline run transition: expected ${expected}, found ${this.#phase}`\n );\n }\n }\n\n #expectAllStepsTerminal(): void {\n for (const [stepId, status] of this.#currentStepStatuses) {\n if (status === \"planned\" || status === \"running\") {\n throw new Error(`Cannot finish pipeline run while step ${stepId} is ${status}`);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"pipeline-run-state.js","sourceRoot":"","sources":["../../src/core/pipeline-run-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { isCancellationOnly } from \"./pipeline-execution-error.js\";\nimport type { PipelineLifecycleObserver } from \"./lifecycle.js\";\nimport { RUN_MODEL_VERSION } from \"./pipeline-ids.js\";\nimport type {\n PipelineError,\n PipelinePlan,\n PipelinePlanStep,\n PipelineRun,\n PipelineRunStatus,\n PipelineStepCancelledReport,\n PipelineStepCompleteReport,\n PipelineStepFailedReport,\n PipelineStepProgress,\n PipelineStepReport,\n PipelineStepSkipReason,\n PipelineStepSkippedReport,\n PipelineStepStatus,\n} from \"./pipeline-types.js\";\n\nexport interface PipelineStepAttempt {\n outputSource?: \"override\";\n attemptId: string;\n startedAtMs: number;\n}\n\ntype RunPhase = \"created\" | \"finalizing\" | \"finished\" | \"running\";\n\ntype StepTransitionEffects = {\n error?: { record: boolean; value: PipelineError };\n output?: { value: unknown };\n};\n\ntype PipelineFinalization<TResult> =\n | { finalized: false; value: undefined }\n | { finalized: true; value: TResult };\n\nfunction terminalRunStatus(errors: readonly PipelineError[]): PipelineRunStatus {\n if (errors.length === 0) return \"completed\";\n return isCancellationOnly(errors) ? \"cancelled\" : \"failed\";\n}\n\nfunction stepReportFromStatus(\n event: Exclude<PipelineStepStatus, { status: \"planned\" | \"running\" }>\n): PipelineStepReport {\n const base = {\n id: event.id,\n name: event.name,\n description: event.description,\n finishedAtMs: event.finishedAtMs,\n ...(event.outputSource ? { outputSource: event.outputSource } : {}),\n };\n switch (event.status) {\n case \"completed\":\n return {\n ...base,\n attemptId: event.attemptId,\n startedAtMs: event.startedAtMs,\n status: \"completed\",\n };\n case \"failed\":\n return {\n ...base,\n attemptId: event.attemptId,\n error: event.error,\n startedAtMs: event.startedAtMs,\n status: \"failed\",\n };\n case \"cancelled\": {\n const report: PipelineStepCancelledReport = {\n ...base,\n error: event.error,\n status: \"cancelled\",\n };\n if (event.attemptId) report.attemptId = event.attemptId;\n if (event.startedAtMs !== undefined) report.startedAtMs = event.startedAtMs;\n return report;\n }\n case \"skipped\": {\n const report: PipelineStepSkippedReport = {\n ...base,\n reason: event.reason,\n status: \"skipped\",\n };\n if (event.attemptId) report.attemptId = event.attemptId;\n if (event.startedAtMs !== undefined) report.startedAtMs = event.startedAtMs;\n if (event.dependencyId) report.dependencyId = event.dependencyId;\n if (event.message) report.message = event.message;\n return report;\n }\n }\n}\n\nexport class PipelineRunState<TResult> {\n readonly #currentStepStatuses = new Map<string, PipelineStepStatus[\"status\"]>();\n readonly #errors: PipelineError[] = [];\n readonly #runErrors = new Set<PipelineError>();\n readonly #outputs = new Map<string, unknown>();\n readonly #stepOrder = new Map<string, number>();\n readonly #reportsByStepId = new Map<string, PipelineStepReport>();\n #definitionIdentity: PipelineRun[\"definitionIdentity\"];\n #finalizationAttempted = false;\n #finalization: PipelineFinalization<TResult> = { finalized: false, value: undefined };\n #nextAttemptSequence = 0;\n #phase: RunPhase = \"created\";\n\n constructor(\n readonly pipelineId: string,\n readonly dryRun: boolean,\n readonly startedAtMs: number,\n readonly identity: { correlationId?: string; parentRunId?: string; runId: string },\n readonly now: () => number,\n readonly lifecycle: Pick<\n PipelineLifecycleObserver,\n | \"pipelineStart\"\n | \"stepStatus\"\n | \"finalizeStart\"\n | \"finalizeComplete\"\n | \"finalizeError\"\n | \"pipelineComplete\"\n | \"flush\"\n >\n ) {}\n\n get errors(): readonly PipelineError[] {\n return this.#errors;\n }\n\n get outputs(): ReadonlyMap<string, unknown> {\n return this.#outputs;\n }\n\n get reportsByStepId(): ReadonlyMap<string, PipelineStepReport> {\n return this.#reportsByStepId;\n }\n\n start(plan: PipelinePlan, targetIds: readonly string[]): void {\n this.#expectPhase(\"created\");\n this.#phase = \"running\";\n this.#definitionIdentity = plan.definition?.identity;\n plan.steps.forEach((step, index) => this.#stepOrder.set(step.id, index));\n this.lifecycle.pipelineStart(plan, targetIds);\n }\n\n planStep(step: PipelinePlanStep): void {\n this.#applyStepStatus({ pipelineId: this.pipelineId, status: \"planned\", step });\n }\n\n beginAttempt(\n step: PipelinePlanStep,\n startedAtMs = this.now(),\n outputSource?: \"override\"\n ): PipelineStepAttempt {\n const attempt = {\n attemptId: `${this.identity.runId}:attempt:${(this.#nextAttemptSequence += 1).toString(36)}`,\n startedAtMs,\n ...(outputSource ? { outputSource } : {}),\n };\n this.#applyStepStatus({\n attemptId: attempt.attemptId,\n ...(attempt.outputSource ? { outputSource: attempt.outputSource } : {}),\n pipelineId: this.pipelineId,\n status: \"running\",\n step,\n });\n return attempt;\n }\n\n reportProgress(\n step: PipelinePlanStep,\n attempt: PipelineStepAttempt,\n progress: PipelineStepProgress\n ): void {\n this.#applyStepStatus({\n attemptId: attempt.attemptId,\n ...(attempt.outputSource ? { outputSource: attempt.outputSource } : {}),\n pipelineId: this.pipelineId,\n progress,\n status: \"running\",\n step,\n });\n }\n\n completeStep(step: PipelinePlanStep, attempt: PipelineStepAttempt, value: unknown): void {\n const report: PipelineStepCompleteReport = {\n ...attempt,\n id: step.id,\n name: step.name,\n description: step.description,\n finishedAtMs: this.now(),\n status: \"completed\",\n };\n this.#applyStepStatus({ ...report, pipelineId: this.pipelineId, step }, { output: { value } });\n }\n\n skipStep(\n step: PipelinePlanStep,\n input: {\n attempt?: PipelineStepAttempt;\n dependencyId?: string;\n message?: string;\n output?: { value: unknown };\n reason: PipelineStepSkipReason;\n }\n ): void {\n const report: PipelineStepSkippedReport = {\n ...input.attempt,\n id: step.id,\n name: step.name,\n description: step.description,\n finishedAtMs: this.now(),\n reason: input.reason,\n status: \"skipped\",\n };\n if (input.dependencyId) report.dependencyId = input.dependencyId;\n if (input.message) report.message = input.message;\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n input.output ? { output: input.output } : undefined\n );\n }\n\n failStep(step: PipelinePlanStep, attempt: PipelineStepAttempt, error: PipelineError): void {\n if (error.kind === \"cancellation\") {\n this.cancelStep(step, error, true, attempt);\n return;\n }\n const report: PipelineStepFailedReport = {\n ...attempt,\n id: step.id,\n name: step.name,\n description: step.description,\n error,\n finishedAtMs: this.now(),\n status: \"failed\",\n };\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n { error: { record: true, value: error } }\n );\n }\n\n cancelStep(\n step: PipelinePlanStep,\n error: PipelineError,\n recordError: boolean,\n attempt?: PipelineStepAttempt\n ): void {\n const report: PipelineStepCancelledReport = {\n ...attempt,\n id: step.id,\n name: step.name,\n description: step.description,\n error,\n finishedAtMs: this.now(),\n status: \"cancelled\",\n };\n this.#applyStepStatus(\n { ...report, pipelineId: this.pipelineId, step },\n { error: { record: recordError, value: error } }\n );\n }\n\n recordRunErrors(errors: readonly PipelineError[]): void {\n this.#expectPhase(\"running\");\n for (const error of errors) this.#runErrors.add(error);\n this.#errors.push(...errors);\n }\n\n beginFinalization(): void {\n this.#expectPhase(\"running\");\n this.#expectAllStepsTerminal();\n if (this.#finalizationAttempted) throw new Error(\"Pipeline finalization already attempted\");\n this.#finalizationAttempted = true;\n this.#phase = \"finalizing\";\n this.lifecycle.finalizeStart();\n }\n\n completeFinalization(value: TResult, durationMs: number): void {\n this.#expectPhase(\"finalizing\");\n this.#finalization = { finalized: true, value };\n this.#phase = \"running\";\n this.lifecycle.finalizeComplete(durationMs, value);\n }\n\n failFinalization(error: PipelineError, durationMs: number): void {\n this.#expectPhase(\"finalizing\");\n this.#errors.push(error);\n this.#phase = \"running\";\n this.lifecycle.finalizeError(error, durationMs);\n }\n\n async finish(): Promise<PipelineRun<TResult>> {\n this.#expectPhase(\"running\");\n this.#expectAllStepsTerminal();\n this.#phase = \"finished\";\n const errorOrder = (error: PipelineError): number => {\n // A run-level diagnostic may identify a step without becoming a step failure.\n if (this.#runErrors.has(error)) return -1;\n if (error.phase === \"finalization\") return this.#stepOrder.size;\n return error.stepId === undefined ? -1 : (this.#stepOrder.get(error.stepId) ?? -1);\n };\n // Live observations retain event order; only the finished record is ordered by plan.\n const errors = [...this.#errors].sort((left, right) => errorOrder(left) - errorOrder(right));\n const steps = [...this.#reportsByStepId.values()].sort(\n (left, right) => this.#stepOrder.get(left.id)! - this.#stepOrder.get(right.id)!\n );\n const result: PipelineRun<TResult> = {\n pipelineId: this.pipelineId,\n dryRun: this.dryRun,\n errors,\n finishedAtMs: this.now(),\n runId: this.identity.runId,\n startedAtMs: this.startedAtMs,\n status: terminalRunStatus(this.#errors),\n steps,\n version: RUN_MODEL_VERSION,\n ...this.#finalization,\n };\n if (this.#definitionIdentity) result.definitionIdentity = this.#definitionIdentity;\n if (this.identity.correlationId !== undefined) {\n result.correlationId = this.identity.correlationId;\n }\n if (this.identity.parentRunId) result.parentRunId = this.identity.parentRunId;\n this.lifecycle.pipelineComplete(result);\n await this.lifecycle.flush();\n return result;\n }\n\n #applyStepStatus(event: PipelineStepStatus, effects: StepTransitionEffects = {}): void {\n this.#expectPhase(\"running\");\n const previous = this.#currentStepStatuses.get(event.step.id);\n const valid =\n (previous === undefined && event.status === \"planned\") ||\n (previous === \"planned\" &&\n (event.status === \"running\" ||\n event.status === \"skipped\" ||\n event.status === \"cancelled\")) ||\n (previous === \"running\" &&\n (event.status === \"running\" ||\n event.status === \"completed\" ||\n event.status === \"skipped\" ||\n event.status === \"cancelled\" ||\n event.status === \"failed\"));\n if (!valid) {\n throw new Error(\n `Invalid step status transition for ${event.step.id}: ${previous ?? \"unobserved\"} -> ${event.status}`\n );\n }\n\n this.#currentStepStatuses.set(event.step.id, event.status);\n if (event.status !== \"planned\" && event.status !== \"running\") {\n const report = stepReportFromStatus(event);\n this.#reportsByStepId.set(event.step.id, report);\n }\n if (effects.output) this.#outputs.set(event.step.id, effects.output.value);\n if (effects.error?.record) this.#errors.push(effects.error.value);\n this.lifecycle.stepStatus(event);\n }\n\n #expectPhase(expected: RunPhase): void {\n if (this.#phase !== expected) {\n throw new Error(\n `Invalid pipeline run transition: expected ${expected}, found ${this.#phase}`\n );\n }\n }\n\n #expectAllStepsTerminal(): void {\n for (const [stepId, status] of this.#currentStepStatuses) {\n if (status === \"planned\" || status === \"running\") {\n throw new Error(`Cannot finish pipeline run while step ${stepId} is ${status}`);\n }\n }\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { type ArtifactRecord } from "../tracing/artifact-metadata.js";
1
2
  import type { AnyStep } from "./pipeline-steps.js";
2
3
  import type { PipelineExecutionContext, PipelineLogger, PipelineStepProgress } from "./pipeline-types.js";
3
4
  import type { PipelineTraceAttributes } from "../tracing/tracing-contracts.js";
@@ -13,6 +14,7 @@ export declare function executeStepAttempt<TOptions extends object>(input: {
13
14
  dryRun: boolean;
14
15
  inputs: Record<string, unknown>;
15
16
  log: PipelineLogger;
17
+ onArtifact?(record: ArtifactRecord, preview: boolean): void;
16
18
  onProgress(progress: PipelineStepProgress): void;
17
19
  onReportAttempt(attempt: number, attributes?: PipelineTraceAttributes): void;
18
20
  outputBoundary: string;
@@ -1,3 +1,4 @@
1
+ import { artifactRecordSchema } from "../tracing/artifact-metadata.js";
1
2
  import { validateStandardSchema } from "./pipeline-validation.js";
2
3
  function normalizeStepSkipDecision(decision) {
3
4
  if (decision == null || decision === false)
@@ -26,14 +27,21 @@ export async function validateStepOutput(step, value, boundary) {
26
27
  }
27
28
  export async function executeStepAttempt(input) {
28
29
  const { step } = input;
29
- let acceptsProgress = true;
30
+ let acceptsReports = true;
30
31
  const stepContext = {
31
32
  ...input.context,
33
+ recordArtifact: (record) => {
34
+ if (!acceptsReports)
35
+ return;
36
+ const snapshot = artifactRecordSchema.decode(record, "artifact record");
37
+ const preview = input.dryRun && (typeof step.dryRun === "function" || snapshot.operation === "write");
38
+ input.onArtifact?.(snapshot, preview);
39
+ },
32
40
  attemptId: input.attemptId,
33
41
  log: input.log,
34
42
  reportAttempt: input.onReportAttempt,
35
43
  reportProgress: (progress) => {
36
- if (acceptsProgress)
44
+ if (acceptsReports)
37
45
  input.onProgress(progress);
38
46
  },
39
47
  };
@@ -45,7 +53,7 @@ export async function executeStepAttempt(input) {
45
53
  : await step.run(input.inputs, stepContext);
46
54
  }
47
55
  finally {
48
- acceptsProgress = false;
56
+ acceptsReports = false;
49
57
  }
50
58
  return validateStepOutput(step, output, input.outputBoundary);
51
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline-step-executor.js","sourceRoot":"","sources":["../../src/core/pipeline-step-executor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,SAAS,yBAAyB,CAAC,QAA0B;IAC3D,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACxD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxE,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAuB,EACvB,MAA+B,EAC/B,OAA2C;IAE3C,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,yBAAyB,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAuB,EACvB,KAAc,EACd,QAAgB;IAEhB,OAAO,IAAI,CAAC,YAAY;QACtB,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,QAAQ,CAAC;QAC5D,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAA0B,KAUjE;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,IAAI,eAAe,GAAG,IAAI,CAAC;IAC3B,MAAM,WAAW,GAAG;QAClB,GAAG,KAAK,CAAC,OAAO;QAChB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,aAAa,EAAE,KAAK,CAAC,eAAe;QACpC,cAAc,EAAE,CAAC,QAA8B,EAAE,EAAE;YACjD,IAAI,eAAe;gBAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;KACF,CAAC;IACF,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM;YACJ,KAAK,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU;gBAC/C,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC;gBAC9C,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClD,CAAC;YAAS,CAAC;QACT,eAAe,GAAG,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;AAChE,CAAC","sourcesContent":["import type { AnyStep } from \"./pipeline-steps.js\";\nimport type {\n PipelineExecutionContext,\n PipelineLogger,\n PipelineStepProgress,\n StepSkipDecision,\n} from \"./pipeline-types.js\";\nimport type { PipelineTraceAttributes } from \"../tracing/tracing-contracts.js\";\nimport { validateStandardSchema } from \"./pipeline-validation.js\";\n\nexport interface NormalizedStepSkipDecision {\n reason: string;\n value?: unknown;\n}\n\nfunction normalizeStepSkipDecision(decision: StepSkipDecision): NormalizedStepSkipDecision | null {\n if (decision == null || decision === false) return null;\n if (typeof decision === \"string\") {\n const reason = decision.trim();\n return reason.length > 0 ? { reason } : null;\n }\n if (typeof decision === \"object\" && typeof decision.reason === \"string\") {\n const reason = decision.reason.trim();\n if (reason.length === 0) return null;\n return { reason, value: decision.value };\n }\n return null;\n}\n\nexport async function evaluateStepSkip<TOptions extends object>(\n step: AnyStep<TOptions>,\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<TOptions>\n): Promise<NormalizedStepSkipDecision | null> {\n if (typeof step.skip !== \"function\") return null;\n return normalizeStepSkipDecision(await step.skip(inputs, context));\n}\n\nexport async function validateStepOutput<TOptions extends object>(\n step: AnyStep<TOptions>,\n value: unknown,\n boundary: string\n): Promise<unknown> {\n return step.outputSchema\n ? validateStandardSchema(step.outputSchema, value, boundary)\n : Promise.resolve(value);\n}\n\nexport async function executeStepAttempt<TOptions extends object>(input: {\n attemptId: string;\n context: PipelineExecutionContext<TOptions>;\n dryRun: boolean;\n inputs: Record<string, unknown>;\n log: PipelineLogger;\n onProgress(progress: PipelineStepProgress): void;\n onReportAttempt(attempt: number, attributes?: PipelineTraceAttributes): void;\n outputBoundary: string;\n step: AnyStep<TOptions>;\n}): Promise<unknown> {\n const { step } = input;\n let acceptsProgress = true;\n const stepContext = {\n ...input.context,\n attemptId: input.attemptId,\n log: input.log,\n reportAttempt: input.onReportAttempt,\n reportProgress: (progress: PipelineStepProgress) => {\n if (acceptsProgress) input.onProgress(progress);\n },\n };\n let output: unknown;\n try {\n output =\n input.dryRun && typeof step.dryRun === \"function\"\n ? await step.dryRun(input.inputs, stepContext)\n : await step.run(input.inputs, stepContext);\n } finally {\n acceptsProgress = false;\n }\n return validateStepOutput(step, output, input.outputBoundary);\n}\n"]}
1
+ {"version":3,"file":"pipeline-step-executor.js","sourceRoot":"","sources":["../../src/core/pipeline-step-executor.ts"],"names":[],"mappings":"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","sourcesContent":["import { artifactRecordSchema, type ArtifactRecord } from \"../tracing/artifact-metadata.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport type {\n PipelineExecutionContext,\n PipelineLogger,\n PipelineStepProgress,\n StepSkipDecision,\n} from \"./pipeline-types.js\";\nimport type { PipelineTraceAttributes } from \"../tracing/tracing-contracts.js\";\nimport { validateStandardSchema } from \"./pipeline-validation.js\";\n\nexport interface NormalizedStepSkipDecision {\n reason: string;\n value?: unknown;\n}\n\nfunction normalizeStepSkipDecision(decision: StepSkipDecision): NormalizedStepSkipDecision | null {\n if (decision == null || decision === false) return null;\n if (typeof decision === \"string\") {\n const reason = decision.trim();\n return reason.length > 0 ? { reason } : null;\n }\n if (typeof decision === \"object\" && typeof decision.reason === \"string\") {\n const reason = decision.reason.trim();\n if (reason.length === 0) return null;\n return { reason, value: decision.value };\n }\n return null;\n}\n\nexport async function evaluateStepSkip<TOptions extends object>(\n step: AnyStep<TOptions>,\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<TOptions>\n): Promise<NormalizedStepSkipDecision | null> {\n if (typeof step.skip !== \"function\") return null;\n return normalizeStepSkipDecision(await step.skip(inputs, context));\n}\n\nexport async function validateStepOutput<TOptions extends object>(\n step: AnyStep<TOptions>,\n value: unknown,\n boundary: string\n): Promise<unknown> {\n return step.outputSchema\n ? validateStandardSchema(step.outputSchema, value, boundary)\n : Promise.resolve(value);\n}\n\nexport async function executeStepAttempt<TOptions extends object>(input: {\n attemptId: string;\n context: PipelineExecutionContext<TOptions>;\n dryRun: boolean;\n inputs: Record<string, unknown>;\n log: PipelineLogger;\n onArtifact?(record: ArtifactRecord, preview: boolean): void;\n onProgress(progress: PipelineStepProgress): void;\n onReportAttempt(attempt: number, attributes?: PipelineTraceAttributes): void;\n outputBoundary: string;\n step: AnyStep<TOptions>;\n}): Promise<unknown> {\n const { step } = input;\n let acceptsReports = true;\n const stepContext = {\n ...input.context,\n recordArtifact: (record: ArtifactRecord) => {\n if (!acceptsReports) return;\n const snapshot = artifactRecordSchema.decode(record, \"artifact record\");\n const preview =\n input.dryRun && (typeof step.dryRun === \"function\" || snapshot.operation === \"write\");\n input.onArtifact?.(snapshot, preview);\n },\n attemptId: input.attemptId,\n log: input.log,\n reportAttempt: input.onReportAttempt,\n reportProgress: (progress: PipelineStepProgress) => {\n if (acceptsReports) input.onProgress(progress);\n },\n };\n let output: unknown;\n try {\n output =\n input.dryRun && typeof step.dryRun === \"function\"\n ? await step.dryRun(input.inputs, stepContext)\n : await step.run(input.inputs, stepContext);\n } finally {\n acceptsReports = false;\n }\n return validateStepOutput(step, output, input.outputBoundary);\n}\n"]}