stageflow 0.33.0 → 0.36.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 (379) hide show
  1. package/README.md +3 -3
  2. package/dist/agent/adapterSpill.d.ts +14 -0
  3. package/dist/agent/adapterSpill.js +83 -0
  4. package/dist/agent/agentBackend.d.ts +2 -2
  5. package/dist/agent/agentBackend.js +2 -2
  6. package/dist/agent/claudeAdapter.d.ts +13 -2
  7. package/dist/agent/claudeAdapter.js +56 -6
  8. package/dist/agent/cursorProvider.d.ts +3 -0
  9. package/dist/agent/cursorProvider.js +23 -6
  10. package/dist/agent/fakeAgent.d.ts +3 -3
  11. package/dist/agent/piAdapter.d.ts +2 -2
  12. package/dist/agent/piAdapter.js +125 -15
  13. package/dist/agent/piIsolatedMcp.d.ts +1 -0
  14. package/dist/agent/piIsolatedMcp.js +19 -1
  15. package/dist/agent/piIsolatedMcpProbe.d.ts +11 -0
  16. package/dist/agent/piIsolatedMcpProbe.js +20 -0
  17. package/dist/agent/port.d.ts +4 -2
  18. package/dist/agent/providerAuth.js +36 -3
  19. package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -8
  20. package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +11 -11
  21. package/dist/agent/stageTurnDriver.d.ts +33 -0
  22. package/dist/agent/stageTurnDriver.js +64 -0
  23. package/dist/agent/toolOutputBudget.d.ts +46 -0
  24. package/dist/agent/toolOutputBudget.js +97 -0
  25. package/dist/agent/toolOutputBudgetExtension.d.ts +22 -0
  26. package/dist/agent/toolOutputBudgetExtension.js +141 -0
  27. package/dist/agent/toolOutputSpill.d.ts +34 -0
  28. package/dist/agent/toolOutputSpill.js +85 -0
  29. package/dist/browser/agentBrowserLiveViewRelay.d.ts +41 -0
  30. package/dist/browser/agentBrowserLiveViewRelay.js +801 -0
  31. package/dist/browser/anchor.d.ts +2 -0
  32. package/dist/browser/anchor.js +2 -1
  33. package/dist/browser/auditSink.d.ts +8 -0
  34. package/dist/browser/browserHost.d.ts +29 -0
  35. package/dist/browser/browserSweep.d.ts +4 -1
  36. package/dist/browser/browserSweep.js +7 -0
  37. package/dist/browser/browserTeardown.d.ts +1 -0
  38. package/dist/browser/browserTeardown.js +32 -2
  39. package/dist/browser/containerBrowserEndpoint.d.ts +11 -0
  40. package/dist/browser/containerBrowserEndpoint.js +57 -0
  41. package/dist/browser/containerBrowserHost.d.ts +24 -0
  42. package/dist/browser/containerBrowserHost.js +147 -0
  43. package/dist/browser/dockerSandboxOrchestrator.d.ts +26 -0
  44. package/dist/browser/dockerSandboxOrchestrator.js +142 -0
  45. package/dist/browser/fakeLiveViewRelay.d.ts +15 -0
  46. package/dist/browser/fakeLiveViewRelay.js +94 -0
  47. package/dist/browser/fakeLiveViewSource.d.ts +6 -0
  48. package/dist/browser/fakeLiveViewSource.js +16 -0
  49. package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -1
  50. package/dist/browser/fakeRemoteBrowserHost.js +2 -1
  51. package/dist/browser/fakeSandboxOrchestrator.d.ts +9 -0
  52. package/dist/browser/fakeSandboxOrchestrator.js +44 -0
  53. package/dist/browser/gateHandoff.d.ts +0 -2
  54. package/dist/browser/gateHandoff.js +5 -11
  55. package/dist/browser/hostCapabilities.d.ts +23 -0
  56. package/dist/browser/hostCapabilities.js +23 -0
  57. package/dist/browser/humanLogin.d.ts +2 -2
  58. package/dist/browser/humanLogin.js +11 -2
  59. package/dist/browser/liveViewPersisted.d.ts +11 -0
  60. package/dist/browser/liveViewPersisted.js +22 -0
  61. package/dist/browser/liveViewRelay.d.ts +76 -0
  62. package/dist/browser/liveViewRelay.js +1 -0
  63. package/dist/browser/liveViewSessions.d.ts +25 -0
  64. package/dist/browser/liveViewSessions.js +139 -0
  65. package/dist/browser/liveViewSource.d.ts +25 -0
  66. package/dist/browser/liveViewSource.js +7 -0
  67. package/dist/browser/liveViewTickets.d.ts +46 -0
  68. package/dist/browser/liveViewTickets.js +122 -0
  69. package/dist/browser/localBrowserHost.d.ts +10 -0
  70. package/dist/browser/localBrowserHost.js +53 -7
  71. package/dist/browser/ownerScope.d.ts +10 -0
  72. package/dist/browser/ownerScope.js +6 -0
  73. package/dist/browser/profileStore.d.ts +5 -2
  74. package/dist/browser/profileStore.js +3 -5
  75. package/dist/browser/sandboxOrchestrator.d.ts +60 -0
  76. package/dist/browser/sandboxOrchestrator.js +8 -0
  77. package/dist/browser/sessionApiSandboxOrchestrator.d.ts +34 -0
  78. package/dist/browser/sessionApiSandboxOrchestrator.js +108 -0
  79. package/dist/browser/stageBrowserEnv.d.ts +7 -0
  80. package/dist/browser/stageBrowserEnv.js +53 -15
  81. package/dist/browser/stageHandoff.d.ts +47 -0
  82. package/dist/browser/stageHandoff.js +101 -0
  83. package/dist/browser/stageProfileLock.d.ts +1 -0
  84. package/dist/browser/stageProfileLock.js +1 -3
  85. package/dist/browser/volumeProfileStore.d.ts +7 -0
  86. package/dist/browser/volumeProfileStore.js +35 -0
  87. package/dist/channels/config.d.ts +11 -0
  88. package/dist/channels/config.js +95 -0
  89. package/dist/channels/configWriter.d.ts +40 -0
  90. package/dist/channels/configWriter.js +148 -0
  91. package/dist/channels/connectionEdits.d.ts +34 -0
  92. package/dist/channels/connectionEdits.js +53 -0
  93. package/dist/channels/errorInfo.d.ts +18 -0
  94. package/dist/channels/errorInfo.js +71 -0
  95. package/dist/channels/errors.d.ts +12 -0
  96. package/dist/channels/errors.js +13 -0
  97. package/dist/channels/health.d.ts +41 -0
  98. package/dist/channels/health.js +99 -0
  99. package/dist/channels/host.d.ts +55 -0
  100. package/dist/channels/host.js +185 -0
  101. package/dist/channels/http.d.ts +31 -0
  102. package/dist/channels/http.js +79 -0
  103. package/dist/channels/index.d.ts +10 -0
  104. package/dist/channels/index.js +9 -0
  105. package/dist/channels/ledger.d.ts +37 -0
  106. package/dist/channels/ledger.js +95 -0
  107. package/dist/channels/providers/agentmail.d.ts +26 -0
  108. package/dist/channels/providers/agentmail.js +81 -0
  109. package/dist/channels/providers/kit.d.ts +40 -0
  110. package/dist/channels/providers/kit.js +78 -0
  111. package/dist/channels/providers/photonImessage.d.ts +45 -0
  112. package/dist/channels/providers/photonImessage.js +152 -0
  113. package/dist/channels/providers/photonWhatsapp.d.ts +49 -0
  114. package/dist/channels/providers/photonWhatsapp.js +146 -0
  115. package/dist/channels/providers/slack.d.ts +25 -0
  116. package/dist/channels/providers/slack.js +101 -0
  117. package/dist/channels/providers/telegram.d.ts +21 -0
  118. package/dist/channels/providers/telegram.js +100 -0
  119. package/dist/channels/providers.d.ts +5 -0
  120. package/dist/channels/providers.js +22 -0
  121. package/dist/channels/registry.d.ts +54 -0
  122. package/dist/channels/registry.js +186 -0
  123. package/dist/channels/secretStore.d.ts +21 -0
  124. package/dist/channels/secretStore.js +75 -0
  125. package/dist/channels/secrets.d.ts +15 -0
  126. package/dist/channels/secrets.js +50 -0
  127. package/dist/channels/service.d.ts +54 -0
  128. package/dist/channels/service.js +307 -0
  129. package/dist/channels/stageChannels.d.ts +45 -0
  130. package/dist/channels/stageChannels.js +110 -0
  131. package/dist/channels/types.d.ts +142 -0
  132. package/dist/channels/types.js +1 -0
  133. package/dist/cli/browserCommand.d.ts +3 -1
  134. package/dist/cli/browserCommand.js +25 -20
  135. package/dist/cli/doctorCommand.js +3 -1
  136. package/dist/cli/resolveCliProjectRoot.d.ts +7 -0
  137. package/dist/cli/resolveCliProjectRoot.js +27 -0
  138. package/dist/cli/runCommand.d.ts +1 -1
  139. package/dist/cli/runCommand.js +59 -17
  140. package/dist/cli/skillsCommand.d.ts +20 -0
  141. package/dist/cli/skillsCommand.js +74 -31
  142. package/dist/cli/validateCommand.d.ts +1 -1
  143. package/dist/cli/validateCommand.js +22 -4
  144. package/dist/cli.js +4 -4
  145. package/dist/config/browseCatalog.d.ts +2 -0
  146. package/dist/config/browseCatalog.js +6 -0
  147. package/dist/config/catalogRelativePath.d.ts +4 -0
  148. package/dist/config/catalogRelativePath.js +37 -9
  149. package/dist/config/createStage.d.ts +1 -0
  150. package/dist/config/createStage.js +11 -2
  151. package/dist/config/createTask.d.ts +30 -0
  152. package/dist/config/createTask.js +161 -0
  153. package/dist/config/createTrigger.d.ts +15 -0
  154. package/dist/config/createTrigger.js +32 -25
  155. package/dist/config/draftPackage.d.ts +42 -0
  156. package/dist/config/draftPackage.js +220 -23
  157. package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
  158. package/dist/config/ensureCatalogScanRoot.js +6 -2
  159. package/dist/config/findTaskInCatalog.d.ts +33 -0
  160. package/dist/config/findTaskInCatalog.js +69 -0
  161. package/dist/config/hostConfig.d.ts +21 -0
  162. package/dist/config/hostConfig.js +114 -1
  163. package/dist/config/importTask.d.ts +19 -0
  164. package/dist/config/importTask.js +133 -0
  165. package/dist/config/installSkillRequest.d.ts +40 -0
  166. package/dist/config/installSkillRequest.js +286 -0
  167. package/dist/config/loadOutcome.d.ts +11 -6
  168. package/dist/config/loadPipeline.js +27 -4
  169. package/dist/config/loadStage.js +17 -0
  170. package/dist/config/loadStageflowManifest.js +4 -1
  171. package/dist/config/loadTask.js +2 -0
  172. package/dist/config/loadTrigger.js +2 -0
  173. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  174. package/dist/config/mergePipelineIncludes.js +30 -0
  175. package/dist/config/normalizePipelineStageEntry.js +10 -1
  176. package/dist/config/pipelineStageKeys.js +1 -0
  177. package/dist/config/printTargetYaml.js +0 -1
  178. package/dist/config/publishDraftPackage.d.ts +5 -1
  179. package/dist/config/publishDraftPackage.js +4 -1
  180. package/dist/config/resolveCatalogRoots.d.ts +4 -1
  181. package/dist/config/resolveCatalogRoots.js +18 -1
  182. package/dist/config/skillUsageIndex.d.ts +6 -0
  183. package/dist/config/skillUsageIndex.js +39 -0
  184. package/dist/config/stageBrowser.js +13 -0
  185. package/dist/config/triggerAdapterStatus.d.ts +11 -0
  186. package/dist/config/triggerAdapterStatus.js +90 -0
  187. package/dist/config/triggerCatalog.d.ts +41 -2
  188. package/dist/config/triggerCatalog.js +107 -15
  189. package/dist/config/updateTask.d.ts +30 -0
  190. package/dist/config/updateTask.js +119 -0
  191. package/dist/config/updateTrigger.d.ts +38 -0
  192. package/dist/config/updateTrigger.js +220 -0
  193. package/dist/config/validateCatalog.d.ts +9 -2
  194. package/dist/config/validateCatalog.js +71 -7
  195. package/dist/config/workshopCatalogFilenames.d.ts +37 -0
  196. package/dist/config/workshopCatalogFilenames.js +125 -0
  197. package/dist/config/workshopCatalogRepair.d.ts +7 -0
  198. package/dist/config/workshopCatalogRepair.js +144 -0
  199. package/dist/config/yamlParsePosition.d.ts +4 -0
  200. package/dist/config/yamlParsePosition.js +9 -0
  201. package/dist/errors/codes.d.ts +1 -1
  202. package/dist/errors/codes.js +1 -0
  203. package/dist/hosted/runtime.d.ts +2 -2
  204. package/dist/hosted/types.d.ts +1 -1
  205. package/dist/hosted/types.js +1 -1
  206. package/dist/index.d.ts +3 -2
  207. package/dist/index.js +2 -1
  208. package/dist/mcp/catalogTools.js +1 -0
  209. package/dist/mcp/getStartedTool.js +15 -6
  210. package/dist/mcp/triggerTools.js +2 -8
  211. package/dist/operatorAgent/agentPort.d.ts +11 -0
  212. package/dist/operatorAgent/agentPort.js +12 -0
  213. package/dist/operatorAgent/index.d.ts +1 -0
  214. package/dist/operatorAgent/index.js +1 -0
  215. package/dist/operatorAgent/piModel.js +26 -6
  216. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
  217. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +4 -2
  218. package/dist/operatorAgent/profiles/workshopAuthorTools.js +103 -16
  219. package/dist/package-meta.d.ts +1 -1
  220. package/dist/package-meta.js +1 -1
  221. package/dist/preflight/channelChecks.d.ts +17 -0
  222. package/dist/preflight/channelChecks.js +106 -0
  223. package/dist/preflight/pipelinePreflight.d.ts +9 -2
  224. package/dist/preflight/pipelinePreflight.js +9 -1
  225. package/dist/project/ensureProjectRootsFromEnv.d.ts +3 -0
  226. package/dist/project/ensureProjectRootsFromEnv.js +22 -0
  227. package/dist/project/globalHome.d.ts +1 -0
  228. package/dist/project/globalHome.js +18 -0
  229. package/dist/project/workspaceCatalog.d.ts +10 -0
  230. package/dist/project/workspaceCatalog.js +91 -0
  231. package/dist/runstore/backup.js +14 -4
  232. package/dist/runstore/port.d.ts +11 -1
  233. package/dist/runstore/restore.js +5 -2
  234. package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -0
  235. package/dist/runstore/sqlite/SqliteRunStore.js +29 -9
  236. package/dist/runstore/sqlite/migrations/012-trigger-fires.d.ts +7 -0
  237. package/dist/runstore/sqlite/migrations/012-trigger-fires.js +18 -0
  238. package/dist/runstore/sqlite/migrations/index.js +2 -0
  239. package/dist/runstore/stageSnapshot.d.ts +3 -1
  240. package/dist/runstore/stageSnapshot.js +19 -0
  241. package/dist/runstore/workspaceLayout.js +27 -0
  242. package/dist/runstore/writeContainedArtifact.d.ts +1 -0
  243. package/dist/runstore/writeContainedArtifact.js +52 -0
  244. package/dist/runtime/credentialBinding.js +14 -6
  245. package/dist/runtime/emailSource.js +20 -28
  246. package/dist/runtime/githubPollSource.js +20 -28
  247. package/dist/runtime/pipelineRunner.d.ts +4 -4
  248. package/dist/runtime/pipelineRunner.js +3 -1
  249. package/dist/runtime/pipelineScheduler.d.ts +2 -2
  250. package/dist/runtime/pipelineScheduler.js +3 -0
  251. package/dist/runtime/repositoryMaterialize.d.ts +1 -1
  252. package/dist/runtime/resumeReconstruct.d.ts +2 -2
  253. package/dist/runtime/resumeTimedOut.d.ts +2 -2
  254. package/dist/runtime/runManager.d.ts +18 -2
  255. package/dist/runtime/runManager.js +99 -31
  256. package/dist/runtime/runRetryCoordinator.d.ts +2 -2
  257. package/dist/runtime/scheduleSource.js +15 -24
  258. package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
  259. package/dist/runtime/stageAttemptBootstrap.js +26 -1
  260. package/dist/runtime/stageProcessLauncher.js +33 -3
  261. package/dist/runtime/stageRoots.js +8 -1
  262. package/dist/runtime/stageRunner.d.ts +2 -2
  263. package/dist/runtime/stageRunner.js +8 -2
  264. package/dist/runtime/stageWorker.js +2 -2
  265. package/dist/runtime/triggerPort.d.ts +5 -3
  266. package/dist/runtime/triggerRunner.d.ts +1 -0
  267. package/dist/runtime/triggerRunner.js +27 -20
  268. package/dist/runtime/webhookAccept.d.ts +25 -0
  269. package/dist/runtime/webhookAccept.js +56 -0
  270. package/dist/server/bootstrap.d.ts +10 -2
  271. package/dist/server/bootstrap.js +19 -1
  272. package/dist/server/channelRoutes.d.ts +9 -0
  273. package/dist/server/channelRoutes.js +88 -0
  274. package/dist/server/controlToken.d.ts +1 -1
  275. package/dist/server/controlToken.js +18 -2
  276. package/dist/server/healthSurfaces.d.ts +12 -0
  277. package/dist/server/healthSurfaces.js +27 -6
  278. package/dist/server/http.d.ts +19 -10
  279. package/dist/server/http.js +616 -85
  280. package/dist/server/liveViewPath.d.ts +9 -0
  281. package/dist/server/liveViewPath.js +8 -0
  282. package/dist/server/liveViewRoutes.d.ts +58 -0
  283. package/dist/server/liveViewRoutes.js +565 -0
  284. package/dist/server/mcpHost.d.ts +4 -2
  285. package/dist/server/mcpHost.js +2 -0
  286. package/dist/server/readCatalogFile.d.ts +29 -0
  287. package/dist/server/readCatalogFile.js +215 -0
  288. package/dist/server/triggerRoutes.d.ts +1 -0
  289. package/dist/server/triggerRoutes.js +200 -73
  290. package/dist/tools/sendMessage.d.ts +21 -0
  291. package/dist/tools/sendMessage.js +25 -0
  292. package/dist/tools/writeStageArtifact.d.ts +9 -0
  293. package/dist/tools/writeStageArtifact.js +2 -47
  294. package/dist/types/pipeline.d.ts +5 -2
  295. package/dist/types/stage.d.ts +14 -1
  296. package/dist/types/stageflowManifest.d.ts +1 -1
  297. package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  298. package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  299. package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  300. package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  301. package/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  302. package/dist/ui/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  303. package/dist/ui/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  304. package/dist/ui/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  305. package/dist/ui/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  306. package/dist/ui/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  307. package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  308. package/dist/ui/assets/index-BOhqnPNg.js +260 -0
  309. package/dist/ui/assets/{index-Bv4p1aPK.css → index-Clv4sJpU.css} +1 -1
  310. package/dist/ui/index.html +4 -4
  311. package/dist/workshop/autosave.d.ts +2 -2
  312. package/dist/workshop/autosave.js +4 -6
  313. package/dist/workshop/buildStore.d.ts +2 -0
  314. package/dist/workshop/chatAttachments.d.ts +27 -0
  315. package/dist/workshop/chatAttachments.js +98 -0
  316. package/dist/workshop/chatTurn.d.ts +5 -2
  317. package/dist/workshop/chatTurn.js +22 -18
  318. package/dist/workshop/sessionMutations.d.ts +17 -0
  319. package/dist/workshop/sessionMutations.js +107 -0
  320. package/dist/workshop/sessionStore.d.ts +10 -0
  321. package/dist/workshop/sessionStore.js +52 -0
  322. package/dist/workshop/workshopPin.d.ts +4 -3
  323. package/dist/workshop/workshopPin.js +26 -6
  324. package/dist/workshop/workshopTranscriptTurn.d.ts +8 -0
  325. package/dist/workshop/workshopTranscriptTurn.js +46 -0
  326. package/examples/README.md +1 -1
  327. package/examples/archify-on-pr/README.md +1 -1
  328. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +0 -1
  329. package/examples/archify-on-pr/author-diagrams.yaml +1 -0
  330. package/examples/channels-smoke/README.md +12 -0
  331. package/examples/channels-smoke/channels-smoke.pipeline.yaml +11 -0
  332. package/examples/channels-smoke/channels-smoke.task.yaml +3 -0
  333. package/examples/channels-smoke/send-email.yaml +32 -0
  334. package/examples/channels-smoke/send-text.yaml +31 -0
  335. package/examples/conditional-fork/branch-a.yaml +1 -1
  336. package/examples/conditional-fork/decide.yaml +2 -1
  337. package/examples/feature-loop/{implement.yaml → feature-implement.yaml} +1 -1
  338. package/examples/feature-loop/feature-loop.pipeline.yaml +10 -10
  339. package/examples/feature-loop/{plan.yaml → feature-plan.yaml} +1 -1
  340. package/examples/feature-loop/{review.yaml → feature-review.yaml} +1 -1
  341. package/examples/feedback-loop/{implement.yaml → feedback-implement.yaml} +1 -1
  342. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +9 -9
  343. package/examples/feedback-loop/feedback-loop.pipeline.yaml +9 -9
  344. package/examples/feedback-loop/{plan.yaml → feedback-plan.yaml} +1 -1
  345. package/examples/feedback-loop/{review.yaml → feedback-review.yaml} +1 -1
  346. package/examples/generic-fan-in/{research.yaml → fan-in-research.yaml} +1 -1
  347. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +3 -3
  348. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +3 -3
  349. package/examples/hello-world/{research.yaml → hello-research.yaml} +1 -1
  350. package/examples/hello-world/hello.pipeline.yaml +2 -2
  351. package/examples/mcp-hitl-tour/{review.yaml → mcp-hitl-review.yaml} +1 -1
  352. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +3 -3
  353. package/examples/oss-issue-contribution/oss-explain-fix.yaml +1 -0
  354. package/examples/oss-issue-contribution/oss-explain-issue.yaml +1 -0
  355. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +0 -2
  356. package/examples/stageflow.yaml +6 -0
  357. package/examples/triggers/sample-github-pr.trigger.yaml +12 -0
  358. package/examples/triggers/sample-inbox-email.trigger.yaml +14 -0
  359. package/examples/triggers/sample-manual-hello.trigger.yaml +5 -0
  360. package/examples/triggers/sample-nightly-hello.trigger.yaml +8 -0
  361. package/examples/triggers/sample-signed-webhook.trigger.yaml +11 -0
  362. package/examples/triggers-readiness/README.md +48 -0
  363. package/examples/triggers-readiness/readiness-emit.yaml +18 -0
  364. package/examples/triggers-readiness/readiness.pipeline.yaml +4 -0
  365. package/examples/triggers-readiness/readiness.task.yaml +6 -0
  366. package/examples/triggers-readiness/stageflow.yaml +13 -0
  367. package/examples/triggers-readiness/triggers/readiness-dynamic-manual.trigger.yaml +4 -0
  368. package/examples/triggers-readiness/triggers/readiness-email.trigger.yaml +12 -0
  369. package/examples/triggers-readiness/triggers/readiness-github-pr.trigger.yaml +12 -0
  370. package/examples/triggers-readiness/triggers/readiness-manual.trigger.yaml +5 -0
  371. package/examples/triggers-readiness/triggers/readiness-schedule.trigger.yaml +8 -0
  372. package/examples/triggers-readiness/triggers/readiness-webhook.trigger.yaml +11 -0
  373. package/package.json +8 -3
  374. package/skills/stageflow/references/control-surface.md +1 -1
  375. package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
  376. package/skills/stageflow-run/SKILL.md +1 -1
  377. package/skills/stageflow-run/references/mcp-call.md +1 -1
  378. package/skills/stageflow-setup/SKILL.md +1 -1
  379. package/dist/ui/assets/index-59cjF0OA.js +0 -133
