tubeless 0.2.2 → 0.2.3
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.
- package/README.md +5 -5
- package/dist/core/child-execution.js +8 -1
- package/dist/core/child-execution.js.map +1 -1
- package/dist/core/lifecycle.js +2 -0
- package/dist/core/lifecycle.js.map +1 -1
- package/dist/core/pipeline-execute.d.ts +2 -0
- package/dist/core/pipeline-execute.js +132 -395
- package/dist/core/pipeline-execute.js.map +1 -1
- package/dist/core/pipeline-plan.js +96 -34
- package/dist/core/pipeline-plan.js.map +1 -1
- package/dist/core/pipeline-run-state.d.ts +49 -0
- package/dist/core/pipeline-run-state.js +284 -0
- package/dist/core/pipeline-run-state.js.map +1 -0
- package/dist/core/pipeline-step-executor.d.ts +20 -0
- package/dist/core/pipeline-step-executor.js +52 -0
- package/dist/core/pipeline-step-executor.js.map +1 -0
- package/dist/core/pipeline-types.d.ts +11 -2
- package/dist/core/pipeline-types.js.map +1 -1
- package/dist/core/pipeline-validation.d.ts +6 -0
- package/dist/core/pipeline-validation.js +41 -0
- package/dist/core/pipeline-validation.js.map +1 -0
- package/dist/run-store/run-store-ndjson.js +2 -295
- package/dist/run-store/run-store-ndjson.js.map +1 -1
- package/dist/run-store/run-store-sqlite.js +91 -42
- package/dist/run-store/run-store-sqlite.js.map +1 -1
- package/dist/run-store/run-store.d.ts +3 -2
- package/dist/run-store/run-store.js +38 -195
- package/dist/run-store/run-store.js.map +1 -1
- package/dist/studio/run-store-ui-client-controller.d.ts +9 -0
- package/dist/studio/run-store-ui-client-controller.js +479 -0
- package/dist/studio/run-store-ui-client-controller.js.map +1 -0
- package/dist/studio/run-store-ui-client-form.d.ts +9 -0
- package/dist/studio/run-store-ui-client-form.js +44 -0
- package/dist/studio/run-store-ui-client-form.js.map +1 -0
- package/dist/studio/run-store-ui-client-model.d.ts +40 -0
- package/dist/studio/run-store-ui-client-model.js +211 -0
- package/dist/studio/run-store-ui-client-model.js.map +1 -0
- package/dist/studio/run-store-ui-client-source.js +1 -1
- package/dist/studio/run-store-ui-client-transport.d.ts +25 -0
- package/dist/studio/run-store-ui-client-transport.js +322 -0
- package/dist/studio/run-store-ui-client-transport.js.map +1 -0
- package/dist/studio/run-store-ui-client-views.d.ts +24 -0
- package/dist/studio/run-store-ui-client-views.js +676 -0
- package/dist/studio/run-store-ui-client-views.js.map +1 -0
- package/dist/studio/run-store-ui-client.d.ts +2 -14
- package/dist/studio/run-store-ui-client.js +7 -1360
- package/dist/studio/run-store-ui-client.js.map +1 -1
- package/dist/studio/run-store-ui-page.d.ts +1 -1
- package/dist/studio/run-store-ui.js +44 -25
- package/dist/studio/run-store-ui.js.map +1 -1
- package/dist/tracing/tracing-codec.d.ts +6 -0
- package/dist/tracing/tracing-codec.js +829 -0
- package/dist/tracing/tracing-codec.js.map +1 -0
- package/dist/tracing/tracing-constants.d.ts +4 -0
- package/dist/tracing/tracing-constants.js +5 -0
- package/dist/tracing/tracing-constants.js.map +1 -0
- package/dist/tracing/tracing-internal.js +116 -81
- package/dist/tracing/tracing-internal.js.map +1 -1
- package/dist/tracing/tracing-otel.js +19 -3
- package/dist/tracing/tracing-otel.js.map +1 -1
- package/dist/tracing/tracing.d.ts +149 -10
- package/dist/tracing/tracing.js.map +1 -1
- package/dist/workbench/workbench-history.js +8 -1
- package/dist/workbench/workbench-history.js.map +1 -1
- package/dist/workbench/workbench-ui.js +26 -6
- package/dist/workbench/workbench-ui.js.map +1 -1
- package/docs/README.md +21 -15
- package/docs/agent-guide.md +48 -35
- package/docs/agent-skills.md +59 -0
- package/docs/api-reference.md +28 -12
- package/docs/api-report.json +29 -13
- package/docs/child-pipeline-composition.md +142 -193
- package/docs/cli.md +83 -61
- package/docs/comparison.md +63 -62
- package/docs/concepts.md +210 -272
- package/docs/getting-started.md +59 -48
- package/docs/llms.txt +7 -4
- package/docs/recipes.md +21 -18
- package/docs/remote-step-composition.md +69 -74
- package/docs/studio.md +146 -71
- package/examples/catalog/pipelines/enrich.ts +2 -2
- package/examples/catalog/tubeless.project.ts +4 -2
- package/examples/host-embedding.ts +4 -5
- package/examples/remote-steps.ts +8 -5
- package/package.json +11 -10
- package/skills/tubeless/SKILL.md +83 -0
- package/skills/tubeless-make-pipeline/SKILL.md +126 -0
package/docs/api-report.json
CHANGED
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"toMappedChildStepProgress",
|
|
80
80
|
"ToMappedChildStepProgressOptions"
|
|
81
81
|
],
|
|
82
|
-
"sha256": "
|
|
82
|
+
"sha256": "caccbd005663d2c525deb371fc465e132d6aa51071f956e25d7632430d955098",
|
|
83
83
|
"specifier": "tubeless"
|
|
84
84
|
},
|
|
85
85
|
{
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"PromptMultiSelectOptions",
|
|
136
136
|
"TUBELESS_WORKBENCH_EXIT_CODE"
|
|
137
137
|
],
|
|
138
|
-
"sha256": "
|
|
138
|
+
"sha256": "3e188b4fa127274a443d327d9a6ce6c4aa97e88d80c9a1420d25a9696993dbc6",
|
|
139
139
|
"specifier": "tubeless/cli"
|
|
140
140
|
},
|
|
141
141
|
{
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
"renderPipelineError",
|
|
170
170
|
"renderPipelinePlan"
|
|
171
171
|
],
|
|
172
|
-
"sha256": "
|
|
172
|
+
"sha256": "07fa0a2cf3db19998b426eee827e0902b10235a169fb80d7731f5254b1a80197",
|
|
173
173
|
"specifier": "tubeless/render"
|
|
174
174
|
},
|
|
175
175
|
{
|
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
"RunReporterConfig",
|
|
190
190
|
"RunReporterOptions"
|
|
191
191
|
],
|
|
192
|
-
"sha256": "
|
|
192
|
+
"sha256": "0b101c3f1c4a3a1f581fbd19df2c05fa5de9c4504537db12399a3fb876c725ff",
|
|
193
193
|
"specifier": "tubeless/reporter"
|
|
194
194
|
},
|
|
195
195
|
{
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
"StoredPipelineStep",
|
|
221
221
|
"StoredRemote"
|
|
222
222
|
],
|
|
223
|
-
"sha256": "
|
|
223
|
+
"sha256": "06bf5a381752346d51682b74347306387d7d06622ff48fd9f29876b0e7a33c7e",
|
|
224
224
|
"specifier": "tubeless/run-store"
|
|
225
225
|
},
|
|
226
226
|
{
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
"OpenSqlitePipelineRunStoreOptions",
|
|
231
231
|
"SqlitePipelineRunStore"
|
|
232
232
|
],
|
|
233
|
-
"sha256": "
|
|
233
|
+
"sha256": "5a497dfdbac584459c79c303c25e3be95e893ea6b5d2047c01f061eceba25ffc",
|
|
234
234
|
"specifier": "tubeless/run-store/sqlite"
|
|
235
235
|
},
|
|
236
236
|
{
|
|
@@ -240,7 +240,7 @@
|
|
|
240
240
|
"openNdjsonPipelineRunStore",
|
|
241
241
|
"OpenNdjsonPipelineRunStoreOptions"
|
|
242
242
|
],
|
|
243
|
-
"sha256": "
|
|
243
|
+
"sha256": "04c65f3e126ed97fe83b427a133450763d4caa996bb188d6c84f366db85fbb9f",
|
|
244
244
|
"specifier": "tubeless/run-store/ndjson"
|
|
245
245
|
},
|
|
246
246
|
{
|
|
@@ -282,7 +282,7 @@
|
|
|
282
282
|
"PipelineRunStudioServer",
|
|
283
283
|
"startPipelineRunStudio"
|
|
284
284
|
],
|
|
285
|
-
"sha256": "
|
|
285
|
+
"sha256": "02dec5c804295fb172f7af226ea2c60a2095685b0ce72cb8ee7902b8913d4a97",
|
|
286
286
|
"specifier": "tubeless/run-store/ui"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
@@ -296,13 +296,19 @@
|
|
|
296
296
|
"PipelineTestRuntimeOptions",
|
|
297
297
|
"PipelineTestSleep"
|
|
298
298
|
],
|
|
299
|
-
"sha256": "
|
|
299
|
+
"sha256": "f84c8c3b0ae48b8c49d6cabb1a2c5988770059838ffab6f94a8444fd0fff695c",
|
|
300
300
|
"specifier": "tubeless/testing"
|
|
301
301
|
},
|
|
302
302
|
{
|
|
303
303
|
"declaration": "./dist/tracing/tracing.d.ts",
|
|
304
304
|
"exports": [
|
|
305
305
|
"composeTraceExporters",
|
|
306
|
+
"PipelineCompletedTraceEvent",
|
|
307
|
+
"PipelineFinalizeCompletedTraceEvent",
|
|
308
|
+
"PipelineFinalizeFailedTraceEvent",
|
|
309
|
+
"PipelineFinalizeStartedTraceEvent",
|
|
310
|
+
"PipelineLogTraceEvent",
|
|
311
|
+
"PipelineStartedTraceEvent",
|
|
306
312
|
"PipelineTraceAttributes",
|
|
307
313
|
"PipelineTraceAttributeValue",
|
|
308
314
|
"PipelineTraceContext",
|
|
@@ -310,15 +316,25 @@
|
|
|
310
316
|
"PipelineTraceEvent",
|
|
311
317
|
"PipelineTraceEventName",
|
|
312
318
|
"PipelineTraceExporter",
|
|
313
|
-
"
|
|
319
|
+
"PipelineTraceNestedPipeline",
|
|
320
|
+
"PipelineTraceProgress",
|
|
321
|
+
"PipelineTraceRemote",
|
|
322
|
+
"PipelineTracingOptions",
|
|
323
|
+
"StepAttemptedTraceEvent",
|
|
324
|
+
"StepCancelledTraceEvent",
|
|
325
|
+
"StepCompletedTraceEvent",
|
|
326
|
+
"StepFailedTraceEvent",
|
|
327
|
+
"StepPlannedTraceEvent",
|
|
328
|
+
"StepRunningTraceEvent",
|
|
329
|
+
"StepSkippedTraceEvent"
|
|
314
330
|
],
|
|
315
|
-
"sha256": "
|
|
331
|
+
"sha256": "caccbd005663d2c525deb371fc465e132d6aa51071f956e25d7632430d955098",
|
|
316
332
|
"specifier": "tubeless/tracing"
|
|
317
333
|
},
|
|
318
334
|
{
|
|
319
335
|
"declaration": "./dist/tracing/tracing-json.d.ts",
|
|
320
336
|
"exports": ["createJsonTraceExporter", "JsonTraceExporterOptions"],
|
|
321
|
-
"sha256": "
|
|
337
|
+
"sha256": "040c6496477e3be9618eedd0ee74b317bff12fd390c6cbf0b36c725c5e4a5464",
|
|
322
338
|
"specifier": "tubeless/tracing/json"
|
|
323
339
|
},
|
|
324
340
|
{
|
|
@@ -329,7 +345,7 @@
|
|
|
329
345
|
"OpenTelemetryLikeTracer",
|
|
330
346
|
"OpenTelemetryTraceExporterOptions"
|
|
331
347
|
],
|
|
332
|
-
"sha256": "
|
|
348
|
+
"sha256": "0f86d65848e5dc133265f0e3379c64e6a8490c345a1e7077d2570cc630f669fe",
|
|
333
349
|
"specifier": "tubeless/tracing/otel"
|
|
334
350
|
}
|
|
335
351
|
],
|
|
@@ -1,98 +1,23 @@
|
|
|
1
1
|
# Child-pipeline composition
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use a child pipeline when part of a workflow is useful on its own and should
|
|
4
|
+
also run inside a larger pipeline. Tubeless provides two step builders:
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
shape as their skip value. Child lifecycle hooks stay isolated, and child work reports
|
|
10
|
-
through parent-step progress. Interactive reporters display selected child steps
|
|
11
|
-
as an indented tree, retaining their terminal states and inner work counts.
|
|
6
|
+
| Builder | Use it to | Step output |
|
|
7
|
+
| ---------------------- | ----------------------------------------------- | ---------------------------------------- |
|
|
8
|
+
| `step.fromPipeline` | Run one child pipeline | The child's final result |
|
|
9
|
+
| `step.forEachPipeline` | Run the same child pipeline for a list of items | An array of child results in input order |
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
is returned, so the parent cannot finalize while child side effects are still
|
|
18
|
-
in flight.
|
|
11
|
+
Both builders infer the child options and result types. They forward the
|
|
12
|
+
parent's runtime context and report child progress through the parent step.
|
|
13
|
+
Start with the [single-child example](../examples/child-pipeline.ts) or the
|
|
14
|
+
[fan-out example](../examples/fan-out-progress.ts).
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
effects in dry-run, and convert domain validation errors into failed parent
|
|
22
|
-
steps.
|
|
16
|
+
## Run a child pipeline
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`PipelineStepContext` gives the child the parent's runtime seams, but it also
|
|
28
|
-
gives the child the parent's raw hooks and parent-only `reportProgress`
|
|
29
|
-
callback.
|
|
30
|
-
|
|
31
|
-
The resulting lifecycle stream is flat. A direct nested run emits the child pipeline, step, finalize, and completion events between the parent wrapper step's start and completion events. Most events have no pipeline path or run identity. The interactive reporter also owns one plan, one step map, and one result. A child start replaces its visible plan, and a child completion disposes the reporter before the parent completes.
|
|
32
|
-
|
|
33
|
-
The package needs a composition contract that preserves typing and runtime behavior without exposing two pipeline frames through hooks designed for one pipeline.
|
|
34
|
-
|
|
35
|
-
## Goals
|
|
36
|
-
|
|
37
|
-
- Model a child pipeline as one typed step in the parent DAG.
|
|
38
|
-
- Infer parent dependency inputs, parent options, child options, the child result, and any mapped result.
|
|
39
|
-
- Preserve cancellation, logging, timing, working-directory, dry-run, progress, and failure behavior.
|
|
40
|
-
- Keep raw child lifecycle hooks inside the adapter while reporting useful progress through the opaque parent step.
|
|
41
|
-
- Keep the first slice bounded: one opaque child, or a mapped set of the same child.
|
|
42
|
-
|
|
43
|
-
## Supported: policy skip on opaque steps
|
|
44
|
-
|
|
45
|
-
Policy skip (`step.skippable` / `StepSkipDecision`) is part of the shipped API and
|
|
46
|
-
applies to ordinary steps, `fromPipeline` adapters, and mapped
|
|
47
|
-
`forEachPipeline` adapters (the opaque parent step is a normal step under the
|
|
48
|
-
hood):
|
|
49
|
-
|
|
50
|
-
- Return a non-empty string or `{ reason, value? }` from `skip` to skip without
|
|
51
|
-
calling `run` (or without running the child). Reporters show a yellow skip
|
|
52
|
-
whose terminal report has `status: "skipped"` and `reason: "policy"`.
|
|
53
|
-
- Policy skips unlock required dependents. A bare string (or `{ reason }`
|
|
54
|
-
without `value`) publishes `undefined` as the step output.
|
|
55
|
-
- Any step that declares `skip` is typed so dependents see `TOut | undefined`
|
|
56
|
-
(including `PipelineResultOf<Child> | undefined` for `fromPipeline` and
|
|
57
|
-
`readonly PipelineResultOf<Child>[] | undefined` for `forEachPipeline`, both
|
|
58
|
-
without `mapResult`). Prefer `{ reason, value }` on every skip path when
|
|
59
|
-
dependents need a real output. With `mapResult`, skip `value` is the
|
|
60
|
-
parent-facing mapped output — one `TOut` for `fromPipeline`, or the complete
|
|
61
|
-
`readonly TOut[]` for `forEachPipeline`. Policy skip does not call `mapResult`.
|
|
62
|
-
|
|
63
|
-
Use `fromPipeline.skippable` or `forEachPipeline.skippable` to policy-skip
|
|
64
|
-
optional child work and publish a concrete disabled result via
|
|
65
|
-
`{ reason, value }`. The ordinary constructors reject `skip` and retain their
|
|
66
|
-
non-optional output types.
|
|
67
|
-
|
|
68
|
-
## Non-goals
|
|
69
|
-
|
|
70
|
-
- Flatten child steps into the parent plan.
|
|
71
|
-
- Add hierarchical or versioned external lifecycle events.
|
|
72
|
-
- Support namespaced selection such as `parent.child-step`.
|
|
73
|
-
- Add parallel DAG execution, remote checkpoints, or subcommands.
|
|
74
|
-
- Injected runner overrides (substituting a child pipeline implementation at
|
|
75
|
-
test time via parent options) — separate from policy skip.
|
|
76
|
-
|
|
77
|
-
## Why this shape
|
|
78
|
-
|
|
79
|
-
| Model | Typing | Planning | Hooks and reporting | Selective execution | Failure | Dry run | Cost |
|
|
80
|
-
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
81
|
-
| Continue manual shared-context calls | Each wrapper can map options and return a typed value, but each wrapper repeats the contract and structural context passing makes unsafe fields easy to forward. | The parent sees only the wrapper step; the child creates a separate plan at runtime. | Raw child events enter the parent's flat hook stream. The current interactive reporter replaces the parent frame and disposes on child completion. | Parent selection can select the wrapper. Child selection depends on ad hoc mapped `stepIds`. | `runOrThrow` can fail the wrapper, but consistent child-identifying messages and progress require repeated wrapper code. | Each wrapper must remember parent/child dry-run precedence and per-step policy. | Low per call, with continuing duplication and reporter breakage. |
|
|
82
|
-
| Flatten the child DAG into the parent DAG | The API must translate child option and dependency types into a parent definition without losing inference. | Child ids need stable namespacing, and runtime option mapping can change which child plan is valid. | A flat plan fits current hooks only after defining pipeline identity, paths, and collision rules. | Namespaced filters need semantics for parent dependencies, child dependencies, and finalization. | The parent must define how child failures, partial outputs, and child finalization affect the flattened DAG. | The parent must reconcile its dry-run rules with every flattened child step. | High. It requires event identity and selection semantics before the first useful slice. |
|
|
83
|
-
| Opaque typed child-step adapter | A parent-scoped factory can infer dependency inputs and parent options while a typed child pipeline constrains mapped options and results. | The parent plan contains one stable step. The adapter validates the child plan immediately before running it. | Parent hooks see the opaque step only. An internal bridge translates child terminal events into parent-step progress. | Selecting the opaque parent step runs the child according to mapped child options. Nested selection is deferred. | An unusable child result throws a parent-step error that retains the child pipeline and failing step identity. | Framework-owned parent `dryRun` overrides the mapper, then the child applies its own per-step rules. | Medium. It uses existing pipeline and hook primitives without changing the external event model. |
|
|
84
|
-
|
|
85
|
-
Shared raw hooks are rejected because they already corrupt the interactive reporter's single frame and cannot distinguish nested runs. Immediate flattening is rejected because it needs stable identity, selection, dependency, failure, and finalization rules that the current event and plan models don't provide. The opaque adapter addresses the existing composition case without deciding those broader contracts.
|
|
86
|
-
|
|
87
|
-
## Contract
|
|
88
|
-
|
|
89
|
-
The parent DAG contains one ordinary step. That step maps its typed parent inputs and context into typed child options, validates the child plan, runs the child with an isolated internal hook bridge, and returns either the child result or a mapped parent result.
|
|
90
|
-
|
|
91
|
-
The bridge owns child lifecycle events. Parent and custom hooks receive only the parent pipeline and opaque parent-step events. The bridge reports terminal child-step counts through the parent step's `reportProgress`, so existing reporters keep one live frame.
|
|
92
|
-
|
|
93
|
-
## API
|
|
94
|
-
|
|
95
|
-
The parent-scoped step factory owns the adapter:
|
|
18
|
+
Use `fromPipeline` with `pipeline` and `mapOptions`. The mapper receives the
|
|
19
|
+
parent step's dependency outputs and context, and returns the inputs the child
|
|
20
|
+
needs. Add `mapResult` if the parent needs a different result shape.
|
|
96
21
|
|
|
97
22
|
```ts
|
|
98
23
|
const seedIndexStage = step.fromPipeline("seed-index", {
|
|
@@ -107,11 +32,10 @@ const seedIndexStage = step.fromPipeline("seed-index", {
|
|
|
107
32
|
});
|
|
108
33
|
```
|
|
109
34
|
|
|
110
|
-
|
|
111
|
-
child result when `mapResult` is absent, and infer the mapped result when it
|
|
112
|
-
is present.
|
|
35
|
+
## Run a child for each item
|
|
113
36
|
|
|
114
|
-
|
|
37
|
+
Use `items` to return the list to process, `key` for stable item IDs, and
|
|
38
|
+
`concurrency` to limit simultaneous child runs:
|
|
115
39
|
|
|
116
40
|
```ts
|
|
117
41
|
const processShards = step.forEachPipeline("process-shards", {
|
|
@@ -129,8 +53,7 @@ const processShards = step.forEachPipeline("process-shards", {
|
|
|
129
53
|
});
|
|
130
54
|
```
|
|
131
55
|
|
|
132
|
-
|
|
133
|
-
output explicitly:
|
|
56
|
+
To skip the whole step when there are no items, use the skippable builder:
|
|
134
57
|
|
|
135
58
|
```ts
|
|
136
59
|
const processShards = step.forEachPipeline.skippable("process-shards", {
|
|
@@ -144,101 +67,128 @@ const processShards = step.forEachPipeline.skippable("process-shards", {
|
|
|
144
67
|
});
|
|
145
68
|
```
|
|
146
69
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
`mapResult
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
`
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
the
|
|
70
|
+
## Results and type inference
|
|
71
|
+
|
|
72
|
+
Without `mapResult`, a `fromPipeline` step returns the child's final result.
|
|
73
|
+
With `mapResult`, it returns the mapped value. An asynchronous mapper is awaited
|
|
74
|
+
before the value becomes available to dependent steps. Its policy-skip value,
|
|
75
|
+
if supplied, must match that resolved result type.
|
|
76
|
+
|
|
77
|
+
`forEachPipeline` returns results in input order, even when child runs finish
|
|
78
|
+
in a different order. `concurrency` limits the number of child runs in flight.
|
|
79
|
+
Keys must be stable and unique; duplicate keys fail before any child starts.
|
|
80
|
+
All running children finish or cancel before the parent step returns a failure.
|
|
81
|
+
The parent therefore cannot finalize while those children are still running.
|
|
82
|
+
|
|
83
|
+
Use `.skippable` when the entire child step may be intentionally omitted.
|
|
84
|
+
Its `skip` callback returns `false` to proceed, a non-empty reason string to
|
|
85
|
+
skip, or `{ reason, value }` to skip with an output. A skip without a value
|
|
86
|
+
publishes `undefined`. Policy skips allow required dependents to run, so those
|
|
87
|
+
dependents must handle `undefined` explicitly.
|
|
88
|
+
|
|
89
|
+
The ordinary builders reject `skip` and keep non-optional output types.
|
|
90
|
+
`fromPipeline.skippable` returns `T | undefined`, and
|
|
91
|
+
`forEachPipeline.skippable` returns `readonly T[] | undefined`. For fan-out,
|
|
92
|
+
the skip value is the complete result array. Skipping does not call `items`,
|
|
93
|
+
run children, or apply `mapResult`.
|
|
94
|
+
|
|
95
|
+
## Planning and execution controls
|
|
96
|
+
|
|
97
|
+
The parent plan contains one step for the child workflow. This is what
|
|
98
|
+
"opaque" means in the API: child steps are not added to `PipelinePlan.steps`.
|
|
99
|
+
The parent's `nestedPipeline` metadata still identifies the child pipeline,
|
|
100
|
+
its declared step IDs, and whether it runs once or for multiple items.
|
|
101
|
+
|
|
102
|
+
Selecting the parent step runs the child using the values returned by
|
|
103
|
+
`mapOptions`. Parent and child step IDs are separate. A parent target does not
|
|
104
|
+
select an identically named child step, and `parent.child-step` selection is
|
|
105
|
+
not supported.
|
|
106
|
+
|
|
107
|
+
| Control | Child behavior |
|
|
108
|
+
| ----------------- | --------------------------------------------------------------------------------------------- |
|
|
109
|
+
| `dryRun` | Always takes the parent's value, overriding any value in `mapOptions` |
|
|
110
|
+
| `stepIds` | Uses only a child-specific value supplied by `mapOptions` |
|
|
111
|
+
| `targets` | Uses only a child-specific value supplied by `mapOptions`; IDs must be declared child targets |
|
|
112
|
+
| `continueOnError` | Uses only a value supplied by `mapOptions` |
|
|
113
|
+
|
|
114
|
+
Child `mapOptions` returns domain inputs and any child-specific controls in
|
|
115
|
+
one object. The adapter separates them before invoking the child. An invalid
|
|
116
|
+
child plan fails the parent step before child execution begins.
|
|
117
|
+
|
|
118
|
+
In a dry run, each child step still follows its own policy. Mark child writes
|
|
119
|
+
with `dryRun: "skip"` or provide a side-effect-free preview handler. You can
|
|
120
|
+
also set a dry-run policy on the parent wrapper step to skip or preview the
|
|
121
|
+
whole child workflow.
|
|
122
|
+
|
|
123
|
+
Composition adds no checkpoints or crash recovery. Fan-out runs children
|
|
124
|
+
concurrently within one parent step; it does not make the parent graph execute
|
|
125
|
+
its steps in parallel.
|
|
126
|
+
|
|
127
|
+
## Failures and cancellation
|
|
128
|
+
|
|
129
|
+
A child must finish with status `"completed"` to provide a successful parent
|
|
130
|
+
step output. `continueOnError` can let independent child work finish, but a
|
|
131
|
+
failed child still fails the parent step. Successful siblings in a failed
|
|
132
|
+
fan-out do not produce a partial parent-step output.
|
|
133
|
+
|
|
134
|
+
Child failures use `code: "TUBELESS_CHILD_FAILED"`, `phase: "execution"`, and
|
|
135
|
+
`kind: "child"`. The error identifies the child pipeline and first failing
|
|
136
|
+
step, and includes a JSON-safe cause chain. For multiple child runs, failure
|
|
137
|
+
takes precedence over cancellation: the parent step is cancelled only when
|
|
138
|
+
every unsuccessful child was cancelled.
|
|
139
|
+
|
|
140
|
+
Children receive the parent's exact `AbortSignal`. They must pass it to their
|
|
141
|
+
I/O and other cancellable work. The adapter waits for running children to
|
|
142
|
+
finish or cancel before returning.
|
|
143
|
+
|
|
144
|
+
If partial child results are valid for your application, use an ordinary step
|
|
145
|
+
that calls the child's `run()` and explicitly handles its report. Supply an
|
|
146
|
+
appropriate child context; do not forward the parent's raw hooks or progress
|
|
147
|
+
callback, which belong to the parent run's reporter.
|
|
148
|
+
|
|
149
|
+
## Progress and hooks
|
|
150
|
+
|
|
151
|
+
The builders forward the parent's working directory, logger, clock, sleep
|
|
152
|
+
function, and abort signal. Parent hooks observe the parent step. Child hooks
|
|
153
|
+
are handled internally and converted into progress updates on that step.
|
|
154
|
+
This keeps parent and child reporting separate.
|
|
155
|
+
|
|
156
|
+
The interactive CLI displays `fromPipeline` child steps beneath the parent.
|
|
157
|
+
For `forEachPipeline`, it adds an item-key row above each child's steps.
|
|
158
|
+
Completed rows remain visible; failed, cancelled, and skipped rows keep their
|
|
159
|
+
own statuses. Filtered steps are omitted. Nested progress counts and details
|
|
160
|
+
are preserved, so a child can report progress inside a long-running step.
|
|
161
|
+
|
|
162
|
+
The parent progress count advances as child steps reach a terminal state.
|
|
163
|
+
For fan-out, `completed` counts finished child steps across items, and `total`
|
|
164
|
+
is the number of items multiplied by the number of child steps. Use
|
|
165
|
+
`progress.itemNoun` or `progress.formatMessage` to change labels and summaries
|
|
166
|
+
without changing execution.
|
|
167
|
+
|
|
168
|
+
### Display and trace limits
|
|
169
|
+
|
|
170
|
+
Live fan-out updates show up to 32 item groups by default. Active items and
|
|
171
|
+
failures take priority, and displayed groups remain in input order. An overflow
|
|
172
|
+
row shows the number of omitted groups. All groups are retained, and a complete
|
|
173
|
+
tree is emitted when the fan-out finishes. Set `progress.detailLimit` to change
|
|
174
|
+
the live limit; this also limits the final snapshot.
|
|
175
|
+
|
|
176
|
+
The CLI shows a scrolling window when the tree is taller than the terminal and
|
|
177
|
+
prints the retained tree at completion. Non-interactive output uses summary
|
|
178
|
+
messages. Progress data is not built when neither hooks nor tracing observe it.
|
|
179
|
+
The standalone `mappedChildProgressDetails` helper formats the entries provided
|
|
180
|
+
to it and has no default item limit.
|
|
181
|
+
|
|
182
|
+
Custom renderers can read `details` as rows ordered parent before child.
|
|
183
|
+
`depth: 0` (or no depth) identifies a direct child; each nested level adds one.
|
|
184
|
+
IDs are stable within their group, and `name` is an optional label. Row
|
|
185
|
+
`completed` and `total` values describe work inside the child, independently
|
|
186
|
+
of the parent's count of finished steps. CLI indentation is capped at 32 levels.
|
|
187
|
+
|
|
188
|
+
Recorded trace snapshots have separate limits: 128 rows, 4096 characters per
|
|
189
|
+
field, and a 256 KiB encoded payload. `detailCount` records the row count before
|
|
190
|
+
truncation. The byte limit includes UTF-8 encoding and JSON escaping, leaving
|
|
191
|
+
space for event metadata within the default 1 MiB NDJSON event limit.
|
|
242
192
|
|
|
243
193
|
## Structured fan-out failures
|
|
244
194
|
|
|
@@ -263,6 +213,5 @@ unstarted work after cancellation. Reruns are ordinary new pipeline runs; the
|
|
|
263
213
|
caller owns retry policy and side-effect safety. See the helper in
|
|
264
214
|
[`fan-out-progress.ts`](../examples/fan-out-progress.ts).
|
|
265
215
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Successful siblings still do not produce a partial parent step output.
|
|
216
|
+
The diagnostics describe which items failed; they do not retry work or change
|
|
217
|
+
the parent step's failure behavior.
|