tubeless 0.2.2 → 0.2.4

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 (199) hide show
  1. package/README.md +52 -52
  2. package/dist/cli/cli-types.d.ts +1 -1
  3. package/dist/cli/cli-types.js.map +1 -1
  4. package/dist/cli/cli.d.ts +2 -4
  5. package/dist/cli/cli.js +1 -3
  6. package/dist/cli/cli.js.map +1 -1
  7. package/dist/core/child-execution.js +9 -4
  8. package/dist/core/child-execution.js.map +1 -1
  9. package/dist/core/lifecycle.d.ts +1 -1
  10. package/dist/core/lifecycle.js +2 -0
  11. package/dist/core/lifecycle.js.map +1 -1
  12. package/dist/core/pipeline-compiler.d.ts +17 -0
  13. package/dist/core/pipeline-compiler.js +44 -0
  14. package/dist/core/pipeline-compiler.js.map +1 -0
  15. package/dist/core/pipeline-definition-validation.d.ts +4 -0
  16. package/dist/core/pipeline-definition-validation.js +101 -0
  17. package/dist/core/pipeline-definition-validation.js.map +1 -0
  18. package/dist/core/pipeline-definition.d.ts +28 -0
  19. package/dist/core/pipeline-definition.js +2 -0
  20. package/dist/core/pipeline-definition.js.map +1 -0
  21. package/dist/core/pipeline-disposition.d.ts +26 -0
  22. package/dist/core/pipeline-disposition.js +44 -0
  23. package/dist/core/pipeline-disposition.js.map +1 -0
  24. package/dist/core/pipeline-errors.d.ts +8 -0
  25. package/dist/core/pipeline-errors.js +20 -0
  26. package/dist/core/pipeline-errors.js.map +1 -0
  27. package/dist/core/pipeline-execute.d.ts +3 -1
  28. package/dist/core/pipeline-execute.js +136 -396
  29. package/dist/core/pipeline-execute.js.map +1 -1
  30. package/dist/core/pipeline-finalizer.d.ts +18 -0
  31. package/dist/core/pipeline-finalizer.js +37 -0
  32. package/dist/core/pipeline-finalizer.js.map +1 -0
  33. package/dist/core/pipeline-graph.d.ts +23 -0
  34. package/dist/core/pipeline-graph.js +135 -0
  35. package/dist/core/pipeline-graph.js.map +1 -0
  36. package/dist/core/pipeline-identity.d.ts +5 -0
  37. package/dist/core/pipeline-identity.js +11 -0
  38. package/dist/core/pipeline-identity.js.map +1 -0
  39. package/dist/core/pipeline-mermaid.d.ts +4 -0
  40. package/dist/core/pipeline-mermaid.js +56 -0
  41. package/dist/core/pipeline-mermaid.js.map +1 -0
  42. package/dist/core/pipeline-plan.d.ts +5 -94
  43. package/dist/core/pipeline-plan.js +5 -392
  44. package/dist/core/pipeline-plan.js.map +1 -1
  45. package/dist/core/pipeline-run-state.d.ts +49 -0
  46. package/dist/core/pipeline-run-state.js +284 -0
  47. package/dist/core/pipeline-run-state.js.map +1 -0
  48. package/dist/core/pipeline-step-executor.d.ts +20 -0
  49. package/dist/core/pipeline-step-executor.js +52 -0
  50. package/dist/core/pipeline-step-executor.js.map +1 -0
  51. package/dist/core/pipeline-step-metadata.d.ts +4 -0
  52. package/dist/core/pipeline-step-metadata.js +5 -0
  53. package/dist/core/pipeline-step-metadata.js.map +1 -0
  54. package/dist/core/pipeline-steps.d.ts +1 -1
  55. package/dist/core/pipeline-steps.js +1 -1
  56. package/dist/core/pipeline-steps.js.map +1 -1
  57. package/dist/core/pipeline-types.d.ts +17 -8
  58. package/dist/core/pipeline-types.js +8 -0
  59. package/dist/core/pipeline-types.js.map +1 -1
  60. package/dist/core/pipeline-validation.d.ts +6 -0
  61. package/dist/core/pipeline-validation.js +41 -0
  62. package/dist/core/pipeline-validation.js.map +1 -0
  63. package/dist/core/pipeline.d.ts +8 -9
  64. package/dist/core/pipeline.js +9 -6
  65. package/dist/core/pipeline.js.map +1 -1
  66. package/dist/node/node.d.ts +0 -3
  67. package/dist/node/node.js +0 -3
  68. package/dist/node/node.js.map +1 -1
  69. package/dist/reporter/reporter-entry.d.ts +1 -2
  70. package/dist/reporter/reporter-entry.js +1 -2
  71. package/dist/reporter/reporter-entry.js.map +1 -1
  72. package/dist/run-store/run-store-codec.d.ts +4 -0
  73. package/dist/run-store/run-store-codec.js +31 -0
  74. package/dist/run-store/run-store-codec.js.map +1 -0
  75. package/dist/run-store/run-store-ndjson.js +2 -295
  76. package/dist/run-store/run-store-ndjson.js.map +1 -1
  77. package/dist/run-store/run-store-sqlite.js +41 -38
  78. package/dist/run-store/run-store-sqlite.js.map +1 -1
  79. package/dist/run-store/run-store.d.ts +4 -3
  80. package/dist/run-store/run-store.js +38 -195
  81. package/dist/run-store/run-store.js.map +1 -1
  82. package/dist/studio/run-store-ui-client-app.d.ts +12 -0
  83. package/dist/studio/run-store-ui-client-app.js +224 -0
  84. package/dist/studio/run-store-ui-client-app.js.map +1 -0
  85. package/dist/studio/run-store-ui-client-browser.d.ts +1 -0
  86. package/dist/studio/run-store-ui-client-browser.js +2 -0
  87. package/dist/studio/run-store-ui-client-commands.d.ts +18 -0
  88. package/dist/studio/run-store-ui-client-commands.js +98 -0
  89. package/dist/studio/run-store-ui-client-commands.js.map +1 -0
  90. package/dist/studio/run-store-ui-client-form.d.ts +11 -0
  91. package/dist/studio/run-store-ui-client-form.js +54 -0
  92. package/dist/studio/run-store-ui-client-form.js.map +1 -0
  93. package/dist/studio/run-store-ui-client-modals.d.ts +20 -0
  94. package/dist/studio/run-store-ui-client-modals.js +154 -0
  95. package/dist/studio/run-store-ui-client-modals.js.map +1 -0
  96. package/dist/studio/run-store-ui-client-model.d.ts +19 -0
  97. package/dist/studio/run-store-ui-client-model.js +189 -0
  98. package/dist/studio/run-store-ui-client-model.js.map +1 -0
  99. package/dist/studio/run-store-ui-client-runs.d.ts +24 -0
  100. package/dist/studio/run-store-ui-client-runs.js +78 -0
  101. package/dist/studio/run-store-ui-client-runs.js.map +1 -0
  102. package/dist/studio/run-store-ui-client-shared.d.ts +22 -0
  103. package/dist/studio/run-store-ui-client-shared.js +63 -0
  104. package/dist/studio/run-store-ui-client-shared.js.map +1 -0
  105. package/dist/studio/run-store-ui-client-transport.d.ts +25 -0
  106. package/dist/studio/run-store-ui-client-transport.js +317 -0
  107. package/dist/studio/run-store-ui-client-transport.js.map +1 -0
  108. package/dist/studio/run-store-ui-client.d.ts +2 -14
  109. package/dist/studio/run-store-ui-client.js +9 -1360
  110. package/dist/studio/run-store-ui-client.js.map +1 -1
  111. package/dist/studio/run-store-ui-page.d.ts +2 -2
  112. package/dist/studio/run-store-ui-page.js +7 -71
  113. package/dist/studio/run-store-ui-page.js.map +1 -1
  114. package/dist/studio/run-store-ui.d.ts +1 -1
  115. package/dist/studio/run-store-ui.js +43 -25
  116. package/dist/studio/run-store-ui.js.map +1 -1
  117. package/dist/tracing/tracing-codec.d.ts +5 -0
  118. package/dist/tracing/tracing-codec.js +13 -0
  119. package/dist/tracing/tracing-codec.js.map +1 -0
  120. package/dist/tracing/tracing-constants.d.ts +4 -0
  121. package/dist/tracing/tracing-constants.js +5 -0
  122. package/dist/tracing/tracing-constants.js.map +1 -0
  123. package/dist/tracing/tracing-contracts.d.ts +31 -0
  124. package/dist/tracing/tracing-contracts.js +2 -0
  125. package/dist/tracing/tracing-contracts.js.map +1 -0
  126. package/dist/tracing/tracing-internal.d.ts +1 -1
  127. package/dist/tracing/tracing-internal.js +116 -81
  128. package/dist/tracing/tracing-internal.js.map +1 -1
  129. package/dist/tracing/tracing-schema.d.ts +809 -0
  130. package/dist/tracing/tracing-schema.js +429 -0
  131. package/dist/tracing/tracing-schema.js.map +1 -0
  132. package/dist/tracing/tracing.d.ts +2 -54
  133. package/dist/tracing/tracing.js.map +1 -1
  134. package/dist/tracing/wire-schema.d.ts +50 -0
  135. package/dist/tracing/wire-schema.js +193 -0
  136. package/dist/tracing/wire-schema.js.map +1 -0
  137. package/dist/workbench/pipeline-module.js +4 -4
  138. package/dist/workbench/pipeline-module.js.map +1 -1
  139. package/dist/workbench/workbench-entry.d.ts +2 -0
  140. package/dist/workbench/workbench-entry.js +3 -0
  141. package/dist/workbench/workbench-entry.js.map +1 -0
  142. package/dist/workbench/workbench-history.js +8 -1
  143. package/dist/workbench/workbench-history.js.map +1 -1
  144. package/dist/workbench/workbench-ui.js +39 -43
  145. package/dist/workbench/workbench-ui.js.map +1 -1
  146. package/docs/README.md +22 -15
  147. package/docs/agent-guide.md +62 -68
  148. package/docs/agent-skills.md +59 -0
  149. package/docs/api-reference.md +14 -178
  150. package/docs/api-report.json +13 -215
  151. package/docs/child-pipeline-composition.md +139 -193
  152. package/docs/cli.md +86 -64
  153. package/docs/comparison.md +64 -62
  154. package/docs/concepts.md +210 -281
  155. package/docs/getting-started.md +61 -49
  156. package/docs/llms.txt +8 -8
  157. package/docs/recipes.md +42 -45
  158. package/docs/remote-step-composition.md +69 -74
  159. package/docs/studio.md +110 -73
  160. package/examples/catalog/pipelines/enrich.ts +2 -2
  161. package/examples/catalog/scripts/enrich.ts +1 -1
  162. package/examples/catalog/scripts/import.ts +1 -1
  163. package/examples/catalog/scripts/publish.ts +1 -1
  164. package/examples/catalog/tubeless.project.ts +6 -3
  165. package/examples/cli-job.ts +1 -1
  166. package/examples/host-embedding.ts +4 -5
  167. package/examples/live-tui.ts +1 -1
  168. package/examples/peloton.ts +1 -1
  169. package/examples/remote-steps.ts +8 -5
  170. package/examples/tracing.ts +96 -5
  171. package/package.json +17 -64
  172. package/skills/tubeless/SKILL.md +85 -0
  173. package/skills/tubeless-make-pipeline/SKILL.md +126 -0
  174. package/dist/node/env.d.ts +0 -1
  175. package/dist/node/env.js +0 -8
  176. package/dist/node/env.js.map +0 -1
  177. package/dist/node/file-utils.d.ts +0 -3
  178. package/dist/node/file-utils.js +0 -17
  179. package/dist/node/file-utils.js.map +0 -1
  180. package/dist/node/paths.d.ts +0 -8
  181. package/dist/node/paths.js +0 -19
  182. package/dist/node/paths.js.map +0 -1
  183. package/dist/reporter/prompt-select.d.ts +0 -80
  184. package/dist/reporter/prompt-select.js +0 -197
  185. package/dist/reporter/prompt-select.js.map +0 -1
  186. package/dist/studio/run-store-ui-client-source.d.ts +0 -1
  187. package/dist/studio/run-store-ui-client-source.js +0 -1
  188. package/dist/tracing/tracing-json.d.ts +0 -11
  189. package/dist/tracing/tracing-json.js +0 -8
  190. package/dist/tracing/tracing-json.js.map +0 -1
  191. package/dist/tracing/tracing-otel.d.ts +0 -35
  192. package/dist/tracing/tracing-otel.js +0 -60
  193. package/dist/tracing/tracing-otel.js.map +0 -1
  194. package/dist/workbench/workbench-studio.d.ts +0 -29
  195. package/dist/workbench/workbench-studio.js +0 -61
  196. package/dist/workbench/workbench-studio.js.map +0 -1
  197. package/examples/catalog/tubeless.studio.ts +0 -20
  198. package/examples/local-observability.ts +0 -105
  199. package/examples/rendering.ts +0 -34
