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.
Files changed (224) hide show
  1. package/README.md +179 -14
  2. package/dist/agent/activity.d.ts +12 -1
  3. package/dist/agent/activity.js +37 -2
  4. package/dist/agent/activityObserver.d.ts +5 -1
  5. package/dist/agent/activityObserver.js +174 -11
  6. package/dist/agent/cursorProvider.d.ts +1 -10
  7. package/dist/agent/cursorProvider.js +18 -10
  8. package/dist/agent/fakeAgent.js +15 -7
  9. package/dist/agent/piAdapter.d.ts +18 -1
  10. package/dist/agent/piAdapter.js +115 -45
  11. package/dist/agent/port.d.ts +7 -0
  12. package/dist/agent/port.js +3 -0
  13. package/dist/agent/providerAuth.js +12 -7
  14. package/dist/catalog/displayCatalogPath.d.ts +12 -0
  15. package/dist/catalog/displayCatalogPath.js +28 -0
  16. package/dist/cli/artifactCommand.d.ts +10 -0
  17. package/dist/cli/artifactCommand.js +120 -0
  18. package/dist/cli/envelopeCommand.d.ts +32 -0
  19. package/dist/cli/envelopeCommand.js +285 -0
  20. package/dist/cli/exportRunCommand.d.ts +10 -0
  21. package/dist/cli/exportRunCommand.js +150 -0
  22. package/dist/cli/handoffFormat.d.ts +22 -0
  23. package/dist/cli/handoffFormat.js +61 -0
  24. package/dist/cli/initCommand.d.ts +9 -0
  25. package/dist/cli/initCommand.js +71 -0
  26. package/dist/cli/initTemplates.d.ts +3 -0
  27. package/dist/cli/initTemplates.js +19 -0
  28. package/dist/cli/operatorCatalog.d.ts +10 -0
  29. package/dist/cli/operatorCatalog.js +16 -0
  30. package/dist/cli/runCommand.d.ts +7 -1
  31. package/dist/cli/runCommand.js +83 -11
  32. package/dist/cli/runOutput.d.ts +4 -1
  33. package/dist/cli/runOutput.js +36 -8
  34. package/dist/cli/skillsCommand.d.ts +16 -0
  35. package/dist/cli/skillsCommand.js +459 -0
  36. package/dist/cli/validateCommand.d.ts +1 -1
  37. package/dist/cli/validateCommand.js +20 -3
  38. package/dist/cli.d.ts +1 -0
  39. package/dist/cli.js +128 -22
  40. package/dist/config/browseCatalog.d.ts +45 -0
  41. package/dist/config/browseCatalog.js +170 -0
  42. package/dist/config/createPipeline.d.ts +12 -3
  43. package/dist/config/createPipeline.js +292 -100
  44. package/dist/config/createStage.d.ts +10 -4
  45. package/dist/config/createStage.js +44 -14
  46. package/dist/config/listConfig.d.ts +14 -19
  47. package/dist/config/listConfig.js +26 -191
  48. package/dist/config/listModelsFromManifest.d.ts +2 -0
  49. package/dist/config/listModelsFromManifest.js +4 -0
  50. package/dist/config/loadOutcome.d.ts +4 -0
  51. package/dist/config/loadPipeline.d.ts +1 -15
  52. package/dist/config/loadPipeline.js +88 -142
  53. package/dist/config/loadStage.d.ts +4 -0
  54. package/dist/config/loadStage.js +60 -32
  55. package/dist/config/loadStageflowManifest.d.ts +5 -0
  56. package/dist/config/loadStageflowManifest.js +157 -0
  57. package/dist/config/mergePipelineIncludes.d.ts +9 -0
  58. package/dist/config/mergePipelineIncludes.js +141 -0
  59. package/dist/config/normalizePipelineStageEntry.d.ts +18 -0
  60. package/dist/config/normalizePipelineStageEntry.js +210 -0
  61. package/dist/config/pipelineStageKeys.d.ts +4 -0
  62. package/dist/config/pipelineStageKeys.js +14 -0
  63. package/dist/config/resolveCatalogContext.d.ts +13 -0
  64. package/dist/config/resolveCatalogContext.js +13 -0
  65. package/dist/config/resolveForkEmitContext.d.ts +4 -0
  66. package/dist/config/resolveForkEmitContext.js +34 -0
  67. package/dist/config/resolvePipelineDag.d.ts +5 -1
  68. package/dist/config/resolvePipelineDag.js +86 -36
  69. package/dist/config/scanCatalogPaths.d.ts +4 -0
  70. package/dist/config/scanCatalogPaths.js +83 -0
  71. package/dist/config/validateCatalog.d.ts +22 -4
  72. package/dist/config/validateCatalog.js +169 -132
  73. package/dist/envelope/check.d.ts +2 -0
  74. package/dist/envelope/check.js +58 -0
  75. package/dist/envelope/cloneForks.d.ts +2 -0
  76. package/dist/envelope/cloneForks.js +62 -0
  77. package/dist/envelope/forkChoice.d.ts +3 -0
  78. package/dist/envelope/forkChoice.js +47 -0
  79. package/dist/index.d.ts +6 -0
  80. package/dist/index.js +6 -0
  81. package/dist/mcp/catalogTools.d.ts +3 -0
  82. package/dist/mcp/catalogTools.js +187 -0
  83. package/dist/mcp/controlTools.d.ts +3 -0
  84. package/dist/mcp/controlTools.js +147 -0
  85. package/dist/mcp/deps.d.ts +11 -0
  86. package/dist/mcp/deps.js +1 -0
  87. package/dist/mcp/projectRun.d.ts +1 -37
  88. package/dist/mcp/projectRun.js +1 -57
  89. package/dist/mcp/resources.d.ts +5 -0
  90. package/dist/mcp/resources.js +45 -0
  91. package/dist/mcp/server.d.ts +16 -3
  92. package/dist/mcp/server.js +159 -3
  93. package/dist/mcp/toolResults.d.ts +7 -0
  94. package/dist/mcp/toolResults.js +6 -0
  95. package/dist/mcp/tools.d.ts +2 -7
  96. package/dist/mcp/tools.js +52 -86
  97. package/dist/mcp/waitRun.d.ts +46 -0
  98. package/dist/mcp/waitRun.js +146 -0
  99. package/dist/mcp/waitingGates.d.ts +12 -0
  100. package/dist/mcp/waitingGates.js +83 -0
  101. package/dist/project/findProjectRoot.d.ts +2 -0
  102. package/dist/project/findProjectRoot.js +51 -0
  103. package/dist/project/globalHome.d.ts +2 -0
  104. package/dist/project/globalHome.js +19 -0
  105. package/dist/project/resolveProjectContext.d.ts +9 -0
  106. package/dist/project/resolveProjectContext.js +38 -0
  107. package/dist/project/resolveStageflowContext.d.ts +11 -0
  108. package/dist/project/resolveStageflowContext.js +66 -0
  109. package/dist/projection/projectRun.d.ts +44 -0
  110. package/dist/projection/projectRun.js +71 -0
  111. package/dist/prompt/priorEnvelope.d.ts +1 -1
  112. package/dist/prompt/priorEnvelope.js +4 -1
  113. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  114. package/dist/runstore/normalizeCatalogPath.js +4 -0
  115. package/dist/runstore/paths.js +2 -0
  116. package/dist/runstore/pipelineDagSnapshot.d.ts +9 -0
  117. package/dist/runstore/pipelineDagSnapshot.js +90 -1
  118. package/dist/runstore/port.d.ts +22 -2
  119. package/dist/runstore/port.js +4 -1
  120. package/dist/runstore/runProjection.d.ts +1 -1
  121. package/dist/runstore/runProjection.js +25 -4
  122. package/dist/runstore/sqlite/SqliteRunStore.d.ts +3 -2
  123. package/dist/runstore/sqlite/SqliteRunStore.js +65 -7
  124. package/dist/runstore/sqlite/schema.d.ts +1 -1
  125. package/dist/runstore/sqlite/schema.js +4 -1
  126. package/dist/runstore/stageInstanceId.d.ts +4 -0
  127. package/dist/runstore/stageInstanceId.js +23 -0
  128. package/dist/runstore/syntheticStageSnapshot.d.ts +1 -1
  129. package/dist/runstore/syntheticStageSnapshot.js +2 -1
  130. package/dist/runstore/trackProjection.js +28 -12
  131. package/dist/runstore/workspaceLayout.d.ts +1 -0
  132. package/dist/runstore/workspaceLayout.js +1 -1
  133. package/dist/runtime/cloneSchedule.d.ts +18 -0
  134. package/dist/runtime/cloneSchedule.js +233 -0
  135. package/dist/runtime/credentialBinding.d.ts +8 -6
  136. package/dist/runtime/credentialBinding.js +18 -24
  137. package/dist/runtime/envelopeRouting.d.ts +2 -1
  138. package/dist/runtime/envelopeRouting.js +80 -13
  139. package/dist/runtime/pipelineRunner.d.ts +3 -0
  140. package/dist/runtime/pipelineRunner.js +15 -1
  141. package/dist/runtime/pipelineScheduler.d.ts +8 -2
  142. package/dist/runtime/pipelineScheduler.js +215 -39
  143. package/dist/runtime/reloadRunCatalog.d.ts +5 -0
  144. package/dist/runtime/reloadRunCatalog.js +44 -0
  145. package/dist/runtime/resumeReconstruct.d.ts +1 -0
  146. package/dist/runtime/resumeReconstruct.js +31 -10
  147. package/dist/runtime/runChangeBus.d.ts +18 -0
  148. package/dist/runtime/runChangeBus.js +83 -0
  149. package/dist/runtime/runManager.d.ts +4 -0
  150. package/dist/runtime/runManager.js +36 -16
  151. package/dist/runtime/settingsFile.d.ts +12 -0
  152. package/dist/runtime/settingsFile.js +87 -6
  153. package/dist/runtime/stageAttemptBootstrap.d.ts +1 -0
  154. package/dist/runtime/stageAttemptBootstrap.js +18 -7
  155. package/dist/runtime/stageProcessLauncher.js +3 -0
  156. package/dist/runtime/stageRecovery.js +3 -1
  157. package/dist/runtime/stageRunner.d.ts +1 -0
  158. package/dist/runtime/stageRunner.js +17 -15
  159. package/dist/runtime/stageWorker.js +13 -10
  160. package/dist/server/bootstrap.d.ts +32 -0
  161. package/dist/server/bootstrap.js +56 -0
  162. package/dist/server/createHttpHost.d.ts +34 -0
  163. package/dist/server/createHttpHost.js +70 -0
  164. package/dist/server/http.d.ts +6 -13
  165. package/dist/server/http.js +297 -352
  166. package/dist/server/mcpHost.d.ts +22 -0
  167. package/dist/server/mcpHost.js +21 -0
  168. package/dist/server/operatorResults.d.ts +13 -0
  169. package/dist/server/operatorResults.js +22 -0
  170. package/dist/tools/emitStageEnvelope.d.ts +12 -1
  171. package/dist/tools/emitStageEnvelope.js +27 -1
  172. package/dist/types/envelope.d.ts +3 -0
  173. package/dist/types/forkChoice.d.ts +30 -0
  174. package/dist/types/forkChoice.js +1 -0
  175. package/dist/types/pipeline.d.ts +59 -2
  176. package/dist/types/stageflowManifest.d.ts +23 -0
  177. package/dist/types/stageflowManifest.js +1 -0
  178. package/dist/ui/assets/{index-DCsDopak.css → index-C3N7MXAC.css} +1 -1
  179. package/dist/ui/assets/index-CSoGDA3A.js +118 -0
  180. package/dist/ui/index.html +3 -2
  181. package/dist/ui/stageflow-icon.svg +12 -0
  182. package/package.json +8 -5
  183. package/skills/install-suite.sh +107 -0
  184. package/skills/stageflow/SKILL.md +26 -0
  185. package/skills/stageflow/references/control-surface.md +26 -0
  186. package/skills/stageflow/scripts/detect-host.mjs +54 -0
  187. package/skills/stageflow/scripts/detect-host.test.mjs +97 -0
  188. package/skills/stageflow-author/SKILL.md +58 -0
  189. package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -0
  190. package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -0
  191. package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +13 -0
  192. package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +10 -0
  193. package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +9 -0
  194. package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +10 -0
  195. package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +10 -0
  196. package/skills/stageflow-author/assets/examples/linear-review/review.yaml +15 -0
  197. package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -0
  198. package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +10 -0
  199. package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +10 -0
  200. package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -0
  201. package/skills/stageflow-author/references/catalog-mapping.md +131 -0
  202. package/skills/stageflow-author/references/catalog-write-conventions.md +29 -0
  203. package/skills/stageflow-author/references/stage-prompt-template.md +55 -0
  204. package/skills/stageflow-author/references/validate-and-report.md +38 -0
  205. package/skills/stageflow-delegate/SKILL.md +18 -0
  206. package/skills/stageflow-delegate/references/authoring-or-run.md +15 -0
  207. package/skills/stageflow-delegate/references/example-walkthrough.md +30 -0
  208. package/skills/stageflow-delegate/references/pattern-detection.md +44 -0
  209. package/skills/stageflow-run/SKILL.md +151 -0
  210. package/skills/stageflow-run/references/mcp-call.md +17 -0
  211. package/skills/stageflow-run/references/task-and-pipeline-selection.md +52 -0
  212. package/skills/stageflow-run/scripts/mcp-call.mjs +299 -0
  213. package/skills/stageflow-run/scripts/mcp-call.test.mjs +271 -0
  214. package/skills/stageflow-session-capture/SKILL.md +94 -0
  215. package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +7 -0
  216. package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +8 -0
  217. package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +8 -0
  218. package/skills/stageflow-session-capture/references/catalog-authoring.md +40 -0
  219. package/skills/stageflow-session-capture/references/transcript-sources.md +25 -0
  220. package/skills/stageflow-session-capture/scripts/check-provider-gate.mjs +43 -0
  221. package/skills/stageflow-session-capture/scripts/locate-session-transcript.mjs +141 -0
  222. package/skills/stageflow-session-capture/scripts/resolve-catalog-id.mjs +119 -0
  223. package/skills/stageflow-setup/SKILL.md +110 -0
  224. package/dist/ui/assets/index-Cry0Tpfx.js +0 -118
