tubeless 0.2.7 → 0.2.9

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 (283) hide show
  1. package/README.md +20 -20
  2. package/dist/cli/cli-command.d.ts +1 -0
  3. package/dist/cli/cli-command.js +2 -0
  4. package/dist/cli/cli-command.js.map +1 -1
  5. package/dist/cli/cli-pipeline-command.d.ts +24 -6
  6. package/dist/cli/cli-pipeline-command.js +32 -12
  7. package/dist/cli/cli-pipeline-command.js.map +1 -1
  8. package/dist/cli/cli-schema.d.ts +25 -0
  9. package/dist/cli/cli-schema.js +129 -0
  10. package/dist/cli/cli-schema.js.map +1 -0
  11. package/dist/cli/cli-types.d.ts +18 -0
  12. package/dist/cli/cli-types.js +2 -0
  13. package/dist/cli/cli-types.js.map +1 -1
  14. package/dist/cli/cli.d.ts +2 -2
  15. package/dist/cli/cli.js.map +1 -1
  16. package/dist/core/child-execution.d.ts +3 -7
  17. package/dist/core/child-execution.js +34 -185
  18. package/dist/core/child-execution.js.map +1 -1
  19. package/dist/core/child-progress.d.ts +15 -5
  20. package/dist/core/child-progress.js +252 -9
  21. package/dist/core/child-progress.js.map +1 -1
  22. package/dist/core/mapped-child-progress.d.ts +4 -20
  23. package/dist/core/mapped-child-progress.js +2 -34
  24. package/dist/core/mapped-child-progress.js.map +1 -1
  25. package/dist/core/pipeline-compiler.d.ts +3 -2
  26. package/dist/core/pipeline-compiler.js +22 -5
  27. package/dist/core/pipeline-compiler.js.map +1 -1
  28. package/dist/core/pipeline-definition-identity.d.ts +14 -0
  29. package/dist/core/pipeline-definition-identity.js +141 -0
  30. package/dist/core/pipeline-definition-identity.js.map +1 -0
  31. package/dist/core/pipeline-definition-validation.js +13 -5
  32. package/dist/core/pipeline-definition-validation.js.map +1 -1
  33. package/dist/core/pipeline-definition.d.ts +26 -4
  34. package/dist/core/pipeline-definition.js.map +1 -1
  35. package/dist/core/pipeline-execute.d.ts +1 -2
  36. package/dist/core/pipeline-execute.js +80 -73
  37. package/dist/core/pipeline-execute.js.map +1 -1
  38. package/dist/core/pipeline-finalizer.d.ts +1 -1
  39. package/dist/core/pipeline-finalizer.js +1 -2
  40. package/dist/core/pipeline-finalizer.js.map +1 -1
  41. package/dist/core/pipeline-ids.js +1 -6
  42. package/dist/core/pipeline-ids.js.map +1 -1
  43. package/dist/core/pipeline-plan.js +2 -0
  44. package/dist/core/pipeline-plan.js.map +1 -1
  45. package/dist/core/pipeline-run-state.js +22 -4
  46. package/dist/core/pipeline-run-state.js.map +1 -1
  47. package/dist/core/pipeline-scheduler.d.ts +10 -0
  48. package/dist/core/pipeline-scheduler.js +54 -0
  49. package/dist/core/pipeline-scheduler.js.map +1 -0
  50. package/dist/core/pipeline-steps.d.ts +23 -18
  51. package/dist/core/pipeline-steps.js +5 -9
  52. package/dist/core/pipeline-steps.js.map +1 -1
  53. package/dist/core/pipeline-types.d.ts +71 -9
  54. package/dist/core/pipeline-types.js.map +1 -1
  55. package/dist/core/pipeline.d.ts +17 -6
  56. package/dist/core/pipeline.js +14 -3
  57. package/dist/core/pipeline.js.map +1 -1
  58. package/dist/node/checkpoint.d.ts +2 -0
  59. package/dist/node/checkpoint.js +1 -0
  60. package/dist/node/checkpoint.js.map +1 -1
  61. package/dist/node/env.d.ts +1 -0
  62. package/dist/node/env.js +1 -0
  63. package/dist/node/env.js.map +1 -1
  64. package/dist/node/file-utils.d.ts +3 -0
  65. package/dist/node/file-utils.js +3 -0
  66. package/dist/node/file-utils.js.map +1 -1
  67. package/dist/node/node.d.ts +2 -0
  68. package/dist/node/node.js +1 -0
  69. package/dist/node/node.js.map +1 -1
  70. package/dist/node/paths.d.ts +2 -1
  71. package/dist/node/paths.js +2 -1
  72. package/dist/node/paths.js.map +1 -1
  73. package/dist/node/worker-thread-adapter.d.ts +19 -0
  74. package/dist/node/worker-thread-adapter.js +194 -0
  75. package/dist/node/worker-thread-adapter.js.map +1 -0
  76. package/dist/node/worker-thread-protocol.d.ts +57 -0
  77. package/dist/node/worker-thread-protocol.js +26 -0
  78. package/dist/node/worker-thread-protocol.js.map +1 -0
  79. package/dist/node/worker-thread-runtime.js +53 -0
  80. package/dist/node/worker-thread-runtime.js.map +1 -0
  81. package/dist/project/pipeline-project.d.ts +37 -0
  82. package/dist/project/pipeline-project.js +90 -0
  83. package/dist/project/pipeline-project.js.map +1 -0
  84. package/dist/project/project-compiler.d.ts +26 -7
  85. package/dist/project/project-compiler.js +125 -15
  86. package/dist/project/project-compiler.js.map +1 -1
  87. package/dist/project/project-document.d.ts +32 -2
  88. package/dist/project/project-document.js +39 -4
  89. package/dist/project/project-document.js.map +1 -1
  90. package/dist/project/project.d.ts +2 -3
  91. package/dist/project/project.js +2 -3
  92. package/dist/project/project.js.map +1 -1
  93. package/dist/render/render.d.ts +3 -7
  94. package/dist/render/render.js +5 -2
  95. package/dist/render/render.js.map +1 -1
  96. package/dist/reporter/interactive-reporter.d.ts +5 -0
  97. package/dist/reporter/interactive-reporter.js +41 -38
  98. package/dist/reporter/interactive-reporter.js.map +1 -1
  99. package/dist/reporter/live-ticker-worker.js +58 -50
  100. package/dist/reporter/live-ticker-worker.js.map +1 -1
  101. package/dist/reporter/live-ticker.d.ts +6 -9
  102. package/dist/reporter/live-ticker.js +185 -190
  103. package/dist/reporter/live-ticker.js.map +1 -1
  104. package/dist/reporter/reporter.d.ts +5 -0
  105. package/dist/reporter/reporter.js +27 -17
  106. package/dist/reporter/reporter.js.map +1 -1
  107. package/dist/reporter/terminal-text.d.ts +2 -0
  108. package/dist/reporter/terminal-text.js +20 -0
  109. package/dist/reporter/terminal-text.js.map +1 -0
  110. package/dist/run-store/definition-diff.d.ts +9 -0
  111. package/dist/run-store/definition-diff.js +39 -0
  112. package/dist/run-store/definition-diff.js.map +1 -0
  113. package/dist/run-store/run-store-codec.d.ts +2 -2
  114. package/dist/run-store/run-store-codec.js +14 -14
  115. package/dist/run-store/run-store-codec.js.map +1 -1
  116. package/dist/run-store/run-store-event-decoder.d.ts +3 -0
  117. package/dist/run-store/run-store-event-decoder.js +18 -0
  118. package/dist/run-store/run-store-event-decoder.js.map +1 -0
  119. package/dist/run-store/run-store-ndjson.js +2 -2
  120. package/dist/run-store/run-store-ndjson.js.map +1 -1
  121. package/dist/run-store/run-store-sqlite.js +3 -3
  122. package/dist/run-store/run-store-sqlite.js.map +1 -1
  123. package/dist/run-store/run-store.d.ts +4 -1
  124. package/dist/run-store/run-store.js +23 -9
  125. package/dist/run-store/run-store.js.map +1 -1
  126. package/dist/studio/run-store-ui-client-browser.js +2 -2
  127. package/dist/studio/run-store-ui-client-transport.d.ts +7 -1
  128. package/dist/studio/run-store-ui-client-transport.js +9 -6
  129. package/dist/studio/run-store-ui-client-transport.js.map +1 -1
  130. package/dist/studio/run-store-ui-client.d.ts +68 -1
  131. package/dist/studio/run-store-ui-client.js +764 -3
  132. package/dist/studio/run-store-ui-client.js.map +1 -1
  133. package/dist/studio/run-store-ui-data-controller.d.ts +24 -0
  134. package/dist/studio/run-store-ui-data-controller.js +238 -0
  135. package/dist/studio/run-store-ui-data-controller.js.map +1 -0
  136. package/dist/studio/run-store-ui-definitions.d.ts +6 -0
  137. package/dist/studio/run-store-ui-definitions.js +29 -0
  138. package/dist/studio/run-store-ui-definitions.js.map +1 -0
  139. package/dist/studio/run-store-ui-page.d.ts +1 -1
  140. package/dist/studio/run-store-ui-page.js +6 -1
  141. package/dist/studio/run-store-ui-page.js.map +1 -1
  142. package/dist/studio/run-store-ui.js +1 -1
  143. package/dist/studio/run-store-ui.js.map +1 -1
  144. package/dist/testing/testing.d.ts +2 -0
  145. package/dist/testing/testing.js.map +1 -1
  146. package/dist/tracing/tracing-internal.js +18 -3
  147. package/dist/tracing/tracing-internal.js.map +1 -1
  148. package/dist/tracing/tracing-schema.d.ts +167 -12
  149. package/dist/tracing/tracing-schema.js +57 -1
  150. package/dist/tracing/tracing-schema.js.map +1 -1
  151. package/dist/utilities/batch.d.ts +4 -1
  152. package/dist/utilities/batch.js +3 -1
  153. package/dist/utilities/batch.js.map +1 -1
  154. package/dist/utilities/pipeline-command-marker.d.ts +4 -0
  155. package/dist/utilities/pipeline-command-marker.js +16 -0
  156. package/dist/utilities/pipeline-command-marker.js.map +1 -0
  157. package/dist/utilities/rate-limit.d.ts +1 -0
  158. package/dist/utilities/rate-limit.js +1 -0
  159. package/dist/utilities/rate-limit.js.map +1 -1
  160. package/dist/utilities/retry.d.ts +3 -1
  161. package/dist/utilities/retry.js +1 -0
  162. package/dist/utilities/retry.js.map +1 -1
  163. package/dist/workbench/pipeline-module.d.ts +1 -0
  164. package/dist/workbench/pipeline-module.js +5 -5
  165. package/dist/workbench/pipeline-module.js.map +1 -1
  166. package/dist/workbench/workbench-bin.d.ts +2 -6
  167. package/dist/workbench/workbench-bin.js +8 -20
  168. package/dist/workbench/workbench-bin.js.map +1 -1
  169. package/dist/workbench/workbench-commands.d.ts +6 -0
  170. package/dist/workbench/workbench-commands.js +288 -0
  171. package/dist/workbench/workbench-commands.js.map +1 -0
  172. package/dist/workbench/workbench-history.js +1 -1
  173. package/dist/workbench/workbench-history.js.map +1 -1
  174. package/dist/workbench/workbench-launch-session.d.ts +25 -0
  175. package/dist/workbench/workbench-launch-session.js +91 -0
  176. package/dist/workbench/workbench-launch-session.js.map +1 -0
  177. package/dist/workbench/workbench-project-loader.d.ts +28 -26
  178. package/dist/workbench/workbench-project-loader.js +94 -86
  179. package/dist/workbench/workbench-project-loader.js.map +1 -1
  180. package/dist/workbench/workbench-run.js +7 -4
  181. package/dist/workbench/workbench-run.js.map +1 -1
  182. package/dist/workbench/workbench-shared.d.ts +4 -15
  183. package/dist/workbench/workbench-shared.js +12 -43
  184. package/dist/workbench/workbench-shared.js.map +1 -1
  185. package/dist/workbench/workbench-ui.js +45 -148
  186. package/dist/workbench/workbench-ui.js.map +1 -1
  187. package/dist/workbench/workbench.d.ts +1 -1
  188. package/dist/workbench/workbench.js +4 -8
  189. package/dist/workbench/workbench.js.map +1 -1
  190. package/docs/README.md +23 -23
  191. package/docs/agent-guide.md +107 -30
  192. package/docs/agent-skills.md +1 -1
  193. package/docs/api-reference.md +156 -151
  194. package/docs/api-report.json +20 -35
  195. package/docs/assets/social.svg +192 -56
  196. package/docs/child-pipeline-composition.md +17 -12
  197. package/docs/cli.md +243 -81
  198. package/docs/comparison.md +21 -29
  199. package/docs/concepts.md +112 -17
  200. package/docs/declarative-pipelines.md +128 -51
  201. package/docs/getting-started.md +97 -20
  202. package/docs/llms.txt +8 -7
  203. package/docs/pipeline-document.schema.json +53 -2
  204. package/docs/recipes.md +65 -36
  205. package/docs/remote-step-composition.md +81 -1
  206. package/docs/studio.md +115 -31
  207. package/examples/automatic-cli.ts +12 -0
  208. package/examples/child-pipeline.ts +0 -9
  209. package/examples/cli-job.ts +2 -14
  210. package/examples/declarative/handlers.ts +49 -6
  211. package/examples/declarative/peloton-handlers.ts +2 -2
  212. package/examples/declarative/pipelines.yaml +29 -7
  213. package/examples/live-tui.ts +4 -1
  214. package/examples/minimal-pipeline.ts +24 -0
  215. package/examples/parallel-dag.ts +46 -0
  216. package/examples/prime-worker.ts +22 -0
  217. package/examples/{catalog → project}/pipelines/enrich.ts +2 -2
  218. package/examples/{catalog → project}/scripts/enrich.ts +1 -0
  219. package/examples/{catalog → project}/scripts/import.ts +1 -0
  220. package/examples/{catalog → project}/scripts/publish.ts +1 -0
  221. package/examples/project/tubeless.project.ts +47 -0
  222. package/examples/tracing.ts +3 -0
  223. package/examples/tubeless.project.ts +9 -0
  224. package/examples/typed-import.ts +0 -10
  225. package/examples/validated-boundaries.ts +8 -12
  226. package/examples/worker-threads.ts +50 -0
  227. package/examples/yaml-peloton.ts +3 -3
  228. package/examples/yaml-pipelines.ts +7 -5
  229. package/package.json +6 -11
  230. package/skills/tubeless/SKILL.md +56 -17
  231. package/skills/tubeless-make-pipeline/SKILL.md +1 -1
  232. package/dist/cli/pipeline-command-marker.d.ts +0 -4
  233. package/dist/cli/pipeline-command-marker.js +0 -21
  234. package/dist/cli/pipeline-command-marker.js.map +0 -1
  235. package/dist/project/project-manifest.d.ts +0 -27
  236. package/dist/project/project-manifest.js +0 -66
  237. package/dist/project/project-manifest.js.map +0 -1
  238. package/dist/reporter/live-ticker-supervisor.js +0 -44
  239. package/dist/reporter/live-ticker-supervisor.js.map +0 -1
  240. package/dist/studio/run-store-ui-client-app.d.ts +0 -12
  241. package/dist/studio/run-store-ui-client-app.js +0 -224
  242. package/dist/studio/run-store-ui-client-app.js.map +0 -1
  243. package/dist/studio/run-store-ui-client-commands.d.ts +0 -18
  244. package/dist/studio/run-store-ui-client-commands.js +0 -98
  245. package/dist/studio/run-store-ui-client-commands.js.map +0 -1
  246. package/dist/studio/run-store-ui-client-form.d.ts +0 -11
  247. package/dist/studio/run-store-ui-client-form.js +0 -54
  248. package/dist/studio/run-store-ui-client-form.js.map +0 -1
  249. package/dist/studio/run-store-ui-client-modals.d.ts +0 -20
  250. package/dist/studio/run-store-ui-client-modals.js +0 -154
  251. package/dist/studio/run-store-ui-client-modals.js.map +0 -1
  252. package/dist/studio/run-store-ui-client-model.d.ts +0 -19
  253. package/dist/studio/run-store-ui-client-model.js +0 -189
  254. package/dist/studio/run-store-ui-client-model.js.map +0 -1
  255. package/dist/studio/run-store-ui-client-runs.d.ts +0 -24
  256. package/dist/studio/run-store-ui-client-runs.js +0 -78
  257. package/dist/studio/run-store-ui-client-runs.js.map +0 -1
  258. package/dist/studio/run-store-ui-client-shared.d.ts +0 -22
  259. package/dist/studio/run-store-ui-client-shared.js +0 -63
  260. package/dist/studio/run-store-ui-client-shared.js.map +0 -1
  261. package/dist/workbench/workbench-graph.d.ts +0 -2
  262. package/dist/workbench/workbench-graph.js +0 -64
  263. package/dist/workbench/workbench-graph.js.map +0 -1
  264. package/dist/workbench/workbench-inspect.d.ts +0 -2
  265. package/dist/workbench/workbench-inspect.js +0 -70
  266. package/dist/workbench/workbench-inspect.js.map +0 -1
  267. package/dist/workbench/workbench-list.d.ts +0 -2
  268. package/dist/workbench/workbench-list.js +0 -53
  269. package/dist/workbench/workbench-list.js.map +0 -1
  270. package/dist/workbench/workbench-plan.d.ts +0 -2
  271. package/dist/workbench/workbench-plan.js +0 -67
  272. package/dist/workbench/workbench-plan.js.map +0 -1
  273. package/dist/workbench/workbench-trampoline.d.ts +0 -71
  274. package/dist/workbench/workbench-trampoline.js +0 -136
  275. package/dist/workbench/workbench-trampoline.js.map +0 -1
  276. package/dist/workbench/workbench-validate.d.ts +0 -2
  277. package/dist/workbench/workbench-validate.js +0 -76
  278. package/dist/workbench/workbench-validate.js.map +0 -1
  279. package/examples/catalog/tubeless.project.ts +0 -74
  280. /package/dist/{reporter/live-ticker-supervisor.d.ts → node/worker-thread-runtime.d.ts} +0 -0
  281. /package/examples/{catalog → project}/pipelines/import.ts +0 -0
  282. /package/examples/{catalog → project}/pipelines/normalize.ts +0 -0
  283. /package/examples/{catalog → project}/pipelines/publish.ts +0 -0