@@ -0,0 +1,17 @@
1
+ import type { PipelineDefinition, StepsOptions } from "./pipeline-definition.js";
2
+ import { type CompiledStepGraph } from "./pipeline-graph.js";
3
+ import type { AnyStep } from "./pipeline-steps.js";
4
+ import type { StandardSchemaV1 } from "./pipeline-types.js";
5
+ export interface CompiledPipeline<TSteps extends readonly AnyStep[] = readonly AnyStep[], TResult = unknown, TTargets extends readonly TSteps[number][] = readonly [], TResultSchema extends StandardSchemaV1 | undefined = undefined> {
6
+ readonly declaredTargets: readonly AnyStep<StepsOptions<TSteps>>[];
7
+ readonly finalize: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>["finalize"];
8
+ readonly id: string;
9
+ readonly optionsSchema: StandardSchemaV1 | undefined;
10
+ readonly orderedSteps: readonly AnyStep<StepsOptions<TSteps>>[];
11
+ readonly requiredFinalizerSteps: readonly AnyStep<StepsOptions<TSteps>>[] | undefined;
12
+ readonly stepGraph: ReadonlyMap<AnyStep, CompiledStepGraph>;
13
+ readonly resultSchema: TResultSchema | undefined;
14
+ readonly stepIds: readonly string[];
15
+ readonly targetIds: readonly string[];
16
+ }
17
+ export declare function compilePipeline<TSteps extends readonly AnyStep[], TResult, TTargets extends readonly TSteps[number][], TResultSchema extends StandardSchemaV1 | undefined>(definition: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>): CompiledPipeline<TSteps, TResult, TTargets, TResultSchema>;
@@ -0,0 +1,44 @@
1
+ import { validatePipelineDefinition } from "./pipeline-definition-validation.js";
2
+ import { PipelineDefinitionError } from "./pipeline-errors.js";
3
+ import { requiredFinalizerMetadata } from "./pipeline-finalizer.js";
4
+ import { compilePipelineGraph } from "./pipeline-graph.js";
5
+ import { STEP_OPTIONS_SCHEMA } from "./pipeline-step-metadata.js";
6
+ export function compilePipeline(definition) {
7
+ const errors = validatePipelineDefinition(definition);
8
+ if (errors.length > 0) {
9
+ throw new PipelineDefinitionError(definition.id, errors);
10
+ }
11
+ // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores
12
+ // the `TOptions` generic that the tuple erased, without changing the values.
13
+ const { compiledByAuthorStep, orderedSteps, stepGraph } = compilePipelineGraph(definition.steps);
14
+ const finalizerMetadata = requiredFinalizerMetadata(definition.finalize);
15
+ const requiredFinalizerSteps = finalizerMetadata?.steps;
16
+ // SAFETY: targets are a subset of `TSteps[number]`, each an `AnyStep<TOptions>`.
17
+ const declaredTargets = (definition.targets ?? []);
18
+ const compiledTargets = declaredTargets.map((target) => compiledByAuthorStep.get(target));
19
+ const compiledRequiredFinalizerSteps = requiredFinalizerSteps?.map((step) => compiledByAuthorStep.get(step));
20
+ const compiledFinalize = finalizerMetadata
21
+ ? finalizerMetadata.compile(compiledRequiredFinalizerSteps.map((step) => step.id))
22
+ : (outputs, context) => definition.finalize(outputs, context);
23
+ return Object.freeze({
24
+ declaredTargets: Object.freeze(compiledTargets),
25
+ // Invoke ordinary finalizers on the author's definition so method-style
26
+ // implementations keep `this`. Required finalizers compile the same input
27
+ // and context contract with stable required ids.
28
+ // SAFETY: both branches preserve `definition.finalize`'s call signature.
29
+ finalize: compiledFinalize,
30
+ id: definition.id,
31
+ optionsSchema: definition.steps.length === 0
32
+ ? undefined
33
+ : compiledByAuthorStep.get(definition.steps[0])?.[STEP_OPTIONS_SCHEMA],
34
+ orderedSteps: Object.freeze([...orderedSteps]),
35
+ stepGraph,
36
+ requiredFinalizerSteps: compiledRequiredFinalizerSteps
37
+ ? Object.freeze(compiledRequiredFinalizerSteps)
38
+ : undefined,
39
+ resultSchema: definition.resultSchema,
40
+ stepIds: Object.freeze(definition.steps.map((step) => compiledByAuthorStep.get(step).id)),
41
+ targetIds: Object.freeze(compiledTargets.map((step) => step.id)),
42
+ });
43
+ }
44
+ //# sourceMappingURL=pipeline-compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-compiler.js","sourceRoot":"","sources":["../../src/core/pipeline-compiler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PipelineDefinition, StepsOptions } from \"./pipeline-definition.js\";\nimport { validatePipelineDefinition } from \"./pipeline-definition-validation.js\";\nimport { PipelineDefinitionError } from \"./pipeline-errors.js\";\nimport { requiredFinalizerMetadata } from \"./pipeline-finalizer.js\";\nimport { compilePipelineGraph, type CompiledStepGraph } from \"./pipeline-graph.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport { STEP_OPTIONS_SCHEMA } from \"./pipeline-step-metadata.js\";\nimport type { StandardSchemaV1 } from \"./pipeline-types.js\";\n\nexport interface CompiledPipeline<\n TSteps extends readonly AnyStep[] = readonly AnyStep[],\n TResult = unknown,\n TTargets extends readonly TSteps[number][] = readonly [],\n TResultSchema extends StandardSchemaV1 | undefined = undefined,\n> {\n readonly declaredTargets: readonly AnyStep<StepsOptions<TSteps>>[];\n readonly finalize: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>[\"finalize\"];\n readonly id: string;\n readonly optionsSchema: StandardSchemaV1 | undefined;\n readonly orderedSteps: readonly AnyStep<StepsOptions<TSteps>>[];\n readonly requiredFinalizerSteps: readonly AnyStep<StepsOptions<TSteps>>[] | undefined;\n readonly stepGraph: ReadonlyMap<AnyStep, CompiledStepGraph>;\n readonly resultSchema: TResultSchema | undefined;\n readonly stepIds: readonly string[];\n readonly targetIds: readonly string[];\n}\n\nexport function compilePipeline<\n TSteps extends readonly AnyStep[],\n TResult,\n TTargets extends readonly TSteps[number][],\n TResultSchema extends StandardSchemaV1 | undefined,\n>(\n definition: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>\n): CompiledPipeline<TSteps, TResult, TTargets, TResultSchema> {\n const errors = validatePipelineDefinition(definition);\n if (errors.length > 0) {\n throw new PipelineDefinitionError(definition.id, errors);\n }\n type TOptions = StepsOptions<TSteps>;\n // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores\n // the `TOptions` generic that the tuple erased, without changing the values.\n const { compiledByAuthorStep, orderedSteps, stepGraph } = compilePipelineGraph(\n definition.steps as readonly AnyStep<TOptions>[]\n );\n const finalizerMetadata = requiredFinalizerMetadata<TOptions>(definition.finalize);\n const requiredFinalizerSteps = finalizerMetadata?.steps;\n // SAFETY: targets are a subset of `TSteps[number]`, each an `AnyStep<TOptions>`.\n const declaredTargets = (definition.targets ?? []) as readonly AnyStep<TOptions>[];\n const compiledTargets = declaredTargets.map((target) => compiledByAuthorStep.get(target)!);\n const compiledRequiredFinalizerSteps = requiredFinalizerSteps?.map((step) =>\n compiledByAuthorStep.get(step)!\n );\n const compiledFinalize = finalizerMetadata\n ? finalizerMetadata.compile(compiledRequiredFinalizerSteps!.map((step) => step.id))\n : (\n outputs: Parameters<typeof definition.finalize>[0],\n context: Parameters<typeof definition.finalize>[1]\n ) => definition.finalize(outputs, context);\n return Object.freeze({\n declaredTargets: Object.freeze(compiledTargets),\n // Invoke ordinary finalizers on the author's definition so method-style\n // implementations keep `this`. Required finalizers compile the same input\n // and context contract with stable required ids.\n // SAFETY: both branches preserve `definition.finalize`'s call signature.\n finalize: compiledFinalize as typeof definition.finalize,\n id: definition.id,\n optionsSchema:\n definition.steps.length === 0\n ? undefined\n : compiledByAuthorStep.get(definition.steps[0]!)?.[STEP_OPTIONS_SCHEMA],\n orderedSteps: Object.freeze([...orderedSteps]),\n stepGraph,\n requiredFinalizerSteps: compiledRequiredFinalizerSteps\n ? Object.freeze(compiledRequiredFinalizerSteps)\n : undefined,\n resultSchema: definition.resultSchema,\n stepIds: Object.freeze(definition.steps.map((step) => compiledByAuthorStep.get(step)!.id)),\n targetIds: Object.freeze(compiledTargets.map((step) => step.id)),\n });\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { PipelineDefinition } from "./pipeline-definition.js";
2
+ import type { AnyStep } from "./pipeline-steps.js";
3
+ import type { PipelineError, StandardSchemaV1 } from "./pipeline-types.js";
4
+ export declare function validatePipelineDefinition<TSteps extends readonly AnyStep[], TResult, TTargets extends readonly TSteps[number][], TResultSchema extends StandardSchemaV1 | undefined>(definition: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>): PipelineError[];
@@ -0,0 +1,101 @@
1
+ import { duplicateValues } from "../utilities/collections.js";
2
+ import { requiredFinalizerMetadata } from "./pipeline-finalizer.js";
3
+ import { stepEdges, targetClosure, topologicalSort } from "./pipeline-graph.js";
4
+ import { pipelineDiagnostic } from "./pipeline-errors.js";
5
+ import { PIPELINE_FINALIZE_STEP_ID, STEP_OPTIONS_SCHEMA } from "./pipeline-step-metadata.js";
6
+ export function validatePipelineDefinition(definition) {
7
+ const steps = definition.steps;
8
+ const errors = [];
9
+ if (definition.id.trim().length === 0) {
10
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_PIPELINE_ID_BLANK", "definition", "definition", "Pipeline id must not be blank"));
11
+ }
12
+ const stepIds = steps.map((step) => step.id);
13
+ const duplicateStepIds = duplicateValues(stepIds);
14
+ if (duplicateStepIds.length > 0) {
15
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_STEP_IDS_DUPLICATE", "definition", "definition", `Pipeline ${definition.id} has duplicate step ids: ${duplicateStepIds.join(", ")}`));
16
+ }
17
+ const optionsSchemas = new Set(steps.map((step) => step[STEP_OPTIONS_SCHEMA]));
18
+ if (optionsSchemas.size > 1 && [...optionsSchemas].some(Boolean)) {
19
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_OPTIONS_SCHEMA_CONFLICT", "definition", "definition", `Pipeline ${definition.id} mixes steps from different options-schema scopes`));
20
+ }
21
+ for (const step of steps) {
22
+ if (step.id.trim().length === 0) {
23
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_STEP_ID_BLANK", "definition", "definition", `Pipeline ${definition.id} has a step with a blank id`, { stepId: step.id }));
24
+ }
25
+ if (step.id === PIPELINE_FINALIZE_STEP_ID) {
26
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_STEP_ID_RESERVED", "definition", "definition", `Pipeline ${definition.id} uses reserved step id ${PIPELINE_FINALIZE_STEP_ID}`, { stepId: step.id }));
27
+ }
28
+ if (step.name !== undefined && step.name.trim().length === 0) {
29
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_STEP_NAME_BLANK", "definition", "definition", `Pipeline ${definition.id} step ${step.id} has a blank display name`, { stepId: step.id }));
30
+ }
31
+ const dependencyGroups = [
32
+ ["dependsOn", step.dependsOn ?? []],
33
+ ["optionalDependsOn", step.optionalDependsOn ?? []],
34
+ ["skipAfterFailureOf", step.skipAfterFailureOf ?? []],
35
+ ];
36
+ for (const [field, dependencies] of dependencyGroups) {
37
+ const duplicates = duplicateValues(dependencies.map((dependency) => dependency.id));
38
+ if (duplicates.length > 0) {
39
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_DEPENDENCY_DUPLICATE", "definition", "definition", `Pipeline ${definition.id} step ${step.id} repeats ${field}: ${duplicates.join(", ")}`, { stepId: step.id }));
40
+ }
41
+ if (dependencies.includes(step)) {
42
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_DEPENDENCY_SELF_REFERENCE", "definition", "definition", `Pipeline ${definition.id} step ${step.id} cannot reference itself in ${field}`, { stepId: step.id }));
43
+ }
44
+ }
45
+ const required = new Set(step.dependsOn ?? []);
46
+ const contradictory = (step.optionalDependsOn ?? []).filter((dependency) => required.has(dependency));
47
+ if (contradictory.length > 0) {
48
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_DEPENDENCY_CONTRADICTORY", "definition", "definition", `Pipeline ${definition.id} step ${step.id} declares dependencies as both required and optional: ${contradictory.map(({ id }) => id).join(", ")}`, { stepId: step.id }));
49
+ }
50
+ }
51
+ // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores
52
+ // the `TOptions` generic that the tuple erased, without changing the values.
53
+ const knownSteps = new Set(steps);
54
+ // SAFETY: targets are a subset of `TSteps[number]`, each an `AnyStep<TOptions>`.
55
+ const declaredTargets = (definition.targets ?? []);
56
+ const duplicateTargetIds = duplicateValues(declaredTargets.map((target) => target.id));
57
+ if (duplicateTargetIds.length > 0) {
58
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_TARGETS_DUPLICATE", "definition", "definition", `Pipeline ${definition.id} declares duplicate targets: ${duplicateTargetIds.join(", ")}`));
59
+ }
60
+ const missingTargets = declaredTargets.filter((target) => !knownSteps.has(target));
61
+ if (missingTargets.length > 0) {
62
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_TARGET_NOT_IN_STEPS", "definition", "definition", `Pipeline ${definition.id} declares target step(s) not included in its steps list: ${missingTargets.map(({ id }) => id).join(", ")}`));
63
+ }
64
+ const missingReferences = [];
65
+ // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores the
66
+ // `TOptions` generic that the tuple erased, without changing the values.
67
+ for (const step of steps) {
68
+ for (const dependency of stepEdges(step)) {
69
+ if (!knownSteps.has(dependency)) {
70
+ missingReferences.push(`${step.id} -> ${dependency.id}`);
71
+ }
72
+ }
73
+ }
74
+ if (missingReferences.length > 0) {
75
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_DEPENDENCY_NOT_IN_STEPS", "definition", "definition", `Pipeline ${definition.id} references step(s) not included in its steps list: ${missingReferences.join(", ")}`));
76
+ }
77
+ const requiredFinalizerSteps = requiredFinalizerMetadata(definition.finalize)?.steps;
78
+ const missingFinalizerSteps = (requiredFinalizerSteps ?? []).filter((step) => !knownSteps.has(step));
79
+ if (missingFinalizerSteps.length > 0) {
80
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_FINALIZER_STEP_NOT_IN_STEPS", "definition", "definition", `Pipeline ${definition.id} requires finalizer output from step(s) not included in its steps list: ${missingFinalizerSteps.map(({ id }) => id).join(", ")}`));
81
+ }
82
+ if (requiredFinalizerSteps &&
83
+ missingTargets.length === 0 &&
84
+ missingReferences.length === 0 &&
85
+ missingFinalizerSteps.length === 0) {
86
+ for (const target of declaredTargets) {
87
+ const selected = targetClosure([target]);
88
+ const missingRequiredSteps = requiredFinalizerSteps.filter((step) => !selected.has(step));
89
+ if (missingRequiredSteps.length > 0) {
90
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_TARGET_FINALIZER_MISMATCH", "definition", "definition", `Pipeline ${definition.id} target ${target.id} cannot satisfy required finalizer output(s): ${missingRequiredSteps.map(({ id }) => id).join(", ")}`, { stepId: target.id }));
91
+ }
92
+ }
93
+ }
94
+ // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores the
95
+ // `TOptions` generic that the tuple erased, without changing the values.
96
+ if (errors.length === 0 && !topologicalSort(steps)) {
97
+ errors.push(pipelineDiagnostic("TUBELESS_DEFINITION_DEPENDENCY_CYCLE", "definition", "definition", `Pipeline ${definition.id} has a dependency cycle`));
98
+ }
99
+ return errors;
100
+ }
101
+ //# sourceMappingURL=pipeline-definition-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-definition-validation.js","sourceRoot":"","sources":["../../src/core/pipeline-definition-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { duplicateValues } from \"../utilities/collections.js\";\nimport type { PipelineDefinition, StepsOptions } from \"./pipeline-definition.js\";\nimport { requiredFinalizerMetadata } from \"./pipeline-finalizer.js\";\nimport { stepEdges, targetClosure, topologicalSort } from \"./pipeline-graph.js\";\nimport { pipelineDiagnostic } from \"./pipeline-errors.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport { PIPELINE_FINALIZE_STEP_ID, STEP_OPTIONS_SCHEMA } from \"./pipeline-step-metadata.js\";\nimport type { PipelineError, StandardSchemaV1 } from \"./pipeline-types.js\";\n\nexport function validatePipelineDefinition<\n TSteps extends readonly AnyStep[],\n TResult,\n TTargets extends readonly TSteps[number][],\n TResultSchema extends StandardSchemaV1 | undefined,\n>(definition: PipelineDefinition<TSteps, TResult, TTargets, TResultSchema>): PipelineError[] {\n type TOptions = StepsOptions<TSteps>;\n const steps = definition.steps;\n const errors: PipelineError[] = [];\n if (definition.id.trim().length === 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_PIPELINE_ID_BLANK\",\n \"definition\",\n \"definition\",\n \"Pipeline id must not be blank\"\n )\n );\n }\n\n const stepIds = steps.map((step) => step.id);\n const duplicateStepIds = duplicateValues(stepIds);\n if (duplicateStepIds.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_STEP_IDS_DUPLICATE\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} has duplicate step ids: ${duplicateStepIds.join(\", \")}`\n )\n );\n }\n const optionsSchemas = new Set(steps.map((step) => step[STEP_OPTIONS_SCHEMA]));\n if (optionsSchemas.size > 1 && [...optionsSchemas].some(Boolean)) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_OPTIONS_SCHEMA_CONFLICT\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} mixes steps from different options-schema scopes`\n )\n );\n }\n for (const step of steps) {\n if (step.id.trim().length === 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_STEP_ID_BLANK\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} has a step with a blank id`,\n { stepId: step.id }\n )\n );\n }\n if (step.id === PIPELINE_FINALIZE_STEP_ID) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_STEP_ID_RESERVED\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} uses reserved step id ${PIPELINE_FINALIZE_STEP_ID}`,\n { stepId: step.id }\n )\n );\n }\n if (step.name !== undefined && step.name.trim().length === 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_STEP_NAME_BLANK\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} step ${step.id} has a blank display name`,\n { stepId: step.id }\n )\n );\n }\n const dependencyGroups = [\n [\"dependsOn\", step.dependsOn ?? []],\n [\"optionalDependsOn\", step.optionalDependsOn ?? []],\n [\"skipAfterFailureOf\", step.skipAfterFailureOf ?? []],\n ] as const;\n for (const [field, dependencies] of dependencyGroups) {\n const duplicates = duplicateValues(dependencies.map((dependency) => dependency.id));\n if (duplicates.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_DEPENDENCY_DUPLICATE\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} step ${step.id} repeats ${field}: ${duplicates.join(\", \")}`,\n { stepId: step.id }\n )\n );\n }\n if (dependencies.includes(step)) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_DEPENDENCY_SELF_REFERENCE\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} step ${step.id} cannot reference itself in ${field}`,\n { stepId: step.id }\n )\n );\n }\n }\n\n const required = new Set(step.dependsOn ?? []);\n const contradictory = (step.optionalDependsOn ?? []).filter((dependency) =>\n required.has(dependency)\n );\n if (contradictory.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_DEPENDENCY_CONTRADICTORY\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} step ${step.id} declares dependencies as both required and optional: ${contradictory.map(({ id }) => id).join(\", \")}`,\n { stepId: step.id }\n )\n );\n }\n }\n\n // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores\n // the `TOptions` generic that the tuple erased, without changing the values.\n const knownSteps = new Set<AnyStep<TOptions>>(steps as readonly AnyStep<TOptions>[]);\n // SAFETY: targets are a subset of `TSteps[number]`, each an `AnyStep<TOptions>`.\n const declaredTargets = (definition.targets ?? []) as readonly AnyStep<TOptions>[];\n const duplicateTargetIds = duplicateValues(declaredTargets.map((target) => target.id));\n if (duplicateTargetIds.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_TARGETS_DUPLICATE\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} declares duplicate targets: ${duplicateTargetIds.join(\", \")}`\n )\n );\n }\n const missingTargets = declaredTargets.filter((target) => !knownSteps.has(target));\n if (missingTargets.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_TARGET_NOT_IN_STEPS\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} declares target step(s) not included in its steps list: ${missingTargets.map(({ id }) => id).join(\", \")}`\n )\n );\n }\n const missingReferences: string[] = [];\n // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores the\n // `TOptions` generic that the tuple erased, without changing the values.\n for (const step of steps as readonly AnyStep<TOptions>[]) {\n for (const dependency of stepEdges(step)) {\n if (!knownSteps.has(dependency)) {\n missingReferences.push(`${step.id} -> ${dependency.id}`);\n }\n }\n }\n if (missingReferences.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_DEPENDENCY_NOT_IN_STEPS\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} references step(s) not included in its steps list: ${missingReferences.join(\", \")}`\n )\n );\n }\n\n const requiredFinalizerSteps = requiredFinalizerMetadata<TOptions>(definition.finalize)?.steps;\n const missingFinalizerSteps = (requiredFinalizerSteps ?? []).filter(\n (step) => !knownSteps.has(step)\n );\n if (missingFinalizerSteps.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_FINALIZER_STEP_NOT_IN_STEPS\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} requires finalizer output from step(s) not included in its steps list: ${missingFinalizerSteps.map(({ id }) => id).join(\", \")}`\n )\n );\n }\n\n if (\n requiredFinalizerSteps &&\n missingTargets.length === 0 &&\n missingReferences.length === 0 &&\n missingFinalizerSteps.length === 0\n ) {\n for (const target of declaredTargets) {\n const selected = targetClosure([target]);\n const missingRequiredSteps = requiredFinalizerSteps.filter((step) => !selected.has(step));\n if (missingRequiredSteps.length > 0) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_TARGET_FINALIZER_MISMATCH\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} target ${target.id} cannot satisfy required finalizer output(s): ${missingRequiredSteps.map(({ id }) => id).join(\", \")}`,\n { stepId: target.id }\n )\n );\n }\n }\n }\n\n // SAFETY: `steps` is `TSteps extends readonly AnyStep[]`; the cast restores the\n // `TOptions` generic that the tuple erased, without changing the values.\n if (errors.length === 0 && !topologicalSort(steps as readonly AnyStep<TOptions>[])) {\n errors.push(\n pipelineDiagnostic(\n \"TUBELESS_DEFINITION_DEPENDENCY_CYCLE\",\n \"definition\",\n \"definition\",\n `Pipeline ${definition.id} has a dependency cycle`\n )\n );\n }\n return errors;\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import type { AnyStep, Step, StepOutput } from "./pipeline-steps.js";
2
+ import type { InferSchemaInput, PipelineExecutionContext, StandardSchemaV1 } from "./pipeline-types.js";
3
+ /**
4
+ * Recovers the options type from the steps themselves rather than taking it as its own
5
+ * generic parameter. A `TOptions` parameter constrained by `TSteps extends
6
+ * readonly AnyStep<TOptions>[]` is self-referential — TypeScript can't solve that at a
7
+ * `definePipeline(...)` call site and silently widens `TOptions` to its bare
8
+ * `object` constraint (context.options would lose every pipeline-specific
9
+ * field). Structuring it as "derive TOptions from TSteps" instead of "constrain TSteps by
10
+ * TOptions" avoids the cycle, so callers never write out any of these type parameters.
11
+ */
12
+ export type StepsOptions<TSteps extends readonly AnyStep[]> = TSteps[number] extends AnyStep<infer TOptions> ? TOptions : object;
13
+ export type StepsInputOptions<TSteps extends readonly AnyStep[]> = TSteps[number] extends Step<string, unknown, object, infer TInputOptions, infer _TRunOut> ? TInputOptions : StepsOptions<TSteps>;
14
+ export type StepIds<TSteps extends readonly AnyStep[]> = TSteps[number]["id"];
15
+ export type TargetIds<TTargets extends readonly AnyStep[]> = TTargets[number]["id"];
16
+ type PipelineOutputs<TSteps extends readonly AnyStep[]> = {
17
+ [S in TSteps[number] as S["id"]]: StepOutput<S>;
18
+ };
19
+ export interface PipelineDefinition<TSteps extends readonly AnyStep[], TResult, TTargets extends readonly TSteps[number][] = readonly [], TResultSchema extends StandardSchemaV1 | undefined = undefined> {
20
+ id: string;
21
+ steps: TSteps;
22
+ /** Public downstream goals that callers may select with `targets`. */
23
+ targets?: TTargets;
24
+ /** Optional Standard Schema for the finalized result. */
25
+ resultSchema?: TResultSchema;
26
+ finalize(outputs: Partial<PipelineOutputs<TSteps>>, context: PipelineExecutionContext<StepsOptions<TSteps>>): (TResultSchema extends StandardSchemaV1 ? InferSchemaInput<TResultSchema> : TResult) | Promise<TResultSchema extends StandardSchemaV1 ? InferSchemaInput<TResultSchema> : TResult>;
27
+ }
28
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline-definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-definition.js","sourceRoot":"","sources":["../../src/core/pipeline-definition.ts"],"names":[],"mappings":"","sourcesContent":["import type { AnyStep, Step, StepOutput } from \"./pipeline-steps.js\";\nimport type {\n InferSchemaInput,\n PipelineExecutionContext,\n StandardSchemaV1,\n} from \"./pipeline-types.js\";\n\n/**\n * Recovers the options type from the steps themselves rather than taking it as its own\n * generic parameter. A `TOptions` parameter constrained by `TSteps extends\n * readonly AnyStep<TOptions>[]` is self-referential — TypeScript can't solve that at a\n * `definePipeline(...)` call site and silently widens `TOptions` to its bare\n * `object` constraint (context.options would lose every pipeline-specific\n * field). Structuring it as \"derive TOptions from TSteps\" instead of \"constrain TSteps by\n * TOptions\" avoids the cycle, so callers never write out any of these type parameters.\n */\nexport type StepsOptions<TSteps extends readonly AnyStep[]> =\n TSteps[number] extends AnyStep<infer TOptions> ? TOptions : object;\n\nexport type StepsInputOptions<TSteps extends readonly AnyStep[]> =\n TSteps[number] extends Step<string, unknown, object, infer TInputOptions, infer _TRunOut>\n ? TInputOptions\n : StepsOptions<TSteps>;\n\nexport type StepIds<TSteps extends readonly AnyStep[]> = TSteps[number][\"id\"];\n\nexport type TargetIds<TTargets extends readonly AnyStep[]> = TTargets[number][\"id\"];\n\ntype PipelineOutputs<TSteps extends readonly AnyStep[]> = {\n [S in TSteps[number] as S[\"id\"]]: StepOutput<S>;\n};\n\nexport interface PipelineDefinition<\n TSteps extends readonly AnyStep[],\n TResult,\n TTargets extends readonly TSteps[number][] = readonly [],\n TResultSchema extends StandardSchemaV1 | undefined = undefined,\n> {\n id: string;\n steps: TSteps;\n /** Public downstream goals that callers may select with `targets`. */\n targets?: TTargets;\n /** Optional Standard Schema for the finalized result. */\n resultSchema?: TResultSchema;\n finalize(\n outputs: Partial<PipelineOutputs<TSteps>>,\n context: PipelineExecutionContext<StepsOptions<TSteps>>\n ):\n | (TResultSchema extends StandardSchemaV1 ? InferSchemaInput<TResultSchema> : TResult)\n | Promise<TResultSchema extends StandardSchemaV1 ? InferSchemaInput<TResultSchema> : TResult>;\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { CompiledStepGraph } from "./pipeline-graph.js";
2
+ import type { AnyStep } from "./pipeline-steps.js";
3
+ import type { PipelinePlanStep, PipelineStepReport, PipelineStepSkipReason } from "./pipeline-types.js";
4
+ type StepDispositionInput<TOptions extends object> = {
5
+ dryRun: boolean;
6
+ graph: CompiledStepGraph<TOptions>;
7
+ planned: PipelinePlanStep;
8
+ reportsByStepId: ReadonlyMap<string, PipelineStepReport>;
9
+ step: AnyStep<TOptions>;
10
+ };
11
+ type StepDisposition = {
12
+ kind: "run";
13
+ } | {
14
+ kind: "skip";
15
+ reason: PipelineStepSkipReason;
16
+ dependencyId?: string;
17
+ message?: string;
18
+ };
19
+ /**
20
+ * Single skip ladder for plan and live execution.
21
+ * Policy skips stay outside: they run only after a step is scheduled.
22
+ * Remainder copies plan `skipReason` for structural skips and marks planned-run
23
+ * steps fail-fast or cancelled, so this ladder has no abort/fail-fast mode.
24
+ */
25
+ export declare function decideStepDisposition<TOptions extends object>(input: StepDispositionInput<TOptions>): StepDisposition;
26
+ export {};
@@ -0,0 +1,44 @@
1
+ /** Required dependencies are met when completed, or intentionally policy-skipped. */
2
+ function isRequiredDependencyMet(report) {
3
+ if (!report)
4
+ return false;
5
+ if (report.status === "completed")
6
+ return true;
7
+ return report.status === "skipped" && report.reason === "policy";
8
+ }
9
+ /**
10
+ * Single skip ladder for plan and live execution.
11
+ * Policy skips stay outside: they run only after a step is scheduled.
12
+ * Remainder copies plan `skipReason` for structural skips and marks planned-run
13
+ * steps fail-fast or cancelled, so this ladder has no abort/fail-fast mode.
14
+ */
15
+ export function decideStepDisposition(input) {
16
+ const { dryRun, graph, planned, reportsByStepId, step } = input;
17
+ if (!planned.selected) {
18
+ return { kind: "skip", reason: "filtered" };
19
+ }
20
+ const unsuccessfulAncestor = graph.skipAfterFailureOf.find((dep) => {
21
+ const status = reportsByStepId.get(dep.id)?.status;
22
+ return status === "failed" || status === "cancelled";
23
+ });
24
+ if (unsuccessfulAncestor) {
25
+ return {
26
+ kind: "skip",
27
+ reason: "failed-dependency",
28
+ dependencyId: unsuccessfulAncestor.id,
29
+ };
30
+ }
31
+ const unmetDependency = graph.dependsOn.find((dep) => !isRequiredDependencyMet(reportsByStepId.get(dep.id)));
32
+ if (unmetDependency) {
33
+ return {
34
+ kind: "skip",
35
+ reason: "unmet-dependency",
36
+ dependencyId: unmetDependency.id,
37
+ };
38
+ }
39
+ if (dryRun && step.dryRun === "skip") {
40
+ return { kind: "skip", reason: "dry-run" };
41
+ }
42
+ return { kind: "run" };
43
+ }
44
+ //# sourceMappingURL=pipeline-disposition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-disposition.js","sourceRoot":"","sources":["../../src/core/pipeline-disposition.ts"],"names":[],"mappings":"AAQA,qFAAqF;AACrF,SAAS,uBAAuB,CAAC,MAAsC;IACrE,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC;AACnE,CAAC;AAmBD;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAqC;IAErC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAEhE,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC9C,CAAC;IAED,MAAM,oBAAoB,GAAG,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACnD,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,WAAW,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,IAAI,oBAAoB,EAAE,CAAC;QACzB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,mBAAmB;YAC3B,YAAY,EAAE,oBAAoB,CAAC,EAAE;SACtC,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,uBAAuB,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAC/D,CAAC;IACF,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,kBAAkB;YAC1B,YAAY,EAAE,eAAe,CAAC,EAAE;SACjC,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC","sourcesContent":["import type { CompiledStepGraph } from \"./pipeline-graph.js\";\nimport type { AnyStep } from \"./pipeline-steps.js\";\nimport type {\n PipelinePlanStep,\n PipelineStepReport,\n PipelineStepSkipReason,\n} from \"./pipeline-types.js\";\n\n/** Required dependencies are met when completed, or intentionally policy-skipped. */\nfunction isRequiredDependencyMet(report: PipelineStepReport | undefined): boolean {\n if (!report) return false;\n if (report.status === \"completed\") return true;\n return report.status === \"skipped\" && report.reason === \"policy\";\n}\n\ntype StepDispositionInput<TOptions extends object> = {\n dryRun: boolean;\n graph: CompiledStepGraph<TOptions>;\n planned: PipelinePlanStep;\n reportsByStepId: ReadonlyMap<string, PipelineStepReport>;\n step: AnyStep<TOptions>;\n};\n\ntype StepDisposition =\n | { kind: \"run\" }\n | {\n kind: \"skip\";\n reason: PipelineStepSkipReason;\n dependencyId?: string;\n message?: string;\n };\n\n/**\n * Single skip ladder for plan and live execution.\n * Policy skips stay outside: they run only after a step is scheduled.\n * Remainder copies plan `skipReason` for structural skips and marks planned-run\n * steps fail-fast or cancelled, so this ladder has no abort/fail-fast mode.\n */\nexport function decideStepDisposition<TOptions extends object>(\n input: StepDispositionInput<TOptions>\n): StepDisposition {\n const { dryRun, graph, planned, reportsByStepId, step } = input;\n\n if (!planned.selected) {\n return { kind: \"skip\", reason: \"filtered\" };\n }\n\n const unsuccessfulAncestor = graph.skipAfterFailureOf.find((dep) => {\n const status = reportsByStepId.get(dep.id)?.status;\n return status === \"failed\" || status === \"cancelled\";\n });\n if (unsuccessfulAncestor) {\n return {\n kind: \"skip\",\n reason: \"failed-dependency\",\n dependencyId: unsuccessfulAncestor.id,\n };\n }\n\n const unmetDependency = graph.dependsOn.find(\n (dep) => !isRequiredDependencyMet(reportsByStepId.get(dep.id))\n );\n if (unmetDependency) {\n return {\n kind: \"skip\",\n reason: \"unmet-dependency\",\n dependencyId: unmetDependency.id,\n };\n }\n\n if (dryRun && step.dryRun === \"skip\") {\n return { kind: \"skip\", reason: \"dry-run\" };\n }\n\n return { kind: \"run\" };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { PipelineError, PipelineErrorCode, PipelineErrorKind, PipelineErrorPhase } from "./pipeline-types.js";
2
+ export declare function pipelineDiagnostic(code: PipelineErrorCode, phase: PipelineErrorPhase, kind: PipelineErrorKind, message: string, fields?: Pick<PipelineError, "stepId">): PipelineError;
3
+ /** Programmer error raised immediately when a pipeline graph is invalid. */
4
+ export declare class PipelineDefinitionError extends Error {
5
+ readonly pipelineId: string;
6
+ readonly errors: readonly PipelineError[];
7
+ constructor(pipelineId: string, errors: readonly PipelineError[]);
8
+ }
@@ -0,0 +1,20 @@
1
+ import { brandTubelessError } from "../utilities/tubeless-error.js";
2
+ import { formatPipelineError } from "./pipeline-diagnostics.js";
3
+ export function pipelineDiagnostic(code, phase, kind, message, fields = {}) {
4
+ return { code, kind, message, phase, ...fields };
5
+ }
6
+ /** Programmer error raised immediately when a pipeline graph is invalid. */
7
+ export class PipelineDefinitionError extends Error {
8
+ pipelineId;
9
+ errors;
10
+ constructor(pipelineId, errors) {
11
+ super(errors.length > 0
12
+ ? `Invalid pipeline ${pipelineId}: ${errors.map((error) => formatPipelineError(error)).join("; ")}`
13
+ : `Invalid pipeline ${pipelineId}`);
14
+ this.pipelineId = pipelineId;
15
+ this.errors = errors;
16
+ this.name = "PipelineDefinitionError";
17
+ brandTubelessError(this, "pipeline-definition");
18
+ }
19
+ }
20
+ //# sourceMappingURL=pipeline-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-errors.js","sourceRoot":"","sources":["../../src/core/pipeline-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAQhE,MAAM,UAAU,kBAAkB,CAChC,IAAuB,EACvB,KAAyB,EACzB,IAAuB,EACvB,OAAe,EACf,MAAM,GAAkC,EAAE;IAE1C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC;AACnD,CAAC;AAED,4EAA4E;AAC5E,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAErC,UAAU;IACV,MAAM;IAFjB,YACW,UAAkB,EAClB,MAAgC;QAEzC,KAAK,CACH,MAAM,CAAC,MAAM,GAAG,CAAC;YACf,CAAC,CAAC,oBAAoB,UAAU,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACnG,CAAC,CAAC,oBAAoB,UAAU,EAAE,CACrC,CAAC;0BAPO,UAAU;sBACV,MAAM;QAOf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IAClD,CAAC;CACF","sourcesContent":["import { brandTubelessError } from \"../utilities/tubeless-error.js\";\nimport { formatPipelineError } from \"./pipeline-diagnostics.js\";\nimport type {\n PipelineError,\n PipelineErrorCode,\n PipelineErrorKind,\n PipelineErrorPhase,\n} from \"./pipeline-types.js\";\n\nexport function pipelineDiagnostic(\n code: PipelineErrorCode,\n phase: PipelineErrorPhase,\n kind: PipelineErrorKind,\n message: string,\n fields: Pick<PipelineError, \"stepId\"> = {}\n): PipelineError {\n return { code, kind, message, phase, ...fields };\n}\n\n/** Programmer error raised immediately when a pipeline graph is invalid. */\nexport class PipelineDefinitionError extends Error {\n constructor(\n readonly pipelineId: string,\n readonly errors: readonly PipelineError[]\n ) {\n super(\n errors.length > 0\n ? `Invalid pipeline ${pipelineId}: ${errors.map((error) => formatPipelineError(error)).join(\"; \")}`\n : `Invalid pipeline ${pipelineId}`\n );\n this.name = \"PipelineDefinitionError\";\n brandTubelessError(this, \"pipeline-definition\");\n }\n}\n"]}
@@ -1,6 +1,8 @@
1
- import { type CompiledPipeline } from "./pipeline-plan.js";
1
+ import type { CompiledPipeline } from "./pipeline-compiler.js";
2
2
  import type { AnyStep } from "./pipeline-steps.js";
3
3
  import type { InferSchemaOutput, PipelineContext, PipelinePlan, PipelineRun, PipelineRunControls, PipelineRuntime, StandardSchemaV1 } from "./pipeline-types.js";
4
+ /** Observe an execution ID from an internal host without allowing it to be overridden. */
5
+ export declare function observePipelineRunId<TContext extends object>(context: TContext, observer: (runId: string) => void): TContext;
4
6
  export declare class PipelineExecutionError extends Error {
5
7
  readonly result: PipelineRun<unknown>;
6
8
  constructor(result: PipelineRun<unknown>, message?: string);