stageflow 0.25.0 → 0.27.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 (501) hide show
  1. package/README.md +10 -3
  2. package/dist/a2a/contracts.d.ts +1 -0
  3. package/dist/a2a/contracts.js +1 -0
  4. package/dist/a2a/registry.d.ts +2 -0
  5. package/dist/a2a/registry.js +20 -1
  6. package/dist/a2a/server.d.ts +7 -0
  7. package/dist/a2a/server.js +5 -2
  8. package/dist/a2a/service.d.ts +1 -1
  9. package/dist/a2a/service.js +57 -8
  10. package/dist/a2a/store.d.ts +8 -5
  11. package/dist/a2a/store.js +24 -67
  12. package/dist/agent/activity.d.ts +3 -0
  13. package/dist/agent/bootProviderConfig.d.ts +21 -0
  14. package/dist/agent/bootProviderConfig.js +74 -0
  15. package/dist/agent/piAdapter.d.ts +9 -1
  16. package/dist/agent/piAdapter.js +58 -3
  17. package/dist/agent/piIsolatedMcp.d.ts +2 -0
  18. package/dist/agent/piIsolatedMcp.js +10 -2
  19. package/dist/agent/port.d.ts +6 -0
  20. package/dist/agent/streamLogRedact.d.ts +1 -1
  21. package/dist/agent/streamLogRedact.js +4 -11
  22. package/dist/cli/artifactCommand.js +9 -16
  23. package/dist/cli/backupCommand.d.ts +9 -0
  24. package/dist/cli/backupCommand.js +111 -0
  25. package/dist/cli/debugRunCommand.d.ts +10 -0
  26. package/dist/cli/debugRunCommand.js +109 -0
  27. package/dist/cli/doctorCommand.d.ts +32 -0
  28. package/dist/cli/doctorCommand.js +453 -0
  29. package/dist/cli/envelopeCommand.js +9 -2
  30. package/dist/cli/exportAllCommand.d.ts +55 -0
  31. package/dist/cli/exportAllCommand.js +218 -0
  32. package/dist/cli/exportRunCommand.js +23 -21
  33. package/dist/cli/hostClient.d.ts +21 -3
  34. package/dist/cli/hostClient.js +93 -12
  35. package/dist/cli/initTemplates.d.ts +1 -1
  36. package/dist/cli/initTemplates.js +8 -1
  37. package/dist/cli/resolveSafeOutPath.d.ts +2 -0
  38. package/dist/cli/resolveSafeOutPath.js +40 -0
  39. package/dist/cli/restoreCommand.d.ts +10 -0
  40. package/dist/cli/restoreCommand.js +90 -0
  41. package/dist/cli/runCommand.d.ts +3 -2
  42. package/dist/cli/runCommand.js +93 -11
  43. package/dist/cli/runOutput.d.ts +4 -0
  44. package/dist/cli/runOutput.js +33 -7
  45. package/dist/cli/runStageCommand.d.ts +1 -0
  46. package/dist/cli/runStageCommand.js +44 -25
  47. package/dist/cli/runsCommand.d.ts +1 -1
  48. package/dist/cli/runsCommand.js +162 -8
  49. package/dist/cli.js +171 -30
  50. package/dist/config/catalogRelativePath.d.ts +62 -0
  51. package/dist/config/catalogRelativePath.js +118 -0
  52. package/dist/config/configOrigin.d.ts +27 -0
  53. package/dist/config/configOrigin.js +59 -0
  54. package/dist/config/hostConfig.d.ts +55 -0
  55. package/dist/config/hostConfig.js +333 -0
  56. package/dist/config/listSkills.d.ts +26 -0
  57. package/dist/config/listSkills.js +190 -3
  58. package/dist/config/loadOutcome.d.ts +1 -1
  59. package/dist/config/loadPipeline.js +23 -2
  60. package/dist/config/loadStage.js +18 -0
  61. package/dist/config/loadTask.d.ts +2 -0
  62. package/dist/config/loadTask.js +57 -18
  63. package/dist/config/materializeStageModels.js +5 -1
  64. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  65. package/dist/config/mergePipelineIncludes.js +19 -0
  66. package/dist/config/migrateYaml.js +6 -11
  67. package/dist/config/multiProjectCatalog.d.ts +30 -0
  68. package/dist/config/multiProjectCatalog.js +142 -0
  69. package/dist/config/normalizePipelineStageEntry.js +20 -1
  70. package/dist/config/pipelineStageKeys.js +2 -0
  71. package/dist/config/resolveCatalogRoots.d.ts +27 -0
  72. package/dist/config/resolveCatalogRoots.js +76 -0
  73. package/dist/config/resolveModel.d.ts +7 -1
  74. package/dist/config/resolveModel.js +11 -1
  75. package/dist/config/resolveStageMcpServers.d.ts +9 -1
  76. package/dist/config/resolveStageMcpServers.js +36 -9
  77. package/dist/config/secretFromEnvOrFile.d.ts +9 -0
  78. package/dist/config/secretFromEnvOrFile.js +34 -0
  79. package/dist/config/seededCatalog.d.ts +11 -0
  80. package/dist/config/seededCatalog.js +29 -0
  81. package/dist/config/toolRequires.d.ts +24 -0
  82. package/dist/config/toolRequires.js +115 -0
  83. package/dist/config/validateCatalog.d.ts +5 -1
  84. package/dist/config/validateCatalog.js +140 -1
  85. package/dist/diagnostics/checks.d.ts +39 -0
  86. package/dist/diagnostics/checks.js +135 -0
  87. package/dist/errors/codes.d.ts +14 -0
  88. package/dist/errors/codes.js +59 -0
  89. package/dist/git/cache.d.ts +14 -0
  90. package/dist/git/cache.js +150 -0
  91. package/dist/git/credentials.d.ts +9 -0
  92. package/dist/git/credentials.js +88 -0
  93. package/dist/git/errors.d.ts +20 -0
  94. package/dist/git/errors.js +94 -0
  95. package/dist/git/exec.d.ts +16 -0
  96. package/dist/git/exec.js +135 -0
  97. package/dist/git/operations.d.ts +29 -0
  98. package/dist/git/operations.js +153 -0
  99. package/dist/git/version.d.ts +1 -0
  100. package/dist/git/version.js +10 -0
  101. package/dist/logging/audit.d.ts +16 -0
  102. package/dist/logging/audit.js +19 -0
  103. package/dist/logging/commonWords.d.ts +2 -0
  104. package/dist/logging/commonWords.js +13 -0
  105. package/dist/logging/logger.d.ts +49 -0
  106. package/dist/logging/logger.js +193 -0
  107. package/dist/logging/namedSecrets.d.ts +6 -0
  108. package/dist/logging/namedSecrets.js +58 -0
  109. package/dist/logging/redact.d.ts +13 -0
  110. package/dist/logging/redact.js +88 -0
  111. package/dist/mcp/catalogTools.js +456 -80
  112. package/dist/mcp/checkoutTools.d.ts +52 -0
  113. package/dist/mcp/checkoutTools.js +332 -0
  114. package/dist/mcp/controlTools.js +179 -5
  115. package/dist/mcp/deps.d.ts +1 -0
  116. package/dist/mcp/getStartedTool.d.ts +3 -0
  117. package/dist/mcp/getStartedTool.js +62 -0
  118. package/dist/mcp/readArtifact.d.ts +11 -0
  119. package/dist/mcp/readArtifact.js +46 -30
  120. package/dist/mcp/server.js +1 -0
  121. package/dist/mcp/tools.js +4 -0
  122. package/dist/net/proxy.d.ts +14 -0
  123. package/dist/net/proxy.js +78 -0
  124. package/dist/package-meta.d.ts +2 -1
  125. package/dist/package-meta.js +2 -1
  126. package/dist/preflight/bash.d.ts +8 -0
  127. package/dist/preflight/bash.js +34 -0
  128. package/dist/preflight/claudeRoot.d.ts +11 -0
  129. package/dist/preflight/claudeRoot.js +23 -0
  130. package/dist/preflight/mcpCommands.d.ts +8 -0
  131. package/dist/preflight/mcpCommands.js +36 -0
  132. package/dist/preflight/pipelinePreflight.d.ts +40 -0
  133. package/dist/preflight/pipelinePreflight.js +192 -0
  134. package/dist/preflight/tls.d.ts +6 -0
  135. package/dist/preflight/tls.js +18 -0
  136. package/dist/preflight/toolchain.d.ts +45 -0
  137. package/dist/preflight/toolchain.js +219 -0
  138. package/dist/project/findProjectRoot.js +3 -4
  139. package/dist/project/globalHome.d.ts +7 -0
  140. package/dist/project/globalHome.js +63 -2
  141. package/dist/project/resolveProjectContext.js +2 -2
  142. package/dist/project/resolveStageflowContext.js +2 -2
  143. package/dist/projection/projectRun.d.ts +2 -1
  144. package/dist/projection/projectRun.js +1 -0
  145. package/dist/runstore/assertTmpdir.d.ts +1 -0
  146. package/dist/runstore/assertTmpdir.js +21 -0
  147. package/dist/runstore/backup.d.ts +52 -0
  148. package/dist/runstore/backup.js +292 -0
  149. package/dist/runstore/createStore.d.ts +18 -1
  150. package/dist/runstore/createStore.js +64 -5
  151. package/dist/runstore/debugBundle.d.ts +60 -0
  152. package/dist/runstore/debugBundle.js +143 -0
  153. package/dist/runstore/diskUsage.d.ts +50 -0
  154. package/dist/runstore/diskUsage.js +214 -0
  155. package/dist/runstore/exportRunPayload.d.ts +8 -0
  156. package/dist/runstore/exportRunPayload.js +23 -0
  157. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  158. package/dist/runstore/normalizeCatalogPath.js +10 -0
  159. package/dist/runstore/paths.d.ts +5 -0
  160. package/dist/runstore/paths.js +145 -1
  161. package/dist/runstore/port.d.ts +111 -13
  162. package/dist/runstore/port.js +8 -1
  163. package/dist/runstore/restore.d.ts +81 -0
  164. package/dist/runstore/restore.js +355 -0
  165. package/dist/runstore/retention.d.ts +27 -0
  166. package/dist/runstore/retention.js +74 -0
  167. package/dist/runstore/runManifest.d.ts +146 -0
  168. package/dist/runstore/runManifest.js +288 -0
  169. package/dist/runstore/runProjection.d.ts +3 -1
  170. package/dist/runstore/runProjection.js +63 -1
  171. package/dist/runstore/sqlite/SqliteRunStore.d.ts +28 -3
  172. package/dist/runstore/sqlite/SqliteRunStore.js +352 -219
  173. package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
  174. package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
  175. package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
  176. package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
  177. package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
  178. package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
  179. package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
  180. package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
  181. package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
  182. package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
  183. package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
  184. package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
  185. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
  186. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
  187. package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
  188. package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
  189. package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
  190. package/dist/runstore/sqlite/migrations/index.js +72 -0
  191. package/dist/runstore/sqlite/schema.d.ts +20 -1
  192. package/dist/runstore/sqlite/schema.js +277 -1
  193. package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
  194. package/dist/runstore/sqlite/storeOpenError.js +11 -0
  195. package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
  196. package/dist/runstore/sqlite/storeSchemaError.js +8 -0
  197. package/dist/runstore/stageExecution.js +3 -0
  198. package/dist/runstore/storeFilesystem.d.ts +32 -0
  199. package/dist/runstore/storeFilesystem.js +148 -0
  200. package/dist/runstore/trackProjection.js +2 -0
  201. package/dist/runstore/workspaceLayout.d.ts +13 -0
  202. package/dist/runstore/workspaceLayout.js +76 -0
  203. package/dist/runtime/completionCheckRunner.d.ts +3 -0
  204. package/dist/runtime/completionCheckRunner.js +45 -7
  205. package/dist/runtime/containerLimits.d.ts +16 -0
  206. package/dist/runtime/containerLimits.js +84 -0
  207. package/dist/runtime/credentialMaterialisation.d.ts +28 -0
  208. package/dist/runtime/credentialMaterialisation.js +128 -0
  209. package/dist/runtime/gitCheckoutCapability.js +7 -13
  210. package/dist/runtime/pipelineRunner.d.ts +36 -1
  211. package/dist/runtime/pipelineRunner.js +178 -17
  212. package/dist/runtime/pipelineScheduler.d.ts +15 -0
  213. package/dist/runtime/pipelineScheduler.js +135 -27
  214. package/dist/runtime/reloadRunCatalog.js +6 -1
  215. package/dist/runtime/repositoryMaterialize.d.ts +47 -0
  216. package/dist/runtime/repositoryMaterialize.js +235 -0
  217. package/dist/runtime/resumeTimedOut.d.ts +1 -1
  218. package/dist/runtime/resumeTimedOut.js +5 -2
  219. package/dist/runtime/runChangeBus.js +9 -0
  220. package/dist/runtime/runDeletion.d.ts +7 -0
  221. package/dist/runtime/runDeletion.js +37 -0
  222. package/dist/runtime/runManager.d.ts +158 -4
  223. package/dist/runtime/runManager.js +1596 -79
  224. package/dist/runtime/runRetentionSweep.d.ts +31 -0
  225. package/dist/runtime/runRetentionSweep.js +328 -0
  226. package/dist/runtime/runRetryCoordinator.d.ts +2 -0
  227. package/dist/runtime/runRetryCoordinator.js +19 -2
  228. package/dist/runtime/runSkills.d.ts +40 -0
  229. package/dist/runtime/runSkills.js +173 -0
  230. package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
  231. package/dist/runtime/stageAttemptBootstrap.js +195 -24
  232. package/dist/runtime/stageCacheEnv.d.ts +6 -0
  233. package/dist/runtime/stageCacheEnv.js +34 -0
  234. package/dist/runtime/stageConcurrency.d.ts +2 -1
  235. package/dist/runtime/stageConcurrency.js +4 -2
  236. package/dist/runtime/stageEnvironment.d.ts +38 -0
  237. package/dist/runtime/stageEnvironment.js +193 -0
  238. package/dist/runtime/stageProcessLauncher.d.ts +18 -0
  239. package/dist/runtime/stageProcessLauncher.js +194 -38
  240. package/dist/runtime/stageRecovery.d.ts +3 -1
  241. package/dist/runtime/stageRecovery.js +19 -4
  242. package/dist/runtime/stageRoots.d.ts +38 -1
  243. package/dist/runtime/stageRoots.js +118 -0
  244. package/dist/runtime/stageRunner.d.ts +1 -0
  245. package/dist/runtime/stageRunner.js +3 -1
  246. package/dist/runtime/stageSecretDecl.d.ts +9 -0
  247. package/dist/runtime/stageSecretDecl.js +102 -0
  248. package/dist/runtime/stageSecrets.d.ts +40 -0
  249. package/dist/runtime/stageSecrets.js +181 -0
  250. package/dist/runtime/stageWorker.d.ts +3 -2
  251. package/dist/runtime/stageWorker.js +58 -10
  252. package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
  253. package/dist/runtime/stageWorkerProtocol.js +8 -0
  254. package/dist/runtime/startPayload.d.ts +32 -0
  255. package/dist/runtime/startPayload.js +59 -0
  256. package/dist/runtime/taskInput.js +14 -5
  257. package/dist/runtime/verifiedStageExecution.d.ts +1 -0
  258. package/dist/runtime/verifiedStageExecution.js +2 -1
  259. package/dist/runtime/workspaceBinding.d.ts +20 -0
  260. package/dist/runtime/workspaceBinding.js +60 -0
  261. package/dist/server/allowedHosts.d.ts +19 -0
  262. package/dist/server/allowedHosts.js +179 -0
  263. package/dist/server/bootstrap.d.ts +36 -2
  264. package/dist/server/bootstrap.js +209 -5
  265. package/dist/server/controlToken.d.ts +47 -0
  266. package/dist/server/controlToken.js +241 -0
  267. package/dist/server/createHttpHost.d.ts +11 -2
  268. package/dist/server/createHttpHost.js +103 -10
  269. package/dist/server/ensureGlobalService.d.ts +5 -1
  270. package/dist/server/ensureGlobalService.js +35 -1
  271. package/dist/server/healthSurfaces.d.ts +6 -0
  272. package/dist/server/healthSurfaces.js +98 -0
  273. package/dist/server/http.d.ts +12 -1
  274. package/dist/server/http.js +1085 -485
  275. package/dist/server/listenHost.d.ts +5 -0
  276. package/dist/server/listenHost.js +56 -0
  277. package/dist/server/mcpHost.d.ts +10 -1
  278. package/dist/server/mcpHost.js +36 -6
  279. package/dist/server/operatorResults.d.ts +2 -2
  280. package/dist/server/operatorResults.js +40 -29
  281. package/dist/server/requestAuthContext.d.ts +12 -0
  282. package/dist/server/requestAuthContext.js +21 -0
  283. package/dist/server/shutdown.d.ts +69 -0
  284. package/dist/server/shutdown.js +219 -0
  285. package/dist/types/pipeline.d.ts +7 -0
  286. package/dist/types/stage.d.ts +8 -0
  287. package/dist/types/task.d.ts +8 -0
  288. package/dist/ui/assets/index-B6hlSXXn.js +120 -0
  289. package/dist/ui/index.html +1 -1
  290. package/examples/README.md +98 -0
  291. package/examples/archify-on-pr/README.md +213 -0
  292. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
  293. package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
  294. package/examples/archify-on-pr/author-diagrams.yaml +106 -0
  295. package/examples/archify-on-pr/detect-changes.yaml +89 -0
  296. package/examples/ci-validate/README.md +35 -0
  297. package/examples/ci-validate/check.yaml +13 -0
  298. package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
  299. package/examples/ci-validate/validate.sh +5 -0
  300. package/examples/compliance-review-demo/README.md +125 -0
  301. package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
  302. package/examples/compliance-review-demo/connect-account.yaml +47 -0
  303. package/examples/compliance-review-demo/map-to-control.yaml +123 -0
  304. package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
  305. package/examples/compliance-review-demo/publish-report.yaml +79 -0
  306. package/examples/compliance-review-demo/review-verdict.yaml +122 -0
  307. package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
  308. package/examples/compliance-review-demo/store-evidence.yaml +143 -0
  309. package/examples/conditional-fork/README.md +89 -0
  310. package/examples/conditional-fork/branch-a.yaml +13 -0
  311. package/examples/conditional-fork/branch-b.yaml +13 -0
  312. package/examples/conditional-fork/decide.yaml +35 -0
  313. package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
  314. package/examples/conditional-fork/fork-demo.task.yaml +8 -0
  315. package/examples/context7-mcp/README.md +42 -0
  316. package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
  317. package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
  318. package/examples/context7-mcp/fetch-docs.yaml +52 -0
  319. package/examples/context7-mcp/resolve-library.yaml +31 -0
  320. package/examples/context7-mcp/write-brief.yaml +52 -0
  321. package/examples/feature-loop/README.md +104 -0
  322. package/examples/feature-loop/address-feedback.yaml +148 -0
  323. package/examples/feature-loop/align.yaml +116 -0
  324. package/examples/feature-loop/decompose.yaml +86 -0
  325. package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
  326. package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
  327. package/examples/feature-loop/feature-loop.task.yaml +25 -0
  328. package/examples/feature-loop/implement.yaml +128 -0
  329. package/examples/feature-loop/plan.yaml +111 -0
  330. package/examples/feature-loop/publish.yaml +167 -0
  331. package/examples/feature-loop/review.yaml +146 -0
  332. package/examples/feature-loop/verify.yaml +106 -0
  333. package/examples/feedback-loop/README.md +72 -0
  334. package/examples/feedback-loop/VERIFY.md +208 -0
  335. package/examples/feedback-loop/continue-only.task.yaml +4 -0
  336. package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
  337. package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
  338. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
  339. package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
  340. package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
  341. package/examples/feedback-loop/implement.yaml +14 -0
  342. package/examples/feedback-loop/plan.yaml +14 -0
  343. package/examples/feedback-loop/review.yaml +15 -0
  344. package/examples/feedback-loop/send-back-once.task.yaml +6 -0
  345. package/examples/feedback-loop/submit.yaml +12 -0
  346. package/examples/generic-fan-in/README.md +151 -0
  347. package/examples/generic-fan-in/clarify.yaml +18 -0
  348. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
  349. package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
  350. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
  351. package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
  352. package/examples/generic-fan-in/research.yaml +45 -0
  353. package/examples/generic-fan-in/synthesize.yaml +66 -0
  354. package/examples/generic-fan-in/validation.yaml +45 -0
  355. package/examples/github-release/README.md +78 -0
  356. package/examples/github-release/draft-release-notes.yaml +64 -0
  357. package/examples/github-release/github-release.pipeline.yaml +11 -0
  358. package/examples/github-release/github-release.task.yaml +13 -0
  359. package/examples/github-release/publish-github-release.yaml +64 -0
  360. package/examples/hello-world/README.md +28 -0
  361. package/examples/hello-world/hello.pipeline.yaml +4 -0
  362. package/examples/hello-world/my-task.task.yaml +6 -0
  363. package/examples/hello-world/research.yaml +18 -0
  364. package/examples/mcp-hitl-tour/README.md +113 -0
  365. package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
  366. package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
  367. package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
  368. package/examples/mcp-hitl-tour/gather.yaml +31 -0
  369. package/examples/mcp-hitl-tour/intake.yaml +62 -0
  370. package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
  371. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
  372. package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
  373. package/examples/mcp-hitl-tour/polish.yaml +33 -0
  374. package/examples/mcp-hitl-tour/review.yaml +17 -0
  375. package/examples/mcp-hitl-tour/ship.yaml +25 -0
  376. package/examples/oss-issue-contribution/README.md +218 -0
  377. package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
  378. package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
  379. package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
  380. package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
  381. package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
  382. package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
  383. package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
  384. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
  385. package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
  386. package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
  387. package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
  388. package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
  389. package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
  390. package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
  391. package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
  392. package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
  393. package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
  394. package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
  395. package/examples/oss-quick-fix/README.md +65 -0
  396. package/examples/oss-quick-fix/implement-fix.yaml +84 -0
  397. package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
  398. package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
  399. package/examples/oss-quick-fix/ship-fix.yaml +81 -0
  400. package/examples/oss-quick-fix/understand-issue.yaml +67 -0
  401. package/examples/oss-quick-fix/verify-fix.yaml +73 -0
  402. package/examples/plan-review/README.md +37 -0
  403. package/examples/plan-review/plan-review-followup.yaml +13 -0
  404. package/examples/plan-review/plan-review.pipeline.yaml +9 -0
  405. package/examples/plan-review/plan-review.task.yaml +9 -0
  406. package/examples/plan-review/plan-review.yaml +25 -0
  407. package/examples/playwright-mcp/README.md +39 -0
  408. package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
  409. package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
  410. package/examples/playwright-mcp/screenshot.yaml +40 -0
  411. package/examples/retry-tour/README.md +75 -0
  412. package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
  413. package/examples/retry-tour/retry-tour.task.yaml +9 -0
  414. package/examples/route-if-tour/README.md +202 -0
  415. package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
  416. package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
  417. package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
  418. package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
  419. package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
  420. package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
  421. package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
  422. package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
  423. package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
  424. package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
  425. package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
  426. package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
  427. package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
  428. package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
  429. package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
  430. package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
  431. package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
  432. package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
  433. package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
  434. package/examples/route-wiring-smoke-test/README.md +377 -0
  435. package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
  436. package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
  437. package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
  438. package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
  439. package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
  440. package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
  441. package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
  442. package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
  443. package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
  444. package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
  445. package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
  446. package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
  447. package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
  448. package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
  449. package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
  450. package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
  451. package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
  452. package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
  453. package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
  454. package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
  455. package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
  456. package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
  457. package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
  458. package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
  459. package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
  460. package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
  461. package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
  462. package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
  463. package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
  464. package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
  465. package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
  466. package/examples/ship-feature/README.md +190 -0
  467. package/examples/ship-feature/feat-address-feedback.yaml +119 -0
  468. package/examples/ship-feature/feat-implement.yaml +180 -0
  469. package/examples/ship-feature/feat-plan.yaml +120 -0
  470. package/examples/ship-feature/feat-review.yaml +109 -0
  471. package/examples/ship-feature/feat-ship.yaml +203 -0
  472. package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
  473. package/examples/ship-feature/ship-feature.task.yaml +78 -0
  474. package/examples/stage-mcp/README.md +144 -0
  475. package/examples/stage-mcp/echo-mcp.mjs +20 -0
  476. package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
  477. package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
  478. package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
  479. package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
  480. package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
  481. package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
  482. package/examples/stage-mcp/use-echo.yaml +20 -0
  483. package/examples/verify-tour/README.md +80 -0
  484. package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
  485. package/examples/verify-tour/verify-tour.task.yaml +11 -0
  486. package/package.json +5 -1
  487. package/skills/stageflow/SKILL.md +6 -6
  488. package/skills/stageflow/references/control-surface.md +11 -5
  489. package/skills/stageflow/scripts/detect-host.mjs +14 -1
  490. package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
  491. package/skills/stageflow-author/SKILL.md +4 -3
  492. package/skills/stageflow-author/references/catalog-mapping.md +16 -0
  493. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  494. package/skills/stageflow-run/SKILL.md +20 -12
  495. package/skills/stageflow-run/references/mcp-call.md +9 -1
  496. package/skills/stageflow-run/references/task-and-pipeline-selection.md +16 -5
  497. package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
  498. package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
  499. package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
  500. package/skills/stageflow-setup/SKILL.md +40 -8
  501. package/dist/ui/assets/index-Da5EHU6M.js +0 -119