package/README.md CHANGED
@@ -11,11 +11,13 @@
11
11
  <a href="https://www.npmjs.com/package/tubeless"><img alt="npm" src="https://img.shields.io/npm/v/tubeless?style=flat-square&labelColor=121212&color=c4a046"></a>
12
12
  <a href="https://github.com/chetmancini/tubeless/actions/workflows/check.yml"><img alt="check" src="https://img.shields.io/github/actions/workflow/status/chetmancini/tubeless/check.yml?style=flat-square&label=check&labelColor=121212&color=2f6f4a"></a>
13
13
  <a href="./LICENSE"><img alt="MIT" src="https://img.shields.io/npm/l/tubeless?style=flat-square&labelColor=121212&color=c4c0b4"></a>
14
+ <a href="./docs/getting-started.md#install"><img alt="Node" src="https://img.shields.io/node/v/tubeless?style=flat-square&labelColor=121212&color=c4c0b4"></a> <a href="https://www.npmjs.com/package/tubeless"><img alt="provenance" src="https://img.shields.io/badge/provenance-npm-2f6f4a?style=flat-square&labelColor=121212"></a>
14
15
  </p>
15
16
 
16
17
  Tubeless is a TypeScript toolkit for work that unfolds in steps. It fits data
17
18
  pipelines, multi-step application workflows, and AI workloads—anywhere you want
18
- explicit dependencies, typed handoffs, and inspectable execution.
19
+ explicit dependencies, typed handoffs, and inspectable execution. The name is the
20
+ cycling kind of tubeless: no inner tube, and no extra runtime to keep the work rolling.
19
21
 
20
22
  Pipelines run in your process with no runtime dependencies. You can preview
21
23
  execution, select a target and its dependencies, compose child pipelines, and
@@ -36,11 +38,10 @@ Tubeless is pre-1.0, so the public API may change between releases.
36
38
 
37
39
  ## Quick start
38
40
 
39
- This pipeline loads and normalizes strings. `step` creates a step; dependencies give typed
40
- inputs. Adding `skip` makes it skippable and widens its output to include `undefined`.
41
+ This pipeline loads and normalizes strings. `step` creates a step; dependencies give typed inputs.
41
42
 
42
43
  ```ts
43
- import { createSteps, definePipeline, requireOutputs } from "tubeless";
44
+ import { createSteps, definePipeline } from "tubeless";
44
45
 
45
46
  interface ImportOptions {
46
47
  lines: readonly string[];
@@ -60,33 +61,33 @@ const normalize = step("normalize", {
60
61
  export const ImportPipeline = definePipeline({
61
62
  id: "import",
62
63
  steps: [load, normalize],
63
- targets: [normalize],
64
- finalize: requireOutputs([normalize], ({ normalize }) => normalize),
65
64
  });
66
65
 
67
66
  const rows = await ImportPipeline.runOrThrow({ lines: [" Alpha ", "", "Beta"] });
68
67
  // ["alpha", "beta"]
69
68
  ```
70
69
 
71
- `runOrThrow` returns the result or throws if the run fails. Use `run` for a
72
- report with step statuses, errors, and timings; `plan` to preview execution; or
73
- `toMermaid` to draw the graph. See the [getting started guide](./docs/getting-started.md).
70
+ Omitted `targets` and `finalize` use the last step in execution order: `normalize`.
71
+ Missing output returns `undefined`; use `requireOutputs` when absence should fail.
72
+
73
+ `runOrThrow` returns the result or throws on failure. Use `run` for reports, `plan`
74
+ for previews, and `toMermaid` for diagrams. See [getting started](./docs/getting-started.md).
74
75
 
75
76
  ## Use the CLI
76
77
 
77
- Define commands with `tubeless/cli` and catalogs with `tubeless/project`.
78
- The [CLI guide](./docs/cli.md) explains how to set up the manifest and commands.
79
- With an `import-rows` command registered, you can run:
78
+ Projects made with `defineProject(id, pipelines)` are directly usable by the CLI;
79
+ schema-backed pipelines get inferred flags automatically. See the [CLI guide](./docs/cli.md)
80
+ for direct project usage and advanced custom command adapters. From this repository:
80
81
 
81
82
  ```sh
82
- bunx tubeless list # reads ./tubeless.project.ts
83
- bunx tubeless inspect import-rows
84
- bunx tubeless run import-rows -- --source input.json
83
+ bunx tubeless list --project examples/tubeless.project.ts
84
+ bunx tubeless inspect --project examples/tubeless.project.ts validated-import
85
+ bunx tubeless run --project examples/tubeless.project.ts validated-import -- --source rows.txt
85
86
  ```
86
87
 
87
- The CLI loads TypeScript modules with Bun. Pass application flags after `--`.
88
- Record runs with `--store` or save a portable trace with `--trace`, then inspect
89
- them with `tubeless history` or the [local studio](./docs/studio.md).
88
+ In your app, add `tubeless.project.ts` and omit `--project`. Pass application
89
+ flags after `--`. Record runs with `--store` or `--trace`, then inspect them with
90
+ `tubeless history` or the [local studio](./docs/studio.md).
90
91
 
91
92
  ## Find your route
92
93
 
@@ -94,8 +95,7 @@ them with `tubeless history` or the [local studio](./docs/studio.md).
94
95
  [dry runs and write gates](./examples/publish-with-gates.ts) to a publishing job.
95
96
  - Build a larger workflow with [child pipelines](./examples/child-pipeline.ts)
96
97
  and [fan-out](./examples/fan-out-progress.ts).
97
- - Take the [peloton example](./examples/peloton.ts) for a spin: a road-race weekend
98
- workflow that brings several pipeline features together.
98
+ - Optional: the [peloton example](./examples/peloton.ts) is a cycling-themed kitchen sink for the live TUI.
99
99
 
100
100
  The [recipe index](./docs/recipes.md) covers validation, retries, tracing, testing,