@@ -1,14 +1,15 @@
1
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import { storeRootFor } from "../runstore/paths.js";
5
- import { parseCredentialSource, readCredentialSourceFromFile, writeCredentialSourceToFile, } from "./settingsFile.js";
6
- export { parseCredentialSource, readCredentialSourceFromFile, writeCredentialSourceToFile, };
7
- export function sfOwnedAgentDir(cwd) {
8
- return path.join(storeRootFor(cwd), "agent");
4
+ import { ensureGlobalHome } from "../project/globalHome.js";
5
+ import { resolveProjectContext, } from "../project/resolveProjectContext.js";
6
+ import { parseCredentialSource, readCredentialSourceFromContext, writeCredentialSourceToContext, } from "./settingsFile.js";
7
+ export { parseCredentialSource, readCredentialSourceFromContext, writeCredentialSourceToContext, };
8
+ export function sfOwnedAgentDir() {
9
+ return path.join(ensureGlobalHome(), "agent");
9
10
  }
10
- export function sfOwnedAuthPath(cwd) {
11
- return path.join(sfOwnedAgentDir(cwd), "auth.json");
11
+ export function sfOwnedAuthPath() {
12
+ return path.join(sfOwnedAgentDir(), "auth.json");
12
13
  }
13
14
  export function piHomeAuthPath(override) {
14
15
  return (override ??
@@ -25,18 +26,9 @@ export function isUsableAuthFile(authPath) {
25
26
  return false;
26
27
  }
27
28
  }
28
- export function ensureSfOwnedAuthStore(cwd) {
29
- const storeRoot = storeRootFor(cwd);
30
- mkdirSync(storeRoot, { recursive: true });
31
- const agentDir = sfOwnedAgentDir(cwd);
32
- mkdirSync(agentDir, { recursive: true });
33
- try {
34
- chmodSync(agentDir, 0o700);
35
- }
36
- catch {
37
- // best-effort on non-POSIX
38
- }
39
- const authPath = sfOwnedAuthPath(cwd);
29
+ export function ensureSfOwnedAuthStore() {
30
+ ensureGlobalHome();
31
+ const authPath = sfOwnedAuthPath();
40
32
  if (!existsSync(authPath)) {
41
33
  writeFileSync(authPath, "{}\n", { encoding: "utf8", mode: 0o600 });
42
34
  }
@@ -48,14 +40,15 @@ export function ensureSfOwnedAuthStore(cwd) {
48
40
  }
49
41
  return authPath;
50
42
  }
51
- export function resolveCredentialBinding(cwd, options = {}) {
43
+ export function resolveCredentialBinding(ctx, options = {}) {
44
+ const projectCtx = typeof ctx === "string" ? resolveProjectContext(ctx) : ctx;
52
45
  const piHome = piHomeAuthPath(options.piHomeAuthPath);
53
- const persisted = readCredentialSourceFromFile(cwd);
46
+ const persisted = readCredentialSourceFromContext(projectCtx);
54
47
  if (persisted !== undefined) {
55
48
  if (persisted === "sf_owned") {
56
49
  return {
57
50
  source: "sf_owned",
58
- authPath: ensureSfOwnedAuthStore(cwd),
51
+ authPath: ensureSfOwnedAuthStore(),
59
52
  provisional: false,
60
53
  };
61
54
  }
@@ -74,7 +67,8 @@ export function resolveCredentialBinding(cwd, options = {}) {
74
67
  }
75
68
  return {
76
69
  source: "sf_owned",
77
- authPath: ensureSfOwnedAuthStore(cwd),
70
+ authPath: ensureSfOwnedAuthStore(),
78
71
  provisional: true,
79
72
  };
80
73
  }
74
+ export { readCredentialSourceFromFile, writeCredentialSourceToFile, } from "./settingsFile.js";
@@ -2,11 +2,12 @@ import type { RunStore, StageSnapshot } from "../runstore/port.js";
2
2
  import type { StageEnvelope } from "../types/envelope.js";
3
3
  import type { LoadedPipeline, ResolvedPipelineDag } from "../types/pipeline.js";
4
4
  import type { StageConfig } from "../types/stage.js";
5
- export declare function buildCompletedEnvelopesFromRun(store: RunStore, runId: string, stages?: StageSnapshot[]): Promise<Map<string, StageEnvelope>>;
5
+ export declare function buildCompletedEnvelopesFromRun(store: RunStore, runId: string, stages?: StageSnapshot[], dag?: ResolvedPipelineDag): Promise<Map<string, StageEnvelope>>;
6
6
  export declare function buildStageConfigById(loaded: LoadedPipeline): Map<string, StageConfig>;
7
7
  export type ResolvePriorEnvelopeResult = {
8
8
  ok: true;
9
9
  prior: StageEnvelope | null;
10
+ joinPriors?: StageEnvelope[];
10
11
  } | {
11
12
  ok: false;
12
13
  reason: string;
@@ -1,15 +1,34 @@
1
- export async function buildCompletedEnvelopesFromRun(store, runId, stages) {
1
+ import { instancesOfDefinition, } from "../runstore/pipelineDagSnapshot.js";
2
+ import { definitionIdForInstance } from "../runstore/stageInstanceId.js";
3
+ function definitionInstances(dag, catalogId) {
4
+ const snapshot = dag;
5
+ if (Array.isArray(snapshot.stage_ids)) {
6
+ return instancesOfDefinition(snapshot, catalogId);
7
+ }
8
+ return dag.nodes.some((n) => n.id === catalogId) ? [catalogId] : [];
9
+ }
10
+ export async function buildCompletedEnvelopesFromRun(store, runId, stages, dag) {
2
11
  const completedEnvelopes = new Map();
3
12
  const snapshotStages = stages ?? (await store.readRun(runId)).stages;
4
13
  for (const snap of snapshotStages) {
5
- if (snap.status !== "succeeded")
14
+ const isCloneInstance = dag !== undefined &&
15
+ definitionIdForInstance(dag, snap.stage_id) !==
16
+ snap.stage_id;
17
+ if (snap.status !== "succeeded" && !(snap.status === "failed" && isCloneInstance)) {
6
18
  continue;
19
+ }
7
20
  try {
8
21
  const envelope = snap.envelope ?? (await store.readEnvelope(runId, snap.stage_id));
9
22
  completedEnvelopes.set(snap.stage_id, envelope);
10
23
  }
11
24
  catch {
12
- // envelope may be missing for corrupt runs; leave map empty
25
+ if (snap.status === "failed" && isCloneInstance) {
26
+ completedEnvelopes.set(snap.stage_id, {
27
+ status: "failure",
28
+ summary: "stage failed",
29
+ artifacts: [],
30
+ });
31
+ }
13
32
  }
14
33
  }
15
34
  return completedEnvelopes;
@@ -35,15 +54,41 @@ export async function resolvePriorEnvelope(options) {
35
54
  if (node.needs === null) {
36
55
  return { ok: true, prior: null };
37
56
  }
57
+ const joinInstances = definitionInstances(options.dag, node.needs);
58
+ if (joinInstances.length > 1) {
59
+ const joinPriors = [];
60
+ for (const id of joinInstances) {
61
+ const fromMap = options.completedEnvelopes.get(id);
62
+ if (fromMap !== undefined) {
63
+ joinPriors.push(structuredClone(fromMap));
64
+ continue;
65
+ }
66
+ if (options.store !== undefined && options.runId !== undefined) {
67
+ try {
68
+ const envelope = await options.store.readEnvelope(options.runId, id);
69
+ joinPriors.push(structuredClone(envelope));
70
+ continue;
71
+ }
72
+ catch {
73
+ return {
74
+ ok: false,
75
+ reason: `missing envelope for clone instance "${id}"`,
76
+ };
77
+ }
78
+ }
79
+ return {
80
+ ok: false,
81
+ reason: `missing envelope for clone instance "${id}"`,
82
+ };
83
+ }
84
+ return { ok: true, prior: null, joinPriors };
85
+ }
38
86
  const parentId = node.needs;
39
87
  const fromMap = options.completedEnvelopes.get(parentId);
40
- if (fromMap !== undefined) {
41
- return { ok: true, prior: structuredClone(fromMap) };
42
- }
43
- if (options.store !== undefined && options.runId !== undefined) {
88
+ let parent = fromMap;
89
+ if (parent === undefined && options.store !== undefined && options.runId !== undefined) {
44
90
  try {
45
- const envelope = await options.store.readEnvelope(options.runId, parentId);
46
- return { ok: true, prior: structuredClone(envelope) };
91
+ parent = await options.store.readEnvelope(options.runId, parentId);
47
92
  }
48
93
  catch {
49
94
  return {
@@ -52,8 +97,30 @@ export async function resolvePriorEnvelope(options) {
52
97
  };
53
98
  }
54
99
  }
55
- return {
56
- ok: false,
57
- reason: `missing envelope for upstream stage "${parentId}"`,
58
- };
100
+ if (parent === undefined) {
101
+ return {
102
+ ok: false,
103
+ reason: `missing envelope for upstream stage "${parentId}"`,
104
+ };
105
+ }
106
+ for (const item of parent.clone_forks ?? []) {
107
+ if (item.action === "once" && item.successor_id === options.stageId) {
108
+ return { ok: true, prior: structuredClone(item.envelope) };
109
+ }
110
+ if (item.action === "fanout") {
111
+ const instanceIds = definitionInstances(options.dag, item.successor_id);
112
+ const index = instanceIds.indexOf(options.stageId);
113
+ if (index >= 0) {
114
+ const clone = item.clones[index];
115
+ if (clone === undefined) {
116
+ return {
117
+ ok: false,
118
+ reason: `missing clone envelope for instance "${options.stageId}"`,
119
+ };
120
+ }
121
+ return { ok: true, prior: structuredClone(clone.envelope) };
122
+ }
123
+ }
124
+ }
125
+ return { ok: true, prior: structuredClone(parent) };
59
126
  }
@@ -31,6 +31,7 @@ export type PreparedPipeline = {
31
31
  agent: AgentPort;
32
32
  store: RunStore;
33
33
  cwd: string;
34
+ projectRoot: string;
34
35
  checkoutRoot?: string;
35
36
  hitl?: StageHitlController;
36
37
  executionMode?: StageExecutionMode;
@@ -55,6 +56,7 @@ export declare function runPipeline(options: {
55
56
  taskYaml?: string;
56
57
  pipeline: string;
57
58
  cwd?: string;
59
+ projectRoot?: string;
58
60
  checkoutOverride?: string;
59
61
  hitl?: StageHitlController;
60
62
  maxActiveStagesPerRun?: number;
@@ -71,6 +73,7 @@ export declare function startPipeline(options: {
71
73
  taskYaml?: string;
72
74
  pipeline: string;
73
75
  cwd?: string;
76
+ projectRoot?: string;
74
77
  checkoutOverride?: string;
75
78
  gitSha?: string;
76
79
  ciPrUrl?: string;
@@ -1,10 +1,11 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import path from "node:path";
3
- import { loadPipelineValidated } from "../config/loadPipeline.js";
3
+ import { loadPipelineValidated } from "../config/validateCatalog.js";
4
4
  import { loadTaskFromYaml } from "../config/loadTask.js";
5
5
  import { buildValidationResult } from "../config/validateCatalog.js";
6
6
  import { resolveAndValidateCheckout } from "./stageRoots.js";
7
7
  import { buildPipelineDagSnapshotFromLoaded } from "../runstore/pipelineDagSnapshot.js";
8
+ import { normalizeCatalogPath } from "../runstore/normalizeCatalogPath.js";
8
9
  import { runPipelineDag } from "./pipelineScheduler.js";
9
10
  import { readMaxActiveStagesPerRun, readStageExecutionMode, } from "./stageConcurrency.js";
10
11
  import { StageProcessLauncher } from "./stageProcessLauncher.js";
@@ -41,6 +42,11 @@ async function preparePipeline(options) {
41
42
  const label = options.taskPath ?? "task.yaml";
42
43
  const task = loadTaskFromYaml(taskYaml, `task file ${label}`);
43
44
  const checkoutRoot = await resolveAndValidateCheckout(task, options.checkoutOverride, options.cwd);
45
+ const pipelinePath = normalizeCatalogPath(loaded.pipelinePath);
46
+ const taskPath = options.taskPath
47
+ ? normalizeCatalogPath(path.resolve(options.cwd, options.taskPath))
48
+ : undefined;
49
+ const projectRoot = normalizeCatalogPath(options.projectRoot ?? options.cwd);
44
50
  const run = await options.store.createRun({
45
51
  pipelineId: loaded.pipeline.id,
46
52
  taskYaml,
@@ -50,6 +56,9 @@ async function preparePipeline(options) {
50
56
  ciPrUrl: options.ciPrUrl,
51
57
  ciJobUrl: options.ciJobUrl,
52
58
  pipelineDag: buildPipelineDagSnapshotFromLoaded(loaded),
59
+ pipelinePath,
60
+ taskPath,
61
+ projectRoot,
53
62
  });
54
63
  const executionMode = readStageExecutionMode(process.env, options.executionMode);
55
64
  const stageProcessLauncher = resolveStageProcessLauncher(executionMode, options.stageProcessLauncher);
@@ -60,6 +69,7 @@ async function preparePipeline(options) {
60
69
  agent: options.agent,
61
70
  store: options.store,
62
71
  cwd: options.cwd,
72
+ projectRoot: options.projectRoot ?? options.cwd,
63
73
  checkoutRoot,
64
74
  hitl: options.hitl,
65
75
  executionMode,
@@ -86,6 +96,7 @@ export async function executeStages(prepared, options) {
86
96
  }
87
97
  export async function runPipeline(options) {
88
98
  const cwd = options.cwd ?? process.cwd();
99
+ const projectRoot = options.projectRoot ?? cwd;
89
100
  const prepared = await preparePipeline({
90
101
  agent: options.agent,
91
102
  store: options.store,
@@ -93,6 +104,7 @@ export async function runPipeline(options) {
93
104
  taskYaml: options.taskYaml,
94
105
  pipeline: options.pipeline,
95
106
  cwd,
107
+ projectRoot,
96
108
  checkoutOverride: options.checkoutOverride,
97
109
  hitl: options.hitl,
98
110
  executionMode: options.executionMode,
@@ -109,6 +121,7 @@ export async function runPipeline(options) {
109
121
  /** Create the run immediately, then execute stages in the returned promise. */
110
122
  export async function startPipeline(options) {
111
123
  const cwd = options.cwd ?? process.cwd();
124
+ const projectRoot = options.projectRoot ?? cwd;
112
125
  const prepared = await preparePipeline({
113
126
  agent: options.agent,
114
127
  store: options.store,
@@ -116,6 +129,7 @@ export async function startPipeline(options) {
116
129
  taskYaml: options.taskYaml,
117
130
  pipeline: options.pipeline,
118
131
  cwd,
132
+ projectRoot,
119
133
  checkoutOverride: options.checkoutOverride,
120
134
  gitSha: options.gitSha,
121
135
  ciPrUrl: options.ciPrUrl,
@@ -1,8 +1,9 @@
1
1
  import type { AgentPort } from "../agent/port.js";
2
- import type { RunStore, StageSnapshot } from "../runstore/port.js";
2
+ import type { RunPipelineDagSnapshot, RunStore, StageSnapshot } from "../runstore/port.js";
3
3
  import type { StageEnvelope } from "../types/envelope.js";
4
4
  import type { LoadedPipeline, ResolvedPipelineDag } from "../types/pipeline.js";
5
5
  import type { TaskFile } from "../types/task.js";
6
+ import { applyCloneForksFromEnvelopes, applyCloneForksToSchedule } from "./cloneSchedule.js";
6
7
  import type { PipelineRunResult } from "./pipelineRunner.js";
7
8
  import type { StageProcessLauncher } from "./stageProcessLauncher.js";
8
9
  import type { StageExecutionMode } from "./stageConcurrency.js";
@@ -18,6 +19,7 @@ type SchedulerPreparedPipeline = {
18
19
  agent: AgentPort;
19
20
  store: RunStore;
20
21
  cwd: string;
22
+ projectRoot?: string;
21
23
  checkoutRoot?: string;
22
24
  hitl?: StageHitlController;
23
25
  operatorCatalog?: OperatorCatalog;
@@ -38,13 +40,16 @@ type HasWorkOutsideBranchContext = {
38
40
  retryRoots?: ReadonlyMap<string, number>;
39
41
  pendingDeltaStageIds?: ReadonlySet<string>;
40
42
  };
41
- type StageScheduleState = "pending" | "active" | "waiting" | "succeeded" | "failed" | "skipped";
43
+ export type StageScheduleState = "pending" | "active" | "waiting" | "succeeded" | "failed" | "skipped";
42
44
  export type HydratedSchedule = {
43
45
  states: Map<string, StageScheduleState>;
44
46
  completedEnvelopes: Map<string, StageEnvelope>;
45
47
  schedulingHalted: boolean;
46
48
  firstFailureReason: string | undefined;
49
+ dag?: RunPipelineDagSnapshot;
47
50
  };
51
+ export { applyCloneForksFromEnvelopes, applyCloneForksToSchedule, };
52
+ export type { ApplyCloneForksResult } from "./cloneSchedule.js";
48
53
  export declare function snapshotToScheduleState(snap: {
49
54
  status: StageSnapshot["status"];
50
55
  }, overrides: ReadonlyMap<string, StageScheduleState>, stageId: string, executionMode?: StageExecutionMode): StageScheduleState;
@@ -86,6 +91,7 @@ export type RetryRunOptions = {
86
91
  onRetryRootTerminal?: OnRetryRootTerminal;
87
92
  };
88
93
  export declare function retryRun(options: RetryRunOptions): Promise<PipelineRunResult>;
94
+ export declare function applyForkSkipsFromEnvelopes(dag: ResolvedPipelineDag, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope>): void;
89
95
  export declare function applyRetryRootDelta(dag: ResolvedPipelineDag, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope>, retryRoots: Map<string, number>, stageId: string, attempt: number, clearSchedulingHalt?: () => void): void;
90
96
  export declare function hasWorkOutsideBranch(dag: ResolvedPipelineDag, branchRootId: string, states: Map<string, StageScheduleState>, ctx?: HasWorkOutsideBranchContext): boolean;
91
97
  export declare function runPipelineDag(options: RunPipelineDagOptions): Promise<PipelineRunResult>;