stageflow 0.25.0 → 0.30.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 (681) hide show
  1. package/README.md +14 -3
  2. package/builtin-skills/browser/SKILL.md +42 -0
  3. package/dist/a2a/contracts.d.ts +1 -0
  4. package/dist/a2a/contracts.js +1 -0
  5. package/dist/a2a/registry.d.ts +2 -0
  6. package/dist/a2a/registry.js +20 -1
  7. package/dist/a2a/server.d.ts +7 -0
  8. package/dist/a2a/server.js +5 -2
  9. package/dist/a2a/service.d.ts +1 -1
  10. package/dist/a2a/service.js +57 -8
  11. package/dist/a2a/store.d.ts +8 -5
  12. package/dist/a2a/store.js +24 -67
  13. package/dist/agent/activity.d.ts +3 -0
  14. package/dist/agent/bootProviderConfig.d.ts +21 -0
  15. package/dist/agent/bootProviderConfig.js +74 -0
  16. package/dist/agent/claudeAdapter.js +2 -2
  17. package/dist/agent/cursorProvider.d.ts +2 -0
  18. package/dist/agent/cursorProvider.js +30 -5
  19. package/dist/agent/fakeAgent.d.ts +1 -0
  20. package/dist/agent/fakeAgent.js +13 -0
  21. package/dist/agent/piAdapter.d.ts +11 -24
  22. package/dist/agent/piAdapter.js +107 -50
  23. package/dist/agent/piIsolatedMcp.d.ts +2 -0
  24. package/dist/agent/piIsolatedMcp.js +10 -2
  25. package/dist/agent/piSessionFactory.d.ts +38 -0
  26. package/dist/agent/piSessionFactory.js +60 -0
  27. package/dist/agent/port.d.ts +8 -0
  28. package/dist/agent/streamLogRedact.d.ts +7 -1
  29. package/dist/agent/streamLogRedact.js +26 -11
  30. package/dist/browser/anchor.d.ts +27 -0
  31. package/dist/browser/anchor.js +127 -0
  32. package/dist/browser/auditSink.d.ts +38 -0
  33. package/dist/browser/auditSink.js +34 -0
  34. package/dist/browser/browserHost.d.ts +86 -0
  35. package/dist/browser/browserHost.js +7 -0
  36. package/dist/browser/browserSweep.d.ts +14 -0
  37. package/dist/browser/browserSweep.js +54 -0
  38. package/dist/browser/browserTeardown.d.ts +56 -0
  39. package/dist/browser/browserTeardown.js +235 -0
  40. package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -0
  41. package/dist/browser/fakeRemoteBrowserHost.js +34 -0
  42. package/dist/browser/gateHandoff.d.ts +25 -0
  43. package/dist/browser/gateHandoff.js +83 -0
  44. package/dist/browser/humanLogin.d.ts +18 -0
  45. package/dist/browser/humanLogin.js +34 -0
  46. package/dist/browser/keyProvider.d.ts +10 -0
  47. package/dist/browser/keyProvider.js +39 -0
  48. package/dist/browser/localBrowserHost.d.ts +10 -0
  49. package/dist/browser/localBrowserHost.js +152 -0
  50. package/dist/browser/localProfileLock.d.ts +2 -0
  51. package/dist/browser/localProfileLock.js +218 -0
  52. package/dist/browser/localProfileStore.d.ts +5 -0
  53. package/dist/browser/localProfileStore.js +91 -0
  54. package/dist/browser/loginCheck.d.ts +53 -0
  55. package/dist/browser/loginCheck.js +147 -0
  56. package/dist/browser/memoryProfileLock.d.ts +2 -0
  57. package/dist/browser/memoryProfileLock.js +53 -0
  58. package/dist/browser/memoryProfileStore.d.ts +2 -0
  59. package/dist/browser/memoryProfileStore.js +31 -0
  60. package/dist/browser/navigationAudit.d.ts +16 -0
  61. package/dist/browser/navigationAudit.js +53 -0
  62. package/dist/browser/persistedEnv.d.ts +3 -0
  63. package/dist/browser/persistedEnv.js +15 -0
  64. package/dist/browser/profileLock.d.ts +40 -0
  65. package/dist/browser/profileLock.js +10 -0
  66. package/dist/browser/profileStore.d.ts +23 -0
  67. package/dist/browser/profileStore.js +39 -0
  68. package/dist/browser/runLiveness.d.ts +13 -0
  69. package/dist/browser/runLiveness.js +39 -0
  70. package/dist/browser/sitePolicy.d.ts +10 -0
  71. package/dist/browser/sitePolicy.js +61 -0
  72. package/dist/browser/stageBrowserEnv.d.ts +22 -0
  73. package/dist/browser/stageBrowserEnv.js +147 -0
  74. package/dist/browser/stageProfileLock.d.ts +17 -0
  75. package/dist/browser/stageProfileLock.js +39 -0
  76. package/dist/cli/artifactCommand.js +9 -16
  77. package/dist/cli/backupCommand.d.ts +9 -0
  78. package/dist/cli/backupCommand.js +111 -0
  79. package/dist/cli/browserCommand.d.ts +44 -0
  80. package/dist/cli/browserCommand.js +472 -0
  81. package/dist/cli/debugRunCommand.d.ts +10 -0
  82. package/dist/cli/debugRunCommand.js +109 -0
  83. package/dist/cli/doctorCommand.d.ts +32 -0
  84. package/dist/cli/doctorCommand.js +453 -0
  85. package/dist/cli/envelopeCommand.js +9 -2
  86. package/dist/cli/exportAllCommand.d.ts +55 -0
  87. package/dist/cli/exportAllCommand.js +218 -0
  88. package/dist/cli/exportRunCommand.js +23 -21
  89. package/dist/cli/hostClient.d.ts +41 -3
  90. package/dist/cli/hostClient.js +129 -14
  91. package/dist/cli/initCommand.d.ts +1 -0
  92. package/dist/cli/initCommand.js +23 -7
  93. package/dist/cli/initTemplates.d.ts +5 -2
  94. package/dist/cli/initTemplates.js +32 -2
  95. package/dist/cli/resolveSafeOutPath.d.ts +2 -0
  96. package/dist/cli/resolveSafeOutPath.js +40 -0
  97. package/dist/cli/restoreCommand.d.ts +10 -0
  98. package/dist/cli/restoreCommand.js +90 -0
  99. package/dist/cli/runCommand.d.ts +3 -2
  100. package/dist/cli/runCommand.js +93 -11
  101. package/dist/cli/runOutput.d.ts +4 -0
  102. package/dist/cli/runOutput.js +33 -7
  103. package/dist/cli/runStageCommand.d.ts +1 -0
  104. package/dist/cli/runStageCommand.js +44 -25
  105. package/dist/cli/runsCommand.d.ts +1 -1
  106. package/dist/cli/runsCommand.js +168 -10
  107. package/dist/cli/triggerCommand.d.ts +12 -0
  108. package/dist/cli/triggerCommand.js +183 -0
  109. package/dist/cli/validateCommand.d.ts +1 -1
  110. package/dist/cli/validateCommand.js +23 -6
  111. package/dist/cli.js +202 -32
  112. package/dist/config/browseCatalog.d.ts +1 -0
  113. package/dist/config/browseCatalog.js +5 -4
  114. package/dist/config/builtinSkills.d.ts +4 -0
  115. package/dist/config/builtinSkills.js +23 -0
  116. package/dist/config/catalogRelativePath.d.ts +63 -0
  117. package/dist/config/catalogRelativePath.js +126 -0
  118. package/dist/config/configOrigin.d.ts +27 -0
  119. package/dist/config/configOrigin.js +59 -0
  120. package/dist/config/createTrigger.d.ts +27 -0
  121. package/dist/config/createTrigger.js +232 -0
  122. package/dist/config/draftPackage.d.ts +117 -0
  123. package/dist/config/draftPackage.js +550 -0
  124. package/dist/config/ensureCatalogScanRoot.d.ts +16 -0
  125. package/dist/config/ensureCatalogScanRoot.js +73 -0
  126. package/dist/config/hostConfig.d.ts +57 -0
  127. package/dist/config/hostConfig.js +360 -0
  128. package/dist/config/listSkills.d.ts +26 -0
  129. package/dist/config/listSkills.js +206 -5
  130. package/dist/config/loadOutcome.d.ts +7 -1
  131. package/dist/config/loadPipeline.js +39 -2
  132. package/dist/config/loadStage.js +25 -0
  133. package/dist/config/loadStageflowManifest.js +25 -0
  134. package/dist/config/loadTask.d.ts +2 -0
  135. package/dist/config/loadTask.js +57 -18
  136. package/dist/config/loadTrigger.d.ts +9 -0
  137. package/dist/config/loadTrigger.js +120 -0
  138. package/dist/config/materializeStageModels.js +5 -1
  139. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  140. package/dist/config/mergePipelineIncludes.js +19 -0
  141. package/dist/config/migrateYaml.js +6 -11
  142. package/dist/config/multiProjectCatalog.d.ts +32 -0
  143. package/dist/config/multiProjectCatalog.js +150 -0
  144. package/dist/config/normalizePipelineStageEntry.js +27 -1
  145. package/dist/config/parseCompletionContract.js +6 -0
  146. package/dist/config/pipelineStageKeys.js +3 -0
  147. package/dist/config/publishDraftPackage.d.ts +7 -0
  148. package/dist/config/publishDraftPackage.js +25 -0
  149. package/dist/config/resolveCatalogContext.js +1 -1
  150. package/dist/config/resolveCatalogRoots.d.ts +27 -0
  151. package/dist/config/resolveCatalogRoots.js +76 -0
  152. package/dist/config/resolveModel.d.ts +7 -1
  153. package/dist/config/resolveModel.js +11 -1
  154. package/dist/config/resolvePipelineDag.js +1 -1
  155. package/dist/config/resolveStageMcpServers.d.ts +9 -1
  156. package/dist/config/resolveStageMcpServers.js +36 -9
  157. package/dist/config/scanCatalogPaths.d.ts +1 -1
  158. package/dist/config/scanCatalogPaths.js +6 -2
  159. package/dist/config/secretFromEnvOrFile.d.ts +9 -0
  160. package/dist/config/secretFromEnvOrFile.js +34 -0
  161. package/dist/config/seededCatalog.d.ts +11 -0
  162. package/dist/config/seededCatalog.js +29 -0
  163. package/dist/config/stageBrowser.d.ts +12 -0
  164. package/dist/config/stageBrowser.js +118 -0
  165. package/dist/config/toolRequires.d.ts +24 -0
  166. package/dist/config/toolRequires.js +115 -0
  167. package/dist/config/triggerCatalog.d.ts +10 -0
  168. package/dist/config/triggerCatalog.js +37 -0
  169. package/dist/config/validateCatalog.d.ts +17 -3
  170. package/dist/config/validateCatalog.js +223 -3
  171. package/dist/config/validateCompletionContract.js +8 -0
  172. package/dist/diagnostics/checks.d.ts +39 -0
  173. package/dist/diagnostics/checks.js +135 -0
  174. package/dist/envelope/preEmitChecks.d.ts +1 -1
  175. package/dist/envelope/preEmitChecks.js +8 -0
  176. package/dist/errors/codes.d.ts +14 -0
  177. package/dist/errors/codes.js +59 -0
  178. package/dist/git/cache.d.ts +14 -0
  179. package/dist/git/cache.js +150 -0
  180. package/dist/git/credentials.d.ts +9 -0
  181. package/dist/git/credentials.js +88 -0
  182. package/dist/git/errors.d.ts +20 -0
  183. package/dist/git/errors.js +94 -0
  184. package/dist/git/exec.d.ts +16 -0
  185. package/dist/git/exec.js +135 -0
  186. package/dist/git/operations.d.ts +29 -0
  187. package/dist/git/operations.js +153 -0
  188. package/dist/git/version.d.ts +1 -0
  189. package/dist/git/version.js +10 -0
  190. package/dist/logging/audit.d.ts +16 -0
  191. package/dist/logging/audit.js +19 -0
  192. package/dist/logging/commonWords.d.ts +2 -0
  193. package/dist/logging/commonWords.js +13 -0
  194. package/dist/logging/logger.d.ts +49 -0
  195. package/dist/logging/logger.js +193 -0
  196. package/dist/logging/namedSecrets.d.ts +6 -0
  197. package/dist/logging/namedSecrets.js +58 -0
  198. package/dist/logging/redact.d.ts +17 -0
  199. package/dist/logging/redact.js +105 -0
  200. package/dist/mcp/catalogTools.js +492 -81
  201. package/dist/mcp/checkoutTools.d.ts +52 -0
  202. package/dist/mcp/checkoutTools.js +332 -0
  203. package/dist/mcp/controlTools.js +182 -6
  204. package/dist/mcp/deps.d.ts +3 -0
  205. package/dist/mcp/getStartedTool.d.ts +3 -0
  206. package/dist/mcp/getStartedTool.js +62 -0
  207. package/dist/mcp/readArtifact.d.ts +11 -0
  208. package/dist/mcp/readArtifact.js +46 -30
  209. package/dist/mcp/server.js +2 -0
  210. package/dist/mcp/tools.js +6 -0
  211. package/dist/mcp/triggerTools.d.ts +3 -0
  212. package/dist/mcp/triggerTools.js +176 -0
  213. package/dist/net/proxy.d.ts +14 -0
  214. package/dist/net/proxy.js +78 -0
  215. package/dist/operatorAgent/docsRetrieval.d.ts +40 -0
  216. package/dist/operatorAgent/docsRetrieval.js +269 -0
  217. package/dist/operatorAgent/draftContext.d.ts +16 -0
  218. package/dist/operatorAgent/draftContext.js +68 -0
  219. package/dist/operatorAgent/fakeHost.d.ts +39 -0
  220. package/dist/operatorAgent/fakeHost.js +92 -0
  221. package/dist/operatorAgent/host.d.ts +40 -0
  222. package/dist/operatorAgent/host.js +179 -0
  223. package/dist/operatorAgent/index.d.ts +9 -0
  224. package/dist/operatorAgent/index.js +8 -0
  225. package/dist/operatorAgent/piModel.d.ts +80 -0
  226. package/dist/operatorAgent/piModel.js +528 -0
  227. package/dist/operatorAgent/profiles/workshopAuthor.d.ts +23 -0
  228. package/dist/operatorAgent/profiles/workshopAuthor.js +338 -0
  229. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +6 -0
  230. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +103 -0
  231. package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +57 -0
  232. package/dist/operatorAgent/profiles/workshopAuthorTools.js +623 -0
  233. package/dist/operatorAgent/proposals.d.ts +32 -0
  234. package/dist/operatorAgent/proposals.js +144 -0
  235. package/dist/operatorAgent/types.d.ts +128 -0
  236. package/dist/operatorAgent/types.js +1 -0
  237. package/dist/package-meta.d.ts +2 -1
  238. package/dist/package-meta.js +2 -1
  239. package/dist/preflight/bash.d.ts +8 -0
  240. package/dist/preflight/bash.js +34 -0
  241. package/dist/preflight/claudeRoot.d.ts +11 -0
  242. package/dist/preflight/claudeRoot.js +23 -0
  243. package/dist/preflight/mcpCommands.d.ts +8 -0
  244. package/dist/preflight/mcpCommands.js +36 -0
  245. package/dist/preflight/pipelinePreflight.d.ts +40 -0
  246. package/dist/preflight/pipelinePreflight.js +192 -0
  247. package/dist/preflight/tls.d.ts +6 -0
  248. package/dist/preflight/tls.js +18 -0
  249. package/dist/preflight/toolchain.d.ts +45 -0
  250. package/dist/preflight/toolchain.js +219 -0
  251. package/dist/project/findManifestRoot.d.ts +3 -0
  252. package/dist/project/findManifestRoot.js +35 -0
  253. package/dist/project/findProjectRoot.js +3 -4
  254. package/dist/project/globalHome.d.ts +7 -0
  255. package/dist/project/globalHome.js +63 -2
  256. package/dist/project/resolveProjectContext.js +2 -2
  257. package/dist/project/resolveStageflowContext.d.ts +7 -0
  258. package/dist/project/resolveStageflowContext.js +46 -30
  259. package/dist/projection/projectRun.d.ts +2 -1
  260. package/dist/projection/projectRun.js +1 -0
  261. package/dist/runstore/assertTmpdir.d.ts +1 -0
  262. package/dist/runstore/assertTmpdir.js +25 -0
  263. package/dist/runstore/backup.d.ts +52 -0
  264. package/dist/runstore/backup.js +292 -0
  265. package/dist/runstore/createStore.d.ts +18 -1
  266. package/dist/runstore/createStore.js +64 -5
  267. package/dist/runstore/debugBundle.d.ts +60 -0
  268. package/dist/runstore/debugBundle.js +143 -0
  269. package/dist/runstore/diskUsage.d.ts +50 -0
  270. package/dist/runstore/diskUsage.js +214 -0
  271. package/dist/runstore/exportRunPayload.d.ts +8 -0
  272. package/dist/runstore/exportRunPayload.js +23 -0
  273. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  274. package/dist/runstore/normalizeCatalogPath.js +10 -0
  275. package/dist/runstore/paths.d.ts +5 -0
  276. package/dist/runstore/paths.js +145 -1
  277. package/dist/runstore/port.d.ts +139 -13
  278. package/dist/runstore/port.js +8 -1
  279. package/dist/runstore/restore.d.ts +81 -0
  280. package/dist/runstore/restore.js +355 -0
  281. package/dist/runstore/retention.d.ts +27 -0
  282. package/dist/runstore/retention.js +74 -0
  283. package/dist/runstore/runManifest.d.ts +146 -0
  284. package/dist/runstore/runManifest.js +288 -0
  285. package/dist/runstore/runProjection.d.ts +3 -1
  286. package/dist/runstore/runProjection.js +63 -1
  287. package/dist/runstore/sqlite/SqliteRunStore.d.ts +35 -3
  288. package/dist/runstore/sqlite/SqliteRunStore.js +442 -219
  289. package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
  290. package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
  291. package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
  292. package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
  293. package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
  294. package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
  295. package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
  296. package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
  297. package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
  298. package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
  299. package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
  300. package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
  301. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
  302. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
  303. package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
  304. package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
  305. package/dist/runstore/sqlite/migrations/008-triggers-table.d.ts +7 -0
  306. package/dist/runstore/sqlite/migrations/008-triggers-table.js +19 -0
  307. package/dist/runstore/sqlite/migrations/009-trigger-next-run.d.ts +7 -0
  308. package/dist/runstore/sqlite/migrations/009-trigger-next-run.js +19 -0
  309. package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.d.ts +7 -0
  310. package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.js +17 -0
  311. package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
  312. package/dist/runstore/sqlite/migrations/index.js +78 -0
  313. package/dist/runstore/sqlite/schema.d.ts +20 -1
  314. package/dist/runstore/sqlite/schema.js +277 -1
  315. package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
  316. package/dist/runstore/sqlite/storeOpenError.js +11 -0
  317. package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
  318. package/dist/runstore/sqlite/storeSchemaError.js +8 -0
  319. package/dist/runstore/stageExecution.js +3 -0
  320. package/dist/runstore/storeFilesystem.d.ts +32 -0
  321. package/dist/runstore/storeFilesystem.js +148 -0
  322. package/dist/runstore/trackProjection.js +2 -0
  323. package/dist/runstore/workspaceLayout.d.ts +13 -0
  324. package/dist/runstore/workspaceLayout.js +76 -0
  325. package/dist/runtime/answerResume.d.ts +1 -0
  326. package/dist/runtime/answerResume.js +3 -1
  327. package/dist/runtime/completionCheckRunner.d.ts +15 -1
  328. package/dist/runtime/completionCheckRunner.js +67 -7
  329. package/dist/runtime/containerLimits.d.ts +16 -0
  330. package/dist/runtime/containerLimits.js +84 -0
  331. package/dist/runtime/credentialBinding.d.ts +2 -0
  332. package/dist/runtime/credentialBinding.js +3 -0
  333. package/dist/runtime/credentialMaterialisation.d.ts +28 -0
  334. package/dist/runtime/credentialMaterialisation.js +128 -0
  335. package/dist/runtime/emailSource.d.ts +72 -0
  336. package/dist/runtime/emailSource.js +304 -0
  337. package/dist/runtime/gitCheckoutCapability.js +7 -13
  338. package/dist/runtime/githubPollSource.d.ts +86 -0
  339. package/dist/runtime/githubPollSource.js +284 -0
  340. package/dist/runtime/pipelineRunner.d.ts +40 -1
  341. package/dist/runtime/pipelineRunner.js +181 -17
  342. package/dist/runtime/pipelineScheduler.d.ts +17 -0
  343. package/dist/runtime/pipelineScheduler.js +220 -28
  344. package/dist/runtime/reloadRunCatalog.js +6 -1
  345. package/dist/runtime/repositoryMaterialize.d.ts +47 -0
  346. package/dist/runtime/repositoryMaterialize.js +235 -0
  347. package/dist/runtime/resumeTimedOut.d.ts +1 -1
  348. package/dist/runtime/resumeTimedOut.js +5 -2
  349. package/dist/runtime/runChangeBus.js +9 -0
  350. package/dist/runtime/runDeletion.d.ts +7 -0
  351. package/dist/runtime/runDeletion.js +37 -0
  352. package/dist/runtime/runManager.d.ts +169 -4
  353. package/dist/runtime/runManager.js +1748 -83
  354. package/dist/runtime/runRetentionSweep.d.ts +31 -0
  355. package/dist/runtime/runRetentionSweep.js +328 -0
  356. package/dist/runtime/runRetryCoordinator.d.ts +4 -0
  357. package/dist/runtime/runRetryCoordinator.js +20 -2
  358. package/dist/runtime/runSkills.d.ts +40 -0
  359. package/dist/runtime/runSkills.js +173 -0
  360. package/dist/runtime/scheduleSource.d.ts +38 -0
  361. package/dist/runtime/scheduleSource.js +119 -0
  362. package/dist/runtime/settingsFile.d.ts +5 -0
  363. package/dist/runtime/settingsFile.js +61 -54
  364. package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
  365. package/dist/runtime/stageAttemptBootstrap.js +250 -27
  366. package/dist/runtime/stageCacheEnv.d.ts +6 -0
  367. package/dist/runtime/stageCacheEnv.js +34 -0
  368. package/dist/runtime/stageConcurrency.d.ts +2 -1
  369. package/dist/runtime/stageConcurrency.js +4 -2
  370. package/dist/runtime/stageEnvironment.d.ts +38 -0
  371. package/dist/runtime/stageEnvironment.js +194 -0
  372. package/dist/runtime/stageHitl.d.ts +1 -0
  373. package/dist/runtime/stageHitl.js +5 -1
  374. package/dist/runtime/stageProcessLauncher.d.ts +20 -0
  375. package/dist/runtime/stageProcessLauncher.js +236 -41
  376. package/dist/runtime/stageRecovery.d.ts +3 -1
  377. package/dist/runtime/stageRecovery.js +19 -4
  378. package/dist/runtime/stageRoots.d.ts +38 -1
  379. package/dist/runtime/stageRoots.js +118 -0
  380. package/dist/runtime/stageRunner.d.ts +6 -0
  381. package/dist/runtime/stageRunner.js +32 -6
  382. package/dist/runtime/stageSecretDecl.d.ts +9 -0
  383. package/dist/runtime/stageSecretDecl.js +102 -0
  384. package/dist/runtime/stageSecrets.d.ts +40 -0
  385. package/dist/runtime/stageSecrets.js +181 -0
  386. package/dist/runtime/stageStreamLog.d.ts +1 -0
  387. package/dist/runtime/stageStreamLog.js +2 -1
  388. package/dist/runtime/stageWorker.d.ts +3 -2
  389. package/dist/runtime/stageWorker.js +58 -10
  390. package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
  391. package/dist/runtime/stageWorkerProtocol.js +8 -0
  392. package/dist/runtime/startPayload.d.ts +32 -0
  393. package/dist/runtime/startPayload.js +59 -0
  394. package/dist/runtime/taskInput.js +14 -5
  395. package/dist/runtime/triggerCatalog.d.ts +6 -0
  396. package/dist/runtime/triggerCatalog.js +24 -0
  397. package/dist/runtime/triggerEventMatch.d.ts +2 -0
  398. package/dist/runtime/triggerEventMatch.js +6 -0
  399. package/dist/runtime/triggerPort.d.ts +14 -0
  400. package/dist/runtime/triggerPort.js +1 -0
  401. package/dist/runtime/triggerRunner.d.ts +17 -0
  402. package/dist/runtime/triggerRunner.js +89 -0
  403. package/dist/runtime/verifiedStageExecution.d.ts +8 -0
  404. package/dist/runtime/verifiedStageExecution.js +16 -1
  405. package/dist/runtime/webhookSignature.d.ts +1 -0
  406. package/dist/runtime/webhookSignature.js +12 -0
  407. package/dist/runtime/workspaceBinding.d.ts +20 -0
  408. package/dist/runtime/workspaceBinding.js +60 -0
  409. package/dist/server/allowedHosts.d.ts +19 -0
  410. package/dist/server/allowedHosts.js +179 -0
  411. package/dist/server/bootstrap.d.ts +42 -2
  412. package/dist/server/bootstrap.js +273 -5
  413. package/dist/server/controlToken.d.ts +47 -0
  414. package/dist/server/controlToken.js +254 -0
  415. package/dist/server/createHttpHost.d.ts +11 -2
  416. package/dist/server/createHttpHost.js +106 -10
  417. package/dist/server/ensureGlobalService.d.ts +5 -1
  418. package/dist/server/ensureGlobalService.js +35 -1
  419. package/dist/server/healthSurfaces.d.ts +6 -0
  420. package/dist/server/healthSurfaces.js +123 -0
  421. package/dist/server/http.d.ts +27 -1
  422. package/dist/server/http.js +2254 -477
  423. package/dist/server/listenHost.d.ts +5 -0
  424. package/dist/server/listenHost.js +56 -0
  425. package/dist/server/mcpHost.d.ts +10 -1
  426. package/dist/server/mcpHost.js +36 -6
  427. package/dist/server/operatorResults.d.ts +2 -2
  428. package/dist/server/operatorResults.js +40 -29
  429. package/dist/server/requestAuthContext.d.ts +12 -0
  430. package/dist/server/requestAuthContext.js +21 -0
  431. package/dist/server/shutdown.d.ts +69 -0
  432. package/dist/server/shutdown.js +219 -0
  433. package/dist/server/triggerRoutes.d.ts +15 -0
  434. package/dist/server/triggerRoutes.js +268 -0
  435. package/dist/tools/askOperator.d.ts +3 -2
  436. package/dist/types/completion.d.ts +3 -0
  437. package/dist/types/pipeline.d.ts +10 -1
  438. package/dist/types/preEmitCheck.d.ts +7 -0
  439. package/dist/types/stage.d.ts +22 -0
  440. package/dist/types/stageflowManifest.d.ts +3 -0
  441. package/dist/types/task.d.ts +8 -0
  442. package/dist/types/trigger.d.ts +18 -0
  443. package/dist/types/trigger.js +1 -0
  444. package/dist/ui/assets/{index-CSsDued1.css → index-Bv4p1aPK.css} +1 -1
  445. package/dist/ui/assets/index-CntB4bZR.js +133 -0
  446. package/dist/ui/index.html +2 -2
  447. package/dist/workshop/autosave.d.ts +58 -0
  448. package/dist/workshop/autosave.js +222 -0
  449. package/dist/workshop/buildStore.d.ts +79 -0
  450. package/dist/workshop/buildStore.js +326 -0
  451. package/dist/workshop/chatTurn.d.ts +232 -0
  452. package/dist/workshop/chatTurn.js +475 -0
  453. package/dist/workshop/modelSettings.d.ts +18 -0
  454. package/dist/workshop/modelSettings.js +44 -0
  455. package/dist/workshop/sessionStore.d.ts +61 -0
  456. package/dist/workshop/sessionStore.js +254 -0
  457. package/dist/workshop/workshopPin.d.ts +72 -0
  458. package/dist/workshop/workshopPin.js +193 -0
  459. package/examples/README.md +99 -0
  460. package/examples/archify-on-pr/README.md +213 -0
  461. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
  462. package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
  463. package/examples/archify-on-pr/author-diagrams.yaml +106 -0
  464. package/examples/archify-on-pr/detect-changes.yaml +89 -0
  465. package/examples/browser-session/README.md +77 -0
  466. package/examples/browser-session/browser-session.pipeline.yaml +50 -0
  467. package/examples/browser-session/browser-session.task.yaml +6 -0
  468. package/examples/browser-session/check-login.yaml +22 -0
  469. package/examples/browser-session/fixture-server.mjs +64 -0
  470. package/examples/browser-session/human-login.yaml +31 -0
  471. package/examples/browser-session/merge.yaml +36 -0
  472. package/examples/browser-session/work-a.yaml +41 -0
  473. package/examples/browser-session/work-b.yaml +41 -0
  474. package/examples/ci-validate/README.md +35 -0
  475. package/examples/ci-validate/check.yaml +13 -0
  476. package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
  477. package/examples/ci-validate/validate.sh +5 -0
  478. package/examples/compliance-review-demo/README.md +125 -0
  479. package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
  480. package/examples/compliance-review-demo/connect-account.yaml +47 -0
  481. package/examples/compliance-review-demo/map-to-control.yaml +123 -0
  482. package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
  483. package/examples/compliance-review-demo/publish-report.yaml +79 -0
  484. package/examples/compliance-review-demo/review-verdict.yaml +122 -0
  485. package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
  486. package/examples/compliance-review-demo/store-evidence.yaml +143 -0
  487. package/examples/conditional-fork/README.md +89 -0
  488. package/examples/conditional-fork/branch-a.yaml +13 -0
  489. package/examples/conditional-fork/branch-b.yaml +13 -0
  490. package/examples/conditional-fork/decide.yaml +35 -0
  491. package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
  492. package/examples/conditional-fork/fork-demo.task.yaml +8 -0
  493. package/examples/context7-mcp/README.md +42 -0
  494. package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
  495. package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
  496. package/examples/context7-mcp/fetch-docs.yaml +52 -0
  497. package/examples/context7-mcp/resolve-library.yaml +31 -0
  498. package/examples/context7-mcp/write-brief.yaml +52 -0
  499. package/examples/feature-loop/README.md +104 -0
  500. package/examples/feature-loop/address-feedback.yaml +148 -0
  501. package/examples/feature-loop/align.yaml +116 -0
  502. package/examples/feature-loop/decompose.yaml +86 -0
  503. package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
  504. package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
  505. package/examples/feature-loop/feature-loop.task.yaml +25 -0
  506. package/examples/feature-loop/implement.yaml +128 -0
  507. package/examples/feature-loop/plan.yaml +111 -0
  508. package/examples/feature-loop/publish.yaml +167 -0
  509. package/examples/feature-loop/review.yaml +146 -0
  510. package/examples/feature-loop/verify.yaml +106 -0
  511. package/examples/feedback-loop/README.md +72 -0
  512. package/examples/feedback-loop/VERIFY.md +208 -0
  513. package/examples/feedback-loop/continue-only.task.yaml +4 -0
  514. package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
  515. package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
  516. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
  517. package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
  518. package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
  519. package/examples/feedback-loop/implement.yaml +14 -0
  520. package/examples/feedback-loop/plan.yaml +14 -0
  521. package/examples/feedback-loop/review.yaml +15 -0
  522. package/examples/feedback-loop/send-back-once.task.yaml +6 -0
  523. package/examples/feedback-loop/submit.yaml +12 -0
  524. package/examples/generic-fan-in/README.md +151 -0
  525. package/examples/generic-fan-in/clarify.yaml +18 -0
  526. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
  527. package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
  528. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
  529. package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
  530. package/examples/generic-fan-in/research.yaml +45 -0
  531. package/examples/generic-fan-in/synthesize.yaml +66 -0
  532. package/examples/generic-fan-in/validation.yaml +45 -0
  533. package/examples/github-release/README.md +78 -0
  534. package/examples/github-release/draft-release-notes.yaml +64 -0
  535. package/examples/github-release/github-release.pipeline.yaml +11 -0
  536. package/examples/github-release/github-release.task.yaml +13 -0
  537. package/examples/github-release/publish-github-release.yaml +64 -0
  538. package/examples/hello-world/README.md +28 -0
  539. package/examples/hello-world/hello.pipeline.yaml +4 -0
  540. package/examples/hello-world/my-task.task.yaml +6 -0
  541. package/examples/hello-world/research.yaml +18 -0
  542. package/examples/mcp-hitl-tour/README.md +113 -0
  543. package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
  544. package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
  545. package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
  546. package/examples/mcp-hitl-tour/gather.yaml +31 -0
  547. package/examples/mcp-hitl-tour/intake.yaml +62 -0
  548. package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
  549. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
  550. package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
  551. package/examples/mcp-hitl-tour/polish.yaml +33 -0
  552. package/examples/mcp-hitl-tour/review.yaml +17 -0
  553. package/examples/mcp-hitl-tour/ship.yaml +25 -0
  554. package/examples/oss-issue-contribution/README.md +218 -0
  555. package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
  556. package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
  557. package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
  558. package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
  559. package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
  560. package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
  561. package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
  562. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
  563. package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
  564. package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
  565. package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
  566. package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
  567. package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
  568. package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
  569. package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
  570. package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
  571. package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
  572. package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
  573. package/examples/oss-quick-fix/README.md +65 -0
  574. package/examples/oss-quick-fix/implement-fix.yaml +84 -0
  575. package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
  576. package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
  577. package/examples/oss-quick-fix/ship-fix.yaml +81 -0
  578. package/examples/oss-quick-fix/understand-issue.yaml +67 -0
  579. package/examples/oss-quick-fix/verify-fix.yaml +73 -0
  580. package/examples/plan-review/README.md +37 -0
  581. package/examples/plan-review/plan-review-followup.yaml +13 -0
  582. package/examples/plan-review/plan-review.pipeline.yaml +9 -0
  583. package/examples/plan-review/plan-review.task.yaml +9 -0
  584. package/examples/plan-review/plan-review.yaml +25 -0
  585. package/examples/playwright-mcp/README.md +39 -0
  586. package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
  587. package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
  588. package/examples/playwright-mcp/screenshot.yaml +40 -0
  589. package/examples/retry-tour/README.md +75 -0
  590. package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
  591. package/examples/retry-tour/retry-tour.task.yaml +9 -0
  592. package/examples/route-if-tour/README.md +202 -0
  593. package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
  594. package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
  595. package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
  596. package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
  597. package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
  598. package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
  599. package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
  600. package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
  601. package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
  602. package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
  603. package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
  604. package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
  605. package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
  606. package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
  607. package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
  608. package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
  609. package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
  610. package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
  611. package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
  612. package/examples/route-wiring-smoke-test/README.md +377 -0
  613. package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
  614. package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
  615. package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
  616. package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
  617. package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
  618. package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
  619. package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
  620. package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
  621. package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
  622. package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
  623. package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
  624. package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
  625. package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
  626. package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
  627. package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
  628. package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
  629. package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
  630. package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
  631. package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
  632. package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
  633. package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
  634. package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
  635. package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
  636. package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
  637. package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
  638. package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
  639. package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
  640. package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
  641. package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
  642. package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
  643. package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
  644. package/examples/ship-feature/README.md +190 -0
  645. package/examples/ship-feature/feat-address-feedback.yaml +119 -0
  646. package/examples/ship-feature/feat-implement.yaml +180 -0
  647. package/examples/ship-feature/feat-plan.yaml +120 -0
  648. package/examples/ship-feature/feat-review.yaml +109 -0
  649. package/examples/ship-feature/feat-ship.yaml +203 -0
  650. package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
  651. package/examples/ship-feature/ship-feature.task.yaml +78 -0
  652. package/examples/stage-mcp/README.md +145 -0
  653. package/examples/stage-mcp/echo-mcp.mjs +20 -0
  654. package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
  655. package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
  656. package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
  657. package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
  658. package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
  659. package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
  660. package/examples/stage-mcp/use-echo.yaml +20 -0
  661. package/examples/stageflow.yaml +51 -0
  662. package/examples/verify-tour/README.md +80 -0
  663. package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
  664. package/examples/verify-tour/verify-tour.task.yaml +11 -0
  665. package/package.json +9 -1
  666. package/skills/stageflow/SKILL.md +6 -6
  667. package/skills/stageflow/references/control-surface.md +13 -5
  668. package/skills/stageflow/scripts/detect-host.mjs +14 -1
  669. package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
  670. package/skills/stageflow-author/SKILL.md +4 -3
  671. package/skills/stageflow-author/references/catalog-mapping.md +16 -0
  672. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  673. package/skills/stageflow-author/references/stage-prompt-template.md +4 -4
  674. package/skills/stageflow-run/SKILL.md +22 -12
  675. package/skills/stageflow-run/references/mcp-call.md +9 -1
  676. package/skills/stageflow-run/references/task-and-pipeline-selection.md +19 -6
  677. package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
  678. package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
  679. package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
  680. package/skills/stageflow-setup/SKILL.md +51 -8
  681. package/dist/ui/assets/index-Da5EHU6M.js +0 -119