101
101
  and more. For help authoring pipelines with a coding agent, install the
@@ -2,4 +2,5 @@ import { type CliCommand, type CliCommandConfig, type CliParamsSchema } from "./
2
2
  export declare function createCommand<const TSchema extends CliParamsSchema, TResult = void>(config: CliCommandConfig<TSchema, TResult>, mainExits?: {
3
3
  validation?: number;
4
4
  }): CliCommand<TSchema, TResult>;
5
+ /** Create a typed command from a declarative parameter schema and run handler. */
5
6
  export declare function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(config: CliCommandConfig<TSchema, TResult>): CliCommand<TSchema, TResult>;
@@ -8,6 +8,7 @@ function resolveContext(overrides) {
8
8
  cwd: overrides?.cwd ?? process.cwd(),
9
9
  env: overrides?.env ?? process.env,
10
10
  log: overrides?.log ?? console,
11
+ reporterOutput: overrides?.reporterOutput,
11
12
  pipelineContext: overrides?.pipelineContext,
12
13
  signal: overrides?.signal,
13
14
  checkpoint: overrides?.checkpoint,
@@ -291,6 +292,7 @@ function normalizeStructuredValue(key, param, value, errors) {
291
292
  }
292
293
  return value;
293
294
  }
295
+ /** Create a typed command from a declarative parameter schema and run handler. */
294
296
  export function defineCommand(config) {
295
297
  return createCommand(config);
296
298
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cli-command.js","sourceRoot":"","sources":["../../src/cli/cli-command.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\";\nimport { openCheckpoint, type CheckpointStore } from \"../node/checkpoint.js\";\nimport {\n assertNoDuplicateFlags,\n assertValidEnvironmentFallbacks,\n assertValidMultipleParams,\n assertValidPositionals,\n buildEffectiveSchema,\n commandDescriptor,\n renderHelp,\n resolveParam,\n tokenize,\n type ResolvedParamValue,\n} from \"./cli-parser.js\";\nimport {\n CliHelpRequested,\n CliValidationError,\n type CliCommand,\n type CliCommandConfig,\n type CliContext,\n type CliParams,\n type CliParamsSchema,\n type CliParseResult,\n} from \"./cli-types.js\";\nimport { isCliValidationError, isPipelineExecutionError, toExitCode } from \"./cli-exit.js\";\n\nfunction resolveContext(overrides?: Partial<CliContext>): CliContext {\n return {\n cwd: overrides?.cwd ?? process.cwd(),\n env: overrides?.env ?? process.env,\n log: overrides?.log ?? console,\n pipelineContext: overrides?.pipelineContext,\n signal: overrides?.signal,\n checkpoint: overrides?.checkpoint,\n };\n}\n\ninterface ManagedMainSignal {\n context: CliContext;\n wasInterrupted(): boolean;\n cleanup(): void;\n}\n\nconst SIGINT_EXIT_CODE = 130;\n\n/**\n * Give real CLI entrypoints graceful cancellation without making `run()` or\n * `parse()` mutate process-global signal handlers. Embedded callers can pass\n * their own signal through the context instead.\n */\nfunction manageMainSignal(context: CliContext): ManagedMainSignal {\n if (context.signal) {\n return { context, wasInterrupted: () => false, cleanup: () => {} };\n }\n\n const controller = new AbortController();\n let interrupted = false;\n const onSigint = (): void => {\n interrupted = true;\n context.log.warn(\"SIGINT received; cancelling pipeline work.\");\n controller.abort();\n };\n process.once(\"SIGINT\", onSigint);\n\n return {\n context: { ...context, signal: controller.signal },\n wasInterrupted: () => interrupted,\n cleanup: () => process.removeListener(\"SIGINT\", onSigint),\n };\n}\n\n/**\n * An in-memory-only `CheckpointStore` seeded from `seed`: reads and `record()` behave\n * exactly like a real store for the rest of this run, but `flush()`/`clear()` never touch\n * disk. Every dry-run path hands `run` one of these instead of the real store — the\n * managed-checkpoint contract is that a dry run never writes to the checkpoint file, no\n * matter what `run` does with `context.checkpoint` (`record`/`flush`/`clear`, directly or\n * via `withCheckpointedBatch`).\n */\nfunction inMemoryCheckpointView(seed: ReadonlyMap<string, unknown>): CheckpointStore {\n const entries = new Map(seed);\n return {\n has: (key) => entries.has(key),\n record: (key, meta) => {\n entries.set(key, meta);\n },\n entries: () => entries,\n flush: () => {},\n clear: () => {\n entries.clear();\n },\n };\n}\n\nexport function createCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>,\n mainExits?: { validation?: number }\n): CliCommand<TSchema, TResult> {\n const effectiveParams = buildEffectiveSchema(config.params, config.checkpoint);\n assertNoDuplicateFlags(effectiveParams);\n assertValidMultipleParams(effectiveParams);\n assertValidEnvironmentFallbacks(effectiveParams);\n const positionals = [...(config.positionals ?? [])];\n assertValidPositionals(positionals, effectiveParams);\n const descriptor = commandDescriptor(config, effectiveParams, positionals);\n\n function resolveValues(\n readValue: (\n key: string,\n param: CliParamsSchema[string]\n ) => string | boolean | string[] | undefined,\n context: CliContext,\n errors: string[],\n helpText: string\n ): CliParseResult<TSchema> {\n const values: Record<string, ResolvedParamValue> = {};\n for (const [key, param] of Object.entries(effectiveParams)) {\n const errorCount = errors.length;\n const raw = readValue(key, param);\n if (errors.length > errorCount) continue;\n const envValue = raw === undefined && param.env ? context.env?.[param.env] : undefined;\n values[key] = resolveParam(\n key,\n param,\n raw ?? envValue,\n context.cwd,\n errors,\n raw !== undefined ? \"argv\" : envValue !== undefined ? \"env\" : \"default\"\n );\n }\n if (errors.length > 0) return { kind: \"error\", errors, helpText };\n // SAFETY: resolveParam populated every effective schema key and all input checks passed.\n const typedValues = values as CliParams<TSchema>;\n const validationErrors = config.validate?.(typedValues, context) ?? [];\n return validationErrors.length > 0\n ? { kind: \"error\", errors: validationErrors, helpText }\n : { kind: \"values\", values: typedValues };\n }\n\n function parseWithContext(argv: readonly string[], context: CliContext): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const tokenized = tokenize(argv, effectiveParams, positionals);\n if (tokenized.help) return { kind: \"help\", helpText };\n return resolveValues(\n (key) => tokenized.values.get(key),\n context,\n [...tokenized.errors],\n helpText\n );\n }\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n return parseWithContext(argv, resolveContext(contextOverrides));\n }\n\n function parseStructuredWithContext(\n structuredValues: Record<string, unknown>,\n context: CliContext\n ): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const errors: string[] = [];\n for (const key of Object.keys(structuredValues)) {\n if (!Object.prototype.hasOwnProperty.call(effectiveParams, key)) {\n errors.push(`Unknown parameter: ${key}`);\n }\n }\n return resolveValues(\n (key, param) => normalizeStructuredValue(key, param, structuredValues[key], errors),\n context,\n errors,\n helpText\n );\n }\n\n /**\n * No-op unless `config.checkpoint` is set. Respects a caller-provided `context.checkpoint`\n * override (e.g. a stub in tests) instead of opening the real file. Otherwise opens (or\n * clears, if not resuming) the checkpoint before `run` is called — never on the `--help`/\n * error paths, since those return before this is reached.\n */\n function attachCheckpoint(context: CliContext, values: CliParams<TSchema>): CliContext {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig) {\n return context;\n }\n const resolvedPath = path.isAbsolute(checkpointConfig.path)\n ? checkpointConfig.path\n : path.join(context.cwd, checkpointConfig.path);\n // A caller-provided context.checkpoint (e.g. a stub in tests) is used as the\n // underlying store instead of opening the real file, but every rule below — fresh\n // clearing, dry-run wrapping, resume detection/logging — still applies to it; only\n // the \"where does the store come from\" step is skipped.\n const store = context.checkpoint ?? openCheckpoint(resolvedPath);\n const hadExisting = store.entries().size > 0;\n\n if (values.resume) {\n if (hadExisting) {\n context.log.log(\n `Resuming from checkpoint: ${store.entries().size} item(s) already recorded.`\n );\n } else {\n // Without this, --resume against a missing/wrong-path/already-cleared checkpoint\n // silently starts fresh — the exact failure mode that's dangerous for\n // clearOnSuccess: false workflows, where \"fresh\" quietly means \"reprocess\n // everything already done\".\n context.log.warn(\n `--resume was passed, but no checkpoint was found at ${resolvedPath}; starting fresh.`\n );\n }\n // A dry run must never write to the checkpoint file, even while resuming — an\n // in-memory view seeded with the real entries previews it accurately without risk.\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (!hadExisting) {\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (values.dryRun) {\n // Dry run must not touch the file — neither clearing it nor writing new progress —\n // but the preview should still reflect what a real fresh run would see: an empty\n // \"done\" set, not the stale entries a --resume invocation would use.\n context.log.log(\"Dry run: leaving existing checkpoint untouched (would start fresh).\");\n return { ...context, checkpoint: inMemoryCheckpointView(new Map()) };\n }\n\n store.clear();\n context.log.log(\"Starting fresh — cleared existing checkpoint.\");\n return { ...context, checkpoint: store };\n }\n\n /**\n * No-op unless `config.checkpoint` is set, a store is attached, and the run completed\n * without a dry run or caller cancellation.\n */\n function finalizeCheckpoint(context: CliContext, values: CliParams<TSchema>): void {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig || !context.checkpoint || values.dryRun || context.signal?.aborted) {\n return;\n }\n if (checkpointConfig.clearOnSuccess === false) {\n return;\n }\n context.checkpoint.clear();\n }\n\n async function executeValues(values: CliParams<TSchema>, context: CliContext): Promise<TResult> {\n const runContext = attachCheckpoint(context, values);\n const value = await config.run(values, runContext);\n finalizeCheckpoint(runContext, values);\n return value;\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n const context = resolveContext(contextOverrides);\n return parseStructuredWithContext(values, context);\n }\n\n async function execute(\n values: CliParams<TSchema>,\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n return executeValues(values, resolveContext(contextOverrides));\n }\n\n async function run(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n const context = resolveContext(contextOverrides);\n const result = parseWithContext(argv, context);\n if (result.kind === \"help\") throw new CliHelpRequested(result.helpText);\n if (result.kind === \"error\") throw new CliValidationError(result.errors, result.helpText);\n return executeValues(result.values, context);\n }\n\n async function main(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<void> {\n const context = resolveContext(contextOverrides);\n let result: CliParseResult<TSchema>;\n try {\n result = parseWithContext(argv, context);\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode =\n mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n return;\n }\n if (result.kind === \"help\") {\n context.log.log(result.helpText);\n process.exitCode = 0;\n return;\n }\n if (result.kind === \"error\") {\n for (const error of result.errors) {\n context.log.error(`Error: ${error}`);\n }\n context.log.error(\"\");\n context.log.error(result.helpText);\n process.exitCode = mainExits?.validation ?? 1;\n return;\n }\n const managedSignal = manageMainSignal(context);\n try {\n const runContext = attachCheckpoint(managedSignal.context, result.values);\n await config.run(result.values, runContext);\n if (!managedSignal.wasInterrupted()) {\n finalizeCheckpoint(runContext, result.values);\n }\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode = managedSignal.wasInterrupted()\n ? SIGINT_EXIT_CODE\n : mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n } finally {\n if (managedSignal.wasInterrupted()) {\n process.exitCode = SIGINT_EXIT_CODE;\n }\n managedSignal.cleanup();\n }\n }\n\n return { descriptor, execute, parse, parseValues, run, main };\n}\n\nfunction normalizeStructuredValue(\n key: string,\n param: CliParamsSchema[string],\n value: unknown,\n errors: string[]\n): string | boolean | string[] | undefined {\n if (value === undefined) return undefined;\n const label = `--${param.flag ?? key}`;\n if (param.type === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n errors.push(`${label} must be a boolean value.`);\n return undefined;\n }\n if ((param.type === \"number\" || param.type === \"string\") && param.multiple === true) {\n if (!Array.isArray(value)) {\n errors.push(`${label} must be an array.`);\n return undefined;\n }\n if (param.type === \"number\") {\n if (!value.every((item) => typeof item === \"number\" && Number.isFinite(item))) {\n errors.push(`${label} must contain only finite numbers.`);\n return undefined;\n }\n return value.map(String);\n }\n if (!value.every((item) => typeof item === \"string\")) {\n errors.push(`${label} must contain only strings.`);\n return undefined;\n }\n return [...value];\n }\n if (param.type === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n errors.push(`${label} must be a finite number.`);\n return undefined;\n }\n return String(value);\n }\n if (typeof value !== \"string\") {\n errors.push(`${label} must be a string value.`);\n return undefined;\n }\n return value;\n}\n\nexport function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>\n): CliCommand<TSchema, TResult> {\n return createCommand(config);\n}\n"]}
1
+ {"version":3,"file":"cli-command.js","sourceRoot":"","sources":["../../src/cli/cli-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAwB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,QAAQ,GAET,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,GAOnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3F,SAAS,cAAc,CAAC,SAA+B;IACrD,OAAO;QACL,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACpC,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG;QAClC,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,OAAO;QAC9B,cAAc,EAAE,SAAS,EAAE,cAAc;QACzC,eAAe,EAAE,SAAS,EAAE,eAAe;QAC3C,MAAM,EAAE,SAAS,EAAE,MAAM;QACzB,UAAU,EAAE,SAAS,EAAE,UAAU;KAClC,CAAC;AACJ,CAAC;AAQD,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,OAAmB;IAC3C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,WAAW,GAAG,IAAI,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC/D,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEjC,OAAO;QACL,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE;QAClD,cAAc,EAAE,GAAG,EAAE,CAAC,WAAW;QACjC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAAC,IAAkC;IAChE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO;QACL,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QAC9B,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;QACtB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;QACf,KAAK,EAAE,GAAG,EAAE;YACV,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,MAA0C,EAC1C,SAAmC;IAEnC,MAAM,eAAe,GAAG,oBAAoB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/E,sBAAsB,CAAC,eAAe,CAAC,CAAC;IACxC,yBAAyB,CAAC,eAAe,CAAC,CAAC;IAC3C,+BAA+B,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,sBAAsB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;IAE3E,SAAS,aAAa,CACpB,SAG4C,EAC5C,OAAmB,EACnB,MAAgB,EAChB,QAAgB;QAEhB,MAAM,MAAM,GAAuC,EAAE,CAAC;QACtD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;YACjC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,MAAM,CAAC,MAAM,GAAG,UAAU;gBAAE,SAAS;YACzC,MAAM,QAAQ,GAAG,GAAG,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACvF,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CACxB,GAAG,EACH,KAAK,EACL,GAAG,IAAI,QAAQ,EACf,OAAO,CAAC,GAAG,EACX,MAAM,EACN,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CACxE,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAClE,yFAAyF;QACzF,MAAM,WAAW,GAAG,MAA4B,CAAC;QACjD,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACvE,OAAO,gBAAgB,CAAC,MAAM,GAAG,CAAC;YAChC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE;YACvD,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAC9C,CAAC;IAED,SAAS,gBAAgB,CAAC,IAAuB,EAAE,OAAmB;QACpE,MAAM,QAAQ,GAAG,UAAU,CACzB,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,WAAW,EACtB,eAAe,EACf,WAAW,CACZ,CAAC;QACF,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;QAC/D,IAAI,SAAS,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACtD,OAAO,aAAa,CAClB,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAClC,OAAO,EACP,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EACrB,QAAQ,CACT,CAAC;IACJ,CAAC;IAED,SAAS,KAAK,CACZ,IAAI,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAC/C,gBAAsC;QAEtC,OAAO,gBAAgB,CAAC,IAAI,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,SAAS,0BAA0B,CACjC,gBAAyC,EACzC,OAAmB;QAEnB,MAAM,QAAQ,GAAG,UAAU,CACzB,UAAU,CAAC,IAAI,EACf,UAAU,CAAC,WAAW,EACtB,eAAe,EACf,WAAW,CACZ,CAAC;QACF,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,CAAC,EAAE,CAAC;gBAChE,MAAM,CAAC,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,OAAO,aAAa,CAClB,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,wBAAwB,CAAC,GAAG,EAAE,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EACnF,OAAO,EACP,MAAM,EACN,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,SAAS,gBAAgB,CAAC,OAAmB,EAAE,MAA0B;QACvE,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC;QAC3C,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACzD,CAAC,CAAC,gBAAgB,CAAC,IAAI;YACvB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAClD,6EAA6E;QAC7E,kFAAkF;QAClF,mFAAmF;QACnF,wDAAwD;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,IAAI,cAAc,CAAC,YAAY,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC;QAE7C,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,GAAG,CACb,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,4BAA4B,CAC9E,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,iFAAiF;gBACjF,sEAAsE;gBACtE,0EAA0E;gBAC1E,4BAA4B;gBAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,uDAAuD,YAAY,mBAAmB,CACvF,CAAC;YACJ,CAAC;YACD,8EAA8E;YAC9E,mFAAmF;YACnF,OAAO;gBACL,GAAG,OAAO;gBACV,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;aAC5E,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;gBACL,GAAG,OAAO;gBACV,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK;aAC5E,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,mFAAmF;YACnF,iFAAiF;YACjF,qEAAqE;YACrE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;YACvF,OAAO,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,sBAAsB,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC;QACvE,CAAC;QAED,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QACjE,OAAO,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,SAAS,kBAAkB,CAAC,OAAmB,EAAE,MAA0B;QACzE,MAAM,gBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC;QAC3C,IAAI,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACzF,OAAO;QACT,CAAC;QACD,IAAI,gBAAgB,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,OAAO,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,UAAU,aAAa,CAAC,MAA0B,EAAE,OAAmB;QAC1E,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACnD,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,WAAW,CAClB,MAA+B,EAC/B,gBAAsC;QAEtC,MAAM,OAAO,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;QACjD,OAAO,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,UAAU,OAAO,CACpB,MAA0B,EAC1B,gBAAsC;QAEtC,OAAO,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,UAAU,GAAG,CAChB,IAAI,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAC/C,gBAAsC;QAEtC,MAAM,OAAO,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC/C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,IAAI,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1F,OAAO,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,UAAU,IAAI,CACjB,IAAI,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAC/C,gBAAsC;QAEtC,MAAM,OAAO,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;QACjD,IAAI,MAA+B,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3F,OAAO,CAAC,QAAQ;gBACd,SAAS,IAAI,oBAAoB,CAAC,KAAK,CAAC,IAAI,wBAAwB,CAAC,KAAK,CAAC;oBACzE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;oBACnB,CAAC,CAAC,CAAC,CAAC;YACR,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,CAAC,QAAQ,GAAG,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,gBAAgB,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1E,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC5C,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,EAAE,CAAC;gBACpC,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3F,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,cAAc,EAAE;gBAC/C,CAAC,CAAC,gBAAgB;gBAClB,CAAC,CAAC,SAAS,IAAI,oBAAoB,CAAC,KAAK,CAAC,IAAI,wBAAwB,CAAC,KAAK,CAAC;oBAC3E,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC;oBACnB,CAAC,CAAC,CAAC,CAAC;QACV,CAAC;gBAAS,CAAC;YACT,IAAI,aAAa,CAAC,cAAc,EAAE,EAAE,CAAC;gBACnC,OAAO,CAAC,QAAQ,GAAG,gBAAgB,CAAC;YACtC,CAAC;YACD,aAAa,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,wBAAwB,CAC/B,GAAW,EACX,KAA8B,EAC9B,KAAc,EACd,MAAgB;IAEhB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,KAAK,GAAG,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;IACvC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,OAAO,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,2BAA2B,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,CAAC,CAAC;YAC1C,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC9E,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,oCAAoC,CAAC,CAAC;gBAC1D,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,6BAA6B,CAAC,CAAC;YACnD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,2BAA2B,CAAC,CAAC;YACjD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,0BAA0B,CAAC,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAC3B,MAA0C;IAE1C,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC","sourcesContent":["import * as path from \"path\";\nimport { openCheckpoint, type CheckpointStore } from \"../node/checkpoint.js\";\nimport {\n assertNoDuplicateFlags,\n assertValidEnvironmentFallbacks,\n assertValidMultipleParams,\n assertValidPositionals,\n buildEffectiveSchema,\n commandDescriptor,\n renderHelp,\n resolveParam,\n tokenize,\n type ResolvedParamValue,\n} from \"./cli-parser.js\";\nimport {\n CliHelpRequested,\n CliValidationError,\n type CliCommand,\n type CliCommandConfig,\n type CliContext,\n type CliParams,\n type CliParamsSchema,\n type CliParseResult,\n} from \"./cli-types.js\";\nimport { isCliValidationError, isPipelineExecutionError, toExitCode } from \"./cli-exit.js\";\n\nfunction resolveContext(overrides?: Partial<CliContext>): CliContext {\n return {\n cwd: overrides?.cwd ?? process.cwd(),\n env: overrides?.env ?? process.env,\n log: overrides?.log ?? console,\n reporterOutput: overrides?.reporterOutput,\n pipelineContext: overrides?.pipelineContext,\n signal: overrides?.signal,\n checkpoint: overrides?.checkpoint,\n };\n}\n\ninterface ManagedMainSignal {\n context: CliContext;\n wasInterrupted(): boolean;\n cleanup(): void;\n}\n\nconst SIGINT_EXIT_CODE = 130;\n\n/**\n * Give real CLI entrypoints graceful cancellation without making `run()` or\n * `parse()` mutate process-global signal handlers. Embedded callers can pass\n * their own signal through the context instead.\n */\nfunction manageMainSignal(context: CliContext): ManagedMainSignal {\n if (context.signal) {\n return { context, wasInterrupted: () => false, cleanup: () => {} };\n }\n\n const controller = new AbortController();\n let interrupted = false;\n const onSigint = (): void => {\n interrupted = true;\n context.log.warn(\"SIGINT received; cancelling pipeline work.\");\n controller.abort();\n };\n process.once(\"SIGINT\", onSigint);\n\n return {\n context: { ...context, signal: controller.signal },\n wasInterrupted: () => interrupted,\n cleanup: () => process.removeListener(\"SIGINT\", onSigint),\n };\n}\n\n/**\n * An in-memory-only `CheckpointStore` seeded from `seed`: reads and `record()` behave\n * exactly like a real store for the rest of this run, but `flush()`/`clear()` never touch\n * disk. Every dry-run path hands `run` one of these instead of the real store — the\n * managed-checkpoint contract is that a dry run never writes to the checkpoint file, no\n * matter what `run` does with `context.checkpoint` (`record`/`flush`/`clear`, directly or\n * via `withCheckpointedBatch`).\n */\nfunction inMemoryCheckpointView(seed: ReadonlyMap<string, unknown>): CheckpointStore {\n const entries = new Map(seed);\n return {\n has: (key) => entries.has(key),\n record: (key, meta) => {\n entries.set(key, meta);\n },\n entries: () => entries,\n flush: () => {},\n clear: () => {\n entries.clear();\n },\n };\n}\n\nexport function createCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>,\n mainExits?: { validation?: number }\n): CliCommand<TSchema, TResult> {\n const effectiveParams = buildEffectiveSchema(config.params, config.checkpoint);\n assertNoDuplicateFlags(effectiveParams);\n assertValidMultipleParams(effectiveParams);\n assertValidEnvironmentFallbacks(effectiveParams);\n const positionals = [...(config.positionals ?? [])];\n assertValidPositionals(positionals, effectiveParams);\n const descriptor = commandDescriptor(config, effectiveParams, positionals);\n\n function resolveValues(\n readValue: (\n key: string,\n param: CliParamsSchema[string]\n ) => string | boolean | string[] | undefined,\n context: CliContext,\n errors: string[],\n helpText: string\n ): CliParseResult<TSchema> {\n const values: Record<string, ResolvedParamValue> = {};\n for (const [key, param] of Object.entries(effectiveParams)) {\n const errorCount = errors.length;\n const raw = readValue(key, param);\n if (errors.length > errorCount) continue;\n const envValue = raw === undefined && param.env ? context.env?.[param.env] : undefined;\n values[key] = resolveParam(\n key,\n param,\n raw ?? envValue,\n context.cwd,\n errors,\n raw !== undefined ? \"argv\" : envValue !== undefined ? \"env\" : \"default\"\n );\n }\n if (errors.length > 0) return { kind: \"error\", errors, helpText };\n // SAFETY: resolveParam populated every effective schema key and all input checks passed.\n const typedValues = values as CliParams<TSchema>;\n const validationErrors = config.validate?.(typedValues, context) ?? [];\n return validationErrors.length > 0\n ? { kind: \"error\", errors: validationErrors, helpText }\n : { kind: \"values\", values: typedValues };\n }\n\n function parseWithContext(argv: readonly string[], context: CliContext): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const tokenized = tokenize(argv, effectiveParams, positionals);\n if (tokenized.help) return { kind: \"help\", helpText };\n return resolveValues(\n (key) => tokenized.values.get(key),\n context,\n [...tokenized.errors],\n helpText\n );\n }\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n return parseWithContext(argv, resolveContext(contextOverrides));\n }\n\n function parseStructuredWithContext(\n structuredValues: Record<string, unknown>,\n context: CliContext\n ): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const errors: string[] = [];\n for (const key of Object.keys(structuredValues)) {\n if (!Object.prototype.hasOwnProperty.call(effectiveParams, key)) {\n errors.push(`Unknown parameter: ${key}`);\n }\n }\n return resolveValues(\n (key, param) => normalizeStructuredValue(key, param, structuredValues[key], errors),\n context,\n errors,\n helpText\n );\n }\n\n /**\n * No-op unless `config.checkpoint` is set. Respects a caller-provided `context.checkpoint`\n * override (e.g. a stub in tests) instead of opening the real file. Otherwise opens (or\n * clears, if not resuming) the checkpoint before `run` is called — never on the `--help`/\n * error paths, since those return before this is reached.\n */\n function attachCheckpoint(context: CliContext, values: CliParams<TSchema>): CliContext {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig) {\n return context;\n }\n const resolvedPath = path.isAbsolute(checkpointConfig.path)\n ? checkpointConfig.path\n : path.join(context.cwd, checkpointConfig.path);\n // A caller-provided context.checkpoint (e.g. a stub in tests) is used as the\n // underlying store instead of opening the real file, but every rule below — fresh\n // clearing, dry-run wrapping, resume detection/logging — still applies to it; only\n // the \"where does the store come from\" step is skipped.\n const store = context.checkpoint ?? openCheckpoint(resolvedPath);\n const hadExisting = store.entries().size > 0;\n\n if (values.resume) {\n if (hadExisting) {\n context.log.log(\n `Resuming from checkpoint: ${store.entries().size} item(s) already recorded.`\n );\n } else {\n // Without this, --resume against a missing/wrong-path/already-cleared checkpoint\n // silently starts fresh — the exact failure mode that's dangerous for\n // clearOnSuccess: false workflows, where \"fresh\" quietly means \"reprocess\n // everything already done\".\n context.log.warn(\n `--resume was passed, but no checkpoint was found at ${resolvedPath}; starting fresh.`\n );\n }\n // A dry run must never write to the checkpoint file, even while resuming — an\n // in-memory view seeded with the real entries previews it accurately without risk.\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (!hadExisting) {\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (values.dryRun) {\n // Dry run must not touch the file — neither clearing it nor writing new progress —\n // but the preview should still reflect what a real fresh run would see: an empty\n // \"done\" set, not the stale entries a --resume invocation would use.\n context.log.log(\"Dry run: leaving existing checkpoint untouched (would start fresh).\");\n return { ...context, checkpoint: inMemoryCheckpointView(new Map()) };\n }\n\n store.clear();\n context.log.log(\"Starting fresh — cleared existing checkpoint.\");\n return { ...context, checkpoint: store };\n }\n\n /**\n * No-op unless `config.checkpoint` is set, a store is attached, and the run completed\n * without a dry run or caller cancellation.\n */\n function finalizeCheckpoint(context: CliContext, values: CliParams<TSchema>): void {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig || !context.checkpoint || values.dryRun || context.signal?.aborted) {\n return;\n }\n if (checkpointConfig.clearOnSuccess === false) {\n return;\n }\n context.checkpoint.clear();\n }\n\n async function executeValues(values: CliParams<TSchema>, context: CliContext): Promise<TResult> {\n const runContext = attachCheckpoint(context, values);\n const value = await config.run(values, runContext);\n finalizeCheckpoint(runContext, values);\n return value;\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n const context = resolveContext(contextOverrides);\n return parseStructuredWithContext(values, context);\n }\n\n async function execute(\n values: CliParams<TSchema>,\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n return executeValues(values, resolveContext(contextOverrides));\n }\n\n async function run(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n const context = resolveContext(contextOverrides);\n const result = parseWithContext(argv, context);\n if (result.kind === \"help\") throw new CliHelpRequested(result.helpText);\n if (result.kind === \"error\") throw new CliValidationError(result.errors, result.helpText);\n return executeValues(result.values, context);\n }\n\n async function main(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<void> {\n const context = resolveContext(contextOverrides);\n let result: CliParseResult<TSchema>;\n try {\n result = parseWithContext(argv, context);\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode =\n mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n return;\n }\n if (result.kind === \"help\") {\n context.log.log(result.helpText);\n process.exitCode = 0;\n return;\n }\n if (result.kind === \"error\") {\n for (const error of result.errors) {\n context.log.error(`Error: ${error}`);\n }\n context.log.error(\"\");\n context.log.error(result.helpText);\n process.exitCode = mainExits?.validation ?? 1;\n return;\n }\n const managedSignal = manageMainSignal(context);\n try {\n const runContext = attachCheckpoint(managedSignal.context, result.values);\n await config.run(result.values, runContext);\n if (!managedSignal.wasInterrupted()) {\n finalizeCheckpoint(runContext, result.values);\n }\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode = managedSignal.wasInterrupted()\n ? SIGINT_EXIT_CODE\n : mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n } finally {\n if (managedSignal.wasInterrupted()) {\n process.exitCode = SIGINT_EXIT_CODE;\n }\n managedSignal.cleanup();\n }\n }\n\n return { descriptor, execute, parse, parseValues, run, main };\n}\n\nfunction normalizeStructuredValue(\n key: string,\n param: CliParamsSchema[string],\n value: unknown,\n errors: string[]\n): string | boolean | string[] | undefined {\n if (value === undefined) return undefined;\n const label = `--${param.flag ?? key}`;\n if (param.type === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n errors.push(`${label} must be a boolean value.`);\n return undefined;\n }\n if ((param.type === \"number\" || param.type === \"string\") && param.multiple === true) {\n if (!Array.isArray(value)) {\n errors.push(`${label} must be an array.`);\n return undefined;\n }\n if (param.type === \"number\") {\n if (!value.every((item) => typeof item === \"number\" && Number.isFinite(item))) {\n errors.push(`${label} must contain only finite numbers.`);\n return undefined;\n }\n return value.map(String);\n }\n if (!value.every((item) => typeof item === \"string\")) {\n errors.push(`${label} must contain only strings.`);\n return undefined;\n }\n return [...value];\n }\n if (param.type === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n errors.push(`${label} must be a finite number.`);\n return undefined;\n }\n return String(value);\n }\n if (typeof value !== \"string\") {\n errors.push(`${label} must be a string value.`);\n return undefined;\n }\n return value;\n}\n\n/** Create a typed command from a declarative parameter schema and run handler. */\nexport function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>\n): CliCommand<TSchema, TResult> {\n return createCommand(config);\n}\n"]}
@@ -1,5 +1,6 @@
1
- import type { CliBooleanParam, CliCheckpointConfig, CliCommandDescriptor, CliContext, CliParams, CliParamsSchema, CliStringParam } from "./cli-types.js";
2
- import { type Pipeline, type PipelineHooks, type PipelineMermaidOptions, type PipelinePlan, type PipelineRunControls } from "../core/pipeline.js";
1
+ import { type InferredCliParams, type InferredFlagOverrides } from "./cli-schema.js";
2
+ import type { CliBooleanParam, CliCheckpointConfig, CliCommandDescriptor, CliContext, CliNumberParam, CliParams, CliParamsSchema, CliStringParam } from "./cli-types.js";
3
+ import { type Pipeline, type PipelineHooks, type PipelineMermaidOptions, type PipelinePlan, type PipelineRunControls, type StandardSchemaV1 } from "../core/pipeline.js";
3
4
  import { type PipelineReporterConfig } from "../reporter/reporter-entry.js";
4
5
  export type PipelineCliBuiltins = {
5
6
  stepIds: CliStringParam & {
@@ -9,12 +10,16 @@ export type PipelineCliBuiltins = {
9
10
  multiple: true;
10
11
  };
11
12
  continueOnError: CliBooleanParam;
13
+ maxConcurrency: CliNumberParam;
12
14
  };
15
+ /** Validated domain parameters plus the built-in pipeline execution controls. */
13
16
  export type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {
14
17
  stepIds: readonly string[];
15
18
  targets: readonly string[];
16
19
  continueOnError: boolean;
20
+ maxConcurrency: number;
17
21
  };
22
+ /** Parse result returned by commands created with `definePipelineCommand`. */
18
23
  export type PipelineCliParseResult<TSchema extends CliParamsSchema> = {
19
24
  kind: "values";
20
25
  values: PipelineCliValues<TSchema>;
@@ -26,6 +31,7 @@ export type PipelineCliParseResult<TSchema extends CliParamsSchema> = {
26
31
  errors: readonly string[];
27
32
  helpText: string;
28
33
  };
34
+ /** Typed CLI facade over a pipeline with planning and graph helpers. */
29
35
  export interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {
30
36
  readonly descriptor: CliCommandDescriptor;
31
37
  /** Stable identity of the wrapped pipeline. */
@@ -46,20 +52,23 @@ export interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {
46
52
  run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;
47
53
  main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;
48
54
  }
55
+ /** Parsed values and CLI services passed to a pipeline hook factory. */
49
56
  export interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {
50
57
  context: CliContext;
51
58
  values: PipelineCliValues<TSchema>;
52
59
  }
53
- export type PipelineCommandHookSets<TResult> = PipelineHooks<TResult> | readonly PipelineHooks<TResult>[];
60
+ /** One lifecycle hook set or an ordered collection of hook sets. */
61
+ type PipelineCommandHookSets<TResult> = PipelineHooks<TResult> | readonly PipelineHooks<TResult>[];
62
+ /** Static or lazily constructed lifecycle hooks for a pipeline command. */
54
63
  export type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> = PipelineCommandHookSets<TResult> | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);
55
64
  type PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (values: PipelineCliValues<TSchema>, context: CliContext) => TOptions | Promise<TOptions>;
56
- type DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<PipelineCliValues<TSchema>, "continueOnError" | "dryRun" | "resume" | "stepIds" | "targets">;
65
+ type DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<PipelineCliValues<TSchema>, "continueOnError" | "maxConcurrency" | "dryRun" | "resume" | "stepIds" | "targets">;
57
66
  type CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> = DefaultPipelineCommandOptions<TSchema> extends TOptions ? Exclude<keyof TSchema, keyof TOptions> extends never ? true : false : false;
58
67
  interface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {
59
68
  /** Defaults to pipeline.id. */
60
69
  name?: string;
61
70
  description?: string;
62
- /** Extra flags beyond the command and pipeline built-ins. */
71
+ /** Advanced: replace inferred flags for type-only pipelines or custom CLI inputs. */
63
72
  params?: TSchema;
64
73
  /** Extra parameter keys accepted in positional order. */
65
74
  positionals?: readonly (keyof TSchema & string)[];
@@ -80,6 +89,15 @@ export type DefinePipelineCommandConfig<TOptions extends object, TResult, TSchem
80
89
  /** Required when parsed flags do not already satisfy the pipeline's domain options. */
81
90
  mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;
82
91
  });
83
- /** Turn a typed pipeline into a command with selection, plan, and reporting defaults. */
92
+ /** Turn a pipeline into a CLI; infer domain flags from its Standard JSON Schema input. */
93
+ export declare function definePipelineCommand<TOptions extends object, TResult>(pipeline: Pipeline<TOptions, TResult> & (keyof TOptions extends never ? unknown : {
94
+ readonly optionsSchema: StandardSchemaV1;
95
+ }), config?: Omit<DefinePipelineCommandConfigBase<TResult, InferredCliParams<NoInfer<TOptions>>>, "params"> & {
96
+ params?: never;
97
+ mapOptions?: never;
98
+ /** Advanced: customize flag spelling, aliases, help or environment fallbacks. */
99
+ overrides?: InferredFlagOverrides<NoInfer<TOptions>>;
100
+ }): PipelineCommand<InferredCliParams<TOptions>, TResult>;
101
+ /** Advanced: declare CLI inputs explicitly, mapping them only when their shape differs. */
84
102
  export declare function definePipelineCommand<TOptions extends object, TResult, const TSchema extends CliParamsSchema = {}>(pipeline: Pipeline<TOptions, TResult>, config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>): PipelineCommand<TSchema, TResult>;
85
103
  export {};
@@ -1,11 +1,12 @@
1
1
  import { createCommand } from "./cli-command.js";
2
2
  import { flagName } from "./cli-parser.js";
3
- import { markPipelineCommand } from "./pipeline-command-marker.js";
3
+ import { inferCliParams, } from "./cli-schema.js";
4
+ import { markPipelineCommand } from "../utilities/pipeline-command-marker.js";
4
5
  import {} from "../core/pipeline.js";
5
6
  import { createPipelineReporter } from "../reporter/reporter-entry.js";
6
7
  import { TUBELESS_WORKBENCH_EXIT_CODE } from "./cli-exit.js";
7
- const PIPELINE_COMMAND_KEYS = new Set(["continueOnError", "stepIds", "targets"]);
8
- const PIPELINE_COMMAND_FLAGS = new Set(["continue-on-error", "step", "target"]);
8
+ const PIPELINE_COMMAND_KEYS = new Set(["continueOnError", "maxConcurrency", "stepIds", "targets"]);
9
+ const PIPELINE_COMMAND_FLAGS = new Set(["continue-on-error", "max-concurrency", "step", "target"]);
9
10
  function assertNoPipelineCommandConflicts(params) {
10
11
  for (const [key, param] of Object.entries(params)) {
11
12
  if (PIPELINE_COMMAND_KEYS.has(key)) {
@@ -19,7 +20,7 @@ function assertNoPipelineCommandConflicts(params) {
19
20
  }
20
21
  function normalizePipelineCliValues(values) {
21
22
  // SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin
22
- // `stepIds`/`targets`/`continueOnError` keys, all of which `CliParams<PipelineCliBuiltins & TSchema>`
23
+ // `stepIds`/`targets`/`continueOnError`/`maxConcurrency` keys, which `CliParams<PipelineCliBuiltins & TSchema>`
23
24
  // already provides, so the runtime shape matches the target type.
24
25
  const pipelineValues = values;
25
26
  const { continueOnError, stepIds, targets } = pipelineValues;
@@ -34,6 +35,7 @@ function pipelineRunControlsFromCliValues(values) {
34
35
  const controls = {
35
36
  dryRun: values.dryRun,
36
37
  continueOnError: values.continueOnError,
38
+ maxConcurrency: values.maxConcurrency,
37
39
  };
38
40
  if (values.stepIds.length > 0)
39
41
  controls.stepIds = values.stepIds;
@@ -51,14 +53,19 @@ function isHookConfigFunction(config) {
51
53
  return typeof config === "function";
52
54
  }
53
55
  function defaultPipelineCommandOptions(values) {
54
- const { continueOnError: _continueOnError, dryRun: _dryRun, resume: _resume, stepIds: _stepIds, targets: _targets, ...domainValues } = values;
56
+ const { continueOnError: _continueOnError, maxConcurrency: _maxConcurrency, dryRun: _dryRun, resume: _resume, stepIds: _stepIds, targets: _targets, ...domainValues } = values;
55
57
  return domainValues;
56
58
  }
57
- /** Turn a typed pipeline into a command with selection, plan, and reporting defaults. */
58
- export function definePipelineCommand(pipeline, config) {
59
- // SAFETY: `config.params` is declared as `TSchema`; the empty-object fallback is only
60
- // reached when the caller omits `params`, which is exactly the `{}` schema case.
61
- const userParams = config.params ?? {};
59
+ export function definePipelineCommand(pipeline, config = {}) {
60
+ // SAFETY: explicit params retain TSchema; the inferred overload derives its schema
61
+ // from the same pipeline input type. Type-only pipelines have no runtime fields.
62
+ const userParams = (config.params ??
63
+ (pipeline.optionsSchema && !config.mapOptions
64
+ ? inferCliParams(pipeline.optionsSchema, config.overrides)
65
+ : {}));
66
+ if (config.overrides && (config.params || config.mapOptions || !pipeline.optionsSchema)) {
67
+ throw new Error("Flag overrides require inferred pipeline flags; use params for an explicit CLI.");
68
+ }
62
69
  assertNoPipelineCommandConflicts(userParams);
63
70
  const targetFlagEnabled = pipeline.targetIds.length > 0;
64
71
  const bridgeParams = {
@@ -76,6 +83,14 @@ export function definePipelineCommand(pipeline, config) {
76
83
  group: "execution",
77
84
  description: "Continue independent work after a step fails.",
78
85
  },
86
+ maxConcurrency: {
87
+ type: "number",
88
+ group: "execution",
89
+ default: 1,
90
+ integer: true,
91
+ min: 1,
92
+ description: "Maximum simultaneous steps in this run.",
93
+ },
79
94
  };
80
95
  if (targetFlagEnabled) {
81
96
  bridgeParams.targets = {
@@ -119,12 +134,17 @@ export function definePipelineCommand(pipeline, config) {
119
134
  const controls = pipelineRunControlsFromCliValues({
120
135
  dryRun: values.dryRun,
121
136
  continueOnError: pipelineValues.continueOnError,
137
+ maxConcurrency: pipelineValues.maxConcurrency,
122
138
  stepIds: pipelineValues.stepIds,
123
139
  targets: targetFlagEnabled ? pipelineValues.targets : [],
124
140
  });
125
141
  const reporter = config.reporter === false
126
142
  ? undefined
127
- : createPipelineReporter({ log: cliContext.log, ...(config.reporter ?? {}) });
143
+ : createPipelineReporter({
144
+ log: cliContext.log,
145
+ ...(config.reporter ?? {}),
146
+ ...(cliContext.reporterOutput ? { output: cliContext.reporterOutput } : {}),
147
+ });
128
148
  const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;
129
149
  let result;
130
150
  try {
@@ -186,6 +206,6 @@ export function definePipelineCommand(pipeline, config) {
186
206
  toMermaid: (options) => pipeline.toMermaid(options),
187
207
  run: command.run,
188
208
  main: command.main,
189
- });
209
+ }, pipeline);
190
210
  }
191
211
  //# sourceMappingURL=cli-pipeline-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-pipeline-command.js","sourceRoot":"","sources":["../../src/cli/cli-pipeline-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCommand } from \"./cli-command.js\";\nimport { flagName } from \"./cli-parser.js\";\nimport type {\n CliBooleanParam,\n CliCheckpointConfig,\n CliCommandConfig,\n CliCommandDescriptor,\n CliContext,\n CliParams,\n CliParamsSchema,\n CliStringParam,\n} from \"./cli-types.js\";\nimport { markPipelineCommand } from \"./pipeline-command-marker.js\";\nimport {\n type Pipeline,\n type PipelineHooks,\n type PipelineMermaidOptions,\n type PipelinePlan,\n type PipelineRunControls,\n} from \"../core/pipeline.js\";\nimport { createPipelineReporter, type PipelineReporterConfig } from \"../reporter/reporter-entry.js\";\nimport { TUBELESS_WORKBENCH_EXIT_CODE } from \"./cli-exit.js\";\n\nexport type PipelineCliBuiltins = {\n stepIds: CliStringParam & { multiple: true };\n targets: CliStringParam & { multiple: true };\n continueOnError: CliBooleanParam;\n};\n\nexport type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {\n stepIds: readonly string[];\n targets: readonly string[];\n continueOnError: boolean;\n};\n\nexport type PipelineCliParseResult<TSchema extends CliParamsSchema> =\n | { kind: \"values\"; values: PipelineCliValues<TSchema> }\n | { kind: \"help\"; helpText: string }\n | { kind: \"error\"; errors: readonly string[]; helpText: string };\n\nexport interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {\n readonly descriptor: CliCommandDescriptor;\n /** Stable identity of the wrapped pipeline. */\n readonly id: string;\n /** Stable definition-order step ids for discovery surfaces such as CLI help. */\n readonly stepIds: readonly string[];\n /** Stable declared goal ids that support dependency-aware target execution. */\n readonly targetIds: readonly string[];\n /** Plan without parsing or requiring domain parameters. */\n plan(controls?: PipelineRunControls): PipelinePlan;\n /** Generate a static Mermaid flowchart without running or planning the pipeline. */\n toMermaid(options?: PipelineMermaidOptions): string;\n parse(argv?: readonly string[], context?: Partial<CliContext>): PipelineCliParseResult<TSchema>;\n /** Validate structured form values without tokenizing argv. */\n parseValues(\n values: Record<string, unknown>,\n context?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema>;\n /** Execute already validated form values. */\n execute(values: PipelineCliValues<TSchema>, context?: Partial<CliContext>): Promise<TResult>;\n run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;\n main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;\n}\n\nexport interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {\n context: CliContext;\n values: PipelineCliValues<TSchema>;\n}\n\nexport type PipelineCommandHookSets<TResult> =\n | PipelineHooks<TResult>\n | readonly PipelineHooks<TResult>[];\n\nexport type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> =\n | PipelineCommandHookSets<TResult>\n | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);\n\ntype PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (\n values: PipelineCliValues<TSchema>,\n context: CliContext\n) => TOptions | Promise<TOptions>;\n\ntype DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<\n PipelineCliValues<TSchema>,\n \"continueOnError\" | \"dryRun\" | \"resume\" | \"stepIds\" | \"targets\"\n>;\n\ntype CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> =\n DefaultPipelineCommandOptions<TSchema> extends TOptions\n ? Exclude<keyof TSchema, keyof TOptions> extends never\n ? true\n : false\n : false;\n\ninterface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {\n /** Defaults to pipeline.id. */\n name?: string;\n description?: string;\n /** Extra flags beyond the command and pipeline built-ins. */\n params?: TSchema;\n /** Extra parameter keys accepted in positional order. */\n positionals?: readonly (keyof TSchema & string)[];\n checkpoint?: CliCheckpointConfig;\n /** Additional lifecycle hooks, or a factory resolved from parsed values and CLI context. */\n hooks?: PipelineCommandHookConfig<TResult, TSchema>;\n /** Configure plain/interactive reporting, or disable it. Defaults to automatic mode. */\n reporter?: false | PipelineReporterConfig;\n /** Print domain-specific result lines after a successful run. */\n summarize?(\n result: TResult,\n values: PipelineCliValues<TSchema>,\n context: CliContext\n ): readonly string[] | void;\n validate?(values: PipelineCliValues<TSchema>, context: CliContext): string[] | void;\n}\n\n/** Configuration for a typed pipeline command. Mapping is optional only for compatible flags. */\nexport type DefinePipelineCommandConfig<\n TOptions extends object,\n TResult,\n TSchema extends CliParamsSchema,\n> = DefinePipelineCommandConfigBase<TResult, TSchema> &\n (CanDefaultPipelineCommandOptions<TOptions, TSchema> extends true\n ? {\n /** Override the default same-name flag-to-option mapping. */\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n }\n : {\n /** Required when parsed flags do not already satisfy the pipeline's domain options. */\n mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;\n });\n\nconst PIPELINE_COMMAND_KEYS = new Set([\"continueOnError\", \"stepIds\", \"targets\"]);\nconst PIPELINE_COMMAND_FLAGS = new Set([\"continue-on-error\", \"step\", \"target\"]);\n\nfunction assertNoPipelineCommandConflicts(params: CliParamsSchema): void {\n for (const [key, param] of Object.entries(params)) {\n if (PIPELINE_COMMAND_KEYS.has(key)) {\n throw new Error(\n `\"${key}\" is a reserved parameter provided automatically by pipeline commands; remove it from params.`\n );\n }\n const flag = flagName(key, param);\n if (PIPELINE_COMMAND_FLAGS.has(flag)) {\n throw new Error(\n `--${flag} is a reserved flag provided automatically by pipeline commands; remove \"${key}\" from params or give it a different flag name.`\n );\n }\n }\n}\n\nfunction normalizePipelineCliValues<TSchema extends CliParamsSchema>(\n values: CliParams<PipelineCliBuiltins & TSchema>\n): PipelineCliValues<TSchema> {\n // SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin\n // `stepIds`/`targets`/`continueOnError` keys, all of which `CliParams<PipelineCliBuiltins & TSchema>`\n // already provides, so the runtime shape matches the target type.\n const pipelineValues = values as PipelineCliValues<TSchema>;\n const { continueOnError, stepIds, targets } = pipelineValues;\n return {\n ...pipelineValues,\n continueOnError,\n stepIds,\n targets: targets ?? [],\n };\n}\n\nfunction pipelineRunControlsFromCliValues(values: {\n continueOnError: boolean;\n dryRun: boolean;\n stepIds: readonly string[];\n targets: readonly string[];\n}): PipelineRunControls {\n const controls: PipelineRunControls = {\n dryRun: values.dryRun,\n continueOnError: values.continueOnError,\n };\n if (values.stepIds.length > 0) controls.stepIds = values.stepIds;\n if (values.targets.length > 0) controls.targets = values.targets;\n return controls;\n}\n\nfunction normalizePipelineHookSets<TResult>(\n hooks: PipelineCommandHookSets<TResult> | undefined\n): PipelineHooks<TResult>[] {\n if (!hooks) return [];\n // SAFETY: a non-array `PipelineCommandHookSets` is always a single `PipelineHooks`.\n return Array.isArray(hooks) ? [...hooks] : [hooks as PipelineHooks<TResult>];\n}\n\nfunction isHookConfigFunction<TResult, TSchema extends CliParamsSchema>(\n config: PipelineCommandHookConfig<TResult, TSchema> | undefined\n): config is (\n input: PipelineCommandHookContext<TSchema>\n) => PipelineCommandHookSets<TResult> | undefined {\n return typeof config === \"function\";\n}\n\nfunction defaultPipelineCommandOptions<TSchema extends CliParamsSchema>(\n values: PipelineCliValues<TSchema>\n): DefaultPipelineCommandOptions<TSchema> {\n const {\n continueOnError: _continueOnError,\n dryRun: _dryRun,\n resume: _resume,\n stepIds: _stepIds,\n targets: _targets,\n ...domainValues\n } = values;\n return domainValues;\n}\n\n/** Turn a typed pipeline into a command with selection, plan, and reporting defaults. */\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>\n): PipelineCommand<TSchema, TResult> {\n // SAFETY: `config.params` is declared as `TSchema`; the empty-object fallback is only\n // reached when the caller omits `params`, which is exactly the `{}` schema case.\n const userParams = config.params ?? ({} as TSchema);\n assertNoPipelineCommandConflicts(userParams);\n\n const targetFlagEnabled = pipeline.targetIds.length > 0;\n const bridgeParams: CliParamsSchema = {\n stepIds: {\n type: \"string\",\n multiple: true,\n flag: \"step\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.stepIds,\n description: `Run exactly this step. Steps: ${pipeline.stepIds.join(\", \")}`,\n },\n continueOnError: {\n type: \"boolean\",\n group: \"execution\",\n description: \"Continue independent work after a step fails.\",\n },\n };\n if (targetFlagEnabled) {\n bridgeParams.targets = {\n type: \"string\",\n multiple: true,\n flag: \"target\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.targetIds,\n description: `Run this declared target and its prerequisites. Targets: ${pipeline.targetIds.join(\", \")}`,\n };\n }\n\n // SAFETY: `bridgeParams` supplies the `PipelineCliBuiltins` keys and `userParams` is\n // `TSchema`, so the merged object satisfies `PipelineCliBuiltins & TSchema`.\n const params = { ...bridgeParams, ...userParams } as PipelineCliBuiltins & TSchema;\n\n const commandConfig = {\n name: config.name ?? pipeline.id,\n description: config.description,\n params,\n positionals: config.positionals,\n checkpoint: config.checkpoint,\n validate: (values, context) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n const errors = config.validate?.(pipelineValues, context) ?? [];\n if (pipelineValues.stepIds.length > 0 && pipelineValues.targets.length > 0) {\n return [\"--step and --target cannot be used together.\", ...errors];\n }\n return errors.length > 0 ? errors : undefined;\n },\n run: async (values, cliContext) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n let mapped: TOptions;\n if (config.mapOptions) {\n mapped = await config.mapOptions(pipelineValues, cliContext);\n } else {\n // SAFETY: `defaultPipelineCommandOptions` returns exactly the domain options the\n // `CanDefaultPipelineCommandOptions` constraint guarantees map to `TOptions`.\n mapped = defaultPipelineCommandOptions(pipelineValues) as TOptions;\n }\n const controls = pipelineRunControlsFromCliValues({\n dryRun: values.dryRun,\n continueOnError: pipelineValues.continueOnError,\n stepIds: pipelineValues.stepIds,\n targets: targetFlagEnabled ? pipelineValues.targets : [],\n });\n\n const reporter =\n config.reporter === false\n ? undefined\n : createPipelineReporter<TResult>({ log: cliContext.log, ...(config.reporter ?? {}) });\n const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;\n let result: TResult;\n try {\n const configuredHooks = isHookConfigFunction(config.hooks)\n ? config.hooks({ context: runtimeContext, values: pipelineValues })\n : config.hooks;\n const hooks: PipelineHooks<TResult>[] = [\n ...normalizePipelineHookSets(cliContext.pipelineContext?.hooks),\n ...(reporter ? [reporter.hooks] : []),\n ...normalizePipelineHookSets(configuredHooks),\n ];\n\n result = await pipeline.runOrThrow(mapped, controls, {\n ...cliContext.pipelineContext,\n cwd: runtimeContext.cwd,\n log: runtimeContext.log,\n hooks: hooks.length > 0 ? hooks : undefined,\n signal: runtimeContext.signal,\n });\n } finally {\n reporter?.dispose();\n }\n for (const line of config.summarize?.(result, pipelineValues, cliContext) ?? []) {\n cliContext.log.log(line);\n }\n return result;\n },\n } satisfies CliCommandConfig<PipelineCliBuiltins & TSchema, TResult>;\n\n const command = createCommand(commandConfig, {\n validation: TUBELESS_WORKBENCH_EXIT_CODE.validation,\n });\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parse(argv, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n function plan(controls: PipelineRunControls = {}): PipelinePlan {\n return pipeline.plan(controls);\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parseValues(values, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n return markPipelineCommand({\n descriptor: command.descriptor,\n id: pipeline.id,\n stepIds: pipeline.stepIds,\n targetIds: pipeline.targetIds,\n execute: (values, contextOverrides) =>\n // SAFETY: `execute` receives `PipelineCliValues<TSchema>` from the public interface,\n // which is a subtype of `CliParams<PipelineCliBuiltins & TSchema>`.\n command.execute(values as CliParams<PipelineCliBuiltins & TSchema>, contextOverrides),\n parse,\n parseValues,\n plan,\n toMermaid: (options) => pipeline.toMermaid(options),\n run: command.run,\n main: command.main,\n });\n}\n"]}
1
+ {"version":3,"file":"cli-pipeline-command.js","sourceRoot":"","sources":["../../src/cli/cli-pipeline-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCommand } from \"./cli-command.js\";\nimport { flagName } from \"./cli-parser.js\";\nimport {\n inferCliParams,\n type InferredCliParams,\n type InferredFlagOverrides,\n} from \"./cli-schema.js\";\nimport type {\n CliBooleanParam,\n CliCheckpointConfig,\n CliCommandConfig,\n CliCommandDescriptor,\n CliContext,\n CliNumberParam,\n CliParams,\n CliParamsSchema,\n CliStringParam,\n} from \"./cli-types.js\";\nimport { markPipelineCommand } from \"../utilities/pipeline-command-marker.js\";\nimport {\n type Pipeline,\n type PipelineHooks,\n type PipelineMermaidOptions,\n type PipelinePlan,\n type PipelineRunControls,\n type StandardSchemaV1,\n} from \"../core/pipeline.js\";\nimport { createPipelineReporter, type PipelineReporterConfig } from \"../reporter/reporter-entry.js\";\nimport { TUBELESS_WORKBENCH_EXIT_CODE } from \"./cli-exit.js\";\n\nexport type PipelineCliBuiltins = {\n stepIds: CliStringParam & { multiple: true };\n targets: CliStringParam & { multiple: true };\n continueOnError: CliBooleanParam;\n maxConcurrency: CliNumberParam;\n};\n\n/** Validated domain parameters plus the built-in pipeline execution controls. */\nexport type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {\n stepIds: readonly string[];\n targets: readonly string[];\n continueOnError: boolean;\n maxConcurrency: number;\n};\n\n/** Parse result returned by commands created with `definePipelineCommand`. */\nexport type PipelineCliParseResult<TSchema extends CliParamsSchema> =\n | { kind: \"values\"; values: PipelineCliValues<TSchema> }\n | { kind: \"help\"; helpText: string }\n | { kind: \"error\"; errors: readonly string[]; helpText: string };\n\n/** Typed CLI facade over a pipeline with planning and graph helpers. */\nexport interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {\n readonly descriptor: CliCommandDescriptor;\n /** Stable identity of the wrapped pipeline. */\n readonly id: string;\n /** Stable definition-order step ids for discovery surfaces such as CLI help. */\n readonly stepIds: readonly string[];\n /** Stable declared goal ids that support dependency-aware target execution. */\n readonly targetIds: readonly string[];\n /** Plan without parsing or requiring domain parameters. */\n plan(controls?: PipelineRunControls): PipelinePlan;\n /** Generate a static Mermaid flowchart without running or planning the pipeline. */\n toMermaid(options?: PipelineMermaidOptions): string;\n parse(argv?: readonly string[], context?: Partial<CliContext>): PipelineCliParseResult<TSchema>;\n /** Validate structured form values without tokenizing argv. */\n parseValues(\n values: Record<string, unknown>,\n context?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema>;\n /** Execute already validated form values. */\n execute(values: PipelineCliValues<TSchema>, context?: Partial<CliContext>): Promise<TResult>;\n run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;\n main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;\n}\n\n/** Parsed values and CLI services passed to a pipeline hook factory. */\nexport interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {\n context: CliContext;\n values: PipelineCliValues<TSchema>;\n}\n\n/** One lifecycle hook set or an ordered collection of hook sets. */\ntype PipelineCommandHookSets<TResult> = PipelineHooks<TResult> | readonly PipelineHooks<TResult>[];\n\n/** Static or lazily constructed lifecycle hooks for a pipeline command. */\nexport type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> =\n | PipelineCommandHookSets<TResult>\n | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);\n\ntype PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (\n values: PipelineCliValues<TSchema>,\n context: CliContext\n) => TOptions | Promise<TOptions>;\n\ntype DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<\n PipelineCliValues<TSchema>,\n \"continueOnError\" | \"maxConcurrency\" | \"dryRun\" | \"resume\" | \"stepIds\" | \"targets\"\n>;\n\ntype CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> =\n DefaultPipelineCommandOptions<TSchema> extends TOptions\n ? Exclude<keyof TSchema, keyof TOptions> extends never\n ? true\n : false\n : false;\n\ninterface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {\n /** Defaults to pipeline.id. */\n name?: string;\n description?: string;\n /** Advanced: replace inferred flags for type-only pipelines or custom CLI inputs. */\n params?: TSchema;\n /** Extra parameter keys accepted in positional order. */\n positionals?: readonly (keyof TSchema & string)[];\n checkpoint?: CliCheckpointConfig;\n /** Additional lifecycle hooks, or a factory resolved from parsed values and CLI context. */\n hooks?: PipelineCommandHookConfig<TResult, TSchema>;\n /** Configure plain/interactive reporting, or disable it. Defaults to automatic mode. */\n reporter?: false | PipelineReporterConfig;\n /** Print domain-specific result lines after a successful run. */\n summarize?(\n result: TResult,\n values: PipelineCliValues<TSchema>,\n context: CliContext\n ): readonly string[] | void;\n validate?(values: PipelineCliValues<TSchema>, context: CliContext): string[] | void;\n}\n\n/** Configuration for a typed pipeline command. Mapping is optional only for compatible flags. */\nexport type DefinePipelineCommandConfig<\n TOptions extends object,\n TResult,\n TSchema extends CliParamsSchema,\n> = DefinePipelineCommandConfigBase<TResult, TSchema> &\n (CanDefaultPipelineCommandOptions<TOptions, TSchema> extends true\n ? {\n /** Override the default same-name flag-to-option mapping. */\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n }\n : {\n /** Required when parsed flags do not already satisfy the pipeline's domain options. */\n mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;\n });\n\nconst PIPELINE_COMMAND_KEYS = new Set([\"continueOnError\", \"maxConcurrency\", \"stepIds\", \"targets\"]);\nconst PIPELINE_COMMAND_FLAGS = new Set([\"continue-on-error\", \"max-concurrency\", \"step\", \"target\"]);\n\nfunction assertNoPipelineCommandConflicts(params: CliParamsSchema): void {\n for (const [key, param] of Object.entries(params)) {\n if (PIPELINE_COMMAND_KEYS.has(key)) {\n throw new Error(\n `\"${key}\" is a reserved parameter provided automatically by pipeline commands; remove it from params.`\n );\n }\n const flag = flagName(key, param);\n if (PIPELINE_COMMAND_FLAGS.has(flag)) {\n throw new Error(\n `--${flag} is a reserved flag provided automatically by pipeline commands; remove \"${key}\" from params or give it a different flag name.`\n );\n }\n }\n}\n\nfunction normalizePipelineCliValues<TSchema extends CliParamsSchema>(\n values: CliParams<PipelineCliBuiltins & TSchema>\n): PipelineCliValues<TSchema> {\n // SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin\n // `stepIds`/`targets`/`continueOnError`/`maxConcurrency` keys, which `CliParams<PipelineCliBuiltins & TSchema>`\n // already provides, so the runtime shape matches the target type.\n const pipelineValues = values as PipelineCliValues<TSchema>;\n const { continueOnError, stepIds, targets } = pipelineValues;\n return {\n ...pipelineValues,\n continueOnError,\n stepIds,\n targets: targets ?? [],\n };\n}\n\nfunction pipelineRunControlsFromCliValues(values: {\n continueOnError: boolean;\n maxConcurrency: number;\n dryRun: boolean;\n stepIds: readonly string[];\n targets: readonly string[];\n}): PipelineRunControls {\n const controls: PipelineRunControls = {\n dryRun: values.dryRun,\n continueOnError: values.continueOnError,\n maxConcurrency: values.maxConcurrency,\n };\n if (values.stepIds.length > 0) controls.stepIds = values.stepIds;\n if (values.targets.length > 0) controls.targets = values.targets;\n return controls;\n}\n\nfunction normalizePipelineHookSets<TResult>(\n hooks: PipelineCommandHookSets<TResult> | undefined\n): PipelineHooks<TResult>[] {\n if (!hooks) return [];\n // SAFETY: a non-array `PipelineCommandHookSets` is always a single `PipelineHooks`.\n return Array.isArray(hooks) ? [...hooks] : [hooks as PipelineHooks<TResult>];\n}\n\nfunction isHookConfigFunction<TResult, TSchema extends CliParamsSchema>(\n config: PipelineCommandHookConfig<TResult, TSchema> | undefined\n): config is (\n input: PipelineCommandHookContext<TSchema>\n) => PipelineCommandHookSets<TResult> | undefined {\n return typeof config === \"function\";\n}\n\nfunction defaultPipelineCommandOptions<TSchema extends CliParamsSchema>(\n values: PipelineCliValues<TSchema>\n): DefaultPipelineCommandOptions<TSchema> {\n const {\n continueOnError: _continueOnError,\n maxConcurrency: _maxConcurrency,\n dryRun: _dryRun,\n resume: _resume,\n stepIds: _stepIds,\n targets: _targets,\n ...domainValues\n } = values;\n return domainValues;\n}\n\n/** Turn a pipeline into a CLI; infer domain flags from its Standard JSON Schema input. */\nexport function definePipelineCommand<TOptions extends object, TResult>(\n pipeline: Pipeline<TOptions, TResult> &\n (keyof TOptions extends never ? unknown : { readonly optionsSchema: StandardSchemaV1 }),\n config?: Omit<\n DefinePipelineCommandConfigBase<TResult, InferredCliParams<NoInfer<TOptions>>>,\n \"params\"\n > & {\n params?: never;\n mapOptions?: never;\n /** Advanced: customize flag spelling, aliases, help or environment fallbacks. */\n overrides?: InferredFlagOverrides<NoInfer<TOptions>>;\n }\n): PipelineCommand<InferredCliParams<TOptions>, TResult>;\n/** Advanced: declare CLI inputs explicitly, mapping them only when their shape differs. */\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>\n): PipelineCommand<TSchema, TResult>;\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfigBase<TResult, TSchema> & {\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n overrides?: InferredFlagOverrides<TOptions>;\n } = {}\n): PipelineCommand<TSchema, TResult> {\n // SAFETY: explicit params retain TSchema; the inferred overload derives its schema\n // from the same pipeline input type. Type-only pipelines have no runtime fields.\n const userParams = (config.params ??\n (pipeline.optionsSchema && !config.mapOptions\n ? inferCliParams(pipeline.optionsSchema, config.overrides)\n : {})) as TSchema;\n if (config.overrides && (config.params || config.mapOptions || !pipeline.optionsSchema)) {\n throw new Error(\n \"Flag overrides require inferred pipeline flags; use params for an explicit CLI.\"\n );\n }\n assertNoPipelineCommandConflicts(userParams);\n\n const targetFlagEnabled = pipeline.targetIds.length > 0;\n const bridgeParams: CliParamsSchema = {\n stepIds: {\n type: \"string\",\n multiple: true,\n flag: \"step\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.stepIds,\n description: `Run exactly this step. Steps: ${pipeline.stepIds.join(\", \")}`,\n },\n continueOnError: {\n type: \"boolean\",\n group: \"execution\",\n description: \"Continue independent work after a step fails.\",\n },\n maxConcurrency: {\n type: \"number\",\n group: \"execution\",\n default: 1,\n integer: true,\n min: 1,\n description: \"Maximum simultaneous steps in this run.\",\n },\n };\n if (targetFlagEnabled) {\n bridgeParams.targets = {\n type: \"string\",\n multiple: true,\n flag: \"target\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.targetIds,\n description: `Run this declared target and its prerequisites. Targets: ${pipeline.targetIds.join(\", \")}`,\n };\n }\n\n // SAFETY: `bridgeParams` supplies the `PipelineCliBuiltins` keys and `userParams` is\n // `TSchema`, so the merged object satisfies `PipelineCliBuiltins & TSchema`.\n const params = { ...bridgeParams, ...userParams } as PipelineCliBuiltins & TSchema;\n\n const commandConfig = {\n name: config.name ?? pipeline.id,\n description: config.description,\n params,\n positionals: config.positionals,\n checkpoint: config.checkpoint,\n validate: (values, context) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n const errors = config.validate?.(pipelineValues, context) ?? [];\n if (pipelineValues.stepIds.length > 0 && pipelineValues.targets.length > 0) {\n return [\"--step and --target cannot be used together.\", ...errors];\n }\n return errors.length > 0 ? errors : undefined;\n },\n run: async (values, cliContext) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n let mapped: TOptions;\n if (config.mapOptions) {\n mapped = await config.mapOptions(pipelineValues, cliContext);\n } else {\n // SAFETY: `defaultPipelineCommandOptions` returns exactly the domain options the\n // `CanDefaultPipelineCommandOptions` constraint guarantees map to `TOptions`.\n mapped = defaultPipelineCommandOptions(pipelineValues) as TOptions;\n }\n const controls = pipelineRunControlsFromCliValues({\n dryRun: values.dryRun,\n continueOnError: pipelineValues.continueOnError,\n maxConcurrency: pipelineValues.maxConcurrency,\n stepIds: pipelineValues.stepIds,\n targets: targetFlagEnabled ? pipelineValues.targets : [],\n });\n\n const reporter =\n config.reporter === false\n ? undefined\n : createPipelineReporter<TResult>({\n log: cliContext.log,\n ...(config.reporter ?? {}),\n ...(cliContext.reporterOutput ? { output: cliContext.reporterOutput } : {}),\n });\n const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;\n let result: TResult;\n try {\n const configuredHooks = isHookConfigFunction(config.hooks)\n ? config.hooks({ context: runtimeContext, values: pipelineValues })\n : config.hooks;\n const hooks: PipelineHooks<TResult>[] = [\n ...normalizePipelineHookSets(cliContext.pipelineContext?.hooks),\n ...(reporter ? [reporter.hooks] : []),\n ...normalizePipelineHookSets(configuredHooks),\n ];\n\n result = await pipeline.runOrThrow(mapped, controls, {\n ...cliContext.pipelineContext,\n cwd: runtimeContext.cwd,\n log: runtimeContext.log,\n hooks: hooks.length > 0 ? hooks : undefined,\n signal: runtimeContext.signal,\n });\n } finally {\n reporter?.dispose();\n }\n for (const line of config.summarize?.(result, pipelineValues, cliContext) ?? []) {\n cliContext.log.log(line);\n }\n return result;\n },\n } satisfies CliCommandConfig<PipelineCliBuiltins & TSchema, TResult>;\n\n const command = createCommand(commandConfig, {\n validation: TUBELESS_WORKBENCH_EXIT_CODE.validation,\n });\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parse(argv, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n function plan(controls: PipelineRunControls = {}): PipelinePlan {\n return pipeline.plan(controls);\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parseValues(values, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n return markPipelineCommand(\n {\n descriptor: command.descriptor,\n id: pipeline.id,\n stepIds: pipeline.stepIds,\n targetIds: pipeline.targetIds,\n execute: (values, contextOverrides) =>\n // SAFETY: `execute` receives `PipelineCliValues<TSchema>` from the public interface,\n // which is a subtype of `CliParams<PipelineCliBuiltins & TSchema>`.\n command.execute(values as CliParams<PipelineCliBuiltins & TSchema>, contextOverrides),\n parse,\n parseValues,\n plan,\n toMermaid: (options) => pipeline.toMermaid(options),\n run: command.run,\n main: command.main,\n },\n pipeline\n );\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import type { StandardSchemaV1 } from "../core/pipeline.js";
2
+ import type { CliParam, CliParamsSchema } from "./cli-types.js";
3
+ type ScalarParam<T> = [T] extends [string] ? {
4
+ type: "string";
5
+ choices: readonly T[];
6
+ } : [T] extends [number] ? {
7
+ type: "number";
8
+ } : [T] extends [boolean] ? {
9
+ type: "boolean";
10
+ } : never;
11
+ /** Input types describe flag values; the runtime schema supplies their metadata. */
12
+ export type InferredCliParams<TOptions extends object> = {
13
+ [K in keyof TOptions]-?: NonNullable<TOptions[K]> extends readonly (infer TItem)[] ? ScalarParam<TItem> & {
14
+ multiple: true;
15
+ } : ScalarParam<NonNullable<TOptions[K]>> & (undefined extends TOptions[K] ? {
16
+ optional: true;
17
+ } : {});
18
+ };
19
+ type FlagOverride = Pick<CliParam, "description" | "flag" | "short" | "env">;
20
+ export type InferredFlagOverrides<TOptions extends object> = {
21
+ [K in keyof TOptions]?: FlagOverride;
22
+ };
23
+ /** Convert metadata only. Domain validation and transformations still belong to the pipeline. */
24
+ export declare function inferCliParams(optionsSchema: StandardSchemaV1, overrides?: Record<string, FlagOverride | undefined>): CliParamsSchema;
25
+ export {};