@@ -82,11 +82,43 @@ export function selectCatalogRootForStart(roots, projectRoot) {
82
82
  if (roots.length === 1) {
83
83
  return roots[0];
84
84
  }
85
- const writable = roots.filter((r) => r.kind !== "seeded");
86
- if (writable.length === 1) {
87
- return writable[0];
85
+ const registeredOnly = roots.filter((r) => r.kind === "registered");
86
+ if (registeredOnly.length === 1) {
87
+ return registeredOnly[0];
88
88
  }
89
- throw new CatalogPathError("project_root is required when multiple catalog roots are configured", "unknown_project_root", registered);
89
+ const nonSeeded = roots.filter((r) => r.kind !== "seeded");
90
+ if (nonSeeded.length === 1) {
91
+ return nonSeeded[0];
92
+ }
93
+ const ids = roots.map((r) => r.project_root).join(", ");
94
+ throw new CatalogPathError(`project_root is required when multiple catalog roots are configured (${ids})`, "unknown_project_root", registered);
95
+ }
96
+ function workspaceRoot(roots) {
97
+ return roots.find((r) => r.kind === "workspace");
98
+ }
99
+ export async function resolveDefaultWriteRoot(options, projectRoot) {
100
+ const roots = await resolveCatalogRoots(options);
101
+ const registered = roots.map((r) => r.project_root);
102
+ if (projectRoot !== undefined) {
103
+ const found = findCatalogRoot(roots, projectRoot);
104
+ if (found === undefined) {
105
+ throw new CatalogPathError(`Unknown project_root: ${projectRoot}`, "unknown_project_root", registered);
106
+ }
107
+ if (found.read_only) {
108
+ throw new CatalogPathError(`Catalog root ${found.project_root} is read-only`, "catalog_root_read_only", registered);
109
+ }
110
+ if (found.kind === "workspace" && found.available === false) {
111
+ throw new CatalogPathError(found.unavailable_reason ??
112
+ `Workspace catalog is not writable (${found.path})`, "unknown_project_root", registered);
113
+ }
114
+ return { roots, wireRoot: found };
115
+ }
116
+ const ws = workspaceRoot(roots);
117
+ if (ws === undefined || ws.available === false) {
118
+ throw new CatalogPathError(ws?.unavailable_reason ??
119
+ "Workspace catalog is unavailable; set project_root explicitly", "unknown_project_root", registered);
120
+ }
121
+ return { roots, wireRoot: ws };
90
122
  }
91
123
  /**
92
124
  * Shared helper: resolveCatalogRoots → selectCatalogRootForStart.
@@ -102,11 +134,7 @@ export async function resolveCatalogStartInput(options, projectRoot) {
102
134
  * Used by write surfaces (POST /api/stages, POST /api/pipelines).
103
135
  */
104
136
  export async function resolveWritableCatalogRoot(options, projectRoot) {
105
- const { roots, wireRoot } = await resolveCatalogStartInput(options, projectRoot);
106
- if (wireRoot.read_only) {
107
- throw new CatalogPathError(`Catalog root ${wireRoot.project_root} is read-only`, "catalog_root_read_only", roots.map((r) => r.project_root));
108
- }
109
- return { roots, wireRoot };
137
+ return resolveDefaultWriteRoot(options, projectRoot);
110
138
  }
111
139
  /**
112
140
  * Local CLI control: turn a cwd-resolved filesystem path into a catalog-relative
@@ -7,6 +7,7 @@ export type CreateStageInput = {
7
7
  system_prompt: string;
8
8
  model?: string;
9
9
  gate_kinds?: StageGateKind[];
10
+ skill?: string;
10
11
  };
11
12
  export type CreatedStageListing = {
12
13
  path: string;
@@ -41,8 +41,12 @@ export function parseCreateStageBody(body) {
41
41
  if ("payload_schema" in body) {
42
42
  return { ok: false, status: 400, error: "payload_schema is not supported" };
43
43
  }
44
- if ("skill" in body) {
45
- return { ok: false, status: 400, error: "skill is not supported" };
44
+ let skill;
45
+ if (body.skill !== undefined) {
46
+ if (typeof body.skill !== "string" || body.skill.trim() === "") {
47
+ return { ok: false, status: 400, error: "skill must be a non-empty string" };
48
+ }
49
+ skill = body.skill.trim();
46
50
  }
47
51
  if (typeof body.pipeline_directory !== "string" || !body.pipeline_directory.trim()) {
48
52
  return { ok: false, status: 400, error: "pipeline_directory is required" };
@@ -84,6 +88,7 @@ export function parseCreateStageBody(body) {
84
88
  system_prompt: body.system_prompt,
85
89
  ...(model !== undefined ? { model } : {}),
86
90
  ...(gateKinds !== undefined ? { gate_kinds: gateKinds } : {}),
91
+ ...(skill !== undefined ? { skill } : {}),
87
92
  };
88
93
  }
89
94
  function formatInlineYamlScalar(value) {
@@ -122,6 +127,9 @@ export function stageConfigToYaml(stage) {
122
127
  if (stage.model !== undefined && stage.model.length > 0) {
123
128
  lines.push(`model: ${formatInlineYamlScalar(stage.model)}`);
124
129
  }
130
+ if (stage.skill !== undefined && stage.skill.length > 0) {
131
+ lines.push(`skill: ${formatInlineYamlScalar(stage.skill)}`);
132
+ }
125
133
  lines.push("io:");
126
134
  lines.push(" input:");
127
135
  lines.push(" schema:");
@@ -204,6 +212,7 @@ export async function createStage(projectRoot, input) {
204
212
  system_prompt: input.system_prompt,
205
213
  ...(input.model !== undefined && input.model.length > 0 ? { model: input.model } : {}),
206
214
  ...(input.gate_kinds !== undefined ? { gate_kinds: input.gate_kinds } : {}),
215
+ ...(input.skill !== undefined && input.skill.length > 0 ? { skill: input.skill } : {}),
207
216
  }), "utf8");
208
217
  }
209
218
  catch (err) {
@@ -0,0 +1,30 @@
1
+ import type { TaskDetail } from "./findTaskInCatalog.js";
2
+ export type CreateTaskInput = {
3
+ directory: string;
4
+ id: string;
5
+ goal: string;
6
+ context?: string;
7
+ constraints?: string;
8
+ checkout?: string;
9
+ repository?: string;
10
+ ref?: string;
11
+ };
12
+ export type CreateTaskParseError = {
13
+ ok: false;
14
+ status: 400;
15
+ error: string;
16
+ };
17
+ export type CreateTaskResult = {
18
+ ok: true;
19
+ task: TaskDetail;
20
+ } | {
21
+ ok: false;
22
+ status: 400 | 404 | 409 | 500 | 502;
23
+ error: string;
24
+ };
25
+ export declare function validateTaskId(id: string): string | null;
26
+ export declare function parseCreateTaskBody(body: unknown): CreateTaskInput | CreateTaskParseError;
27
+ export declare function resolveTaskDirectory(projectRoot: string, directory: string): string | null;
28
+ export declare function taskFieldsToYaml(fields: CreateTaskInput): string;
29
+ export declare function findTaskIdCollision(projectRoot: string, id: string, targetPath: string): Promise<string | null>;
30
+ export declare function createTask(rawProjectRoot: string, input: CreateTaskInput): Promise<CreateTaskResult>;
@@ -0,0 +1,161 @@
1
+ import { access, mkdir, realpath, unlink, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { stringify as stringifyYaml } from "yaml";
4
+ import { getCatalogScanPaths } from "./browseCatalog.js";
5
+ import { STAGE_ID_PATTERN } from "./createStage.js";
6
+ import { loadTaskOutcome } from "./loadTask.js";
7
+ import { catalogContextFromStageflow } from "./resolveCatalogContext.js";
8
+ import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
9
+ const OPTIONAL_KEYS = ["context", "constraints", "checkout", "repository", "ref"];
10
+ function isPlainObject(value) {
11
+ return value !== null && typeof value === "object" && !Array.isArray(value);
12
+ }
13
+ export function validateTaskId(id) {
14
+ if (id.length === 0 || id.length > 64) {
15
+ return "id must be 1-64 characters";
16
+ }
17
+ if (!STAGE_ID_PATTERN.test(id)) {
18
+ return "id must be lowercase kebab-case";
19
+ }
20
+ return null;
21
+ }
22
+ function optionalCreateString(body, key) {
23
+ if (!Object.hasOwn(body, key) || body[key] === undefined || body[key] === null) {
24
+ return { ok: true };
25
+ }
26
+ if (typeof body[key] !== "string") {
27
+ return { ok: false, error: `${key} must be a string` };
28
+ }
29
+ if (body[key].length === 0)
30
+ return { ok: true };
31
+ return { ok: true, value: body[key] };
32
+ }
33
+ export function parseCreateTaskBody(body) {
34
+ if (!isPlainObject(body)) {
35
+ return { ok: false, status: 400, error: "Request body must be an object" };
36
+ }
37
+ if (typeof body.directory !== "string" || body.directory.trim().length === 0) {
38
+ return { ok: false, status: 400, error: "directory is required" };
39
+ }
40
+ const directory = body.directory.trim().replace(/\\/g, "/").replace(/\/+$/, "");
41
+ if (directory.length === 0) {
42
+ return { ok: false, status: 400, error: "directory is required" };
43
+ }
44
+ if (typeof body.id !== "string") {
45
+ return { ok: false, status: 400, error: "id is required" };
46
+ }
47
+ const idError = validateTaskId(body.id);
48
+ if (idError) {
49
+ return { ok: false, status: 400, error: idError };
50
+ }
51
+ if (typeof body.goal !== "string" || body.goal.length === 0) {
52
+ return { ok: false, status: 400, error: "goal is required" };
53
+ }
54
+ const input = {
55
+ directory,
56
+ id: body.id,
57
+ goal: body.goal,
58
+ };
59
+ for (const key of OPTIONAL_KEYS) {
60
+ const parsed = optionalCreateString(body, key);
61
+ if (!parsed.ok) {
62
+ return { ok: false, status: 400, error: parsed.error };
63
+ }
64
+ if (parsed.value !== undefined)
65
+ input[key] = parsed.value;
66
+ }
67
+ return input;
68
+ }
69
+ export function resolveTaskDirectory(projectRoot, directory) {
70
+ const absDirectory = path.resolve(projectRoot, directory);
71
+ const rel = path.relative(projectRoot, absDirectory);
72
+ if (rel.startsWith("..") || path.isAbsolute(rel)) {
73
+ return null;
74
+ }
75
+ return absDirectory;
76
+ }
77
+ async function fileExists(filePath) {
78
+ try {
79
+ await access(filePath);
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ export function taskFieldsToYaml(fields) {
87
+ const doc = {
88
+ id: fields.id,
89
+ goal: fields.goal,
90
+ };
91
+ for (const key of OPTIONAL_KEYS) {
92
+ const value = fields[key];
93
+ if (typeof value === "string" && value.length > 0)
94
+ doc[key] = value;
95
+ }
96
+ const text = stringifyYaml(doc, { indent: 2, lineWidth: 0 });
97
+ return text.endsWith("\n") ? text : `${text}\n`;
98
+ }
99
+ export async function findTaskIdCollision(projectRoot, id, targetPath) {
100
+ if (await fileExists(targetPath)) {
101
+ return path.relative(projectRoot, targetPath).replace(/\\/g, "/");
102
+ }
103
+ const ctx = catalogContextFromStageflow(await resolveStageflowContext(projectRoot));
104
+ const scanPaths = await getCatalogScanPaths(ctx);
105
+ if (!scanPaths)
106
+ return null;
107
+ const resolvedTarget = path.resolve(targetPath);
108
+ for (const filePath of scanPaths.taskPaths) {
109
+ if (path.resolve(filePath) === resolvedTarget)
110
+ continue;
111
+ const outcome = await loadTaskOutcome(filePath);
112
+ if (outcome.ok && outcome.value.id === id) {
113
+ return path.relative(projectRoot, filePath).replace(/\\/g, "/");
114
+ }
115
+ }
116
+ return null;
117
+ }
118
+ function taskDetail(task, projectRoot, filePath) {
119
+ return {
120
+ ...task,
121
+ path: path.relative(projectRoot, filePath).replace(/\\/g, "/"),
122
+ };
123
+ }
124
+ export async function createTask(rawProjectRoot, input) {
125
+ const idError = validateTaskId(input.id);
126
+ if (idError) {
127
+ return { ok: false, status: 400, error: idError };
128
+ }
129
+ const projectRoot = await realpath(rawProjectRoot).catch(() => rawProjectRoot);
130
+ const directory = resolveTaskDirectory(projectRoot, input.directory);
131
+ if (!directory) {
132
+ return { ok: false, status: 400, error: "directory must be inside the project root" };
133
+ }
134
+ const filePath = path.join(directory, `${input.id}.task.yaml`);
135
+ const collision = await findTaskIdCollision(projectRoot, input.id, filePath);
136
+ if (collision) {
137
+ const targetRel = path.relative(projectRoot, filePath).replace(/\\/g, "/");
138
+ const error = collision === targetRel
139
+ ? `Task file already exists (${collision})`
140
+ : `Task id already exists (${collision})`;
141
+ return { ok: false, status: 409, error };
142
+ }
143
+ try {
144
+ await mkdir(directory, { recursive: true });
145
+ await writeFile(filePath, taskFieldsToYaml(input), "utf8");
146
+ }
147
+ catch (err) {
148
+ const message = err instanceof Error ? err.message : String(err);
149
+ return { ok: false, status: 500, error: message };
150
+ }
151
+ const outcome = await loadTaskOutcome(filePath);
152
+ if (!outcome.ok) {
153
+ await unlink(filePath).catch(() => { });
154
+ return {
155
+ ok: false,
156
+ status: 400,
157
+ error: outcome.issues[0]?.message ?? "Invalid task",
158
+ };
159
+ }
160
+ return { ok: true, task: taskDetail(outcome.value, projectRoot, filePath) };
161
+ }
@@ -23,5 +23,20 @@ export type CreateTriggerResult = {
23
23
  status: 400 | 409 | 422 | 500;
24
24
  error: string;
25
25
  };
26
+ type ParsedField<T> = {
27
+ ok: true;
28
+ value: T | undefined;
29
+ } | {
30
+ ok: false;
31
+ message: string;
32
+ };
33
+ export declare function parseScheduleField(raw: unknown): ParsedField<TriggerSchedule>;
34
+ export declare function parseEventField(raw: unknown): ParsedField<TriggerEvent>;
26
35
  export declare function parseCreateTriggerBody(body: unknown): CreateTriggerInput | CreateTriggerParseError;
36
+ export declare function scheduleCronError(schedule: TriggerSchedule): string | null;
37
+ export declare function triggerReferenceError(scanPaths: {
38
+ pipelinePaths: string[];
39
+ taskPaths: string[];
40
+ }, pipeline: string, task: string | undefined): Promise<string | null>;
27
41
  export declare function createTrigger(rawProjectRoot: string, input: CreateTriggerInput): Promise<CreateTriggerResult>;
42
+ export {};
@@ -21,7 +21,7 @@ function validateTriggerId(id) {
21
21
  }
22
22
  return null;
23
23
  }
24
- function parseScheduleField(raw) {
24
+ export function parseScheduleField(raw) {
25
25
  if (raw === undefined)
26
26
  return { ok: true, value: undefined };
27
27
  if (!isPlainObject(raw)) {
@@ -41,7 +41,7 @@ function parseScheduleField(raw) {
41
41
  },
42
42
  };
43
43
  }
44
- function parseEventField(raw) {
44
+ export function parseEventField(raw) {
45
45
  if (raw === undefined)
46
46
  return { ok: true, value: undefined };
47
47
  if (!isPlainObject(raw)) {
@@ -129,6 +129,29 @@ function resolveDirectory(projectRoot, directory) {
129
129
  }
130
130
  return absDirectory;
131
131
  }
132
+ export function scheduleCronError(schedule) {
133
+ try {
134
+ new Cron(schedule.cron, schedule.timezone !== undefined ? { timezone: schedule.timezone } : {});
135
+ return null;
136
+ }
137
+ catch (err) {
138
+ const message = err instanceof Error ? err.message : String(err);
139
+ return `Invalid schedule.cron: ${message}`;
140
+ }
141
+ }
142
+ export async function triggerReferenceError(scanPaths, pipeline, task) {
143
+ const pipelineIds = await collectPipelineIdsFromPaths(scanPaths.pipelinePaths);
144
+ if (!pipelineIds.has(pipeline)) {
145
+ return `Trigger references unknown pipeline "${pipeline}"`;
146
+ }
147
+ if (task !== undefined) {
148
+ const taskIds = await collectTaskIdsFromPaths(scanPaths.taskPaths);
149
+ if (!taskIds.has(task)) {
150
+ return `Trigger references unknown task "${task}"`;
151
+ }
152
+ }
153
+ return null;
154
+ }
132
155
  function triggerInputToYaml(input, enabled) {
133
156
  const doc = {
134
157
  id: input.id,
@@ -172,34 +195,17 @@ export async function createTrigger(rawProjectRoot, input) {
172
195
  error: `Trigger id already exists (${path.relative(projectRoot, collisionPath).replace(/\\/g, "/")})`,
173
196
  };
174
197
  }
175
- const pipelineIds = await collectPipelineIdsFromPaths(scanPaths.pipelinePaths);
176
- if (!pipelineIds.has(input.pipeline)) {
177
- return {
178
- ok: false,
179
- status: 422,
180
- error: `Trigger references unknown pipeline "${input.pipeline}"`,
181
- };
182
- }
183
- if (input.task !== undefined) {
184
- const taskIds = await collectTaskIdsFromPaths(scanPaths.taskPaths);
185
- if (!taskIds.has(input.task)) {
186
- return {
187
- ok: false,
188
- status: 422,
189
- error: `Trigger references unknown task "${input.task}"`,
190
- };
191
- }
198
+ const refError = await triggerReferenceError(scanPaths, input.pipeline, input.task);
199
+ if (refError) {
200
+ return { ok: false, status: 422, error: refError };
192
201
  }
193
202
  if (input.kind === "schedule") {
194
203
  if (!input.schedule) {
195
204
  return { ok: false, status: 422, error: "schedule.cron is required for kind=schedule" };
196
205
  }
197
- try {
198
- new Cron(input.schedule.cron, input.schedule.timezone !== undefined ? { timezone: input.schedule.timezone } : {});
199
- }
200
- catch (err) {
201
- const message = err instanceof Error ? err.message : String(err);
202
- return { ok: false, status: 422, error: `Invalid schedule.cron: ${message}` };
206
+ const cronError = scheduleCronError(input.schedule);
207
+ if (cronError) {
208
+ return { ok: false, status: 422, error: cronError };
203
209
  }
204
210
  }
205
211
  const filePath = path.join(directory, `${input.id}.trigger.yaml`);
@@ -227,6 +233,7 @@ export async function createTrigger(rawProjectRoot, input) {
227
233
  trigger: {
228
234
  ...loadOutcome.value,
229
235
  definition_ref: relPath,
236
+ project_root: projectRoot,
230
237
  },
231
238
  };
232
239
  }
@@ -12,6 +12,7 @@ export type DraftPackage = {
12
12
  model?: unknown;
13
13
  schemas?: unknown;
14
14
  requires?: unknown;
15
+ channels?: unknown;
15
16
  };
16
17
  stages?: DraftStageArtifact[];
17
18
  task?: {
@@ -81,9 +82,50 @@ export type LoadTaskArtifactResult = {
81
82
  status: 400 | 404;
82
83
  error: string;
83
84
  };
85
+ /** Move uses-wrapper skill: onto the matching stage artifact body, then clear the wrapper. */
86
+ export declare function hoistUsesWrapperSkills(draft: DraftPackage): DraftPackage;
84
87
  export declare function validateDraftPackage(draft: DraftPackage, options?: ValidateDraftPackageOptions): Promise<ValidationResult>;
85
88
  export declare function overwriteDraftPackage(projectRoot: string, input: OverwriteDraftPackageInput): Promise<OverwriteDraftPackageResult>;
86
89
  export declare function createDraftPackage(projectRoot: string, input: CreateDraftPackageInput): Promise<CreateDraftPackageResult>;
90
+ export type DraftPlanMode = "create" | "overwrite";
91
+ export type DraftPlanFile = {
92
+ path: string;
93
+ kind: "pipeline" | "stage" | "task";
94
+ action: "new" | "overwrite" | "unchanged";
95
+ added: number;
96
+ removed: number;
97
+ };
98
+ export type DraftPlanResult = {
99
+ pipelinePath: string;
100
+ directory: string;
101
+ files: DraftPlanFile[];
102
+ pipelineIdTaken: boolean;
103
+ };
104
+ export type PlanDraftPackageOptions = {
105
+ mode?: DraftPlanMode;
106
+ catalogPipelines?: ReadonlyArray<{
107
+ id: string;
108
+ path: string;
109
+ }>;
110
+ };
111
+ export declare function countLineChanges(before: string, after: string): {
112
+ added: number;
113
+ removed: number;
114
+ };
115
+ export declare function planDraftPackage(projectRoot: string, input: CreateDraftPackageInput, options?: PlanDraftPackageOptions): Promise<({
116
+ ok: true;
117
+ } & DraftPlanResult) | {
118
+ ok: false;
119
+ status: 400;
120
+ error: string;
121
+ }>;
122
+ export declare function parsePlanDraftPackageBody(body: unknown): (CreateDraftPackageInput & {
123
+ mode: DraftPlanMode;
124
+ }) | {
125
+ ok: false;
126
+ status: 400;
127
+ error: string;
128
+ };
87
129
  export declare function parseDraftPackageBody(body: unknown): DraftPackage | {
88
130
  ok: false;
89
131
  status: 400;