@@ -0,0 +1,550 @@
1
+ import { access, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import path from "node:path";
4
+ import { loadPipelineOutcome } from "./loadPipeline.js";
5
+ import { parseTaskFile } from "./loadTask.js";
6
+ import { stringifyTargetYaml } from "./printTargetYaml.js";
7
+ import { readYamlObject } from "./readYamlObject.js";
8
+ import { buildValidationResult, findingsFromLoadIssues, loadPipelineValidated, validatePipeline, } from "./validateCatalog.js";
9
+ function isPlainObject(value) {
10
+ return value !== null && typeof value === "object" && !Array.isArray(value);
11
+ }
12
+ function normalizeStageRelPath(stagePath) {
13
+ return stagePath.replace(/\\/g, "/").replace(/^\.\//, "");
14
+ }
15
+ function pipelineHasExternalUses(pipeline) {
16
+ return pipeline.stages.some((stage) => typeof stage.uses === "string" && stage.uses.trim().length > 0);
17
+ }
18
+ function pipelineDocument(pipeline) {
19
+ const doc = {
20
+ id: pipeline.id,
21
+ stages: pipeline.stages,
22
+ };
23
+ if (pipeline.agent !== undefined)
24
+ doc.agent = pipeline.agent;
25
+ if (pipeline.model !== undefined)
26
+ doc.model = pipeline.model;
27
+ if (pipeline.schemas !== undefined)
28
+ doc.schemas = pipeline.schemas;
29
+ if (pipeline.requires !== undefined)
30
+ doc.requires = pipeline.requires;
31
+ return doc;
32
+ }
33
+ function resolveDirectory(projectRoot, directory) {
34
+ const absDirectory = path.resolve(projectRoot, directory);
35
+ const rel = path.relative(projectRoot, absDirectory);
36
+ if (rel.startsWith("..") || path.isAbsolute(rel)) {
37
+ return null;
38
+ }
39
+ return absDirectory;
40
+ }
41
+ async function fileExists(filePath) {
42
+ try {
43
+ await access(filePath);
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ }
50
+ async function materializeDraft(draft, dir, pipelineFilename) {
51
+ await mkdir(dir, { recursive: true });
52
+ await writeFile(path.join(dir, pipelineFilename), stringifyTargetYaml(pipelineDocument(draft.pipeline)), "utf8");
53
+ for (const stage of draft.stages ?? []) {
54
+ const rel = normalizeStageRelPath(stage.path);
55
+ const stagePath = path.join(dir, rel);
56
+ await mkdir(path.dirname(stagePath), { recursive: true });
57
+ await writeFile(stagePath, stringifyTargetYaml(stage.body), "utf8");
58
+ }
59
+ if (draft.task) {
60
+ await writeFile(path.join(dir, path.basename(draft.task.filename)), stringifyTargetYaml(draft.task.body), "utf8");
61
+ }
62
+ }
63
+ function collectTaskFindings(cwd, draft) {
64
+ if (!draft.task)
65
+ return [];
66
+ const outcome = parseTaskFile(draft.task.body, `task ${draft.task.filename}`);
67
+ if (outcome.ok)
68
+ return [];
69
+ const absPath = path.resolve(cwd, path.basename(draft.task.filename));
70
+ return findingsFromLoadIssues(cwd, absPath, outcome.issues);
71
+ }
72
+ export async function validateDraftPackage(draft, options = {}) {
73
+ if (!isPlainObject(draft) || !isPlainObject(draft.pipeline)) {
74
+ return buildValidationResult("pipeline", [
75
+ {
76
+ severity: "error",
77
+ code: "pipeline.invalid_shape",
78
+ path: "<draft>",
79
+ message: "draft package must include a pipeline object",
80
+ category: "pipeline",
81
+ },
82
+ ], options.strict ?? false);
83
+ }
84
+ const cwd = options.cwd ?? process.cwd();
85
+ const projectRoot = options.projectRoot ?? cwd;
86
+ const strict = options.strict ?? false;
87
+ const findings = [];
88
+ const needsMaterialize = pipelineHasExternalUses(draft.pipeline) ||
89
+ (draft.stages !== undefined && draft.stages.length > 0);
90
+ if (needsMaterialize) {
91
+ const tempRoot = await mkdtemp(path.join(tmpdir(), "sf-draft-"));
92
+ try {
93
+ const pipelineFilename = `${draft.pipeline.id}.pipeline.yaml`;
94
+ await materializeDraft(draft, tempRoot, pipelineFilename);
95
+ const pipelineResult = await validatePipeline(pipelineFilename, {
96
+ cwd: tempRoot,
97
+ projectRoot: tempRoot,
98
+ validateStages: true,
99
+ strict,
100
+ });
101
+ findings.push(...pipelineResult.findings);
102
+ }
103
+ finally {
104
+ await rm(tempRoot, { recursive: true, force: true });
105
+ }
106
+ }
107
+ else {
108
+ const inline = {
109
+ id: draft.pipeline.id,
110
+ stages: draft.pipeline.stages,
111
+ ...(draft.pipeline.agent !== undefined ? { agent: draft.pipeline.agent } : {}),
112
+ ...(draft.pipeline.model !== undefined ? { model: draft.pipeline.model } : {}),
113
+ ...(draft.pipeline.schemas !== undefined ? { schemas: draft.pipeline.schemas } : {}),
114
+ ...(draft.pipeline.requires !== undefined
115
+ ? { requires: draft.pipeline.requires }
116
+ : {}),
117
+ };
118
+ const result = await loadPipelineValidated(inline, {
119
+ cwd,
120
+ projectRoot,
121
+ validateStages: true,
122
+ });
123
+ findings.push(...result.findings);
124
+ }
125
+ findings.push(...collectTaskFindings(cwd, draft));
126
+ return buildValidationResult("pipeline", findings, strict);
127
+ }
128
+ function buildPipelineListing(projectRoot, relPath, loaded) {
129
+ return {
130
+ path: relPath,
131
+ id: loaded.pipeline.id,
132
+ stages: loaded.stages.map((stage) => {
133
+ const source = loaded.stageSources?.[stage.id];
134
+ const listing = {
135
+ id: stage.id,
136
+ ...(stage.gate_kinds !== undefined ? { gate_kinds: stage.gate_kinds } : {}),
137
+ };
138
+ if (source?.kind === "inline") {
139
+ return { ...listing, inline: true };
140
+ }
141
+ if (source?.kind === "file") {
142
+ return {
143
+ ...listing,
144
+ uses_path: path.relative(projectRoot, source.path).replace(/\\/g, "/"),
145
+ };
146
+ }
147
+ return listing;
148
+ }),
149
+ };
150
+ }
151
+ function listingFromDraft(pipelineRelPath, draft, stagePaths) {
152
+ return {
153
+ path: pipelineRelPath,
154
+ id: draft.pipeline.id,
155
+ stages: draft.pipeline.stages.map((stage, index) => {
156
+ const id = typeof stage.id === "string" ? stage.id : `stage-${index}`;
157
+ if (typeof stage.uses === "string" && stage.uses.trim()) {
158
+ const match = stagePaths.find((p) => p.endsWith(normalizeStageRelPath(stage.uses)));
159
+ return {
160
+ id,
161
+ ...(match !== undefined ? { uses_path: match } : {}),
162
+ };
163
+ }
164
+ return { id, inline: true };
165
+ }),
166
+ };
167
+ }
168
+ function resolveDraftWriteTarget(projectRoot, input) {
169
+ if (typeof input.directory !== "string" || !input.directory.trim()) {
170
+ return { ok: false, status: 400, error: "directory is required" };
171
+ }
172
+ const directory = input.directory.trim().replace(/\\/g, "/");
173
+ if (directory.endsWith(".yaml") || directory.endsWith(".yml")) {
174
+ return {
175
+ ok: false,
176
+ status: 400,
177
+ error: "directory must be a catalog folder, not a pipeline file path",
178
+ };
179
+ }
180
+ const packageDirectory = resolveDirectory(projectRoot, directory);
181
+ if (!packageDirectory) {
182
+ return {
183
+ ok: false,
184
+ status: 400,
185
+ error: "directory must be inside the project root",
186
+ };
187
+ }
188
+ const draft = input.draft;
189
+ if (!isPlainObject(draft?.pipeline) || typeof draft.pipeline.id !== "string") {
190
+ return { ok: false, status: 400, error: "draft.pipeline.id is required" };
191
+ }
192
+ const pipelineFilename = input.pipelineFilename?.trim() || `${draft.pipeline.id}.pipeline.yaml`;
193
+ const pipelineAbsPath = path.join(packageDirectory, path.basename(pipelineFilename));
194
+ const pipelineRelPath = path
195
+ .relative(projectRoot, pipelineAbsPath)
196
+ .replace(/\\/g, "/");
197
+ return {
198
+ ok: true,
199
+ value: {
200
+ packageDirectory,
201
+ draft,
202
+ pipelineFilename,
203
+ pipelineAbsPath,
204
+ pipelineRelPath,
205
+ },
206
+ };
207
+ }
208
+ async function gateDraftWrite(projectRoot, draft, allowInvalid) {
209
+ if (allowInvalid)
210
+ return null;
211
+ const validation = await validateDraftPackage(draft, {
212
+ cwd: projectRoot,
213
+ projectRoot,
214
+ strict: true,
215
+ });
216
+ if (validation.ok)
217
+ return null;
218
+ const errorFinding = validation.findings.find((finding) => finding.severity === "error");
219
+ return {
220
+ ok: false,
221
+ status: 422,
222
+ error: errorFinding?.message ?? "Package validation failed",
223
+ findings: validation.findings,
224
+ };
225
+ }
226
+ async function writeDraftPackageFiles(projectRoot, target, allowInvalid) {
227
+ const { packageDirectory, draft, pipelineAbsPath, pipelineRelPath } = target;
228
+ const stagePaths = [];
229
+ for (const stage of draft.stages ?? []) {
230
+ const rel = normalizeStageRelPath(stage.path);
231
+ if (!rel || path.isAbsolute(rel) || rel.split(/[/\\]/).includes("..")) {
232
+ return {
233
+ ok: false,
234
+ status: 400,
235
+ error: `Stage path escapes package directory (${stage.path})`,
236
+ };
237
+ }
238
+ const stageAbs = path.resolve(packageDirectory, rel);
239
+ const relToPackage = path.relative(packageDirectory, stageAbs);
240
+ if (relToPackage.startsWith("..") || path.isAbsolute(relToPackage)) {
241
+ return {
242
+ ok: false,
243
+ status: 400,
244
+ error: `Stage path escapes package directory (${stage.path})`,
245
+ };
246
+ }
247
+ }
248
+ try {
249
+ await mkdir(packageDirectory, { recursive: true });
250
+ await writeFile(pipelineAbsPath, stringifyTargetYaml(pipelineDocument(draft.pipeline)), "utf8");
251
+ for (const stage of draft.stages ?? []) {
252
+ const rel = normalizeStageRelPath(stage.path);
253
+ const stageAbs = path.resolve(packageDirectory, rel);
254
+ await mkdir(path.dirname(stageAbs), { recursive: true });
255
+ await writeFile(stageAbs, stringifyTargetYaml(stage.body), "utf8");
256
+ stagePaths.push(path.relative(projectRoot, stageAbs).replace(/\\/g, "/"));
257
+ }
258
+ let taskPath;
259
+ if (draft.task) {
260
+ const taskAbs = path.join(packageDirectory, path.basename(draft.task.filename));
261
+ await writeFile(taskAbs, stringifyTargetYaml(draft.task.body), "utf8");
262
+ taskPath = path.relative(projectRoot, taskAbs).replace(/\\/g, "/");
263
+ }
264
+ const loadOutcome = await loadPipelineOutcome(pipelineRelPath, {
265
+ cwd: projectRoot,
266
+ });
267
+ const pipeline = loadOutcome.ok
268
+ ? buildPipelineListing(projectRoot, pipelineRelPath, loadOutcome.value)
269
+ : listingFromDraft(pipelineRelPath, draft, stagePaths);
270
+ if (!loadOutcome.ok && !allowInvalid) {
271
+ return {
272
+ ok: false,
273
+ status: 500,
274
+ error: loadOutcome.issues[0]?.message ?? "Failed to load written pipeline",
275
+ };
276
+ }
277
+ return {
278
+ ok: true,
279
+ pipeline,
280
+ pipelinePath: pipelineRelPath,
281
+ stagePaths,
282
+ ...(taskPath !== undefined ? { taskPath } : {}),
283
+ };
284
+ }
285
+ catch (err) {
286
+ const message = err instanceof Error ? err.message : String(err);
287
+ return { ok: false, status: 500, error: message };
288
+ }
289
+ }
290
+ export async function overwriteDraftPackage(projectRoot, input) {
291
+ const resolved = resolveDraftWriteTarget(projectRoot, input);
292
+ if (!resolved.ok)
293
+ return resolved;
294
+ if (!(await fileExists(resolved.value.pipelineAbsPath))) {
295
+ return {
296
+ ok: false,
297
+ status: 404,
298
+ error: `Pipeline does not exist (${resolved.value.pipelineRelPath})`,
299
+ };
300
+ }
301
+ const blocked = await gateDraftWrite(projectRoot, resolved.value.draft, input.allowInvalid);
302
+ if (blocked)
303
+ return blocked;
304
+ return writeDraftPackageFiles(projectRoot, resolved.value, input.allowInvalid);
305
+ }
306
+ export async function createDraftPackage(projectRoot, input) {
307
+ const resolved = resolveDraftWriteTarget(projectRoot, input);
308
+ if (!resolved.ok)
309
+ return resolved;
310
+ if (await fileExists(resolved.value.pipelineAbsPath)) {
311
+ return {
312
+ ok: false,
313
+ status: 409,
314
+ error: `Pipeline already exists (${resolved.value.pipelineRelPath})`,
315
+ };
316
+ }
317
+ const blocked = await gateDraftWrite(projectRoot, resolved.value.draft, input.allowInvalid);
318
+ if (blocked)
319
+ return blocked;
320
+ return writeDraftPackageFiles(projectRoot, resolved.value, input.allowInvalid);
321
+ }
322
+ export function parseDraftPackageBody(body) {
323
+ if (!isPlainObject(body)) {
324
+ return { ok: false, status: 400, error: "JSON object body required" };
325
+ }
326
+ const draftValue = isPlainObject(body.draft) ? body.draft : body;
327
+ if (!isPlainObject(draftValue.pipeline)) {
328
+ return { ok: false, status: 400, error: "draft.pipeline is required" };
329
+ }
330
+ if (typeof draftValue.pipeline.id !== "string" || !draftValue.pipeline.id.trim()) {
331
+ return { ok: false, status: 400, error: "draft.pipeline.id is required" };
332
+ }
333
+ if (!Array.isArray(draftValue.pipeline.stages)) {
334
+ return { ok: false, status: 400, error: "draft.pipeline.stages must be an array" };
335
+ }
336
+ return draftValue;
337
+ }
338
+ export function parseCreateDraftPackageBody(body) {
339
+ if (!isPlainObject(body)) {
340
+ return { ok: false, status: 400, error: "JSON object body required" };
341
+ }
342
+ const draftParsed = parseDraftPackageBody(body);
343
+ if ("ok" in draftParsed)
344
+ return draftParsed;
345
+ if (typeof body.directory !== "string" || !body.directory.trim()) {
346
+ return { ok: false, status: 400, error: "directory is required" };
347
+ }
348
+ return {
349
+ directory: body.directory.trim(),
350
+ draft: draftParsed,
351
+ ...(typeof body.pipelineFilename === "string"
352
+ ? { pipelineFilename: body.pipelineFilename }
353
+ : {}),
354
+ ...(body.allowInvalid === true ? { allowInvalid: true } : {}),
355
+ };
356
+ }
357
+ export const parseOverwriteDraftPackageBody = parseCreateDraftPackageBody;
358
+ export function parseOpenDraftPackageBody(body) {
359
+ if (!isPlainObject(body)) {
360
+ return { ok: false, status: 400, error: "JSON object body required" };
361
+ }
362
+ if (typeof body.path !== "string" || !body.path.trim()) {
363
+ return { ok: false, status: 400, error: "path is required" };
364
+ }
365
+ const pathValue = body.path.trim().replace(/\\/g, "/");
366
+ const taskRaw = typeof body.task === "string"
367
+ ? body.task
368
+ : typeof body.taskPath === "string"
369
+ ? body.taskPath
370
+ : undefined;
371
+ return {
372
+ path: pathValue,
373
+ ...(taskRaw?.trim() ? { taskPath: taskRaw.trim().replace(/\\/g, "/") } : {}),
374
+ };
375
+ }
376
+ function resolveProjectRelativePath(projectRoot, relPath) {
377
+ const abs = path.resolve(projectRoot, relPath);
378
+ const rel = path.relative(projectRoot, abs);
379
+ if (rel.startsWith("..") || path.isAbsolute(rel)) {
380
+ return null;
381
+ }
382
+ return abs;
383
+ }
384
+ /** Load a catalog task file into a draft task artifact (attach without reloading the pipeline). */
385
+ export async function loadTaskArtifact(projectRoot, taskRelPath) {
386
+ if (typeof taskRelPath !== "string" || !taskRelPath.trim()) {
387
+ return { ok: false, status: 400, error: "task path is required" };
388
+ }
389
+ const taskRel = taskRelPath.trim().replace(/\\/g, "/");
390
+ const taskAbs = resolveProjectRelativePath(projectRoot, taskRel);
391
+ if (!taskAbs) {
392
+ return {
393
+ ok: false,
394
+ status: 400,
395
+ error: "task path must be inside the project root",
396
+ };
397
+ }
398
+ if (!(await fileExists(taskAbs))) {
399
+ return {
400
+ ok: false,
401
+ status: 404,
402
+ error: `Task does not exist (${taskRel})`,
403
+ };
404
+ }
405
+ try {
406
+ const body = await readYamlObject(taskAbs);
407
+ return {
408
+ ok: true,
409
+ task: {
410
+ filename: path.basename(taskAbs),
411
+ body,
412
+ },
413
+ taskPath: path.relative(projectRoot, taskAbs).replace(/\\/g, "/"),
414
+ };
415
+ }
416
+ catch (err) {
417
+ const message = err instanceof Error ? err.message : String(err);
418
+ return { ok: false, status: 400, error: `Failed to read task: ${message}` };
419
+ }
420
+ }
421
+ export function parseAttachTaskBody(body) {
422
+ if (!isPlainObject(body)) {
423
+ return { ok: false, status: 400, error: "JSON object body required" };
424
+ }
425
+ const taskRaw = typeof body.task === "string"
426
+ ? body.task
427
+ : typeof body.taskPath === "string"
428
+ ? body.taskPath
429
+ : undefined;
430
+ if (!taskRaw?.trim()) {
431
+ return { ok: false, status: 400, error: "task path is required" };
432
+ }
433
+ return { taskPath: taskRaw.trim().replace(/\\/g, "/") };
434
+ }
435
+ export async function loadDraftPackage(projectRoot, pipelineRelPath, options = {}) {
436
+ if (typeof pipelineRelPath !== "string" || !pipelineRelPath.trim()) {
437
+ return { ok: false, status: 400, error: "path is required" };
438
+ }
439
+ const normalizedRel = pipelineRelPath.trim().replace(/\\/g, "/");
440
+ const pipelineAbs = resolveProjectRelativePath(projectRoot, normalizedRel);
441
+ if (!pipelineAbs) {
442
+ return {
443
+ ok: false,
444
+ status: 400,
445
+ error: "path must be inside the project root",
446
+ };
447
+ }
448
+ if (!(await fileExists(pipelineAbs))) {
449
+ return {
450
+ ok: false,
451
+ status: 404,
452
+ error: `Pipeline does not exist (${normalizedRel})`,
453
+ };
454
+ }
455
+ let raw;
456
+ try {
457
+ raw = await readYamlObject(pipelineAbs);
458
+ }
459
+ catch (err) {
460
+ const message = err instanceof Error ? err.message : String(err);
461
+ return { ok: false, status: 400, error: `Failed to read pipeline: ${message}` };
462
+ }
463
+ if (typeof raw.id !== "string" || !raw.id.trim()) {
464
+ return { ok: false, status: 400, error: "pipeline id is required" };
465
+ }
466
+ if (!Array.isArray(raw.stages)) {
467
+ return { ok: false, status: 400, error: "pipeline stages must be an array" };
468
+ }
469
+ const packageDirectory = path.dirname(pipelineAbs);
470
+ const pipelineFilename = path.basename(pipelineAbs);
471
+ const directory = path
472
+ .relative(projectRoot, packageDirectory)
473
+ .replace(/\\/g, "/") || ".";
474
+ const pipelinePath = path
475
+ .relative(projectRoot, pipelineAbs)
476
+ .replace(/\\/g, "/");
477
+ const pipelineStages = raw.stages.filter(isPlainObject);
478
+ const stageArtifacts = [];
479
+ const seenUses = new Set();
480
+ for (const stage of pipelineStages) {
481
+ if (typeof stage.uses !== "string" || !stage.uses.trim())
482
+ continue;
483
+ const uses = stage.uses.trim().replace(/\\/g, "/");
484
+ const key = normalizeStageRelPath(uses);
485
+ if (seenUses.has(key))
486
+ continue;
487
+ seenUses.add(key);
488
+ const stageAbs = path.resolve(packageDirectory, uses);
489
+ const stageRelToRoot = path.relative(projectRoot, stageAbs);
490
+ if (stageRelToRoot.startsWith("..") || path.isAbsolute(stageRelToRoot)) {
491
+ return {
492
+ ok: false,
493
+ status: 400,
494
+ error: `Stage path escapes project root (${uses})`,
495
+ };
496
+ }
497
+ if (!(await fileExists(stageAbs))) {
498
+ return {
499
+ ok: false,
500
+ status: 404,
501
+ error: `Stage file does not exist (${path
502
+ .relative(projectRoot, stageAbs)
503
+ .replace(/\\/g, "/")})`,
504
+ };
505
+ }
506
+ try {
507
+ const body = await readYamlObject(stageAbs);
508
+ stageArtifacts.push({ path: uses, body });
509
+ }
510
+ catch (err) {
511
+ const message = err instanceof Error ? err.message : String(err);
512
+ return {
513
+ ok: false,
514
+ status: 400,
515
+ error: `Failed to read stage ${uses}: ${message}`,
516
+ };
517
+ }
518
+ }
519
+ const draft = {
520
+ pipeline: {
521
+ id: raw.id,
522
+ stages: pipelineStages,
523
+ ...(raw.agent !== undefined ? { agent: raw.agent } : {}),
524
+ ...(raw.model !== undefined ? { model: raw.model } : {}),
525
+ ...(raw.schemas !== undefined ? { schemas: raw.schemas } : {}),
526
+ ...(raw.requires !== undefined ? { requires: raw.requires } : {}),
527
+ },
528
+ ...(stageArtifacts.length > 0 ? { stages: stageArtifacts } : {}),
529
+ };
530
+ let attachedTaskPath;
531
+ if (options.taskPath?.trim()) {
532
+ const loaded = await loadTaskArtifact(projectRoot, options.taskPath);
533
+ if (!loaded.ok) {
534
+ return {
535
+ ok: false,
536
+ status: loaded.status,
537
+ error: loaded.error,
538
+ };
539
+ }
540
+ draft.task = loaded.task;
541
+ attachedTaskPath = loaded.taskPath;
542
+ }
543
+ return {
544
+ ok: true,
545
+ draft,
546
+ destination: { directory, pipelineFilename },
547
+ pipelinePath,
548
+ ...(attachedTaskPath !== undefined ? { taskPath: attachedTaskPath } : {}),
549
+ };
550
+ }
@@ -0,0 +1,16 @@
1
+ /** Directory scanned for workshop-authored pipelines and tasks. */
2
+ export declare const WORKSHOP_PACKAGE_ROOT = "workshop";
3
+ export declare function normalizeCatalogDir(directory: string): string;
4
+ /** Untitled workshop saves land here so Run can see them without a new catalog edit. */
5
+ export declare function defaultWorkshopPackageDirectory(pipelineId: string | undefined): string;
6
+ /**
7
+ * Catalog root that covers this package directory.
8
+ * Packages under `workshop/` share one root. Any other folder is listed itself
9
+ * so a named save still shows up without scanning a whole parent tree.
10
+ */
11
+ export declare function catalogScanRootForDirectory(directory: string): string;
12
+ /**
13
+ * Make sure `stageflow.yaml` scans `directory` for both pipelines and tasks.
14
+ * Returns true when the manifest changed. Missing or unreadable manifests are left alone.
15
+ */
16
+ export declare function ensureCatalogScanRoot(projectRoot: string, directory: string): Promise<boolean>;
@@ -0,0 +1,73 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { isSeq, parseDocument } from "yaml";
3
+ import { manifestPathForProject } from "./loadStageflowManifest.js";
4
+ /** Directory scanned for workshop-authored pipelines and tasks. */
5
+ export const WORKSHOP_PACKAGE_ROOT = "workshop";
6
+ export function normalizeCatalogDir(directory) {
7
+ return directory.replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
8
+ }
9
+ /** Untitled workshop saves land here so Run can see them without a new catalog edit. */
10
+ export function defaultWorkshopPackageDirectory(pipelineId) {
11
+ const slug = (pipelineId ?? "")
12
+ .toLowerCase()
13
+ .replace(/[^a-z0-9]+/g, "-")
14
+ .replace(/^-+|-+$/g, "")
15
+ .slice(0, 40);
16
+ return `${WORKSHOP_PACKAGE_ROOT}/${slug || "untitled"}`;
17
+ }
18
+ /**
19
+ * Catalog root that covers this package directory.
20
+ * Packages under `workshop/` share one root. Any other folder is listed itself
21
+ * so a named save still shows up without scanning a whole parent tree.
22
+ */
23
+ export function catalogScanRootForDirectory(directory) {
24
+ const normalized = normalizeCatalogDir(directory);
25
+ if (normalized === WORKSHOP_PACKAGE_ROOT ||
26
+ normalized.startsWith(`${WORKSHOP_PACKAGE_ROOT}/`)) {
27
+ return WORKSHOP_PACKAGE_ROOT;
28
+ }
29
+ return normalized;
30
+ }
31
+ function isCovered(entries, root) {
32
+ return entries.some((entry) => {
33
+ const normalized = normalizeCatalogDir(entry);
34
+ return root === normalized || root.startsWith(`${normalized}/`);
35
+ });
36
+ }
37
+ /**
38
+ * Make sure `stageflow.yaml` scans `directory` for both pipelines and tasks.
39
+ * Returns true when the manifest changed. Missing or unreadable manifests are left alone.
40
+ */
41
+ export async function ensureCatalogScanRoot(projectRoot, directory) {
42
+ const root = catalogScanRootForDirectory(directory);
43
+ if (!root || root.split("/").includes(".."))
44
+ return false;
45
+ const manifestPath = manifestPathForProject(projectRoot);
46
+ let text;
47
+ try {
48
+ text = await readFile(manifestPath, "utf8");
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ const doc = parseDocument(text);
54
+ let changed = false;
55
+ for (const key of ["pipelines", "tasks"]) {
56
+ const seq = doc.getIn(["catalog", key]);
57
+ if (!isSeq(seq))
58
+ continue;
59
+ const values = seq.toJSON();
60
+ const entries = Array.isArray(values)
61
+ ? values.filter((item) => typeof item === "string")
62
+ : [];
63
+ if (isCovered(entries, root))
64
+ continue;
65
+ seq.add(root);
66
+ changed = true;
67
+ }
68
+ if (!changed)
69
+ return false;
70
+ const next = String(doc);
71
+ await writeFile(manifestPath, next.endsWith("\n") ? next : `${next}\n`, "utf8");
72
+ return true;
73
+ }
@@ -0,0 +1,57 @@
1
+ export declare class HostConfigError extends Error {
2
+ readonly code: "config_unknown_key" | "config_invalid";
3
+ readonly key?: string;
4
+ constructor(message: string, code: "config_unknown_key" | "config_invalid", key?: string);
5
+ }
6
+ /** Env keys that are known STAGEFLOW_* (or dynamic families) so unknown-key check accepts them. */
7
+ export declare const KNOWN_STAGEFLOW_ENV_KEYS: Set<string>;
8
+ /** Per-caller concurrent-active quota from host `callers:` config. */
9
+ export type CallerQuotaConfig = {
10
+ maxConcurrent: number;
11
+ };
12
+ export type HostConfig = {
13
+ maxConcurrentRuns: number;
14
+ maxConcurrentRunsPerProject: number | undefined;
15
+ maxQueued: number;
16
+ requireProviders: string[];
17
+ trustWorkspaceConfig: string[];
18
+ allowUnknownConfig: boolean;
19
+ controlToken: string | undefined;
20
+ readToken: string | undefined;
21
+ /** caller_id → quota; empty when unset. */
22
+ callers: Record<string, CallerQuotaConfig>;
23
+ /** Domains no browser stage may use (`browser.blocked_sites` in config.yaml). */
24
+ browserBlockedSites: string[];
25
+ /** Absolute path of config.yaml when loaded; undefined if absent. */
26
+ configFilePath: string | undefined;
27
+ warnings: string[];
28
+ /** True when maxConcurrentRuns came from override, env, or file (not bare default). */
29
+ maxConcurrentRunsExplicit: boolean;
30
+ };
31
+ export type HostConfigOverrides = {
32
+ maxConcurrentRuns?: number;
33
+ };
34
+ export type HostConfigSecretsEcho = {
35
+ controlToken: "set" | "unset";
36
+ readToken: "set" | "unset";
37
+ };
38
+ export type HostConfigPublicEcho = {
39
+ maxConcurrentRuns: number;
40
+ maxConcurrentRunsPerProject: number | undefined;
41
+ maxQueued: number;
42
+ requireProviders: string[];
43
+ trustWorkspaceConfig: string[];
44
+ allowUnknownConfig: boolean;
45
+ callers: Record<string, CallerQuotaConfig>;
46
+ secrets: HostConfigSecretsEcho;
47
+ };
48
+ /**
49
+ * Assemble HostConfig once at boot. Precedence: overrides (CLI flags) > env > file > default.
50
+ */
51
+ export declare function loadHostConfig(options?: {
52
+ env?: NodeJS.ProcessEnv;
53
+ homeDir?: string;
54
+ overrides?: HostConfigOverrides;
55
+ configFilePath?: string | null;
56
+ }): HostConfig;
57
+ export declare function redactHostConfig(config: HostConfig): HostConfigPublicEcho;