stageflow 0.2.0 → 0.8.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.
- package/README.md +179 -14
- package/dist/agent/activity.d.ts +12 -1
- package/dist/agent/activity.js +37 -2
- package/dist/agent/activityObserver.d.ts +5 -1
- package/dist/agent/activityObserver.js +174 -11
- package/dist/agent/cursorProvider.d.ts +1 -10
- package/dist/agent/cursorProvider.js +18 -10
- package/dist/agent/fakeAgent.js +15 -7
- package/dist/agent/piAdapter.d.ts +18 -1
- package/dist/agent/piAdapter.js +115 -45
- package/dist/agent/port.d.ts +7 -0
- package/dist/agent/port.js +3 -0
- package/dist/agent/providerAuth.js +12 -7
- package/dist/catalog/displayCatalogPath.d.ts +12 -0
- package/dist/catalog/displayCatalogPath.js +28 -0
- package/dist/cli/artifactCommand.d.ts +10 -0
- package/dist/cli/artifactCommand.js +120 -0
- package/dist/cli/envelopeCommand.d.ts +32 -0
- package/dist/cli/envelopeCommand.js +285 -0
- package/dist/cli/exportRunCommand.d.ts +10 -0
- package/dist/cli/exportRunCommand.js +150 -0
- package/dist/cli/handoffFormat.d.ts +22 -0
- package/dist/cli/handoffFormat.js +61 -0
- package/dist/cli/initCommand.d.ts +9 -0
- package/dist/cli/initCommand.js +71 -0
- package/dist/cli/initTemplates.d.ts +3 -0
- package/dist/cli/initTemplates.js +19 -0
- package/dist/cli/operatorCatalog.d.ts +10 -0
- package/dist/cli/operatorCatalog.js +16 -0
- package/dist/cli/runCommand.d.ts +7 -1
- package/dist/cli/runCommand.js +83 -11
- package/dist/cli/runOutput.d.ts +4 -1
- package/dist/cli/runOutput.js +36 -8
- package/dist/cli/skillsCommand.d.ts +16 -0
- package/dist/cli/skillsCommand.js +459 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +20 -3
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +128 -22
- package/dist/config/browseCatalog.d.ts +45 -0
- package/dist/config/browseCatalog.js +170 -0
- package/dist/config/createPipeline.d.ts +12 -3
- package/dist/config/createPipeline.js +292 -100
- package/dist/config/createStage.d.ts +10 -4
- package/dist/config/createStage.js +44 -14
- package/dist/config/listConfig.d.ts +14 -19
- package/dist/config/listConfig.js +26 -191
- package/dist/config/listModelsFromManifest.d.ts +2 -0
- package/dist/config/listModelsFromManifest.js +4 -0
- package/dist/config/loadOutcome.d.ts +4 -0
- package/dist/config/loadPipeline.d.ts +1 -15
- package/dist/config/loadPipeline.js +88 -142
- package/dist/config/loadStage.d.ts +4 -0
- package/dist/config/loadStage.js +60 -32
- package/dist/config/loadStageflowManifest.d.ts +5 -0
- package/dist/config/loadStageflowManifest.js +157 -0
- package/dist/config/mergePipelineIncludes.d.ts +9 -0
- package/dist/config/mergePipelineIncludes.js +141 -0
- package/dist/config/normalizePipelineStageEntry.d.ts +18 -0
- package/dist/config/normalizePipelineStageEntry.js +210 -0
- package/dist/config/pipelineStageKeys.d.ts +4 -0
- package/dist/config/pipelineStageKeys.js +14 -0
- package/dist/config/resolveCatalogContext.d.ts +13 -0
- package/dist/config/resolveCatalogContext.js +13 -0
- package/dist/config/resolveForkEmitContext.d.ts +4 -0
- package/dist/config/resolveForkEmitContext.js +34 -0
- package/dist/config/resolvePipelineDag.d.ts +5 -1
- package/dist/config/resolvePipelineDag.js +86 -36
- package/dist/config/scanCatalogPaths.d.ts +4 -0
- package/dist/config/scanCatalogPaths.js +83 -0
- package/dist/config/validateCatalog.d.ts +22 -4
- package/dist/config/validateCatalog.js +169 -132
- package/dist/envelope/check.d.ts +2 -0
- package/dist/envelope/check.js +58 -0
- package/dist/envelope/cloneForks.d.ts +2 -0
- package/dist/envelope/cloneForks.js +62 -0
- package/dist/envelope/forkChoice.d.ts +3 -0
- package/dist/envelope/forkChoice.js +47 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/mcp/catalogTools.d.ts +3 -0
- package/dist/mcp/catalogTools.js +187 -0
- package/dist/mcp/controlTools.d.ts +3 -0
- package/dist/mcp/controlTools.js +147 -0
- package/dist/mcp/deps.d.ts +11 -0
- package/dist/mcp/deps.js +1 -0
- package/dist/mcp/projectRun.d.ts +1 -37
- package/dist/mcp/projectRun.js +1 -57
- package/dist/mcp/resources.d.ts +5 -0
- package/dist/mcp/resources.js +45 -0
- package/dist/mcp/server.d.ts +16 -3
- package/dist/mcp/server.js +159 -3
- package/dist/mcp/toolResults.d.ts +7 -0
- package/dist/mcp/toolResults.js +6 -0
- package/dist/mcp/tools.d.ts +2 -7
- package/dist/mcp/tools.js +52 -86
- package/dist/mcp/waitRun.d.ts +46 -0
- package/dist/mcp/waitRun.js +146 -0
- package/dist/mcp/waitingGates.d.ts +12 -0
- package/dist/mcp/waitingGates.js +83 -0
- package/dist/project/findProjectRoot.d.ts +2 -0
- package/dist/project/findProjectRoot.js +51 -0
- package/dist/project/globalHome.d.ts +2 -0
- package/dist/project/globalHome.js +19 -0
- package/dist/project/resolveProjectContext.d.ts +9 -0
- package/dist/project/resolveProjectContext.js +38 -0
- package/dist/project/resolveStageflowContext.d.ts +11 -0
- package/dist/project/resolveStageflowContext.js +66 -0
- package/dist/projection/projectRun.d.ts +44 -0
- package/dist/projection/projectRun.js +71 -0
- package/dist/prompt/priorEnvelope.d.ts +1 -1
- package/dist/prompt/priorEnvelope.js +4 -1
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +4 -0
- package/dist/runstore/paths.js +2 -0
- package/dist/runstore/pipelineDagSnapshot.d.ts +9 -0
- package/dist/runstore/pipelineDagSnapshot.js +90 -1
- package/dist/runstore/port.d.ts +22 -2
- package/dist/runstore/port.js +4 -1
- package/dist/runstore/runProjection.d.ts +1 -1
- package/dist/runstore/runProjection.js +25 -4
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +3 -2
- package/dist/runstore/sqlite/SqliteRunStore.js +65 -7
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +4 -1
- package/dist/runstore/stageInstanceId.d.ts +4 -0
- package/dist/runstore/stageInstanceId.js +23 -0
- package/dist/runstore/syntheticStageSnapshot.d.ts +1 -1
- package/dist/runstore/syntheticStageSnapshot.js +2 -1
- package/dist/runstore/trackProjection.js +28 -12
- package/dist/runstore/workspaceLayout.d.ts +1 -0
- package/dist/runstore/workspaceLayout.js +1 -1
- package/dist/runtime/cloneSchedule.d.ts +18 -0
- package/dist/runtime/cloneSchedule.js +233 -0
- package/dist/runtime/credentialBinding.d.ts +8 -6
- package/dist/runtime/credentialBinding.js +18 -24
- package/dist/runtime/envelopeRouting.d.ts +2 -1
- package/dist/runtime/envelopeRouting.js +80 -13
- package/dist/runtime/pipelineRunner.d.ts +3 -0
- package/dist/runtime/pipelineRunner.js +15 -1
- package/dist/runtime/pipelineScheduler.d.ts +8 -2
- package/dist/runtime/pipelineScheduler.js +215 -39
- package/dist/runtime/reloadRunCatalog.d.ts +5 -0
- package/dist/runtime/reloadRunCatalog.js +44 -0
- package/dist/runtime/resumeReconstruct.d.ts +1 -0
- package/dist/runtime/resumeReconstruct.js +31 -10
- package/dist/runtime/runChangeBus.d.ts +18 -0
- package/dist/runtime/runChangeBus.js +83 -0
- package/dist/runtime/runManager.d.ts +4 -0
- package/dist/runtime/runManager.js +36 -16
- package/dist/runtime/settingsFile.d.ts +12 -0
- package/dist/runtime/settingsFile.js +87 -6
- package/dist/runtime/stageAttemptBootstrap.d.ts +1 -0
- package/dist/runtime/stageAttemptBootstrap.js +18 -7
- package/dist/runtime/stageProcessLauncher.js +3 -0
- package/dist/runtime/stageRecovery.js +3 -1
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +17 -15
- package/dist/runtime/stageWorker.js +13 -10
- package/dist/server/bootstrap.d.ts +32 -0
- package/dist/server/bootstrap.js +56 -0
- package/dist/server/createHttpHost.d.ts +34 -0
- package/dist/server/createHttpHost.js +70 -0
- package/dist/server/http.d.ts +6 -13
- package/dist/server/http.js +297 -352
- package/dist/server/mcpHost.d.ts +22 -0
- package/dist/server/mcpHost.js +21 -0
- package/dist/server/operatorResults.d.ts +13 -0
- package/dist/server/operatorResults.js +22 -0
- package/dist/tools/emitStageEnvelope.d.ts +12 -1
- package/dist/tools/emitStageEnvelope.js +27 -1
- package/dist/types/envelope.d.ts +3 -0
- package/dist/types/forkChoice.d.ts +30 -0
- package/dist/types/forkChoice.js +1 -0
- package/dist/types/pipeline.d.ts +59 -2
- package/dist/types/stageflowManifest.d.ts +23 -0
- package/dist/types/stageflowManifest.js +1 -0
- package/dist/ui/assets/{index-DCsDopak.css → index-C3N7MXAC.css} +1 -1
- package/dist/ui/assets/index-CSoGDA3A.js +118 -0
- package/dist/ui/index.html +3 -2
- package/dist/ui/stageflow-icon.svg +12 -0
- package/package.json +8 -5
- package/skills/install-suite.sh +107 -0
- package/skills/stageflow/SKILL.md +26 -0
- package/skills/stageflow/references/control-surface.md +26 -0
- package/skills/stageflow/scripts/detect-host.mjs +54 -0
- package/skills/stageflow/scripts/detect-host.test.mjs +97 -0
- package/skills/stageflow-author/SKILL.md +58 -0
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -0
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -0
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +13 -0
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +9 -0
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +15 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -0
- package/skills/stageflow-author/references/catalog-mapping.md +131 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +29 -0
- package/skills/stageflow-author/references/stage-prompt-template.md +55 -0
- package/skills/stageflow-author/references/validate-and-report.md +38 -0
- package/skills/stageflow-delegate/SKILL.md +18 -0
- package/skills/stageflow-delegate/references/authoring-or-run.md +15 -0
- package/skills/stageflow-delegate/references/example-walkthrough.md +30 -0
- package/skills/stageflow-delegate/references/pattern-detection.md +44 -0
- package/skills/stageflow-run/SKILL.md +151 -0
- package/skills/stageflow-run/references/mcp-call.md +17 -0
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +52 -0
- package/skills/stageflow-run/scripts/mcp-call.mjs +299 -0
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +271 -0
- package/skills/stageflow-session-capture/SKILL.md +94 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +7 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +8 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +8 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +40 -0
- package/skills/stageflow-session-capture/references/transcript-sources.md +25 -0
- package/skills/stageflow-session-capture/scripts/check-provider-gate.mjs +43 -0
- package/skills/stageflow-session-capture/scripts/locate-session-transcript.mjs +141 -0
- package/skills/stageflow-session-capture/scripts/resolve-catalog-id.mjs +119 -0
- package/skills/stageflow-setup/SKILL.md +110 -0
- package/dist/ui/assets/index-Cry0Tpfx.js +0 -118
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { readdir } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import { loadPipelineOutcome,
|
|
2
|
+
import { loadPipelineOutcome, resolvePipelinePath } from "./loadPipeline.js";
|
|
4
3
|
import { loadStageOutcome } from "./loadStage.js";
|
|
4
|
+
import { loadTaskOutcome } from "./loadTask.js";
|
|
5
5
|
import { readYamlObject } from "./readYamlObject.js";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveCatalogContext } from "./resolveCatalogContext.js";
|
|
7
|
+
import { getCatalogScanPaths } from "./browseCatalog.js";
|
|
8
|
+
import { manifestPathForProject } from "./loadStageflowManifest.js";
|
|
7
9
|
export function relPath(cwd, absPath) {
|
|
8
|
-
return path.relative(cwd, absPath);
|
|
10
|
+
return path.relative(cwd, absPath).replace(/\\/g, "/");
|
|
9
11
|
}
|
|
12
|
+
const STRICT_CATALOG_WARNINGS = new Set([
|
|
13
|
+
"catalog.manifest_missing",
|
|
14
|
+
"catalog.empty_catalog",
|
|
15
|
+
]);
|
|
10
16
|
const SEVERITY_RANK = {
|
|
11
17
|
error: 0,
|
|
12
18
|
warning: 1,
|
|
@@ -28,7 +34,7 @@ function sortFindings(findings) {
|
|
|
28
34
|
export function effectiveSeverity(finding, strict) {
|
|
29
35
|
if (strict &&
|
|
30
36
|
finding.severity === "warning" &&
|
|
31
|
-
finding.code
|
|
37
|
+
STRICT_CATALOG_WARNINGS.has(finding.code)) {
|
|
32
38
|
return "error";
|
|
33
39
|
}
|
|
34
40
|
return finding.severity;
|
|
@@ -82,6 +88,24 @@ function findingStageError(cwd, absPath, message, code, stageId) {
|
|
|
82
88
|
stageId,
|
|
83
89
|
}, "error");
|
|
84
90
|
}
|
|
91
|
+
function findingTaskError(cwd, absPath, message, code) {
|
|
92
|
+
return baseFinding({
|
|
93
|
+
cwd,
|
|
94
|
+
absPath,
|
|
95
|
+
message,
|
|
96
|
+
code,
|
|
97
|
+
category: "task",
|
|
98
|
+
}, "error");
|
|
99
|
+
}
|
|
100
|
+
function findingCatalog(cwd, absPath, message, code, severity) {
|
|
101
|
+
return baseFinding({
|
|
102
|
+
cwd,
|
|
103
|
+
absPath,
|
|
104
|
+
message,
|
|
105
|
+
code,
|
|
106
|
+
category: "catalog",
|
|
107
|
+
}, severity);
|
|
108
|
+
}
|
|
85
109
|
export function findingsFromLoadIssues(cwd, absPath, issues) {
|
|
86
110
|
return issues.flatMap((issue) => {
|
|
87
111
|
if (issue.category === "pipeline") {
|
|
@@ -94,6 +118,18 @@ export function findingsFromLoadIssues(cwd, absPath, issues) {
|
|
|
94
118
|
findingStageError(cwd, absPath, issue.message, issue.code, issue.stageId),
|
|
95
119
|
];
|
|
96
120
|
}
|
|
121
|
+
if (issue.category === "task") {
|
|
122
|
+
return [
|
|
123
|
+
findingTaskError(cwd, absPath, issue.message, issue.code),
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
if (issue.category === "catalog") {
|
|
127
|
+
const code = issue.code;
|
|
128
|
+
const severity = code === "catalog.manifest_missing" || code === "catalog.empty_catalog"
|
|
129
|
+
? "warning"
|
|
130
|
+
: "error";
|
|
131
|
+
return [findingCatalog(cwd, absPath, issue.message, code, severity)];
|
|
132
|
+
}
|
|
97
133
|
return [];
|
|
98
134
|
});
|
|
99
135
|
}
|
|
@@ -107,40 +143,6 @@ export function findingStageIdFilenameMismatch(cwd, absPath, fileStem, declaredI
|
|
|
107
143
|
stageId: declaredId,
|
|
108
144
|
}, "error");
|
|
109
145
|
}
|
|
110
|
-
function findingCatalogDuplicatePipelineId(cwd, absPath, pipelineId, conflictingPaths) {
|
|
111
|
-
const relConflicts = conflictingPaths.map((p) => relPath(cwd, p));
|
|
112
|
-
return baseFinding({
|
|
113
|
-
cwd,
|
|
114
|
-
absPath,
|
|
115
|
-
message: `Duplicate pipeline id "${pipelineId}" declared in: ${relConflicts.join(", ")}`,
|
|
116
|
-
code: "catalog.duplicate_pipeline_id",
|
|
117
|
-
category: "catalog",
|
|
118
|
-
pipelineId,
|
|
119
|
-
}, "error");
|
|
120
|
-
}
|
|
121
|
-
function findingCatalogOrphanStage(cwd, absPath, stageId) {
|
|
122
|
-
return baseFinding({
|
|
123
|
-
cwd,
|
|
124
|
-
absPath,
|
|
125
|
-
message: `Stage "${stageId}" is not referenced by any pipeline`,
|
|
126
|
-
code: "catalog.orphan_stage",
|
|
127
|
-
category: "catalog",
|
|
128
|
-
stageId,
|
|
129
|
-
}, "warning");
|
|
130
|
-
}
|
|
131
|
-
async function listYamlFiles(dir) {
|
|
132
|
-
let entries;
|
|
133
|
-
try {
|
|
134
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
return [];
|
|
138
|
-
}
|
|
139
|
-
return entries
|
|
140
|
-
.filter((entry) => entry.isFile() && entry.name.endsWith(".yaml"))
|
|
141
|
-
.map((entry) => path.join(dir, entry.name))
|
|
142
|
-
.sort((a, b) => a.localeCompare(b));
|
|
143
|
-
}
|
|
144
146
|
async function checkStageIdFilename(cwd, stagePath) {
|
|
145
147
|
const fileStem = path.basename(stagePath, ".yaml");
|
|
146
148
|
try {
|
|
@@ -169,52 +171,79 @@ async function validateStageFile(cwd, stagePath) {
|
|
|
169
171
|
}
|
|
170
172
|
return findings;
|
|
171
173
|
}
|
|
172
|
-
async function
|
|
173
|
-
const { cwd,
|
|
174
|
-
|
|
175
|
-
const referencedStageIds = new Set();
|
|
176
|
-
let pipelineId;
|
|
174
|
+
async function runPipelineValidation(nameOrPath, options) {
|
|
175
|
+
const { cwd, validateStages } = options;
|
|
176
|
+
let pipelinePath;
|
|
177
177
|
try {
|
|
178
|
-
|
|
179
|
-
if (typeof raw?.id === "string") {
|
|
180
|
-
pipelineId = raw.id;
|
|
181
|
-
if (Array.isArray(raw.stages)) {
|
|
182
|
-
const stageIds = extractPipelineStageIds(raw.stages);
|
|
183
|
-
if (stageIds) {
|
|
184
|
-
for (const stageId of stageIds) {
|
|
185
|
-
referencedStageIds.add(stageId);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
178
|
+
pipelinePath = await resolvePipelinePath(nameOrPath, cwd);
|
|
190
179
|
}
|
|
191
|
-
catch {
|
|
192
|
-
|
|
180
|
+
catch (err) {
|
|
181
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
182
|
+
return {
|
|
183
|
+
ok: false,
|
|
184
|
+
findings: findingsFromLoadIssues(cwd, path.resolve(cwd, nameOrPath), [
|
|
185
|
+
{
|
|
186
|
+
code: "pipeline.load_error",
|
|
187
|
+
message,
|
|
188
|
+
category: "pipeline",
|
|
189
|
+
},
|
|
190
|
+
]),
|
|
191
|
+
};
|
|
193
192
|
}
|
|
194
|
-
const outcome = await loadPipelineOutcome(pipelinePath, { cwd
|
|
193
|
+
const outcome = await loadPipelineOutcome(pipelinePath, { cwd });
|
|
194
|
+
const findings = [];
|
|
195
195
|
if (!outcome.ok) {
|
|
196
196
|
findings.push(...findingsFromLoadIssues(cwd, pipelinePath, outcome.issues));
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
return { ok: false, findings };
|
|
198
|
+
}
|
|
199
|
+
if (validateStages && outcome.value.stageSources) {
|
|
200
|
+
for (const source of Object.values(outcome.value.stageSources)) {
|
|
201
|
+
if (source.kind === "file") {
|
|
202
|
+
findings.push(...(await validateStageFile(cwd, source.path)));
|
|
201
203
|
}
|
|
202
204
|
}
|
|
203
|
-
return { findings, pipelineId, referencedStageIds };
|
|
204
205
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (validateStages) {
|
|
208
|
-
const stagePath = path.join(stagesDir, `${stageId}.yaml`);
|
|
209
|
-
findings.push(...(await validateStageFile(cwd, stagePath)));
|
|
210
|
-
}
|
|
206
|
+
if (findings.some((finding) => finding.severity === "error")) {
|
|
207
|
+
return { ok: false, findings };
|
|
211
208
|
}
|
|
212
|
-
return {
|
|
209
|
+
return { ok: true, loaded: outcome.value, findings };
|
|
210
|
+
}
|
|
211
|
+
export async function validatePipeline(nameOrPath, options = {}) {
|
|
212
|
+
const cwd = options.cwd ?? process.cwd();
|
|
213
|
+
const validateStages = options.validateStages ?? true;
|
|
214
|
+
const strict = options.strict ?? false;
|
|
215
|
+
const core = await runPipelineValidation(nameOrPath, { cwd, validateStages });
|
|
216
|
+
return buildValidationResult("pipeline", core.findings, strict);
|
|
213
217
|
}
|
|
214
|
-
async function
|
|
215
|
-
const
|
|
218
|
+
export async function loadPipelineValidated(nameOrPath, options = {}) {
|
|
219
|
+
const cwd = options.cwd ?? process.cwd();
|
|
220
|
+
const validateStages = options.validateStages ?? true;
|
|
221
|
+
const core = await runPipelineValidation(nameOrPath, { cwd, validateStages });
|
|
222
|
+
if (core.ok) {
|
|
223
|
+
return { ok: true, loaded: core.loaded };
|
|
224
|
+
}
|
|
225
|
+
return { ok: false, findings: core.findings };
|
|
226
|
+
}
|
|
227
|
+
function findingCatalogDuplicatePipelineId(cwd, absPath, pipelineId, conflictingPaths) {
|
|
228
|
+
const relConflicts = conflictingPaths.map((p) => relPath(cwd, p));
|
|
229
|
+
return baseFinding({
|
|
230
|
+
cwd,
|
|
231
|
+
absPath,
|
|
232
|
+
message: `Duplicate pipeline id "${pipelineId}" declared in: ${relConflicts.join(", ")}`,
|
|
233
|
+
code: "catalog.duplicate_pipeline_id",
|
|
234
|
+
category: "catalog",
|
|
235
|
+
pipelineId,
|
|
236
|
+
}, "error");
|
|
237
|
+
}
|
|
238
|
+
function findingManifestMissing(cwd, projectRoot) {
|
|
239
|
+
return findingCatalog(cwd, manifestPathForProject(projectRoot), "No stageflow.yaml manifest found at project root", "catalog.manifest_missing", "warning");
|
|
240
|
+
}
|
|
241
|
+
function findingEmptyCatalog(cwd, manifestPath, kind) {
|
|
242
|
+
return findingCatalog(cwd, manifestPath, `Manifest catalog.${kind} is empty`, "catalog.empty_catalog", "warning");
|
|
243
|
+
}
|
|
244
|
+
async function collectPipelineIdsFromPaths(pipelinePaths) {
|
|
216
245
|
const idToPaths = new Map();
|
|
217
|
-
for (const filePath of
|
|
246
|
+
for (const filePath of pipelinePaths) {
|
|
218
247
|
try {
|
|
219
248
|
const raw = await readYamlObject(filePath);
|
|
220
249
|
if (typeof raw?.id !== "string")
|
|
@@ -240,83 +269,91 @@ function findingsForDuplicatePipelineIds(cwd, idToPaths) {
|
|
|
240
269
|
}
|
|
241
270
|
return findings;
|
|
242
271
|
}
|
|
243
|
-
async function
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (typeof raw?.id !== "string" || !Array.isArray(raw.stages))
|
|
250
|
-
continue;
|
|
251
|
-
const stageIds = extractPipelineStageIds(raw.stages);
|
|
252
|
-
if (!stageIds)
|
|
253
|
-
continue;
|
|
254
|
-
for (const stageId of stageIds) {
|
|
255
|
-
referenced.add(stageId);
|
|
256
|
-
}
|
|
272
|
+
async function validateManifestAll(invocationCwd) {
|
|
273
|
+
const ctx = await resolveCatalogContext(invocationCwd);
|
|
274
|
+
const findings = [];
|
|
275
|
+
if (ctx.manifestStatus === "not_git" || ctx.manifestStatus === "missing") {
|
|
276
|
+
if (ctx.projectRoot) {
|
|
277
|
+
findings.push(findingManifestMissing(invocationCwd, ctx.projectRoot));
|
|
257
278
|
}
|
|
258
|
-
|
|
259
|
-
|
|
279
|
+
else {
|
|
280
|
+
findings.push(findingCatalog(invocationCwd, path.resolve(invocationCwd), "Not inside a git repository; no catalog manifest", "catalog.manifest_missing", "warning"));
|
|
260
281
|
}
|
|
282
|
+
return findings;
|
|
261
283
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
findings
|
|
272
|
-
|
|
284
|
+
if (ctx.manifestStatus === "invalid") {
|
|
285
|
+
const manifestPath = ctx.projectRoot
|
|
286
|
+
? manifestPathForProject(ctx.projectRoot)
|
|
287
|
+
: path.resolve(invocationCwd, "stageflow.yaml");
|
|
288
|
+
findings.push(...findingsFromLoadIssues(invocationCwd, manifestPath, ctx.issues));
|
|
289
|
+
return findings;
|
|
290
|
+
}
|
|
291
|
+
const { projectRoot, manifest } = ctx;
|
|
292
|
+
if (!projectRoot || !manifest) {
|
|
293
|
+
return findings;
|
|
294
|
+
}
|
|
295
|
+
if (manifest.manifest.catalog.pipelines.length === 0) {
|
|
296
|
+
findings.push(findingEmptyCatalog(invocationCwd, manifest.path, "pipelines"));
|
|
297
|
+
}
|
|
298
|
+
if (manifest.manifest.catalog.tasks.length === 0) {
|
|
299
|
+
findings.push(findingEmptyCatalog(invocationCwd, manifest.path, "tasks"));
|
|
300
|
+
}
|
|
301
|
+
const scanPaths = await getCatalogScanPaths(ctx);
|
|
302
|
+
if (!scanPaths) {
|
|
303
|
+
return findings;
|
|
304
|
+
}
|
|
305
|
+
const { pipelinePaths, taskPaths } = scanPaths;
|
|
306
|
+
for (const pipelinePath of pipelinePaths) {
|
|
307
|
+
const core = await runPipelineValidation(pipelinePath, {
|
|
308
|
+
cwd: projectRoot,
|
|
309
|
+
validateStages: true,
|
|
310
|
+
});
|
|
311
|
+
if (!core.ok) {
|
|
312
|
+
findings.push(...core.findings);
|
|
313
|
+
}
|
|
273
314
|
}
|
|
315
|
+
for (const taskPath of taskPaths) {
|
|
316
|
+
const outcome = await loadTaskOutcome(taskPath);
|
|
317
|
+
if (!outcome.ok) {
|
|
318
|
+
findings.push(...findingsFromLoadIssues(projectRoot, taskPath, outcome.issues));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const idToPaths = await collectPipelineIdsFromPaths(pipelinePaths);
|
|
322
|
+
findings.push(...findingsForDuplicatePipelineIds(projectRoot, idToPaths));
|
|
274
323
|
return findings;
|
|
275
324
|
}
|
|
325
|
+
async function validateSingleTask(invocationCwd, taskArg) {
|
|
326
|
+
const ctx = await resolveCatalogContext(invocationCwd);
|
|
327
|
+
const relCwd = ctx.projectRoot ?? invocationCwd;
|
|
328
|
+
const taskPath = path.resolve(invocationCwd, taskArg);
|
|
329
|
+
const outcome = await loadTaskOutcome(taskPath);
|
|
330
|
+
if (!outcome.ok) {
|
|
331
|
+
return findingsFromLoadIssues(relCwd, taskPath, outcome.issues);
|
|
332
|
+
}
|
|
333
|
+
return [];
|
|
334
|
+
}
|
|
276
335
|
export async function validateCatalog(options) {
|
|
277
336
|
const cwd = options.cwd ?? process.cwd();
|
|
278
|
-
const stagesDir = options.stagesDir ?? path.join(cwd, "stages");
|
|
279
337
|
const strict = options.strict ?? false;
|
|
280
|
-
const pipelinesDir = path.join(cwd, "pipelines");
|
|
281
338
|
if (options.scope === "pipeline" && !options.pipeline) {
|
|
282
339
|
throw new Error("validateCatalog: pipeline is required when scope is \"pipeline\"");
|
|
283
340
|
}
|
|
341
|
+
if (options.scope === "task" && !options.task) {
|
|
342
|
+
throw new Error("validateCatalog: task is required when scope is \"task\"");
|
|
343
|
+
}
|
|
284
344
|
const allFindings = [];
|
|
285
345
|
if (options.scope === "pipeline") {
|
|
286
|
-
|
|
346
|
+
return validatePipeline(options.pipeline, {
|
|
287
347
|
cwd,
|
|
288
|
-
stagesDir,
|
|
289
348
|
validateStages: true,
|
|
349
|
+
strict,
|
|
290
350
|
});
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
351
|
+
}
|
|
352
|
+
else if (options.scope === "task") {
|
|
353
|
+
allFindings.push(...(await validateSingleTask(cwd, options.task)));
|
|
294
354
|
}
|
|
295
355
|
else {
|
|
296
|
-
|
|
297
|
-
const pipelineFiles = await listYamlFiles(pipelinesDir);
|
|
298
|
-
for (const pipelinePath of pipelineFiles) {
|
|
299
|
-
const result = await validatePipelineFile(pipelinePath, {
|
|
300
|
-
cwd,
|
|
301
|
-
stagesDir,
|
|
302
|
-
validateStages: false,
|
|
303
|
-
});
|
|
304
|
-
allFindings.push(...result.findings);
|
|
305
|
-
for (const stageId of result.referencedStageIds) {
|
|
306
|
-
referencedStageIds.add(stageId);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const validatedStages = new Set();
|
|
310
|
-
for (const stageId of referencedStageIds) {
|
|
311
|
-
if (validatedStages.has(stageId))
|
|
312
|
-
continue;
|
|
313
|
-
validatedStages.add(stageId);
|
|
314
|
-
const stagePath = path.join(stagesDir, `${stageId}.yaml`);
|
|
315
|
-
allFindings.push(...(await validateStageFile(cwd, stagePath)));
|
|
316
|
-
}
|
|
317
|
-
const idToPaths = await collectPipelineIds(pipelinesDir);
|
|
318
|
-
allFindings.push(...findingsForDuplicatePipelineIds(cwd, idToPaths));
|
|
319
|
-
allFindings.push(...(await findingsForOrphanStages(cwd, stagesDir, referencedStageIds)));
|
|
356
|
+
allFindings.push(...(await validateManifestAll(cwd)));
|
|
320
357
|
}
|
|
321
358
|
return buildValidationResult(options.scope, allFindings, strict);
|
|
322
359
|
}
|
package/dist/envelope/check.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { type StageEnvelope } from "../types/envelope.js";
|
|
2
|
+
import type { CloneForkItem } from "../types/forkChoice.js";
|
|
3
|
+
export declare function parseCloneForks(raw: unknown): CloneForkItem[];
|
|
2
4
|
export declare function assertRequiredEnvelope(value: unknown): StageEnvelope;
|
|
3
5
|
export declare function isAdvancingEnvelope(envelope: StageEnvelope): boolean;
|
package/dist/envelope/check.js
CHANGED
|
@@ -1,4 +1,52 @@
|
|
|
1
1
|
import { EnvelopeError, } from "../types/envelope.js";
|
|
2
|
+
function parseCloneForkItem(raw, index) {
|
|
3
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
4
|
+
throw new EnvelopeError(`clone_forks[${index}] must be an object`);
|
|
5
|
+
}
|
|
6
|
+
const record = raw;
|
|
7
|
+
if (typeof record.successor_id !== "string") {
|
|
8
|
+
throw new EnvelopeError(`clone_forks[${index}].successor_id must be a string`);
|
|
9
|
+
}
|
|
10
|
+
const action = record.action;
|
|
11
|
+
if (action !== "skip" && action !== "once" && action !== "fanout") {
|
|
12
|
+
throw new EnvelopeError(`clone_forks[${index}].action must be "skip", "once", or "fanout"`);
|
|
13
|
+
}
|
|
14
|
+
const item = {
|
|
15
|
+
successor_id: record.successor_id,
|
|
16
|
+
action,
|
|
17
|
+
};
|
|
18
|
+
if (record.envelope !== undefined) {
|
|
19
|
+
item.envelope = assertRequiredEnvelope(record.envelope);
|
|
20
|
+
}
|
|
21
|
+
if (record.mode !== undefined) {
|
|
22
|
+
if (record.mode !== "parallel" && record.mode !== "sequential") {
|
|
23
|
+
throw new EnvelopeError(`clone_forks[${index}].mode must be "parallel" or "sequential"`);
|
|
24
|
+
}
|
|
25
|
+
item.mode = record.mode;
|
|
26
|
+
}
|
|
27
|
+
if (record.clones !== undefined) {
|
|
28
|
+
if (!Array.isArray(record.clones)) {
|
|
29
|
+
throw new EnvelopeError(`clone_forks[${index}].clones must be an array`);
|
|
30
|
+
}
|
|
31
|
+
item.clones = record.clones.map((clone, cloneIndex) => {
|
|
32
|
+
if (clone === null || typeof clone !== "object" || Array.isArray(clone)) {
|
|
33
|
+
throw new EnvelopeError(`clone_forks[${index}].clones[${cloneIndex}] must be an object`);
|
|
34
|
+
}
|
|
35
|
+
const cloneRecord = clone;
|
|
36
|
+
if (cloneRecord.envelope === undefined) {
|
|
37
|
+
throw new EnvelopeError(`clone_forks[${index}].clones[${cloneIndex}].envelope is required`);
|
|
38
|
+
}
|
|
39
|
+
return { envelope: assertRequiredEnvelope(cloneRecord.envelope) };
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return item;
|
|
43
|
+
}
|
|
44
|
+
export function parseCloneForks(raw) {
|
|
45
|
+
if (!Array.isArray(raw)) {
|
|
46
|
+
throw new EnvelopeError("clone_forks must be an array");
|
|
47
|
+
}
|
|
48
|
+
return raw.map((item, index) => parseCloneForkItem(item, index));
|
|
49
|
+
}
|
|
2
50
|
export function assertRequiredEnvelope(value) {
|
|
3
51
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4
52
|
throw new EnvelopeError("envelope must be an object");
|
|
@@ -25,6 +73,16 @@ export function assertRequiredEnvelope(value) {
|
|
|
25
73
|
summary: record.summary,
|
|
26
74
|
artifacts: record.artifacts,
|
|
27
75
|
};
|
|
76
|
+
if (record.fork_choice !== undefined) {
|
|
77
|
+
if (!Array.isArray(record.fork_choice) ||
|
|
78
|
+
!record.fork_choice.every((item) => typeof item === "string")) {
|
|
79
|
+
throw new EnvelopeError("fork_choice must be an array of strings");
|
|
80
|
+
}
|
|
81
|
+
envelope.fork_choice = record.fork_choice;
|
|
82
|
+
}
|
|
83
|
+
if (record.clone_forks !== undefined) {
|
|
84
|
+
envelope.clone_forks = parseCloneForks(record.clone_forks);
|
|
85
|
+
}
|
|
28
86
|
if (record.payload !== undefined) {
|
|
29
87
|
if (record.payload === null ||
|
|
30
88
|
typeof record.payload !== "object" ||
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { parseCloneForks } from "./check.js";
|
|
2
|
+
import { EnvelopeError } from "../types/envelope.js";
|
|
3
|
+
function fieldPresent(item, key) {
|
|
4
|
+
return item[key] !== undefined;
|
|
5
|
+
}
|
|
6
|
+
export function assertCloneForks(params, cloneEmitContext) {
|
|
7
|
+
const record = params;
|
|
8
|
+
if (record.status === "failure")
|
|
9
|
+
return;
|
|
10
|
+
if (record.clone_forks === undefined || !Array.isArray(record.clone_forks)) {
|
|
11
|
+
throw new EnvelopeError("clonable successor requires clone_forks on success");
|
|
12
|
+
}
|
|
13
|
+
const items = parseCloneForks(record.clone_forks);
|
|
14
|
+
if (items.length === 0 && cloneEmitContext.clonableSuccessors.length > 0) {
|
|
15
|
+
throw new EnvelopeError("clone_forks must not be empty when clonable successors exist");
|
|
16
|
+
}
|
|
17
|
+
const expectedIds = cloneEmitContext.clonableSuccessors.map((s) => s.successorId);
|
|
18
|
+
const expectedSet = new Set(expectedIds);
|
|
19
|
+
const seen = new Set();
|
|
20
|
+
for (const item of items) {
|
|
21
|
+
if (seen.has(item.successor_id)) {
|
|
22
|
+
throw new EnvelopeError(`clone_forks contains duplicate successor_id: ${item.successor_id}`);
|
|
23
|
+
}
|
|
24
|
+
if (!expectedSet.has(item.successor_id)) {
|
|
25
|
+
throw new EnvelopeError(`clone_forks contains extra successor_id: ${item.successor_id}`);
|
|
26
|
+
}
|
|
27
|
+
seen.add(item.successor_id);
|
|
28
|
+
const capEntry = cloneEmitContext.clonableSuccessors.find((s) => s.successorId === item.successor_id);
|
|
29
|
+
const cloneCap = capEntry?.cloneCap;
|
|
30
|
+
if (item.action === "skip") {
|
|
31
|
+
if (fieldPresent(item, "envelope") ||
|
|
32
|
+
fieldPresent(item, "mode") ||
|
|
33
|
+
fieldPresent(item, "clones")) {
|
|
34
|
+
throw new EnvelopeError(`clone_forks skip for ${item.successor_id} must not include envelope, mode, or clones`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (item.action === "once") {
|
|
38
|
+
if (!fieldPresent(item, "envelope")) {
|
|
39
|
+
throw new EnvelopeError(`clone_forks once for ${item.successor_id} requires envelope`);
|
|
40
|
+
}
|
|
41
|
+
if (fieldPresent(item, "mode") || fieldPresent(item, "clones")) {
|
|
42
|
+
throw new EnvelopeError(`clone_forks once for ${item.successor_id} must not include mode or clones`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (item.action === "fanout") {
|
|
46
|
+
if (fieldPresent(item, "envelope")) {
|
|
47
|
+
throw new EnvelopeError(`clone_forks fanout for ${item.successor_id} must not include a top-level envelope`);
|
|
48
|
+
}
|
|
49
|
+
if (!fieldPresent(item, "mode") || !fieldPresent(item, "clones") || item.clones === undefined) {
|
|
50
|
+
throw new EnvelopeError(`clone_forks fanout for ${item.successor_id} requires mode and clones`);
|
|
51
|
+
}
|
|
52
|
+
if (cloneCap === undefined || item.clones.length < 2 || item.clones.length > cloneCap) {
|
|
53
|
+
throw new EnvelopeError(`clone_forks fanout for ${item.successor_id} must have between 2 and ${cloneCap} clones`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const id of expectedIds) {
|
|
58
|
+
if (!seen.has(id)) {
|
|
59
|
+
throw new EnvelopeError(`clone_forks missing successor_id: ${id}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ForkEmitContext } from "../types/forkChoice.js";
|
|
2
|
+
export declare function assertForkEnvelope(params: unknown, forkEmitContext: ForkEmitContext): void;
|
|
3
|
+
export declare function normalizeForkChoice(raw: string[] | undefined, mode: "emit" | "stored", forkEmitContext?: ForkEmitContext): Set<string>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emit mode rejects missing fork_choice on fork success; stored mode treats
|
|
3
|
+
* undefined as an empty choice set (scheduler defensive path).
|
|
4
|
+
*/
|
|
5
|
+
import { EnvelopeError } from "../types/envelope.js";
|
|
6
|
+
function assertForkChoiceLegality(choices, forkEmitContext) {
|
|
7
|
+
const { immediateSuccessorIds, forkShape } = forkEmitContext;
|
|
8
|
+
for (const id of choices) {
|
|
9
|
+
if (!immediateSuccessorIds.includes(id)) {
|
|
10
|
+
throw new EnvelopeError(`fork_choice contains non-immediate successor: ${id}; clonable successors belong in clone_forks`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (choices.length === 0) {
|
|
14
|
+
if (forkShape === null || !forkShape.allowNone) {
|
|
15
|
+
throw new EnvelopeError("fork_choice must not be empty");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (forkShape !== null && forkShape.cardinality === "one" && choices.length !== 1) {
|
|
19
|
+
throw new EnvelopeError("fork shape requires exactly one choice");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function assertForkEnvelope(params, forkEmitContext) {
|
|
23
|
+
const record = params;
|
|
24
|
+
if (record.status === "failure")
|
|
25
|
+
return;
|
|
26
|
+
if (record.fork_choice === undefined) {
|
|
27
|
+
throw new EnvelopeError("fork stage must include fork_choice on success");
|
|
28
|
+
}
|
|
29
|
+
assertForkChoiceLegality(record.fork_choice, forkEmitContext);
|
|
30
|
+
}
|
|
31
|
+
export function normalizeForkChoice(raw, mode, forkEmitContext) {
|
|
32
|
+
if (mode === "stored") {
|
|
33
|
+
if (raw === undefined)
|
|
34
|
+
return new Set();
|
|
35
|
+
return new Set(raw);
|
|
36
|
+
}
|
|
37
|
+
if (forkEmitContext === undefined) {
|
|
38
|
+
if (raw === undefined)
|
|
39
|
+
return new Set();
|
|
40
|
+
return new Set(raw);
|
|
41
|
+
}
|
|
42
|
+
if (raw === undefined) {
|
|
43
|
+
throw new EnvelopeError("fork stage must include fork_choice on success");
|
|
44
|
+
}
|
|
45
|
+
assertForkChoiceLegality(raw, forkEmitContext);
|
|
46
|
+
return new Set(raw);
|
|
47
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export { findProjectRoot, clearFindProjectRootCacheForTests, } from "./project/findProjectRoot.js";
|
|
2
|
+
export { globalStageflowHome, ensureGlobalHome, } from "./project/globalHome.js";
|
|
3
|
+
export { resolveProjectContext, legacyProjectContext, type ProjectContext, } from "./project/resolveProjectContext.js";
|
|
4
|
+
export { resolveStageflowContext, projectContextFromStageflow, type StageflowContext, type CatalogManifestStatus, } from "./project/resolveStageflowContext.js";
|
|
1
5
|
export { PACKAGE_NAME } from "./package-meta.js";
|
|
2
6
|
export type { StageEnvelope } from "./types/envelope.js";
|
|
3
7
|
export { assertRequiredEnvelope, isAdvancingEnvelope, } from "./envelope/check.js";
|
|
@@ -11,3 +15,5 @@ export type { RunStore, RunSummary, RunDetail, RunMeta, RunStatus, StageSnapshot
|
|
|
11
15
|
export { deriveStatusFromStages } from "./runstore/port.js";
|
|
12
16
|
export { RunManager } from "./runtime/runManager.js";
|
|
13
17
|
export { startUiServer } from "./server/http.js";
|
|
18
|
+
export { startMcpServer } from "./server/mcpHost.js";
|
|
19
|
+
export { DEFAULT_PORT } from "./server/mcpHost.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export { findProjectRoot, clearFindProjectRootCacheForTests, } from "./project/findProjectRoot.js";
|
|
2
|
+
export { globalStageflowHome, ensureGlobalHome, } from "./project/globalHome.js";
|
|
3
|
+
export { resolveProjectContext, legacyProjectContext, } from "./project/resolveProjectContext.js";
|
|
4
|
+
export { resolveStageflowContext, projectContextFromStageflow, } from "./project/resolveStageflowContext.js";
|
|
1
5
|
export { PACKAGE_NAME } from "./package-meta.js";
|
|
2
6
|
export { assertRequiredEnvelope, isAdvancingEnvelope, } from "./envelope/check.js";
|
|
3
7
|
export { runPipeline, startPipeline } from "./runtime/pipelineRunner.js";
|
|
@@ -5,3 +9,5 @@ export { createRunStore } from "./runstore/createStore.js";
|
|
|
5
9
|
export { deriveStatusFromStages } from "./runstore/port.js";
|
|
6
10
|
export { RunManager } from "./runtime/runManager.js";
|
|
7
11
|
export { startUiServer } from "./server/http.js";
|
|
12
|
+
export { startMcpServer } from "./server/mcpHost.js";
|
|
13
|
+
export { DEFAULT_PORT } from "./server/mcpHost.js";
|