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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const cache = new Map();
|
|
5
|
+
function normalizeRoot(dir) {
|
|
6
|
+
try {
|
|
7
|
+
return realpathSync(path.resolve(dir));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return path.resolve(dir);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function findProjectRoot(startDir) {
|
|
14
|
+
const normalized = path.resolve(startDir);
|
|
15
|
+
if (cache.has(normalized)) {
|
|
16
|
+
return cache.get(normalized) ?? null;
|
|
17
|
+
}
|
|
18
|
+
let result = null;
|
|
19
|
+
try {
|
|
20
|
+
const stdout = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
21
|
+
cwd: normalized,
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
24
|
+
});
|
|
25
|
+
const trimmed = stdout.trim();
|
|
26
|
+
if (trimmed.length > 0) {
|
|
27
|
+
result = normalizeRoot(trimmed);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
result = walkForGitRoot(normalized);
|
|
32
|
+
}
|
|
33
|
+
cache.set(normalized, result);
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
function walkForGitRoot(startDir) {
|
|
37
|
+
let dir = path.resolve(startDir);
|
|
38
|
+
for (;;) {
|
|
39
|
+
if (existsSync(path.join(dir, ".git"))) {
|
|
40
|
+
return normalizeRoot(dir);
|
|
41
|
+
}
|
|
42
|
+
const parent = path.dirname(dir);
|
|
43
|
+
if (parent === dir) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
dir = parent;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function clearFindProjectRootCacheForTests() {
|
|
50
|
+
cache.clear();
|
|
51
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync } from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function globalStageflowHome() {
|
|
5
|
+
return path.join(os.homedir(), ".stageflow");
|
|
6
|
+
}
|
|
7
|
+
export function ensureGlobalHome() {
|
|
8
|
+
const globalHome = globalStageflowHome();
|
|
9
|
+
mkdirSync(globalHome, { recursive: true });
|
|
10
|
+
const agentDir = path.join(globalHome, "agent");
|
|
11
|
+
mkdirSync(agentDir, { recursive: true });
|
|
12
|
+
try {
|
|
13
|
+
chmodSync(agentDir, 0o700);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// best-effort on non-POSIX
|
|
17
|
+
}
|
|
18
|
+
return globalHome;
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ProjectContext = {
|
|
2
|
+
invocationCwd: string;
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
globalHome: string;
|
|
5
|
+
isGitProject: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function resolveProjectContext(invocationCwd: string): ProjectContext;
|
|
8
|
+
export declare function legacyProjectContext(cwd: string): ProjectContext;
|
|
9
|
+
export declare function asProjectContext(input: ProjectContext | string): ProjectContext;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { findProjectRoot } from "./findProjectRoot.js";
|
|
4
|
+
import { ensureGlobalHome, globalStageflowHome } from "./globalHome.js";
|
|
5
|
+
export function resolveProjectContext(invocationCwd) {
|
|
6
|
+
const resolvedInvocation = path.resolve(invocationCwd);
|
|
7
|
+
const gitRoot = findProjectRoot(resolvedInvocation);
|
|
8
|
+
const globalHome = ensureGlobalHome();
|
|
9
|
+
if (gitRoot !== null) {
|
|
10
|
+
return {
|
|
11
|
+
invocationCwd: resolvedInvocation,
|
|
12
|
+
projectRoot: gitRoot,
|
|
13
|
+
globalHome,
|
|
14
|
+
isGitProject: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
invocationCwd: resolvedInvocation,
|
|
19
|
+
projectRoot: os.homedir(),
|
|
20
|
+
globalHome,
|
|
21
|
+
isGitProject: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function legacyProjectContext(cwd) {
|
|
25
|
+
const invocationCwd = path.resolve(cwd);
|
|
26
|
+
return {
|
|
27
|
+
invocationCwd,
|
|
28
|
+
projectRoot: invocationCwd,
|
|
29
|
+
globalHome: globalStageflowHome(),
|
|
30
|
+
isGitProject: false,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function asProjectContext(input) {
|
|
34
|
+
if (typeof input !== "string") {
|
|
35
|
+
return input;
|
|
36
|
+
}
|
|
37
|
+
return resolveProjectContext(input);
|
|
38
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LoadedManifest } from "../types/stageflowManifest.js";
|
|
2
|
+
import type { LoadIssue } from "../config/loadOutcome.js";
|
|
3
|
+
import type { ProjectContext } from "./resolveProjectContext.js";
|
|
4
|
+
export type CatalogManifestStatus = "ok" | "missing" | "invalid" | "not_git";
|
|
5
|
+
export type StageflowContext = ProjectContext & {
|
|
6
|
+
manifest: LoadedManifest | null;
|
|
7
|
+
manifestStatus: CatalogManifestStatus;
|
|
8
|
+
manifestIssues: LoadIssue[];
|
|
9
|
+
};
|
|
10
|
+
export declare function projectContextFromStageflow(ctx: StageflowContext): ProjectContext;
|
|
11
|
+
export declare function resolveStageflowContext(invocationCwd: string): Promise<StageflowContext>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { loadStageflowManifestOutcome, manifestPathForProject, } from "../config/loadStageflowManifest.js";
|
|
5
|
+
import { findProjectRoot } from "./findProjectRoot.js";
|
|
6
|
+
import { ensureGlobalHome } from "./globalHome.js";
|
|
7
|
+
export function projectContextFromStageflow(ctx) {
|
|
8
|
+
return {
|
|
9
|
+
invocationCwd: ctx.invocationCwd,
|
|
10
|
+
projectRoot: ctx.projectRoot,
|
|
11
|
+
globalHome: ctx.globalHome,
|
|
12
|
+
isGitProject: ctx.isGitProject,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export async function resolveStageflowContext(invocationCwd) {
|
|
16
|
+
const resolvedInvocation = path.resolve(invocationCwd);
|
|
17
|
+
const gitRoot = findProjectRoot(resolvedInvocation);
|
|
18
|
+
const globalHome = ensureGlobalHome();
|
|
19
|
+
if (gitRoot === null) {
|
|
20
|
+
return {
|
|
21
|
+
invocationCwd: resolvedInvocation,
|
|
22
|
+
projectRoot: os.homedir(),
|
|
23
|
+
globalHome,
|
|
24
|
+
isGitProject: false,
|
|
25
|
+
manifest: null,
|
|
26
|
+
manifestStatus: "not_git",
|
|
27
|
+
manifestIssues: [],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const manifestPath = manifestPathForProject(gitRoot);
|
|
31
|
+
try {
|
|
32
|
+
await access(manifestPath);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return {
|
|
36
|
+
invocationCwd: resolvedInvocation,
|
|
37
|
+
projectRoot: gitRoot,
|
|
38
|
+
globalHome,
|
|
39
|
+
isGitProject: true,
|
|
40
|
+
manifest: null,
|
|
41
|
+
manifestStatus: "missing",
|
|
42
|
+
manifestIssues: [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const outcome = await loadStageflowManifestOutcome(gitRoot);
|
|
46
|
+
if (!outcome.ok) {
|
|
47
|
+
return {
|
|
48
|
+
invocationCwd: resolvedInvocation,
|
|
49
|
+
projectRoot: gitRoot,
|
|
50
|
+
globalHome,
|
|
51
|
+
isGitProject: true,
|
|
52
|
+
manifest: null,
|
|
53
|
+
manifestStatus: "invalid",
|
|
54
|
+
manifestIssues: outcome.issues,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
invocationCwd: resolvedInvocation,
|
|
59
|
+
projectRoot: gitRoot,
|
|
60
|
+
globalHome,
|
|
61
|
+
isGitProject: true,
|
|
62
|
+
manifest: outcome.value,
|
|
63
|
+
manifestStatus: "ok",
|
|
64
|
+
manifestIssues: [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { RunDetail, StageSnapshot } from "../runstore/port.js";
|
|
2
|
+
import type { PipelineTrackProjection, RunSummary } from "../runstore/port.js";
|
|
3
|
+
import type { AskOperatorPrompt } from "../tools/askOperator.js";
|
|
4
|
+
import type { StageEnvelope } from "../types/envelope.js";
|
|
5
|
+
import type { CloneForkItem } from "../types/forkChoice.js";
|
|
6
|
+
export type StageProjection = {
|
|
7
|
+
stage_id: string;
|
|
8
|
+
status: StageSnapshot["status"];
|
|
9
|
+
envelope: {
|
|
10
|
+
status: StageEnvelope["status"];
|
|
11
|
+
summary: string;
|
|
12
|
+
artifacts: string[];
|
|
13
|
+
payload?: Record<string, unknown>;
|
|
14
|
+
fork_choice?: string[];
|
|
15
|
+
clone_forks?: CloneForkItem[];
|
|
16
|
+
} | null;
|
|
17
|
+
artifacts: string[];
|
|
18
|
+
last_at?: string;
|
|
19
|
+
pending_prompt?: AskOperatorPrompt;
|
|
20
|
+
};
|
|
21
|
+
export type RunProjection = {
|
|
22
|
+
run_id: string;
|
|
23
|
+
pipeline_id: string;
|
|
24
|
+
task_id?: string;
|
|
25
|
+
pipeline_path?: string;
|
|
26
|
+
task_path?: string;
|
|
27
|
+
project_root?: string;
|
|
28
|
+
status: RunDetail["status"];
|
|
29
|
+
created_at: string;
|
|
30
|
+
updated_at?: string;
|
|
31
|
+
stages: StageProjection[];
|
|
32
|
+
pipeline_track: PipelineTrackProjection;
|
|
33
|
+
waiting_stage_id?: RunSummary["waiting_stage_id"];
|
|
34
|
+
waiting_stage_ids?: RunSummary["waiting_stage_ids"];
|
|
35
|
+
waiting_summary?: RunSummary["waiting_summary"];
|
|
36
|
+
waiting_kind?: RunSummary["waiting_kind"];
|
|
37
|
+
waiting_prompt_id?: RunSummary["waiting_prompt_id"];
|
|
38
|
+
waiting_artifacts?: RunSummary["waiting_artifacts"];
|
|
39
|
+
waiting_questions?: RunSummary["waiting_questions"];
|
|
40
|
+
failed_stage_id?: RunSummary["failed_stage_id"];
|
|
41
|
+
failed_reason?: RunSummary["failed_reason"];
|
|
42
|
+
};
|
|
43
|
+
export declare function projectRun(detail: RunDetail): RunProjection;
|
|
44
|
+
export { projectRun as projectRunForMcp };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export function projectRun(detail) {
|
|
2
|
+
return {
|
|
3
|
+
run_id: detail.run_id,
|
|
4
|
+
pipeline_id: detail.pipeline_id,
|
|
5
|
+
task_id: detail.task_id,
|
|
6
|
+
...(detail.pipeline_path !== undefined
|
|
7
|
+
? { pipeline_path: detail.pipeline_path }
|
|
8
|
+
: {}),
|
|
9
|
+
...(detail.task_path !== undefined ? { task_path: detail.task_path } : {}),
|
|
10
|
+
...(detail.project_root !== undefined
|
|
11
|
+
? { project_root: detail.project_root }
|
|
12
|
+
: {}),
|
|
13
|
+
status: detail.status,
|
|
14
|
+
created_at: detail.created_at,
|
|
15
|
+
updated_at: detail.updated_at,
|
|
16
|
+
pipeline_track: detail.pipeline_track,
|
|
17
|
+
...(detail.waiting_stage_id !== undefined
|
|
18
|
+
? { waiting_stage_id: detail.waiting_stage_id }
|
|
19
|
+
: {}),
|
|
20
|
+
...(detail.waiting_stage_ids !== undefined
|
|
21
|
+
? { waiting_stage_ids: detail.waiting_stage_ids }
|
|
22
|
+
: {}),
|
|
23
|
+
...(detail.waiting_summary !== undefined
|
|
24
|
+
? { waiting_summary: detail.waiting_summary }
|
|
25
|
+
: {}),
|
|
26
|
+
...(detail.waiting_kind !== undefined
|
|
27
|
+
? { waiting_kind: detail.waiting_kind }
|
|
28
|
+
: {}),
|
|
29
|
+
...(detail.waiting_prompt_id !== undefined
|
|
30
|
+
? { waiting_prompt_id: detail.waiting_prompt_id }
|
|
31
|
+
: {}),
|
|
32
|
+
...(detail.waiting_artifacts !== undefined
|
|
33
|
+
? { waiting_artifacts: detail.waiting_artifacts }
|
|
34
|
+
: {}),
|
|
35
|
+
...(detail.waiting_questions !== undefined
|
|
36
|
+
? { waiting_questions: detail.waiting_questions }
|
|
37
|
+
: {}),
|
|
38
|
+
...(detail.failed_stage_id !== undefined
|
|
39
|
+
? { failed_stage_id: detail.failed_stage_id }
|
|
40
|
+
: {}),
|
|
41
|
+
...(detail.failed_reason !== undefined
|
|
42
|
+
? { failed_reason: detail.failed_reason }
|
|
43
|
+
: {}),
|
|
44
|
+
stages: detail.stages.map((stage) => ({
|
|
45
|
+
stage_id: stage.stage_id,
|
|
46
|
+
status: stage.status,
|
|
47
|
+
envelope: stage.envelope
|
|
48
|
+
? {
|
|
49
|
+
status: stage.envelope.status,
|
|
50
|
+
summary: stage.envelope.summary,
|
|
51
|
+
artifacts: stage.envelope.artifacts,
|
|
52
|
+
...(stage.envelope.payload !== undefined
|
|
53
|
+
? { payload: stage.envelope.payload }
|
|
54
|
+
: {}),
|
|
55
|
+
...(stage.envelope.fork_choice !== undefined
|
|
56
|
+
? { fork_choice: stage.envelope.fork_choice }
|
|
57
|
+
: {}),
|
|
58
|
+
...(stage.envelope.clone_forks !== undefined
|
|
59
|
+
? { clone_forks: stage.envelope.clone_forks }
|
|
60
|
+
: {}),
|
|
61
|
+
}
|
|
62
|
+
: null,
|
|
63
|
+
artifacts: stage.artifacts,
|
|
64
|
+
last_at: stage.last_at,
|
|
65
|
+
...(stage.pending_prompt
|
|
66
|
+
? { pending_prompt: stage.pending_prompt }
|
|
67
|
+
: {}),
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export { projectRun as projectRunForMcp };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
2
|
-
export declare function formatPriorEnvelope(priorEnvelope: StageEnvelope | null): string;
|
|
2
|
+
export declare function formatPriorEnvelope(priorEnvelope: StageEnvelope | null, priorEnvelopes?: StageEnvelope[]): string;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export function formatPriorEnvelope(priorEnvelope) {
|
|
1
|
+
export function formatPriorEnvelope(priorEnvelope, priorEnvelopes) {
|
|
2
|
+
if (priorEnvelopes !== undefined && priorEnvelopes.length > 0) {
|
|
3
|
+
return `Prior envelopes (${priorEnvelopes.length} clones, clone-list order):\n${JSON.stringify(priorEnvelopes, null, 2)}`;
|
|
4
|
+
}
|
|
2
5
|
return priorEnvelope === null
|
|
3
6
|
? "No prior envelope (first stage)."
|
|
4
7
|
: `Prior envelope JSON:\n${JSON.stringify(priorEnvelope, null, 2)}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function normalizeCatalogPath(raw: string): string;
|
package/dist/runstore/paths.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { readdirSync, renameSync, rmdirSync, statSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { guardStageId } from "./workspaceLayout.js";
|
|
4
5
|
export function newRunId() {
|
|
5
6
|
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
6
7
|
return `${stamp}-${randomBytes(3).toString("hex")}`;
|
|
@@ -56,5 +57,6 @@ export function runWorkspaceDir(storeRoot, runId) {
|
|
|
56
57
|
return path.join(runsDir(storeRoot), runId);
|
|
57
58
|
}
|
|
58
59
|
export function stageDir(workspaceDir, stageId) {
|
|
60
|
+
guardStageId(stageId);
|
|
59
61
|
return path.join(workspaceDir, "stages", stageId);
|
|
60
62
|
}
|
|
@@ -3,3 +3,12 @@ import type { RunPipelineDagSnapshot } from "./port.js";
|
|
|
3
3
|
export declare function buildPipelineDagSnapshotFromLoaded(loaded: LoadedPipeline): RunPipelineDagSnapshot;
|
|
4
4
|
export declare function linearCompatDagSnapshot(stageIds: string[]): RunPipelineDagSnapshot;
|
|
5
5
|
export declare function parsePipelineDagSnapshot(raw: unknown): RunPipelineDagSnapshot | null;
|
|
6
|
+
export declare function instancesOfDefinition(snapshot: RunPipelineDagSnapshot, catalogId: string): string[];
|
|
7
|
+
export declare function appendCloneInstances(snapshot: RunPipelineDagSnapshot, input: {
|
|
8
|
+
catalogId: string;
|
|
9
|
+
predecessorId: string;
|
|
10
|
+
count: number;
|
|
11
|
+
}): {
|
|
12
|
+
snapshot: RunPipelineDagSnapshot;
|
|
13
|
+
instanceIds: string[];
|
|
14
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mintCloneInstanceIds } from "./stageInstanceId.js";
|
|
1
2
|
export function buildPipelineDagSnapshotFromLoaded(loaded) {
|
|
2
3
|
const gate_kinds = {};
|
|
3
4
|
for (const stage of loaded.stages) {
|
|
@@ -7,7 +8,10 @@ export function buildPipelineDagSnapshotFromLoaded(loaded) {
|
|
|
7
8
|
}
|
|
8
9
|
return {
|
|
9
10
|
stage_ids: [...loaded.pipeline.stages],
|
|
10
|
-
nodes: loaded.dag.nodes
|
|
11
|
+
nodes: loaded.dag.nodes.map((node) => ({
|
|
12
|
+
...node,
|
|
13
|
+
definition_id: node.id,
|
|
14
|
+
})),
|
|
11
15
|
roots: loaded.dag.roots,
|
|
12
16
|
childrenOf: loaded.dag.childrenOf,
|
|
13
17
|
...(Object.keys(gate_kinds).length > 0 ? { gate_kinds } : {}),
|
|
@@ -19,6 +23,7 @@ export function linearCompatDagSnapshot(stageIds) {
|
|
|
19
23
|
needs: index === 0 ? null : stageIds[index - 1],
|
|
20
24
|
ancestors: index === 0 ? [] : stageIds.slice(0, index),
|
|
21
25
|
stageIndex: index,
|
|
26
|
+
definition_id: id,
|
|
22
27
|
}));
|
|
23
28
|
const childrenOf = {};
|
|
24
29
|
for (let i = 1; i < stageIds.length; i++) {
|
|
@@ -41,3 +46,87 @@ export function parsePipelineDagSnapshot(raw) {
|
|
|
41
46
|
return null;
|
|
42
47
|
return raw;
|
|
43
48
|
}
|
|
49
|
+
export function instancesOfDefinition(snapshot, catalogId) {
|
|
50
|
+
const nodeById = new Map(snapshot.nodes.map((n) => [n.id, n]));
|
|
51
|
+
return snapshot.stage_ids.filter((id) => {
|
|
52
|
+
const node = nodeById.get(id);
|
|
53
|
+
return (node?.definition_id ?? node?.id) === catalogId;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function appendCloneInstances(snapshot, input) {
|
|
57
|
+
const { catalogId, predecessorId, count } = input;
|
|
58
|
+
if (!snapshot.stage_ids.includes(catalogId)) {
|
|
59
|
+
throw new Error(`catalog stage "${catalogId}" is not in the run DAG snapshot`);
|
|
60
|
+
}
|
|
61
|
+
const predNode = snapshot.nodes.find((n) => n.id === predecessorId);
|
|
62
|
+
if (!predNode) {
|
|
63
|
+
throw new Error(`predecessor "${predecessorId}" is not in the run DAG snapshot`);
|
|
64
|
+
}
|
|
65
|
+
const instanceIds = mintCloneInstanceIds(catalogId, count);
|
|
66
|
+
for (const id of instanceIds) {
|
|
67
|
+
if (snapshot.stage_ids.includes(id) ||
|
|
68
|
+
snapshot.nodes.some((n) => n.id === id)) {
|
|
69
|
+
throw new Error(`instance id "${id}" already exists in the run DAG snapshot`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const catalogNode = snapshot.nodes.find((n) => n.id === catalogId);
|
|
73
|
+
if (!catalogNode) {
|
|
74
|
+
throw new Error(`catalog stage "${catalogId}" is not in the run DAG snapshot`);
|
|
75
|
+
}
|
|
76
|
+
const catalogIdx = snapshot.stage_ids.indexOf(catalogId);
|
|
77
|
+
const stage_ids = [
|
|
78
|
+
...snapshot.stage_ids.slice(0, catalogIdx),
|
|
79
|
+
...instanceIds,
|
|
80
|
+
...snapshot.stage_ids.slice(catalogIdx + 1),
|
|
81
|
+
];
|
|
82
|
+
const instanceNodes = instanceIds.map((id) => ({
|
|
83
|
+
id,
|
|
84
|
+
definition_id: catalogId,
|
|
85
|
+
needs: predecessorId,
|
|
86
|
+
ancestors: [...predNode.ancestors, predecessorId],
|
|
87
|
+
stageIndex: 0,
|
|
88
|
+
...(catalogNode.fork !== undefined ? { fork: catalogNode.fork } : {}),
|
|
89
|
+
}));
|
|
90
|
+
const remaining = new Map(snapshot.nodes
|
|
91
|
+
.filter((n) => n.id !== catalogId)
|
|
92
|
+
.map((n) => [n.id, n]));
|
|
93
|
+
const minted = new Map(instanceNodes.map((n) => [n.id, n]));
|
|
94
|
+
const nodes = stage_ids.map((id, index) => {
|
|
95
|
+
const node = minted.get(id) ?? remaining.get(id);
|
|
96
|
+
if (!node) {
|
|
97
|
+
throw new Error(`missing node for "${id}" after clone fan-out`);
|
|
98
|
+
}
|
|
99
|
+
return { ...node, stageIndex: index };
|
|
100
|
+
});
|
|
101
|
+
const childrenOf = {};
|
|
102
|
+
for (const [key, children] of Object.entries(snapshot.childrenOf)) {
|
|
103
|
+
childrenOf[key] = [...children];
|
|
104
|
+
}
|
|
105
|
+
const predChildren = childrenOf[predecessorId] ?? [];
|
|
106
|
+
const predIdx = predChildren.indexOf(catalogId);
|
|
107
|
+
childrenOf[predecessorId] =
|
|
108
|
+
predIdx === -1
|
|
109
|
+
? [...predChildren, ...instanceIds]
|
|
110
|
+
: [
|
|
111
|
+
...predChildren.slice(0, predIdx),
|
|
112
|
+
...instanceIds,
|
|
113
|
+
...predChildren.slice(predIdx + 1),
|
|
114
|
+
];
|
|
115
|
+
const definitionParent = catalogNode.needs;
|
|
116
|
+
if (definitionParent && definitionParent !== predecessorId) {
|
|
117
|
+
const parentChildren = childrenOf[definitionParent] ?? [];
|
|
118
|
+
childrenOf[definitionParent] = parentChildren.filter((id) => id !== catalogId);
|
|
119
|
+
if (childrenOf[definitionParent].length === 0) {
|
|
120
|
+
delete childrenOf[definitionParent];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
snapshot: {
|
|
125
|
+
...snapshot,
|
|
126
|
+
stage_ids,
|
|
127
|
+
nodes,
|
|
128
|
+
childrenOf,
|
|
129
|
+
},
|
|
130
|
+
instanceIds,
|
|
131
|
+
};
|
|
132
|
+
}
|
package/dist/runstore/port.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type PipelineTrackNode = {
|
|
|
18
18
|
blocked_by?: string[];
|
|
19
19
|
gate_kinds?: StageGateKind[];
|
|
20
20
|
attempt_count?: number;
|
|
21
|
+
definition_id?: string;
|
|
21
22
|
};
|
|
22
23
|
export type PipelineTrackEdge = {
|
|
23
24
|
from: string;
|
|
@@ -40,6 +41,9 @@ export type RunMeta = {
|
|
|
40
41
|
ci_pr_url?: string;
|
|
41
42
|
ci_job_url?: string;
|
|
42
43
|
pipeline_dag?: RunPipelineDagSnapshot;
|
|
44
|
+
pipeline_path?: string;
|
|
45
|
+
task_path?: string;
|
|
46
|
+
project_root?: string;
|
|
43
47
|
};
|
|
44
48
|
export type CreatedRun = {
|
|
45
49
|
runId: string;
|
|
@@ -52,7 +56,8 @@ export type StageLogEvent = StageLogLine & {
|
|
|
52
56
|
};
|
|
53
57
|
export type StageSnapshot = {
|
|
54
58
|
stage_id: string;
|
|
55
|
-
|
|
59
|
+
definition_id?: string;
|
|
60
|
+
status: "pending" | "running" | "waiting_for_input" | "succeeded" | "failed" | "skipped";
|
|
56
61
|
events: StageLogEvent[];
|
|
57
62
|
envelope: StageEnvelope | null;
|
|
58
63
|
artifacts: string[];
|
|
@@ -79,11 +84,15 @@ export type CompactStage = {
|
|
|
79
84
|
id: string;
|
|
80
85
|
status: StageSnapshot["status"];
|
|
81
86
|
attempt_count: number;
|
|
87
|
+
definition_id?: string;
|
|
82
88
|
};
|
|
83
89
|
export type RunSummary = {
|
|
84
90
|
run_id: string;
|
|
85
91
|
pipeline_id: string;
|
|
86
92
|
task_id?: string;
|
|
93
|
+
pipeline_path?: string;
|
|
94
|
+
task_path?: string;
|
|
95
|
+
project_root?: string;
|
|
87
96
|
status: RunStatus;
|
|
88
97
|
created_at: string;
|
|
89
98
|
updated_at?: string;
|
|
@@ -115,6 +124,16 @@ export type CreateRunInput = {
|
|
|
115
124
|
ciPrUrl?: string;
|
|
116
125
|
ciJobUrl?: string;
|
|
117
126
|
pipelineDag?: RunPipelineDagSnapshot;
|
|
127
|
+
pipelinePath?: string;
|
|
128
|
+
taskPath?: string;
|
|
129
|
+
projectRoot?: string;
|
|
130
|
+
};
|
|
131
|
+
export type ListRunsFilter = {
|
|
132
|
+
status?: RunStatus;
|
|
133
|
+
/** ISO timestamp; keep runs with created_at >= since */
|
|
134
|
+
since?: string;
|
|
135
|
+
/** Match pipeline_id or pipeline_path */
|
|
136
|
+
pipeline?: string;
|
|
118
137
|
};
|
|
119
138
|
/**
|
|
120
139
|
* Persistence port for pipeline run state.
|
|
@@ -145,8 +164,9 @@ export interface RunStore {
|
|
|
145
164
|
attempt?: number;
|
|
146
165
|
}): Promise<void>;
|
|
147
166
|
listStageEvents(runId: string, stageId: string, attempt?: number): Promise<StageLogEvent[]>;
|
|
148
|
-
listRuns(): Promise<RunSummary[]>;
|
|
167
|
+
listRuns(filter?: ListRunsFilter): Promise<RunSummary[]>;
|
|
149
168
|
readRun(runId: string): Promise<RunDetail>;
|
|
169
|
+
updatePipelineDag(runId: string, dag: RunPipelineDagSnapshot): Promise<void>;
|
|
150
170
|
}
|
|
151
171
|
export declare function stageStatusFromEvents(events: StageLogEvent[]): StageSnapshot["status"];
|
|
152
172
|
export declare function deriveStatusFromStages(stages: StageSnapshot[]): RunStatus;
|
package/dist/runstore/port.js
CHANGED
|
@@ -9,6 +9,8 @@ export function stageStatusFromEvents(events) {
|
|
|
9
9
|
status = "succeeded";
|
|
10
10
|
if (ev.event === "failed")
|
|
11
11
|
status = "failed";
|
|
12
|
+
if (ev.event === "skipped")
|
|
13
|
+
status = "skipped";
|
|
12
14
|
}
|
|
13
15
|
return status;
|
|
14
16
|
}
|
|
@@ -17,8 +19,9 @@ export function deriveStatusFromStages(stages) {
|
|
|
17
19
|
return "created";
|
|
18
20
|
if (stages.some((s) => s.status === "failed"))
|
|
19
21
|
return "failed";
|
|
20
|
-
if (stages.every((s) => s.status === "succeeded"))
|
|
22
|
+
if (stages.every((s) => s.status === "succeeded" || s.status === "skipped")) {
|
|
21
23
|
return "succeeded";
|
|
24
|
+
}
|
|
22
25
|
if (stages.some((s) => s.status === "running" ||
|
|
23
26
|
s.status === "waiting_for_input" ||
|
|
24
27
|
s.status === "succeeded")) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RunDetail, RunMeta, RunPipelineDagSnapshot, RunSummary, StageSnapshot } from "./port.js";
|
|
2
2
|
export { syntheticPendingSnapshot } from "./syntheticStageSnapshot.js";
|
|
3
|
-
export declare function overlayPlannedStages(stageIds: string[], snapshots: StageSnapshot[]): StageSnapshot[];
|
|
3
|
+
export declare function overlayPlannedStages(stageIds: string[], snapshots: StageSnapshot[], dag?: Pick<RunPipelineDagSnapshot, "nodes"> | null): StageSnapshot[];
|
|
4
4
|
export declare function orderStageSnapshots(stageIds: string[], snapshots: StageSnapshot[]): StageSnapshot[];
|
|
5
5
|
export declare function projectRunSummary(meta: RunMeta, stages: StageSnapshot[]): RunSummary;
|
|
6
6
|
export declare function projectRunDetail(meta: RunMeta, stages: StageSnapshot[], task_yaml: string, dagSnapshot?: RunPipelineDagSnapshot | null): RunDetail;
|
|
@@ -3,9 +3,19 @@ import { linearCompatDagSnapshot } from "./pipelineDagSnapshot.js";
|
|
|
3
3
|
import { syntheticPendingSnapshot } from "./syntheticStageSnapshot.js";
|
|
4
4
|
import { buildPipelineTrack } from "./trackProjection.js";
|
|
5
5
|
export { syntheticPendingSnapshot } from "./syntheticStageSnapshot.js";
|
|
6
|
-
export function overlayPlannedStages(stageIds, snapshots) {
|
|
6
|
+
export function overlayPlannedStages(stageIds, snapshots, dag) {
|
|
7
7
|
const byId = new Map(snapshots.map((s) => [s.stage_id, s]));
|
|
8
|
-
|
|
8
|
+
const nodeById = new Map((dag?.nodes ?? []).map((n) => [n.id, n]));
|
|
9
|
+
return stageIds.map((id) => {
|
|
10
|
+
const node = nodeById.get(id);
|
|
11
|
+
const definitionId = node?.definition_id ?? node?.id;
|
|
12
|
+
const existing = byId.get(id);
|
|
13
|
+
const base = existing ?? syntheticPendingSnapshot(id, definitionId);
|
|
14
|
+
if (definitionId === undefined || base.definition_id === definitionId) {
|
|
15
|
+
return base;
|
|
16
|
+
}
|
|
17
|
+
return { ...base, definition_id: definitionId };
|
|
18
|
+
});
|
|
9
19
|
}
|
|
10
20
|
export function orderStageSnapshots(stageIds, snapshots) {
|
|
11
21
|
return overlayPlannedStages(stageIds, snapshots);
|
|
@@ -15,6 +25,7 @@ function compactStages(stages) {
|
|
|
15
25
|
id: s.stage_id,
|
|
16
26
|
status: s.status,
|
|
17
27
|
attempt_count: s.attempt_count,
|
|
28
|
+
...(s.definition_id !== undefined ? { definition_id: s.definition_id } : {}),
|
|
18
29
|
}));
|
|
19
30
|
}
|
|
20
31
|
function waitingSummaryFromPrompt(prompt) {
|
|
@@ -65,14 +76,24 @@ function failedFieldsFromStages(stages) {
|
|
|
65
76
|
};
|
|
66
77
|
}
|
|
67
78
|
function resolveListedStatus(stages, meta) {
|
|
79
|
+
if (stages.length === 0)
|
|
80
|
+
return meta.status ?? "created";
|
|
68
81
|
const derived = deriveStatusFromStages(stages);
|
|
69
|
-
|
|
82
|
+
if (meta.status === "succeeded" && derived === "running") {
|
|
83
|
+
const hasActiveStage = stages.some((s) => s.status === "running" || s.status === "waiting_for_input");
|
|
84
|
+
if (!hasActiveStage)
|
|
85
|
+
return "succeeded";
|
|
86
|
+
}
|
|
87
|
+
return derived;
|
|
70
88
|
}
|
|
71
89
|
export function projectRunSummary(meta, stages) {
|
|
72
90
|
return {
|
|
73
91
|
run_id: meta.run_id,
|
|
74
92
|
pipeline_id: meta.pipeline_id,
|
|
75
93
|
task_id: meta.task_id,
|
|
94
|
+
...(meta.pipeline_path !== undefined ? { pipeline_path: meta.pipeline_path } : {}),
|
|
95
|
+
...(meta.task_path !== undefined ? { task_path: meta.task_path } : {}),
|
|
96
|
+
...(meta.project_root !== undefined ? { project_root: meta.project_root } : {}),
|
|
76
97
|
status: resolveListedStatus(stages, meta),
|
|
77
98
|
created_at: meta.created_at,
|
|
78
99
|
updated_at: meta.updated_at,
|
|
@@ -83,7 +104,7 @@ export function projectRunSummary(meta, stages) {
|
|
|
83
104
|
}
|
|
84
105
|
export function projectRunDetail(meta, stages, task_yaml, dagSnapshot) {
|
|
85
106
|
const ordered = dagSnapshot
|
|
86
|
-
? overlayPlannedStages(dagSnapshot.stage_ids, stages)
|
|
107
|
+
? overlayPlannedStages(dagSnapshot.stage_ids, stages, dagSnapshot)
|
|
87
108
|
: stages;
|
|
88
109
|
const summary = projectRunSummary(meta, ordered);
|
|
89
110
|
const snapshot = dagSnapshot ??
|