stageflow 0.1.0

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 (180) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/agent/activity.d.ts +76 -0
  4. package/dist/agent/activity.js +89 -0
  5. package/dist/agent/activityObserver.d.ts +17 -0
  6. package/dist/agent/activityObserver.js +66 -0
  7. package/dist/agent/cursorExtension.d.ts +12 -0
  8. package/dist/agent/cursorExtension.js +88 -0
  9. package/dist/agent/cursorProvider.d.ts +14 -0
  10. package/dist/agent/cursorProvider.js +139 -0
  11. package/dist/agent/fakeAgent.d.ts +29 -0
  12. package/dist/agent/fakeAgent.js +295 -0
  13. package/dist/agent/oauthSessionManager.d.ts +33 -0
  14. package/dist/agent/oauthSessionManager.js +214 -0
  15. package/dist/agent/piAdapter.d.ts +128 -0
  16. package/dist/agent/piAdapter.js +967 -0
  17. package/dist/agent/port.d.ts +63 -0
  18. package/dist/agent/port.js +46 -0
  19. package/dist/agent/providerAuth.d.ts +101 -0
  20. package/dist/agent/providerAuth.js +282 -0
  21. package/dist/agent/providerSupport.d.ts +28 -0
  22. package/dist/agent/providerSupport.js +19 -0
  23. package/dist/cli/providersCommand.d.ts +11 -0
  24. package/dist/cli/providersCommand.js +275 -0
  25. package/dist/cli/terminalAuthInteraction.d.ts +8 -0
  26. package/dist/cli/terminalAuthInteraction.js +65 -0
  27. package/dist/cli/terminalSecret.d.ts +2 -0
  28. package/dist/cli/terminalSecret.js +67 -0
  29. package/dist/cli/validateCommand.d.ts +11 -0
  30. package/dist/cli/validateCommand.js +81 -0
  31. package/dist/cli/validateOutput.d.ts +8 -0
  32. package/dist/cli/validateOutput.js +75 -0
  33. package/dist/cli.d.ts +2 -0
  34. package/dist/cli.js +273 -0
  35. package/dist/config/createPipeline.d.ts +31 -0
  36. package/dist/config/createPipeline.js +255 -0
  37. package/dist/config/createStage.d.ts +25 -0
  38. package/dist/config/createStage.js +181 -0
  39. package/dist/config/listConfig.d.ts +33 -0
  40. package/dist/config/listConfig.js +195 -0
  41. package/dist/config/listExtensions.d.ts +26 -0
  42. package/dist/config/listExtensions.js +50 -0
  43. package/dist/config/listSkills.d.ts +29 -0
  44. package/dist/config/listSkills.js +55 -0
  45. package/dist/config/loadOutcome.d.ts +27 -0
  46. package/dist/config/loadOutcome.js +6 -0
  47. package/dist/config/loadPipeline.d.ts +25 -0
  48. package/dist/config/loadPipeline.js +196 -0
  49. package/dist/config/loadStage.d.ts +4 -0
  50. package/dist/config/loadStage.js +127 -0
  51. package/dist/config/loadTask.d.ts +7 -0
  52. package/dist/config/loadTask.js +69 -0
  53. package/dist/config/readYamlObject.d.ts +1 -0
  54. package/dist/config/readYamlObject.js +5 -0
  55. package/dist/config/resolvePipelineDag.d.ts +12 -0
  56. package/dist/config/resolvePipelineDag.js +282 -0
  57. package/dist/config/validateCatalog.d.ts +36 -0
  58. package/dist/config/validateCatalog.js +322 -0
  59. package/dist/envelope/check.d.ts +3 -0
  60. package/dist/envelope/check.js +52 -0
  61. package/dist/envelope/payloadSchema.d.ts +10 -0
  62. package/dist/envelope/payloadSchema.js +91 -0
  63. package/dist/hitl/qaTrail.d.ts +31 -0
  64. package/dist/hitl/qaTrail.js +65 -0
  65. package/dist/index.d.ts +13 -0
  66. package/dist/index.js +7 -0
  67. package/dist/mcp/projectRun.d.ts +37 -0
  68. package/dist/mcp/projectRun.js +57 -0
  69. package/dist/mcp/readArtifact.d.ts +2 -0
  70. package/dist/mcp/readArtifact.js +46 -0
  71. package/dist/mcp/server.d.ts +7 -0
  72. package/dist/mcp/server.js +26 -0
  73. package/dist/mcp/tools.d.ts +9 -0
  74. package/dist/mcp/tools.js +96 -0
  75. package/dist/package-meta.d.ts +1 -0
  76. package/dist/package-meta.js +1 -0
  77. package/dist/prompt/priorEnvelope.d.ts +2 -0
  78. package/dist/prompt/priorEnvelope.js +5 -0
  79. package/dist/runstore/catalog.d.ts +8 -0
  80. package/dist/runstore/catalog.js +16 -0
  81. package/dist/runstore/createStore.d.ts +15 -0
  82. package/dist/runstore/createStore.js +23 -0
  83. package/dist/runstore/disk/DiskRunStore.d.ts +30 -0
  84. package/dist/runstore/disk/DiskRunStore.js +238 -0
  85. package/dist/runstore/disk/catalogHelpers.d.ts +11 -0
  86. package/dist/runstore/disk/catalogHelpers.js +102 -0
  87. package/dist/runstore/layout.d.ts +22 -0
  88. package/dist/runstore/layout.js +58 -0
  89. package/dist/runstore/paths.d.ts +7 -0
  90. package/dist/runstore/paths.js +60 -0
  91. package/dist/runstore/pipelineDagSnapshot.d.ts +5 -0
  92. package/dist/runstore/pipelineDagSnapshot.js +43 -0
  93. package/dist/runstore/port.d.ts +146 -0
  94. package/dist/runstore/port.js +28 -0
  95. package/dist/runstore/runProjection.d.ts +6 -0
  96. package/dist/runstore/runProjection.js +102 -0
  97. package/dist/runstore/sqlite/SqliteRunStore.d.ts +48 -0
  98. package/dist/runstore/sqlite/SqliteRunStore.js +460 -0
  99. package/dist/runstore/sqlite/migrateFromDisk.d.ts +5 -0
  100. package/dist/runstore/sqlite/migrateFromDisk.js +108 -0
  101. package/dist/runstore/sqlite/schema.d.ts +1 -0
  102. package/dist/runstore/sqlite/schema.js +59 -0
  103. package/dist/runstore/stageExecution.d.ts +13 -0
  104. package/dist/runstore/stageExecution.js +22 -0
  105. package/dist/runstore/stageSnapshot.d.ts +2 -0
  106. package/dist/runstore/stageSnapshot.js +46 -0
  107. package/dist/runstore/syntheticStageSnapshot.d.ts +2 -0
  108. package/dist/runstore/syntheticStageSnapshot.js +10 -0
  109. package/dist/runstore/trackProjection.d.ts +7 -0
  110. package/dist/runstore/trackProjection.js +94 -0
  111. package/dist/runstore/workspaceLayout.d.ts +31 -0
  112. package/dist/runstore/workspaceLayout.js +172 -0
  113. package/dist/runtime/answerResume.d.ts +16 -0
  114. package/dist/runtime/answerResume.js +22 -0
  115. package/dist/runtime/credentialBinding.d.ts +16 -0
  116. package/dist/runtime/credentialBinding.js +80 -0
  117. package/dist/runtime/dagTraversal.d.ts +3 -0
  118. package/dist/runtime/dagTraversal.js +26 -0
  119. package/dist/runtime/envelopeRouting.d.ts +20 -0
  120. package/dist/runtime/envelopeRouting.js +59 -0
  121. package/dist/runtime/hitlSeams.d.ts +38 -0
  122. package/dist/runtime/hitlSeams.js +2 -0
  123. package/dist/runtime/pipelineRunner.d.ts +77 -0
  124. package/dist/runtime/pipelineRunner.js +141 -0
  125. package/dist/runtime/pipelineScheduler.d.ts +90 -0
  126. package/dist/runtime/pipelineScheduler.js +494 -0
  127. package/dist/runtime/pipelineValidationError.d.ts +6 -0
  128. package/dist/runtime/pipelineValidationError.js +8 -0
  129. package/dist/runtime/resumeReconstruct.d.ts +33 -0
  130. package/dist/runtime/resumeReconstruct.js +144 -0
  131. package/dist/runtime/runManager.d.ts +129 -0
  132. package/dist/runtime/runManager.js +818 -0
  133. package/dist/runtime/runRetryCoordinator.d.ts +85 -0
  134. package/dist/runtime/runRetryCoordinator.js +372 -0
  135. package/dist/runtime/settingsFile.d.ts +17 -0
  136. package/dist/runtime/settingsFile.js +88 -0
  137. package/dist/runtime/stageAttemptBootstrap.d.ts +40 -0
  138. package/dist/runtime/stageAttemptBootstrap.js +82 -0
  139. package/dist/runtime/stageAttemptContext.d.ts +11 -0
  140. package/dist/runtime/stageAttemptContext.js +26 -0
  141. package/dist/runtime/stageConcurrency.d.ts +10 -0
  142. package/dist/runtime/stageConcurrency.js +51 -0
  143. package/dist/runtime/stageHitl.d.ts +95 -0
  144. package/dist/runtime/stageHitl.js +198 -0
  145. package/dist/runtime/stageProcessLauncher.d.ts +45 -0
  146. package/dist/runtime/stageProcessLauncher.js +199 -0
  147. package/dist/runtime/stageRecovery.d.ts +10 -0
  148. package/dist/runtime/stageRecovery.js +43 -0
  149. package/dist/runtime/stageRoots.d.ts +22 -0
  150. package/dist/runtime/stageRoots.js +93 -0
  151. package/dist/runtime/stageRunner.d.ts +59 -0
  152. package/dist/runtime/stageRunner.js +221 -0
  153. package/dist/runtime/stageWorker.d.ts +6 -0
  154. package/dist/runtime/stageWorker.js +109 -0
  155. package/dist/runtime/stageWorkerProtocol.d.ts +27 -0
  156. package/dist/runtime/stageWorkerProtocol.js +16 -0
  157. package/dist/runtime/taskInput.d.ts +15 -0
  158. package/dist/runtime/taskInput.js +38 -0
  159. package/dist/server/http.d.ts +31 -0
  160. package/dist/server/http.js +561 -0
  161. package/dist/server/providerRoutes.d.ts +15 -0
  162. package/dist/server/providerRoutes.js +186 -0
  163. package/dist/tools/askOperator.d.ts +185 -0
  164. package/dist/tools/askOperator.js +409 -0
  165. package/dist/tools/emitStageEnvelope.d.ts +42 -0
  166. package/dist/tools/emitStageEnvelope.js +61 -0
  167. package/dist/tools/writeStageArtifact.d.ts +26 -0
  168. package/dist/tools/writeStageArtifact.js +103 -0
  169. package/dist/types/envelope.d.ts +12 -0
  170. package/dist/types/envelope.js +6 -0
  171. package/dist/types/pipeline.d.ts +25 -0
  172. package/dist/types/pipeline.js +1 -0
  173. package/dist/types/stage.d.ts +12 -0
  174. package/dist/types/stage.js +6 -0
  175. package/dist/types/task.d.ts +7 -0
  176. package/dist/types/task.js +1 -0
  177. package/dist/ui/assets/index-Cry0Tpfx.js +118 -0
  178. package/dist/ui/assets/index-DCsDopak.css +1 -0
  179. package/dist/ui/index.html +21 -0
  180. package/package.json +72 -0