@@ -0,0 +1,218 @@
1
+ import { createWriteStream } from "node:fs";
2
+ import path from "node:path";
3
+ import { projectRun } from "../projection/projectRun.js";
4
+ import { PACKAGE_VERSION } from "../package-meta.js";
5
+ import { globalStageflowHome } from "../project/globalHome.js";
6
+ import { createRunStoreAfterHostEnsure, } from "../runstore/createStore.js";
7
+ import { isInsideDir } from "../runstore/workspaceLayout.js";
8
+ import { ensureGlobalService } from "../server/ensureGlobalService.js";
9
+ export const EXPORT_ALL_USAGE = `Usage:
10
+ sf export --all [--status <status>] [--since <iso>] [--pipeline <id-or-path>] [--out <file>]
11
+
12
+ Streams whole-instance NDJSON (header + one projectRun line per run, including
13
+ non-terminal). Not a backup — restore does not accept export streams.`;
14
+ const defaultIo = {
15
+ log: (line) => console.log(line),
16
+ error: (line) => console.error(line),
17
+ };
18
+ export function buildExportHeader(filter, now = new Date()) {
19
+ return {
20
+ type: "stageflow_export",
21
+ version: 1,
22
+ stageflow_version: PACKAGE_VERSION,
23
+ created_at: now.toISOString(),
24
+ ...(filter !== undefined ? { filter } : {}),
25
+ };
26
+ }
27
+ export function resolveExportPipelineSource(options) {
28
+ if (options.pipelineSource === "inline") {
29
+ if (options.pipelineBody != null && options.pipelineBody !== "") {
30
+ try {
31
+ return {
32
+ kind: "inline",
33
+ pipeline: JSON.parse(options.pipelineBody),
34
+ };
35
+ }
36
+ catch {
37
+ return {
38
+ kind: "unavailable",
39
+ pipeline: null,
40
+ note: "pipeline_body is not valid JSON",
41
+ };
42
+ }
43
+ }
44
+ return {
45
+ kind: "unavailable",
46
+ pipeline: null,
47
+ note: "inline pipeline body missing",
48
+ };
49
+ }
50
+ if (options.pipelineSource === "path" || options.pipelinePath) {
51
+ return {
52
+ kind: "path",
53
+ path: options.pipelinePath ?? "",
54
+ pipeline: null,
55
+ };
56
+ }
57
+ return {
58
+ kind: "unavailable",
59
+ pipeline: null,
60
+ note: "pipeline source not recorded",
61
+ };
62
+ }
63
+ export function projectRunForExport(detail, pipelineBody) {
64
+ return {
65
+ ...projectRun(detail),
66
+ pipeline_source: resolveExportPipelineSource({
67
+ pipelineSource: detail.pipeline_source,
68
+ pipelinePath: detail.pipeline_path,
69
+ pipelineBody,
70
+ }),
71
+ };
72
+ }
73
+ export function assertExportOutPathAllowed(outPath, homeDir = globalStageflowHome(), cwd = process.cwd()) {
74
+ const segments = outPath.split(/[/\\]/);
75
+ if (segments.some((segment) => segment === "..")) {
76
+ throw new Error("path must not contain .. segments");
77
+ }
78
+ const resolved = path.isAbsolute(outPath)
79
+ ? path.resolve(outPath)
80
+ : path.resolve(cwd, outPath);
81
+ const worktrees = path.resolve(homeDir, "worktrees");
82
+ const runs = path.resolve(homeDir, "runs");
83
+ if (isInsideDir(resolved, worktrees) || isInsideDir(resolved, runs)) {
84
+ throw new Error("output path must not be under worktrees/ or runs/");
85
+ }
86
+ return resolved;
87
+ }
88
+ function parseExportArgs(args) {
89
+ let help = false;
90
+ let all = false;
91
+ let status;
92
+ let since;
93
+ let pipeline;
94
+ let outPath;
95
+ for (let i = 0; i < args.length; i += 1) {
96
+ const arg = args[i];
97
+ if (arg === "--help" || arg === "-h") {
98
+ help = true;
99
+ }
100
+ else if (arg === "--all") {
101
+ all = true;
102
+ }
103
+ else if (arg === "--status") {
104
+ const value = args[++i];
105
+ if (value === undefined)
106
+ throw new Error("Missing value for --status");
107
+ status = value;
108
+ }
109
+ else if (arg === "--since") {
110
+ const value = args[++i];
111
+ if (value === undefined)
112
+ throw new Error("Missing value for --since");
113
+ since = value;
114
+ }
115
+ else if (arg === "--pipeline") {
116
+ const value = args[++i];
117
+ if (value === undefined)
118
+ throw new Error("Missing value for --pipeline");
119
+ pipeline = value;
120
+ }
121
+ else if (arg === "--out") {
122
+ const value = args[++i];
123
+ if (value === undefined)
124
+ throw new Error("Missing value for --out");
125
+ outPath = value;
126
+ }
127
+ else if (arg?.startsWith("-")) {
128
+ throw new Error(`Unknown flag: ${arg}`);
129
+ }
130
+ else {
131
+ throw new Error(`Unexpected argument: ${arg}`);
132
+ }
133
+ }
134
+ return { help, all, status, since, pipeline, outPath };
135
+ }
136
+ export async function* iterateExportNdjson(options) {
137
+ yield `${JSON.stringify(buildExportHeader(options.filter, options.now ?? new Date()))}\n`;
138
+ const runs = await options.store.listRuns(options.filter);
139
+ for (const summary of runs) {
140
+ const detail = await options.store.readRun(summary.run_id);
141
+ const pipelineBody = await options.store.readPipelineBody(summary.run_id);
142
+ const line = {
143
+ type: "projectRun",
144
+ run: projectRunForExport(detail, pipelineBody),
145
+ };
146
+ yield `${JSON.stringify(line)}\n`;
147
+ }
148
+ }
149
+ export async function runExportAllCommand(args, options = {}) {
150
+ const cwd = options.cwd ?? process.cwd();
151
+ const out = { ...defaultIo, ...options.io };
152
+ let parsed;
153
+ try {
154
+ parsed = parseExportArgs(args);
155
+ }
156
+ catch (err) {
157
+ const message = err instanceof Error ? err.message : String(err);
158
+ out.error(message);
159
+ out.error(EXPORT_ALL_USAGE);
160
+ return 1;
161
+ }
162
+ if (parsed.help) {
163
+ out.error(EXPORT_ALL_USAGE);
164
+ return 0;
165
+ }
166
+ if (!parsed.all) {
167
+ out.error("sf export requires --all (whole-instance NDJSON)");
168
+ out.error(EXPORT_ALL_USAGE);
169
+ return 1;
170
+ }
171
+ const filter = {};
172
+ if (parsed.status !== undefined)
173
+ filter.status = parsed.status;
174
+ if (parsed.since !== undefined)
175
+ filter.since = parsed.since;
176
+ if (parsed.pipeline !== undefined)
177
+ filter.pipeline = parsed.pipeline;
178
+ const opened = await createRunStoreAfterHostEnsure({ rootDir: globalStageflowHome() }, () => ensureGlobalService());
179
+ if (!opened.ok) {
180
+ out.error(opened.message);
181
+ return 1;
182
+ }
183
+ const store = opened.store;
184
+ try {
185
+ let sink = (line) => out.log(line.replace(/\n$/, ""));
186
+ let close;
187
+ if (parsed.outPath !== undefined) {
188
+ const target = assertExportOutPathAllowed(parsed.outPath, globalStageflowHome(), cwd);
189
+ const stream = createWriteStream(target);
190
+ sink = (line) => {
191
+ stream.write(line);
192
+ };
193
+ close = () => new Promise((resolve, reject) => {
194
+ stream.end(() => resolve());
195
+ stream.on("error", reject);
196
+ });
197
+ }
198
+ for await (const line of iterateExportNdjson({
199
+ store,
200
+ filter: Object.keys(filter).length > 0 ? filter : undefined,
201
+ })) {
202
+ sink(line);
203
+ }
204
+ await close?.();
205
+ if (parsed.outPath !== undefined) {
206
+ out.error(`Wrote ${assertExportOutPathAllowed(parsed.outPath, globalStageflowHome(), cwd)}`);
207
+ }
208
+ return 0;
209
+ }
210
+ catch (err) {
211
+ const message = err instanceof Error ? err.message : String(err);
212
+ out.error(message);
213
+ return 1;
214
+ }
215
+ finally {
216
+ await store.close();
217
+ }
218
+ }
@@ -1,9 +1,10 @@
1
1
  import { readFileSync, writeFileSync } from "node:fs";
