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
@@ -0,0 +1,71 @@
1
+ import { access, mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { findProjectRoot } from "../project/findProjectRoot.js";
4
+ import { ensureGlobalHome } from "../project/globalHome.js";
5
+ import { HELLO_PIPELINE_YAML, HELLO_TASK_YAML, STAGEFLOW_YAML, } from "./initTemplates.js";
6
+ export const INIT_USAGE = `Usage:
7
+ sf init`;
8
+ const defaultIo = {
9
+ log: (line) => console.log(line),
10
+ error: (line) => console.error(line),
11
+ };
12
+ const INIT_TARGETS = [
13
+ { relPath: "stageflow.yaml", content: STAGEFLOW_YAML },
14
+ { relPath: "pipelines/hello.pipeline.yaml", content: HELLO_PIPELINE_YAML },
15
+ { relPath: "tasks/hello.task.yaml", content: HELLO_TASK_YAML },
16
+ ];
17
+ async function fileExists(absPath) {
18
+ try {
19
+ await access(absPath);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ function parseInitArgs(args) {
27
+ if (args.length === 0) {
28
+ return { help: false };
29
+ }
30
+ if (args[0] === "--help" || args[0] === "-h") {
31
+ return { help: true };
32
+ }
33
+ if (args[0].startsWith("-")) {
34
+ throw new Error(`Unknown flag: ${args[0]}`);
35
+ }
36
+ throw new Error(`Unexpected argument: ${args[0]}`);
37
+ }
38
+ export async function runInitCommand(args, options = {}) {
39
+ const cwd = options.cwd ?? process.cwd();
40
+ const out = { ...defaultIo, ...options.io };
41
+ try {
42
+ const parsed = parseInitArgs(args);
43
+ if (parsed.help) {
44
+ out.error(INIT_USAGE);
45
+ return 0;
46
+ }
47
+ const initRoot = findProjectRoot(cwd) ?? path.resolve(cwd);
48
+ ensureGlobalHome();
49
+ for (const target of INIT_TARGETS) {
50
+ const absPath = path.join(initRoot, target.relPath);
51
+ if (await fileExists(absPath)) {
52
+ out.log(`Skipped ${target.relPath} (exists)`);
53
+ continue;
54
+ }
55
+ await mkdir(path.dirname(absPath), { recursive: true });
56
+ await writeFile(absPath, target.content, "utf8");
57
+ out.log(`Created ${target.relPath}`);
58
+ }
59
+ return 0;
60
+ }
61
+ catch (err) {
62
+ const message = err instanceof Error
63
+ ? err.message
64
+ : typeof err === "string"
65
+ ? err
66
+ : "Init command failed";
67
+ out.error(message);
68
+ out.error(INIT_USAGE);
69
+ return 1;
70
+ }
71
+ }
@@ -0,0 +1,3 @@
1
+ export declare const STAGEFLOW_YAML = "version: 1\ncatalog:\n pipelines:\n - pipelines\n tasks:\n - tasks\n patterns:\n pipeline: \"*.pipeline.yaml\"\n task: \"*.task.yaml\"\n";
2
+ export declare const HELLO_PIPELINE_YAML = "id: hello\nstages:\n - id: hello\n system_prompt: Say hello and emit a success envelope.\n model: anthropic/claude-sonnet-4-5\n";
3
+ export declare const HELLO_TASK_YAML = "id: hello\ngoal: Run the hello pipeline scaffold.\n";
@@ -0,0 +1,19 @@
1
+ export const STAGEFLOW_YAML = `version: 1
2
+ catalog:
3
+ pipelines:
4
+ - pipelines
5
+ tasks:
6
+ - tasks
7
+ patterns:
8
+ pipeline: "*.pipeline.yaml"
9
+ task: "*.task.yaml"
10
+ `;
11
+ export const HELLO_PIPELINE_YAML = `id: hello
12
+ stages:
13
+ - id: hello
14
+ system_prompt: Say hello and emit a success envelope.
15
+ model: anthropic/claude-sonnet-4-5
16
+ `;
17
+ export const HELLO_TASK_YAML = `id: hello
18
+ goal: Run the hello pipeline scaffold.
19
+ `;
@@ -0,0 +1,10 @@
1
+ import type { OperatorCatalog } from "../runtime/stageAttemptBootstrap.js";
2
+ export type OperatorCatalogFlags = {
3
+ operatorCwd?: string;
4
+ operatorAgentDir?: string;
5
+ };
6
+ export declare function resolveOperatorCatalog(input: {
7
+ flags: OperatorCatalogFlags;
8
+ env: Record<string, string | undefined>;
9
+ defaultCwd: string;
10
+ }): OperatorCatalog;
@@ -0,0 +1,16 @@
1
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
2
+ function nonempty(value) {
3
+ if (value === undefined)
4
+ return undefined;
5
+ const trimmed = value.trim();
6
+ return trimmed.length === 0 ? undefined : trimmed;
7
+ }
8
+ export function resolveOperatorCatalog(input) {
9
+ const cwd = nonempty(input.flags.operatorCwd) ??
10
+ nonempty(input.env.STAGEFLOW_OPERATOR_CWD) ??
11
+ input.defaultCwd;
12
+ const agentDir = nonempty(input.flags.operatorAgentDir) ??
13
+ nonempty(input.env.STAGEFLOW_OPERATOR_AGENT_DIR) ??
14
+ getAgentDir();
15
+ return { cwd, agentDir };
16
+ }
@@ -1,6 +1,7 @@
1
+ import type { RunStore } from "../runstore/port.js";
1
2
  import { type StartRunResult } from "../runtime/runManager.js";
2
3
  import { type CliRunReportIo } from "./runOutput.js";
3
- export declare const RUN_USAGE = "Usage:\n sf run --task <path> --pipeline <name-or-path> [--checkout <path>] [--json] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>]";
4
+ export declare const RUN_USAGE = "Usage:\n sf run --task <path> --pipeline <path> [--checkout <path>] [--json] [--include stages] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>] [--operator-cwd <path>] [--operator-agent-dir <path>]";
4
5
  export type RunCommandIo = CliRunReportIo;
5
6
  export type StartRunFn = (input: {
6
7
  task: string;
@@ -15,10 +16,15 @@ export declare function completeCliRun(started: Extract<StartRunResult, {
15
16
  ok: true;
16
17
  }>, io?: RunCommandIo, options?: {
17
18
  json?: boolean;
19
+ store?: RunStore;
20
+ includeStages?: boolean;
18
21
  }): Promise<number>;
19
22
  export declare function runRunCommand(args: string[], options?: {
20
23
  cwd?: string;
24
+ projectRoot?: string;
25
+ isGitProject?: boolean;
21
26
  io?: Partial<RunCommandIo>;
22
27
  startRun?: StartRunFn;
28
+ store?: RunStore;
23
29
  env?: Record<string, string | undefined>;
24
30
  }): Promise<number>;
@@ -1,4 +1,3 @@
1
- import { getAgentDir } from "@earendil-works/pi-coding-agent";
2
1
  import { PiAgentAdapter } from "../agent/piAdapter.js";
3
2
  import { createRunStore } from "../runstore/createStore.js";
4
3
  import { PipelineValidationError } from "../runtime/pipelineRunner.js";
@@ -6,19 +5,20 @@ import { RunManager } from "../runtime/runManager.js";
6
5
  import { readStageExecutionMode } from "../runtime/stageConcurrency.js";
7
6
  import { reportCliRun, } from "./runOutput.js";
8
7
  import { resolveCiIdentity } from "./ciIdentity.js";
8
+ import { resolveOperatorCatalog } from "./operatorCatalog.js";
9
9
  import { exitCodeForValidation, formatValidationHuman, formatValidationJson, } from "./validateOutput.js";
10
10
  export const RUN_USAGE = `Usage:
11
- sf run --task <path> --pipeline <name-or-path> [--checkout <path>] [--json] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>]`;
11
+ sf run --task <path> --pipeline <path> [--checkout <path>] [--json] [--include stages] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>] [--operator-cwd <path>] [--operator-agent-dir <path>]`;
12
12
  const defaultIo = {
13
13
  log: (line) => console.log(line),
14
14
  error: (line) => console.error(line),
15
15
  };
16
16
  function parseRunArgs(args) {
17
17
  if (args.length === 0) {
18
- return { help: false, json: false, skipGates: false };
18
+ return { help: false, json: false, includeStages: false, skipGates: false };
19
19
  }
20
20
  if (args[0] === "--help" || args[0] === "-h") {
21
- return { help: true, json: false, skipGates: false };
21
+ return { help: true, json: false, includeStages: false, skipGates: false };
22
22
  }
23
23
  let task;
24
24
  let pipeline;
@@ -26,7 +26,10 @@ function parseRunArgs(args) {
26
26
  let gitSha;
27
27
  let ciPrUrl;
28
28
  let ciJobUrl;
29
+ let operatorCwd;
30
+ let operatorAgentDir;
29
31
  let json = false;
32
+ let includeStages = false;
30
33
  let skipGates = false;
31
34
  let help = false;
32
35
  for (let i = 0; i < args.length; i++) {
@@ -76,9 +79,35 @@ function parseRunArgs(args) {
76
79
  }
77
80
  ciJobUrl = value;
78
81
  }
82
+ else if (arg === "--operator-cwd") {
83
+ const value = args[++i];
84
+ if (value === undefined || value.length === 0) {
85
+ throw new Error("Missing value for --operator-cwd");
86
+ }
87
+ operatorCwd = value;
88
+ }
89
+ else if (arg === "--operator-agent-dir") {
90
+ const value = args[++i];
91
+ if (value === undefined || value.length === 0) {
92
+ throw new Error("Missing value for --operator-agent-dir");
93
+ }
94
+ operatorAgentDir = value;
95
+ }
79
96
  else if (arg === "--json") {
80
97
  json = true;
81
98
  }
99
+ else if (arg === "--include") {
100
+ const value = args[++i];
101
+ if (value === undefined || value.length === 0) {
102
+ throw new Error("Missing value for --include");
103
+ }
104
+ if (value === "stages") {
105
+ includeStages = true;
106
+ }
107
+ else {
108
+ throw new Error(`Unknown --include value: ${value}`);
109
+ }
110
+ }
82
111
  else if (arg === "--skip-gates") {
83
112
  skipGates = true;
84
113
  }
@@ -89,16 +118,31 @@ function parseRunArgs(args) {
89
118
  throw new Error(`Unexpected argument: ${arg}`);
90
119
  }
91
120
  }
92
- return { help, json, skipGates, task, pipeline, checkout, gitSha, ciPrUrl, ciJobUrl };
121
+ return {
122
+ help,
123
+ json,
124
+ includeStages,
125
+ skipGates,
126
+ task,
127
+ pipeline,
128
+ checkout,
129
+ gitSha,
130
+ ciPrUrl,
131
+ ciJobUrl,
132
+ operatorCwd,
133
+ operatorAgentDir,
134
+ };
93
135
  }
94
- function defaultStartRun(cwd) {
136
+ function defaultStartRun(cwd, projectRoot, isGitProject, operatorCatalog) {
95
137
  return async (input) => {
96
- const store = createRunStore({ rootDir: cwd });
138
+ const store = createRunStore({ rootDir: projectRoot });
97
139
  const manager = new RunManager({
98
140
  agent: new PiAgentAdapter(),
99
141
  store,
100
142
  cwd,
101
- operatorCatalog: { cwd, agentDir: getAgentDir() },
143
+ projectRoot,
144
+ isGitProject,
145
+ operatorCatalog,
102
146
  executionMode: readStageExecutionMode(process.env, "process"),
103
147
  });
104
148
  return manager.startRun(input);
@@ -106,10 +150,17 @@ function defaultStartRun(cwd) {
106
150
  }
107
151
  export async function completeCliRun(started, io = defaultIo, options = {}) {
108
152
  const result = await started.done;
109
- return reportCliRun({ kind: "completion", result }, { json: options.json, io });
153
+ return reportCliRun({ kind: "completion", result }, {
154
+ json: options.json,
155
+ io,
156
+ store: options.store,
157
+ includeStages: options.includeStages,
158
+ });
110
159
  }
111
160
  export async function runRunCommand(args, options = {}) {
112
161
  const cwd = options.cwd ?? process.cwd();
162
+ const projectRoot = options.projectRoot ?? cwd;
163
+ const isGitProject = options.isGitProject ?? false;
113
164
  const out = { ...defaultIo, ...options.io };
114
165
  let parsed;
115
166
  try {
@@ -130,7 +181,20 @@ export async function runRunCommand(args, options = {}) {
130
181
  out.error(RUN_USAGE);
131
182
  return 1;
132
183
  }
133
- const startRun = options.startRun ?? defaultStartRun(cwd);
184
+ if (parsed.includeStages && !parsed.json) {
185
+ out.error("error: --include stages requires --json");
186
+ return 1;
187
+ }
188
+ const operatorCatalog = resolveOperatorCatalog({
189
+ flags: {
190
+ operatorCwd: parsed.operatorCwd,
191
+ operatorAgentDir: parsed.operatorAgentDir,
192
+ },
193
+ env: options.env ?? process.env,
194
+ defaultCwd: cwd,
195
+ });
196
+ const startRun = options.startRun ??
197
+ defaultStartRun(cwd, projectRoot, isGitProject, operatorCatalog);
134
198
  const identity = resolveCiIdentity({
135
199
  flags: {
136
200
  gitSha: parsed.gitSha,
@@ -139,6 +203,10 @@ export async function runRunCommand(args, options = {}) {
139
203
  },
140
204
  env: options.env ?? process.env,
141
205
  });
206
+ const store = options.store ??
207
+ (parsed.includeStages
208
+ ? createRunStore({ rootDir: projectRoot })
209
+ : undefined);
142
210
  try {
143
211
  const started = await startRun({
144
212
  task: parsed.task,
@@ -150,7 +218,11 @@ export async function runRunCommand(args, options = {}) {
150
218
  if (!started.ok) {
151
219
  return reportCliRun({ kind: "start-failure", started }, { json: parsed.json, io: out });
152
220
  }
153
- return completeCliRun(started, out, { json: parsed.json });
221
+ return completeCliRun(started, out, {
222
+ json: parsed.json,
223
+ includeStages: parsed.includeStages,
224
+ store,
225
+ });
154
226
  }
155
227
  catch (err) {
156
228
  if (err instanceof PipelineValidationError) {
@@ -1,3 +1,4 @@
1
+ import type { RunStore } from "../runstore/port.js";
1
2
  import type { PipelineRunResult } from "../runtime/pipelineRunner.js";
2
3
  import type { StartRunResult } from "../runtime/runManager.js";
3
4
  export type CliRunReportIo = {
@@ -16,4 +17,6 @@ export type CliRunReportEvent = {
16
17
  export declare function reportCliRun(event: CliRunReportEvent, options: {
17
18
  json?: boolean;
18
19
  io: CliRunReportIo;
19
- }): number;
20
+ store?: RunStore;
21
+ includeStages?: boolean;
22
+ }): Promise<number>;
@@ -1,3 +1,4 @@
1
+ import { projectRun } from "../projection/projectRun.js";
1
2
  function stringify(payload) {
2
3
  return JSON.stringify(payload, null, 2);
3
4
  }
@@ -44,22 +45,22 @@ function formatStartFailureJson(started) {
44
45
  }
45
46
  return formatRunStartFailedJson(started);
46
47
  }
47
- function formatRunCompletionJson(result) {
48
+ function baseRunCompletionPayload(result) {
48
49
  if (result.outcome === "succeeded") {
49
- return stringify({
50
+ return {
50
51
  ok: true,
51
52
  outcome: "succeeded",
52
53
  runId: result.runId,
53
54
  runDir: result.runDir,
54
- });
55
+ };
55
56
  }
56
57
  if (result.outcome === "waiting") {
57
- return stringify({
58
+ return {
58
59
  ok: false,
59
60
  outcome: "waiting",
60
61
  runId: result.runId,
61
62
  runDir: result.runDir,
62
- });
63
+ };
63
64
  }
64
65
  const payload = {
65
66
  ok: false,
@@ -69,7 +70,18 @@ function formatRunCompletionJson(result) {
69
70
  };
70
71
  if (result.reason !== undefined)
71
72
  payload.reason = result.reason;
72
- return stringify(payload);
73
+ return payload;
74
+ }
75
+ function formatRunCompletionJson(result) {
76
+ return stringify(baseRunCompletionPayload(result));
77
+ }
78
+ async function formatRunCompletionJsonWithStages(result, store) {
79
+ const detail = await store.readRun(result.runId);
80
+ const projection = projectRun(detail);
81
+ return stringify({
82
+ ...baseRunCompletionPayload(result),
83
+ stages: projection.stages,
84
+ });
73
85
  }
74
86
  function writeStartFailureHuman(started, io) {
75
87
  const code = started.code ?? "error";
@@ -105,7 +117,7 @@ function exitCodeForRunOutcome(outcome) {
105
117
  return 1;
106
118
  }
107
119
  }
108
- export function reportCliRun(event, options) {
120
+ export async function reportCliRun(event, options) {
109
121
  if (event.kind === "start-failure") {
110
122
  if (options.json) {
111
123
  options.io.log(formatStartFailureJson(event.started));
@@ -116,7 +128,23 @@ export function reportCliRun(event, options) {
116
128
  return 1;
117
129
  }
118
130
  if (options.json) {
119
- options.io.log(formatRunCompletionJson(event.result));
131
+ if (options.includeStages) {
132
+ if (!options.store) {
133
+ options.io.error("error: --include stages requires an internal run store (report bug)");
134
+ return 1;
135
+ }
136
+ try {
137
+ options.io.log(await formatRunCompletionJsonWithStages(event.result, options.store));
138
+ }
139
+ catch (err) {
140
+ const message = err instanceof Error ? err.message : String(err);
141
+ options.io.error(`failed to read run for --include stages: ${message}`);
142
+ return 1;
143
+ }
144
+ }
145
+ else {
146
+ options.io.log(formatRunCompletionJson(event.result));
147
+ }
120
148
  }
121
149
  else {
122
150
  writeCompletionHuman(event.result, options.io);
@@ -0,0 +1,16 @@
1
+ export declare const SKILLS_USAGE = "Usage:\n sf skills list\n sf skills install --from-path <dir> [--skill-name <name>]\n sf skills install --from-zip <url-or-path> [--skill-name <name>] [--checksum sha256:<hex>]";
2
+ export type SkillsCommandIo = {
3
+ log: (line: string) => void;
4
+ error: (line: string) => void;
5
+ fetch: typeof globalThis.fetch;
6
+ runDoctor: (scriptPath: string, cwd: string) => number;
7
+ };
8
+ export declare function runSkillsCommand(args: string[], options?: {
9
+ cwd?: string;
10
+ projectRoot?: string;
11
+ io?: Partial<SkillsCommandIo>;
12
+ }): Promise<number>;
13
+ export declare function createStoredZip(files: {
14
+ name: string;
15
+ content: string | Buffer;
16
+ }[]): Buffer;