@@ -0,0 +1,196 @@
1
+ import { access } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { loadFailure, loadSuccess } from "./loadOutcome.js";
4
+ import { loadStageOutcome } from "./loadStage.js";
5
+ import { readYamlObject } from "./readYamlObject.js";
6
+ import { extractPipelineStageIds, resolvePipelineDag } from "./resolvePipelineDag.js";
7
+ import { findingStageIdFilenameMismatch, findingsFromLoadIssues, } from "./validateCatalog.js";
8
+ async function resolvePipelinePath(nameOrPath, cwd) {
9
+ const direct = path.resolve(cwd, nameOrPath);
10
+ try {
11
+ await access(direct);
12
+ return direct;
13
+ }
14
+ catch {
15
+ const candidate = path.resolve(cwd, "pipelines", `${nameOrPath}.yaml`);
16
+ await access(candidate);
17
+ return candidate;
18
+ }
19
+ }
20
+ export async function loadPipelineOutcome(nameOrPath, options = {}) {
21
+ const cwd = options.cwd ?? process.cwd();
22
+ const stagesDir = options.stagesDir ?? path.join(cwd, "stages");
23
+ let pipelinePath;
24
+ try {
25
+ pipelinePath = await resolvePipelinePath(nameOrPath, cwd);
26
+ }
27
+ catch (err) {
28
+ const message = err instanceof Error ? err.message : String(err);
29
+ return loadFailure([
30
+ {
31
+ code: "pipeline.load_error",
32
+ message,
33
+ category: "pipeline",
34
+ },
35
+ ]);
36
+ }
37
+ let raw;
38
+ try {
39
+ raw = await readYamlObject(pipelinePath);
40
+ }
41
+ catch (err) {
42
+ const message = err instanceof Error ? err.message : String(err);
43
+ return loadFailure([
44
+ {
45
+ code: "pipeline.load_error",
46
+ message,
47
+ category: "pipeline",
48
+ },
49
+ ]);
50
+ }
51
+ if (typeof raw?.id !== "string" || !Array.isArray(raw.stages)) {
52
+ return loadFailure([
53
+ {
54
+ code: "pipeline.invalid_shape",
55
+ message: `Invalid pipeline ${pipelinePath}: id and stages[] are required`,
56
+ category: "pipeline",
57
+ },
58
+ ]);
59
+ }
60
+ const pipelineId = raw.id;
61
+ const ctx = { pipelineId: raw.id, path: pipelinePath };
62
+ let stageIds;
63
+ let dag;
64
+ try {
65
+ const resolved = resolvePipelineDag(raw.stages, ctx);
66
+ stageIds = resolved.stages;
67
+ dag = resolved.dag;
68
+ }
69
+ catch (err) {
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ return loadFailure([
72
+ {
73
+ code: "pipeline.dag_error",
74
+ message,
75
+ category: "pipeline",
76
+ pipelineId,
77
+ },
78
+ ]);
79
+ }
80
+ const pipeline = {
81
+ id: raw.id,
82
+ stages: stageIds,
83
+ };
84
+ const stages = [];
85
+ for (const stageId of pipeline.stages) {
86
+ const stagePath = path.join(stagesDir, `${stageId}.yaml`);
87
+ const stageOutcome = await loadStageOutcome(stagePath);
88
+ if (!stageOutcome.ok) {
89
+ const message = `Pipeline ${pipeline.id} references missing stage "${stageId}" at ${stagePath}`;
90
+ return loadFailure([
91
+ {
92
+ code: "pipeline.missing_stage",
93
+ message,
94
+ category: "pipeline",
95
+ pipelineId,
96
+ },
97
+ ]);
98
+ }
99
+ stages.push(stageOutcome.value);
100
+ }
101
+ return loadSuccess({ pipeline, stages, dag });
102
+ }
103
+ async function checkStageIdFilename(cwd, stagePath) {
104
+ const fileStem = path.basename(stagePath, ".yaml");
105
+ try {
106
+ const raw = await readYamlObject(stagePath);
107
+ if (typeof raw?.id === "string" && raw.id !== fileStem) {
108
+ return findingStageIdFilenameMismatch(cwd, stagePath, fileStem, raw.id);
109
+ }
110
+ }
111
+ catch {
112
+ // loadStageOutcome will report read errors
113
+ }
114
+ return null;
115
+ }
116
+ async function validateStageFile(cwd, stagePath) {
117
+ const findings = [];
118
+ const mismatch = await checkStageIdFilename(cwd, stagePath);
119
+ if (mismatch)
120
+ findings.push(mismatch);
121
+ const outcome = await loadStageOutcome(stagePath);
122
+ if (!outcome.ok) {
123
+ findings.push(...findingsFromLoadIssues(cwd, stagePath, outcome.issues));
124
+ return findings;
125
+ }
126
+ if (!mismatch && path.basename(stagePath, ".yaml") !== outcome.value.id) {
127
+ findings.push(findingStageIdFilenameMismatch(cwd, stagePath, path.basename(stagePath, ".yaml"), outcome.value.id));
128
+ }
129
+ return findings;
130
+ }
131
+ export async function loadPipelineValidated(nameOrPath, options = {}) {
132
+ const cwd = options.cwd ?? process.cwd();
133
+ const stagesDir = options.stagesDir ?? path.join(cwd, "stages");
134
+ const validateStages = options.validateStages ?? true;
135
+ let pipelinePath;
136
+ try {
137
+ pipelinePath = await resolvePipelinePath(nameOrPath, cwd);
138
+ }
139
+ catch (err) {
140
+ const message = err instanceof Error ? err.message : String(err);
141
+ return {
142
+ ok: false,
143
+ findings: findingsFromLoadIssues(cwd, path.resolve(cwd, nameOrPath), [
144
+ {
145
+ code: "pipeline.load_error",
146
+ message,
147
+ category: "pipeline",
148
+ },
149
+ ]),
150
+ };
151
+ }
152
+ const referencedStageIds = new Set();
153
+ try {
154
+ const raw = await readYamlObject(pipelinePath);
155
+ if (typeof raw?.id === "string" && Array.isArray(raw.stages)) {
156
+ const stageIds = extractPipelineStageIds(raw.stages);
157
+ if (stageIds) {
158
+ for (const stageId of stageIds) {
159
+ referencedStageIds.add(stageId);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ catch {
165
+ // loadPipelineOutcome will report read errors
166
+ }
167
+ const outcome = await loadPipelineOutcome(nameOrPath, { cwd, stagesDir });
168
+ const findings = [];
169
+ if (!outcome.ok) {
170
+ findings.push(...findingsFromLoadIssues(cwd, pipelinePath, outcome.issues));
171
+ if (validateStages) {
172
+ for (const stageId of referencedStageIds) {
173
+ const stagePath = path.join(stagesDir, `${stageId}.yaml`);
174
+ findings.push(...(await validateStageFile(cwd, stagePath)));
175
+ }
176
+ }
177
+ return { ok: false, findings };
178
+ }
179
+ if (validateStages) {
180
+ for (const stageId of outcome.value.pipeline.stages) {
181
+ const stagePath = path.join(stagesDir, `${stageId}.yaml`);
182
+ findings.push(...(await validateStageFile(cwd, stagePath)));
183
+ }
184
+ }
185
+ if (findings.some((finding) => finding.severity === "error")) {
186
+ return { ok: false, findings };
187
+ }
188
+ return { ok: true, loaded: outcome.value };
189
+ }
190
+ export async function loadPipeline(nameOrPath, options = {}) {
191
+ const outcome = await loadPipelineOutcome(nameOrPath, options);
192
+ if (!outcome.ok) {
193
+ throw new Error(outcome.issues[0].message);
194
+ }
195
+ return outcome.value;
196
+ }
@@ -0,0 +1,4 @@
1
+ import { type StageConfig } from "../types/stage.js";
2
+ import { type LoadOutcome } from "./loadOutcome.js";
3
+ export declare function loadStageOutcome(filePath: string): Promise<LoadOutcome<StageConfig>>;
4
+ export declare function loadStage(filePath: string): Promise<StageConfig>;
@@ -0,0 +1,127 @@
1
+ import { STAGE_GATE_KINDS, } from "../types/stage.js";
2
+ import { compilePayloadSchema } from "../envelope/payloadSchema.js";
3
+ import { loadFailure, loadSuccess } from "./loadOutcome.js";
4
+ import { readYamlObject } from "./readYamlObject.js";
5
+ function isGateKind(value) {
6
+ return STAGE_GATE_KINDS.includes(value);
7
+ }
8
+ function parseGateKinds(raw, filePath) {
9
+ if (raw === undefined)
10
+ return loadSuccess(undefined);
11
+ if (!Array.isArray(raw) || !raw.every((item) => typeof item === "string")) {
12
+ return loadFailure([
13
+ {
14
+ code: "stage.invalid_gate_kinds",
15
+ message: `Invalid stage file ${filePath}: gate_kinds must be an array of strings`,
16
+ category: "stage",
17
+ },
18
+ ]);
19
+ }
20
+ const kinds = [];
21
+ for (const item of raw) {
22
+ if (!isGateKind(item)) {
23
+ return loadFailure([
24
+ {
25
+ code: "stage.invalid_gate_kinds",
26
+ message: `Invalid stage file ${filePath}: unsupported gate kind "${item}" (allowed: ${STAGE_GATE_KINDS.join(", ")})`,
27
+ category: "stage",
28
+ },
29
+ ]);
30
+ }
31
+ kinds.push(item);
32
+ }
33
+ return loadSuccess(kinds.length > 0 ? kinds : undefined);
34
+ }
35
+ export async function loadStageOutcome(filePath) {
36
+ let raw;
37
+ try {
38
+ raw = await readYamlObject(filePath);
39
+ }
40
+ catch (err) {
41
+ const message = err instanceof Error ? err.message : String(err);
42
+ return loadFailure([
43
+ {
44
+ code: "stage.load_error",
45
+ message,
46
+ category: "stage",
47
+ },
48
+ ]);
49
+ }
50
+ if (typeof raw?.id !== "string" ||
51
+ typeof raw?.system_prompt !== "string" ||
52
+ typeof raw?.model !== "string") {
53
+ return loadFailure([
54
+ {
55
+ code: "stage.invalid_shape",
56
+ message: `Invalid stage file ${filePath}: id, system_prompt, and model are required strings`,
57
+ category: "stage",
58
+ stageId: typeof raw?.id === "string" ? raw.id : undefined,
59
+ },
60
+ ]);
61
+ }
62
+ const stage = {
63
+ id: raw.id,
64
+ system_prompt: raw.system_prompt,
65
+ model: raw.model,
66
+ };
67
+ if (raw.payload_schema !== undefined) {
68
+ if (raw.payload_schema === null ||
69
+ typeof raw.payload_schema !== "object" ||
70
+ Array.isArray(raw.payload_schema)) {
71
+ return loadFailure([
72
+ {
73
+ code: "stage.invalid_payload_schema",
74
+ message: `Invalid stage file ${filePath}: payload_schema must be an object`,
75
+ category: "stage",
76
+ stageId: raw.id,
77
+ },
78
+ ]);
79
+ }
80
+ try {
81
+ compilePayloadSchema(raw.payload_schema);
82
+ }
83
+ catch (err) {
84
+ const message = err instanceof Error ? err.message : String(err);
85
+ return loadFailure([
86
+ {
87
+ code: "stage.invalid_payload_schema",
88
+ message: `Invalid stage file ${filePath}: invalid payload_schema: ${message}`,
89
+ category: "stage",
90
+ stageId: raw.id,
91
+ },
92
+ ]);
93
+ }
94
+ stage.payload_schema = raw.payload_schema;
95
+ }
96
+ const gateKindsOutcome = parseGateKinds(raw.gate_kinds, filePath);
97
+ if (!gateKindsOutcome.ok) {
98
+ const issues = gateKindsOutcome.issues.map((issue) => ({
99
+ ...issue,
100
+ stageId: stage.id,
101
+ }));
102
+ return loadFailure(issues);
103
+ }
104
+ if (gateKindsOutcome.value)
105
+ stage.gate_kinds = gateKindsOutcome.value;
106
+ if (raw.skill !== undefined) {
107
+ if (typeof raw.skill !== "string" || raw.skill.trim() === "") {
108
+ return loadFailure([
109
+ {
110
+ code: "stage.invalid_skill",
111
+ message: `Invalid stage file ${filePath}: skill must be a non-empty string`,
112
+ category: "stage",
113
+ stageId: stage.id,
114
+ },
115
+ ]);
116
+ }
117
+ stage.skill = raw.skill.trim();
118
+ }
119
+ return loadSuccess(stage);
120
+ }
121
+ export async function loadStage(filePath) {
122
+ const outcome = await loadStageOutcome(filePath);
123
+ if (!outcome.ok) {
124
+ throw new Error(outcome.issues[0].message);
125
+ }
126
+ return outcome.value;
127
+ }
@@ -0,0 +1,7 @@
1
+ import type { TaskFile } from "../types/task.js";
2
+ import { type LoadOutcome } from "./loadOutcome.js";
3
+ export declare function parseTaskFile(raw: unknown, source?: string): LoadOutcome<TaskFile>;
4
+ export declare function loadTaskFromYamlOutcome(yamlText: string, source?: string): LoadOutcome<TaskFile>;
5
+ export declare function loadTaskOutcome(filePath: string): Promise<LoadOutcome<TaskFile>>;
6
+ export declare function loadTaskFromYaml(yamlText: string, source?: string): TaskFile;
7
+ export declare function loadTask(filePath: string): Promise<TaskFile>;
@@ -0,0 +1,69 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parse as parseYaml } from "yaml";
3
+ import { loadFailure, loadSuccess } from "./loadOutcome.js";
4
+ export function parseTaskFile(raw, source = "task") {
5
+ const record = raw;
6
+ if (typeof record?.id !== "string" || typeof record?.goal !== "string") {
7
+ return loadFailure([
8
+ {
9
+ code: "task.invalid_shape",
10
+ message: `Invalid ${source}: id and goal are required strings`,
11
+ category: "task",
12
+ taskId: typeof record?.id === "string" ? record.id : undefined,
13
+ },
14
+ ]);
15
+ }
16
+ return loadSuccess({
17
+ id: record.id,
18
+ goal: record.goal,
19
+ context: typeof record.context === "string" ? record.context : undefined,
20
+ constraints: typeof record.constraints === "string" ? record.constraints : undefined,
21
+ checkout: typeof record.checkout === "string" ? record.checkout : undefined,
22
+ });
23
+ }
24
+ export function loadTaskFromYamlOutcome(yamlText, source = "task yaml") {
25
+ let raw;
26
+ try {
27
+ raw = parseYaml(yamlText);
28
+ }
29
+ catch (err) {
30
+ const message = err instanceof Error ? err.message : String(err);
31
+ return loadFailure([
32
+ {
33
+ code: "task.load_error",
34
+ message,
35
+ category: "task",
36
+ },
37
+ ]);
38
+ }
39
+ return parseTaskFile(raw, source);
40
+ }
41
+ export async function loadTaskOutcome(filePath) {
42
+ let yamlText;
43
+ try {
44
+ yamlText = await readFile(filePath, "utf8");
45
+ }
46
+ catch (err) {
47
+ const message = err instanceof Error ? err.message : String(err);
48
+ return loadFailure([
49
+ {
50
+ code: "task.load_error",
51
+ message,
52
+ category: "task",
53
+ },
54
+ ]);
55
+ }
56
+ return loadTaskFromYamlOutcome(yamlText, `task file ${filePath}`);
57
+ }
58
+ export function loadTaskFromYaml(yamlText, source = "task yaml") {
59
+ const outcome = loadTaskFromYamlOutcome(yamlText, source);
60
+ if (!outcome.ok)
61
+ throw new Error(outcome.issues[0].message);
62
+ return outcome.value;
63
+ }
64
+ export async function loadTask(filePath) {
65
+ const outcome = await loadTaskOutcome(filePath);
66
+ if (!outcome.ok)
67
+ throw new Error(outcome.issues[0].message);
68
+ return outcome.value;
69
+ }
@@ -0,0 +1 @@
1
+ export declare function readYamlObject(filePath: string): Promise<Record<string, unknown>>;
@@ -0,0 +1,5 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parse as parseYaml } from "yaml";
3
+ export async function readYamlObject(filePath) {
4
+ return parseYaml(await readFile(filePath, "utf8"));
5
+ }
@@ -0,0 +1,12 @@
1
+ import type { PipelineStageYamlEntry, ResolvedPipelineDag } from "../types/pipeline.js";
2
+ export type ResolvePipelineDagContext = {
3
+ pipelineId: string;
4
+ path: string;
5
+ };
6
+ export declare function parsePipelineStageEntries(raw: unknown, ctx: ResolvePipelineDagContext): PipelineStageYamlEntry[];
7
+ export declare function resolvePipelineDag(rawStages: unknown, ctx: ResolvePipelineDagContext): {
8
+ stages: string[];
9
+ dag: ResolvedPipelineDag;
10
+ };
11
+ export declare function areResolvedDagsEquivalent(a: ResolvedPipelineDag, b: ResolvedPipelineDag): boolean;
12
+ export declare function extractPipelineStageIds(rawStages: unknown[]): string[] | null;