2
2
  import path from "node:path";
3
- import { projectRun } from "../projection/projectRun.js";
4
3
  import { globalStageflowHome } from "../project/globalHome.js";
5
- import { createRunStore } from "../runstore/createStore.js";
6
- import { isInsideDir } from "../runstore/workspaceLayout.js";
4
+ import { createRunStoreAfterHostEnsure, } from "../runstore/createStore.js";
5
+ import { ensureGlobalService, } from "../server/ensureGlobalService.js";
6
+ import { buildRunExportPayload } from "../runstore/exportRunPayload.js";
7
+ import { resolveSafeOutPath } from "./resolveSafeOutPath.js";
7
8
  export const EXPORT_RUN_USAGE = `Usage:
8
9
  sf export-run --run <runId> [--from <sf-run.json>] [--out <file>]`;
9
10
  const defaultIo = {
@@ -75,23 +76,19 @@ function resolveRunIdFromFile(fromPath, cwd) {
75
76
  }
76
77
  return runId;
77
78
  }
78
- function resolveSafeOutPath(outPath, cwd) {
79
- const segments = outPath.split(/[/\\]/);
80
- if (segments.some((segment) => segment === "..")) {
81
- throw new Error("path must not contain .. segments");
82
- }
83
- const resolved = path.resolve(cwd, outPath);
84
- const cwdResolved = path.resolve(cwd);
85
- if (!isInsideDir(resolved, cwdResolved)) {
86
- throw new Error("output path must resolve under the current working directory");
87
- }
88
- return resolved;
89
- }
90
- function assertRunComplete(status, runId) {
91
- if (status === "succeeded" || status === "failed") {
79
+ const EXPORTABLE_STATUSES = new Set([
80
+ "running",
81
+ "succeeded",
82
+ "failed",
83
+ "cancelled",
84
+ "queued",
85
+ "created",
86
+ ]);
87
+ function assertRunExportable(status, runId) {
88
+ if (EXPORTABLE_STATUSES.has(status)) {
92
89
  return;
93
90
  }
94
- throw new Error(`run is not complete: ${runId} (status: ${status})`);
91
+ throw new Error(`run cannot be exported: ${runId} (status: ${status})`);
95
92
  }
96
93
  export async function runExportRunCommand(args, options = {}) {
97
94
  const cwd = options.cwd ?? process.cwd();
@@ -126,11 +123,16 @@ export async function runExportRunCommand(args, options = {}) {
126
123
  out.error(EXPORT_RUN_USAGE);
127
124
  return 1;
128
125
  }
129
- const store = createRunStore({ rootDir: globalStageflowHome() });
126
+ const opened = await createRunStoreAfterHostEnsure({ rootDir: globalStageflowHome() }, () => ensureGlobalService());
127
+ if (!opened.ok) {
128
+ out.error(opened.message);
129
+ return 1;
130
+ }
131
+ const store = opened.store;
130
132
  try {
131
133
  const detail = await store.readRun(runId);
132
- assertRunComplete(detail.status, runId);
133
- const projection = projectRun(detail);
134
+ assertRunExportable(detail.status, runId);
135
+ const projection = buildRunExportPayload(detail);
134
136
  const json = JSON.stringify(projection, null, 2);
135
137
  if (parsed.outPath !== undefined) {
136
138
  const target = resolveSafeOutPath(parsed.outPath, cwd);
@@ -1,8 +1,9 @@
1
1
  import type { PipelineRunResult } from "../runtime/pipelineRunner.js";
2
- import type { AbandonStageResult, DecideFeedbackLoopResult, StartRunResult, StopManualRecoveryResult } from "../runtime/runManager.js";
2
+ import type { AbandonStageResult, CancelRunResult, DecideFeedbackLoopResult, DeleteRunResult, GcRunsResult, StartRunResult, StopManualRecoveryResult } from "../runtime/runManager.js";
3
3
  import type { DeliverAnswerResult } from "../runtime/stageHitl.js";
4
4
  import type { RetryStageResult } from "../runtime/runRetryCoordinator.js";
5
5
  import type { RunDetail, RunStore } from "../runstore/port.js";
6
+ import type { TaskFile } from "../types/task.js";
6
7
  export declare function computeRunDir(runId: string): string;
7
8
  export declare function httpReadRun(base: string, runId: string): Promise<RunDetail>;
8
9
  /** Thin RunStore-shaped reader backed by the global service, for the CLI output helpers that only need `readRun`. */
@@ -13,7 +14,8 @@ export declare function pollRunUntilTerminal(base: string, runId: string, option
13
14
  export declare function runDetailToPipelineRunResult(detail: RunDetail): PipelineRunResult;
14
15
  export type HttpStartRunInput = {
15
16
  pipeline: string;
16
- task: string;
17
+ task: string | TaskFile;
18
+ project_root?: string;
17
19
  checkoutOverride?: string;
18
20
  skipGates?: boolean;
19
21
  gitSha?: string;
@@ -21,7 +23,16 @@ export type HttpStartRunInput = {
21
23
  ciJobUrl?: string;
22
24
  };
23
25
  export declare function httpStartRun(base: string, input: HttpStartRunInput): Promise<StartRunResult>;
24
- export declare function httpRerun(base: string, runId: string): Promise<StartRunResult>;
26
+ export type HttpEnsureProjectResult = {
27
+ ok: true;
28
+ project_root: string;
29
+ } | Extract<StartRunResult, {
30
+ ok: false;
31
+ }>;
32
+ export declare function httpEnsureProject(base: string, projectRoot: string): Promise<HttpEnsureProjectResult>;
33
+ export declare function httpRerun(base: string, runId: string, options?: {
34
+ pinned?: boolean;
35
+ }): Promise<StartRunResult>;
25
36
  export declare function httpDeliverAnswer(base: string, runId: string, stageId: string, answer: unknown): Promise<DeliverAnswerResult>;
26
37
  export declare function httpDecideFeedbackLoop(base: string, runId: string, stageId: string, input: {
27
38
  decision: "extend" | "continue" | "abandon";
@@ -39,5 +50,12 @@ export declare function httpResumeTimedOutStage(base: string, runId: string, sta
39
50
  export declare function httpRecoverManualStageUntilStop(base: string, runId: string, stageId: string, guidance?: string): Promise<RetryOrchestrationResult>;
40
51
  export declare function httpStopManualRecovery(base: string, runId: string, stageId: string): Promise<StopManualRecoveryResult>;
41
52
  export declare function httpAbandonStage(base: string, runId: string, stageId: string): Promise<AbandonStageResult>;
53
+ export declare function httpCancelRun(base: string, runId: string, reason: string): Promise<CancelRunResult>;
54
+ export declare function httpDeleteRun(base: string, runId: string, options?: {
55
+ force?: boolean;
56
+ }): Promise<DeleteRunResult>;
57
+ export declare function httpGcRuns(base: string, options?: {
58
+ execute?: boolean;
59
+ }): Promise<GcRunsResult>;
42
60
  export declare function resolveAbsolute(cwd: string, maybeRelative: string): string;
43
61
  export {};
@@ -1,17 +1,23 @@
1
1
  import path from "node:path";
2
2
  import { globalStageflowHome } from "../project/globalHome.js";
3
3
  import { PipelineValidationError } from "../runtime/pipelineValidationError.js";
4
- import { runWorkspaceDir, storeRootFor } from "../runstore/paths.js";
4
+ import { resolveStoreRoot, runWorkspaceDir } from "../runstore/paths.js";
5
+ import { clientAuthorizationHeaders } from "../server/controlToken.js";
5
6
  async function postJson(base, urlPath, body) {
6
7
  const res = await fetch(`${base}${urlPath}`, {
7
8
  method: "POST",
8
- headers: { "Content-Type": "application/json" },
9
+ headers: {
10
+ "Content-Type": "application/json",
11
+ ...clientAuthorizationHeaders("POST"),
12
+ },
9
13
  body: JSON.stringify(body ?? {}),
10
14
  });
11
15
  return { status: res.status, body: await parseJsonBody(res) };
12
16
  }
13
17
  async function getJson(base, urlPath) {
14
- const res = await fetch(`${base}${urlPath}`);
18
+ const res = await fetch(`${base}${urlPath}`, {
19
+ headers: { ...clientAuthorizationHeaders("GET") },
20
+ });
15
21
  return { status: res.status, body: await parseJsonBody(res) };
16
22
  }
17
23
  async function parseJsonBody(res) {
@@ -35,7 +41,7 @@ function enc(value) {
35
41
  return encodeURIComponent(value);
36
42
  }
37
43
  export function computeRunDir(runId) {
38
- return runWorkspaceDir(storeRootFor(globalStageflowHome()), runId);
44
+ return runWorkspaceDir(resolveStoreRoot(globalStageflowHome()), runId);
39
45
  }
40
46
  export async function httpReadRun(base, runId) {
41
47
  const { status, body } = await getJson(base, `/api/runs/${enc(runId)}`);
@@ -51,6 +57,7 @@ export function httpStoreReader(base) {
51
57
  function isRunTerminal(detail) {
52
58
  return (detail.status === "succeeded" ||
53
59
  detail.status === "failed" ||
60
+ detail.status === "cancelled" ||
54
61
  (detail.status === "running" && detail.waiting_stage_id !== undefined));
55
62
  }
56
63
  function sleep(ms) {
@@ -70,15 +77,20 @@ export function runDetailToPipelineRunResult(detail) {
70
77
  ? "succeeded"
71
78
  : detail.status === "failed"
72
79
  ? "failed"
73
- : "waiting";
80
+ : detail.status === "cancelled"
81
+ ? "cancelled"
82
+ : "waiting";
83
+ const reason = outcome === "cancelled"
84
+ ? (detail.cancel_reason ?? detail.failed_reason)
85
+ : outcome === "failed"
86
+ ? detail.failed_reason
87
+ : undefined;
74
88
  return {
75
89
  ok: outcome === "succeeded",
76
90
  outcome,
77
91
  runId: detail.run_id,
78
92
  runDir: computeRunDir(detail.run_id),
79
- ...(outcome === "failed" && detail.failed_reason !== undefined
80
- ? { reason: detail.failed_reason }
81
- : {}),
93
+ ...(reason !== undefined ? { reason } : {}),
82
94
  };
83
95
  }
84
96
  function toStartFailure(status, body) {
@@ -107,15 +119,36 @@ export async function httpStartRun(base, input) {
107
119
  }
108
120
  if (status !== 202)
109
121
  return toStartFailure(status, body);
110
- const runId = body.runId;
122
+ const parsed = body;
123
+ const runId = parsed.runId;
111
124
  return {
112
125
  ok: true,
113
126
  runId,
127
+ ...(parsed.queued === true
128
+ ? { queued: true, queuePosition: parsed.queuePosition }
129
+ : {}),
114
130
  done: pollRunUntilTerminal(base, runId).then(runDetailToPipelineRunResult),
115
131
  };
116
132
  }
117
- export async function httpRerun(base, runId) {
118
- const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/rerun`, {});
133
+ export async function httpEnsureProject(base, projectRoot) {
134
+ const { status, body } = await postJson(base, "/api/projects", {
135
+ project_root: projectRoot,
136
+ });
137
+ if (status === 200) {
138
+ const parsed = body;
139
+ if (typeof parsed.project_root === "string" && parsed.project_root.length > 0) {
140
+ return { ok: true, project_root: parsed.project_root };
141
+ }
142
+ return {
143
+ ok: false,
144
+ reason: "ensure_project response missing project_root",
145
+ status,
146
+ };
147
+ }
148
+ return toStartFailure(status, body);
149
+ }
150
+ export async function httpRerun(base, runId, options) {
151
+ const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/rerun`, options?.pinned !== undefined ? { pinned: options.pinned } : {});
119
152
  if (status !== 202)
120
153
  return toStartFailure(status, body);
121
154
  const newRunId = body.runId;
@@ -142,7 +175,15 @@ export async function httpDecideFeedbackLoop(base, runId, stageId, input) {
142
175
  export async function httpRetryStageUntilStop(base, runId, stageId) {
143
176
  const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/stages/${enc(stageId)}/retry`, {});
144
177
  if (status !== 202) {
145
- return { ok: false, reason: extractError(body, status), status };
178
+ const code = body && typeof body === "object" && typeof body.code === "string"
179
+ ? body.code
180
+ : undefined;
181
+ return {
182
+ ok: false,
183
+ reason: extractError(body, status),
184
+ status,
185
+ ...(code !== undefined ? { code } : {}),
186
+ };
146
187
  }
147
188
  const detail = await pollRunUntilTerminal(base, runId);
148
189
  return { ok: true, pipeline: runDetailToPipelineRunResult(detail) };
@@ -177,6 +218,46 @@ export async function httpAbandonStage(base, runId, stageId) {
177
218
  }
178
219
  return { ok: false, reason: extractError(body, status), status };
179
220
  }
221
+ export async function httpCancelRun(base, runId, reason) {
222
+ const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/cancel`, { reason });
223
+ if (status === 202) {
224
+ const parsed = body;
225
+ return { ok: true, runId: parsed.runId };
226
+ }
227
+ return { ok: false, reason: extractError(body, status), status };
228
+ }
229
+ export async function httpDeleteRun(base, runId, options) {
230
+ const forceQs = options?.force ? "?force=true" : "";
231
+ const res = await fetch(`${base}/api/runs/${enc(runId)}${forceQs}`, {
232
+ method: "DELETE",
233
+ headers: { ...clientAuthorizationHeaders("DELETE") },
234
+ });
235
+ const body = await parseJsonBody(res);
236
+ if (res.status === 200) {
237
+ const parsed = body;
238
+ return { ok: true, runId: parsed.runId };
239
+ }
240
+ return {
241
+ ok: false,
242
+ reason: extractError(body, res.status),
243
+ status: res.status,
244
+ };
245
+ }
246
+ export async function httpGcRuns(base, options) {
247
+ const { status, body } = await postJson(base, "/api/runs/gc", {
248
+ execute: options?.execute === true,
249
+ });
250
+ if (status === 200) {
251
+ const parsed = body;
252
+ return {
253
+ ok: true,
254
+ slimmed: parsed.slimmed ?? [],
255
+ purged: parsed.purged ?? [],
256
+ bareCachesEvicted: parsed.bareCachesEvicted ?? [],
257
+ };
258
+ }
259
+ return { ok: false, reason: extractError(body, status), status };
260
+ }
180
261
  export function resolveAbsolute(cwd, maybeRelative) {
181
262
  return path.resolve(cwd, maybeRelative);
182
263
  }
@@ -1,3 +1,3 @@
1
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\nmodel: anthropic/claude-sonnet-4-5\nstages:\n - id: hello\n system_prompt: Say hello and emit a success envelope.\n";
2
+ export declare const HELLO_PIPELINE_YAML = "id: hello\nstages:\n - id: hello\n model: anthropic/claude-sonnet-4-5\n system_prompt: Say hello and emit a success envelope.\n io:\n input:\n schema:\n type: object\n output:\n schema:\n type: object\n";
3
3
  export declare const HELLO_TASK_YAML = "id: hello\ngoal: Run the hello pipeline scaffold.\n";
@@ -9,10 +9,17 @@ catalog:
9
9
  task: "*.task.yaml"
10
10
  `;
11
11
  export const HELLO_PIPELINE_YAML = `id: hello
12
- model: anthropic/claude-sonnet-4-5
13
12
  stages:
14
13
  - id: hello
14
+ model: anthropic/claude-sonnet-4-5
15
15
  system_prompt: Say hello and emit a success envelope.
16
+ io:
17
+ input:
18
+ schema:
19
+ type: object
20
+ output:
21
+ schema:
22
+ type: object
16
23
  `;
17
24
  export const HELLO_TASK_YAML = `id: hello
18
25
  goal: Run the hello pipeline scaffold.
@@ -0,0 +1,2 @@
1
+ /** Resolve `--out` under cwd, realpath-normalizing both sides before containment. */
2
+ export declare function resolveSafeOutPath(outPath: string, cwd: string): string;
@@ -0,0 +1,40 @@
1
+ import { realpathSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { isInsideDir } from "../runstore/workspaceLayout.js";
4
+ function resolveEffectiveRealPathSync(candidatePath) {
5
+ try {
6
+ return realpathSync(candidatePath);
7
+ }
8
+ catch {
9
+ const missing = [];
10
+ let current = candidatePath;
11
+ while (true) {
12
+ missing.unshift(path.basename(current));
13
+ const parent = path.dirname(current);
14
+ if (parent === current) {
15
+ return path.resolve(candidatePath);
16
+ }
17
+ try {
18
+ const realParent = realpathSync(parent);
19
+ return path.join(realParent, ...missing);
20
+ }
21
+ catch {
22
+ current = parent;
23
+ }
24
+ }
25
+ }
26
+ }
27
+ /** Resolve `--out` under cwd, realpath-normalizing both sides before containment. */
28
+ export function resolveSafeOutPath(outPath, cwd) {
29
+ const segments = outPath.split(/[/\\]/);
30
+ if (segments.some((segment) => segment === "..")) {
31
+ throw new Error("path must not contain .. segments");
32
+ }
33
+ const resolved = path.resolve(cwd, outPath);
34
+ const cwdResolved = resolveEffectiveRealPathSync(path.resolve(cwd));
35
+ const outResolved = resolveEffectiveRealPathSync(resolved);
36
+ if (!isInsideDir(outResolved, cwdResolved)) {
37
+ throw new Error("output path must resolve under the current working directory");
38
+ }
39
+ return resolved;
40
+ }
@@ -0,0 +1,10 @@
1
+ import { probeGlobalServiceDetailed } from "../server/ensureGlobalService.js";
2
+ export declare const RESTORE_USAGE = "Usage:\n sf restore <file> [--force] [--json]\n\nRestores a Stageflow backup. The Host must be down (probed via /livez).\nNever autostarts a Host. Previous state.db is moved aside, not deleted.";
3
+ export type RestoreCommandIo = {
4
+ log: (line: string) => void;
5
+ error: (line: string) => void;
6
+ };
7
+ export declare function runRestoreCommand(args: string[], options?: {
8
+ io?: Partial<RestoreCommandIo>;
9
+ probe?: typeof probeGlobalServiceDetailed;
10
+ }): Promise<number>;
@@ -0,0 +1,90 @@
1
+ import path from "node:path";
2
+ import { applyRestoreArchive, RestoreError, } from "../runstore/restore.js";
3
+ import { StoreSchemaError } from "../runstore/sqlite/storeSchemaError.js";
4
+ import { globalStageflowHome } from "../project/globalHome.js";
5
+ export const RESTORE_USAGE = `Usage:
6
+ sf restore <file> [--force] [--json]
7
+
8
+ Restores a Stageflow backup. The Host must be down (probed via /livez).
9
+ Never autostarts a Host. Previous state.db is moved aside, not deleted.`;
10
+ const defaultIo = {
11
+ log: (line) => console.log(line),
12
+ error: (line) => console.error(line),
13
+ };
14
+ function parseRestoreArgs(args) {
15
+ let help = false;
16
+ let file;
17
+ let force = false;
18
+ let json = false;
19
+ for (let i = 0; i < args.length; i += 1) {
20
+ const arg = args[i];
21
+ if (arg === "--help" || arg === "-h") {
22
+ help = true;
23
+ }
24
+ else if (arg === "--force") {
25
+ force = true;
26
+ }
27
+ else if (arg === "--json") {
28
+ json = true;
29
+ }
30
+ else if (arg?.startsWith("-")) {
31
+ throw new Error(`Unknown flag: ${arg}`);
32
+ }
33
+ else if (file === undefined) {
34
+ file = arg;
35
+ }
36
+ else {
37
+ throw new Error(`Unexpected argument: ${arg}`);
38
+ }
39
+ }
40
+ return { help, file, force, json };
41
+ }
42
+ export async function runRestoreCommand(args, options = {}) {
43
+ const out = { ...defaultIo, ...options.io };
44
+ let parsed;
45
+ try {
46
+ parsed = parseRestoreArgs(args);
47
+ }
48
+ catch (err) {
49
+ const message = err instanceof Error ? err.message : String(err);
50
+ out.error(message);
51
+ out.error(RESTORE_USAGE);
52
+ return 1;
53
+ }
54
+ if (parsed.help) {
55
+ out.error(RESTORE_USAGE);
56
+ return 0;
57
+ }
58
+ if (!parsed.file) {
59
+ out.error("Missing <file>");
60
+ out.error(RESTORE_USAGE);
61
+ return 1;
62
+ }
63
+ try {
64
+ const result = await applyRestoreArchive({
65
+ archivePath: path.resolve(parsed.file),
66
+ homeDir: globalStageflowHome(),
67
+ force: parsed.force,
68
+ probe: options.probe,
69
+ });
70
+ if (parsed.json) {
71
+ out.log(JSON.stringify({ ok: true, ...result }));
72
+ }
73
+ else {
74
+ out.log(`Restored schema_version=${result.schema_version}` +
75
+ (result.missing_a2a_artifact_rows > 0
76
+ ? ` (missing A2A artifact bytes: ${result.missing_a2a_artifact_rows})`
77
+ : ""));
78
+ }
79
+ return 0;
80
+ }
81
+ catch (err) {
82
+ if (err instanceof RestoreError || err instanceof StoreSchemaError) {
83
+ out.error(`${err.code}: ${err.message}`);
84
+ return 1;
85
+ }
86
+ const message = err instanceof Error ? err.message : String(err);
87
+ out.error(message);
88
+ return 1;
89
+ }
90
+ }