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
@@ -1,39 +1,51 @@
1
- import path from "node:path";
2
1
  import { z } from "zod";
3
- import { browseCatalog, } from "../config/browseCatalog.js";
2
+ import { catalogPathErrorBody, CatalogPathError, resolveCatalogRelativePath, resolveCatalogStartInput, selectCatalogRootForStart, } from "../config/catalogRelativePath.js";
3
+ import { listModelsMultiProject, listPipelinesMultiProject, listTasksMultiProject, } from "../config/multiProjectCatalog.js";
4
+ import { resolveCatalogRoots } from "../config/resolveCatalogRoots.js";
4
5
  import { describePipeline } from "../config/describePipeline.js";
5
6
  import { loadPipeline } from "../config/loadPipeline.js";
6
7
  import { readYamlObject } from "../config/readYamlObject.js";
7
8
  import { validateCatalog } from "../config/validateCatalog.js";
8
- import { PACKAGE_VERSION } from "../package-meta.js";
9
- import { findProjectRoot } from "../project/findProjectRoot.js";
9
+ import { writeAudit } from "../logging/audit.js";
10
+ import { logger as rootLogger } from "../logging/logger.js";
11
+ import { PACKAGE_VERSION, BUILD_SHA } from "../package-meta.js";
12
+ import { globalStageflowHome } from "../project/globalHome.js";
13
+ import { getAuthStatus, } from "../agent/providerAuth.js";
10
14
  import { PipelineValidationError } from "../runtime/pipelineValidationError.js";
15
+ import { PipelinePreflightError } from "../runtime/pipelineRunner.js";
11
16
  import { EnvelopeRefError, resolveEnvelopeRefsToTask, } from "../runtime/resolveEnvelopeRef.js";
12
17
  import { isTerminalProjection, isWaitingProjection, waitRun } from "./waitRun.js";
13
18
  import { mapStoreLookupError } from "../server/operatorResults.js";
19
+ import { callerIdFromRequestAuth, getRequestAuth, } from "../server/requestAuthContext.js";
14
20
  import { projectRunForMcp } from "./projectRun.js";
15
21
  import { classifyArtifactContent, readRunArtifactBytes } from "./readArtifact.js";
16
22
  import { imageResult, textResult } from "./toolResults.js";
17
- /**
18
- * Every project a host serving a global store has ever recorded a run for,
19
- * plus this host's own launch directory (always included so a project with
20
- * zero runs yet still sees its own catalog).
21
- */
22
- async function catalogRootsFor(deps) {
23
- const known = await deps.store.listProjectRoots();
24
- return [...new Set([...known, deps.cwd])];
25
- }
26
- /** Resolve which project a given catalog path (pipeline/task) belongs to. */
27
- function projectRootForPath(deps, catalogPath) {
28
- const absDir = path.dirname(path.resolve(deps.cwd, catalogPath));
29
- return findProjectRoot(absDir) ?? deps.cwd;
30
- }
23
+ import { buildRunExportPayload } from "../runstore/exportRunPayload.js";
24
+ import { redactRunManifestForRead } from "../runstore/runManifest.js";
25
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
26
+ import { runSkillsDir } from "../runtime/runSkills.js";
27
+ import { listSkillsWithOrigin } from "../config/listSkills.js";
28
+ import { findTokenShapedField, pickCheckoutOverride, tokenRejectedPayload, } from "../runtime/startPayload.js";
29
+ import { loadPipelineFromObjectOutcome, loadPipelineOutcome, } from "../config/loadPipeline.js";
30
+ import { preflightFailureCode, runPipelinePreflight, } from "../preflight/pipelinePreflight.js";
31
+ import { toolchainHealthMap } from "../preflight/toolchain.js";
32
+ const auditLog = rootLogger.child({ component: "audit" });
33
+ const gitIdentitySchema = z
34
+ .object({
35
+ name: z.string().optional(),
36
+ email: z.string().optional(),
37
+ })
38
+ .strict();
31
39
  const taskFileSchema = z.object({
32
40
  id: z.string(),
33
41
  goal: z.string(),
34
42
  context: z.string().optional(),
35
43
  constraints: z.string().optional(),
36
44
  checkout: z.string().optional(),
45
+ repository: z.string().optional(),
46
+ ref: z.string().optional(),
47
+ run_branch_template: z.string().optional(),
48
+ git_identity: gitIdentitySchema.optional(),
37
49
  input: z.record(z.string(), z.unknown()).optional(),
38
50
  });
39
51
  /**
@@ -50,16 +62,35 @@ const inlinePipelineSchema = z
50
62
  agent: z.unknown().optional(),
51
63
  model: z.unknown().optional(),
52
64
  schemas: z.unknown().optional(),
65
+ requires: z.unknown().optional(),
53
66
  })
54
67
  .strict();
55
68
  const startRunSchema = z
56
69
  .object({
57
70
  pipeline: z
58
71
  .union([z.string(), inlinePipelineSchema])
59
- .describe("Filesystem path to a pipeline YAML file, or an inline pipeline definition object ({ id, stages: [...] }) authored directly in this call"),
72
+ .describe("Catalog-relative pipeline path, or an inline pipeline definition object ({ id, stages: [...] }) authored directly in this call"),
60
73
  task_path: z.string().optional(),
61
74
  task: taskFileSchema.optional(),
75
+ project_root: z.string().optional(),
76
+ checkout: z
77
+ .string()
78
+ .optional()
79
+ .describe("Catalog-relative checkout path (maps to RunManager checkoutOverride); absolute paths are rejected with absolute_path_not_allowed"),
80
+ checkout_override: z
81
+ .string()
82
+ .optional()
83
+ .describe("Alias of checkout; prefer checkout"),
84
+ skip_gates: z.boolean().optional(),
85
+ git_sha: z.string().optional(),
86
+ ci_pr_url: z.string().optional(),
87
+ ci_job_url: z.string().optional(),
88
+ skills: z
89
+ .record(z.string(), z.record(z.string(), z.string()))
90
+ .optional()
91
+ .describe("Run-scoped skills: name → { relativePath: utf-8 contents }. Requires SKILL.md per name; materialised under the run workspace skills dir (never the worktree)"),
62
92
  })
93
+ .passthrough()
63
94
  .refine((data) => Boolean(data.task_path) !== Boolean(data.task), {
64
95
  message: "Exactly one of task_path or task is required",
65
96
  });
@@ -77,7 +108,11 @@ const runStageSchema = z
77
108
  .object({
78
109
  stage: z
79
110
  .union([z.string(), z.record(z.string(), z.unknown())])
80
- .describe("Filesystem path to a stage YAML file, or a bare inline stage body object ({ id, system_prompt, io, model?, gate_kinds?, mcp?, verify?, timeout_ms? } — no uses:/route/pipeline wrapper) authored directly in this call"),
111
+ .describe("Catalog-relative path to a stage YAML file (same path contract as start_run — absolute paths rejected, must be inside a registered project_root), or a bare inline stage body object ({ id, system_prompt, io, model?, gate_kinds?, mcp?, verify?, timeout_ms? } — no uses:/route/pipeline wrapper) authored directly in this call"),
112
+ project_root: z
113
+ .string()
114
+ .optional()
115
+ .describe("Catalog project root to resolve a string stage path against; required when multiple catalog roots are configured and no sole non-seeded root exists"),
81
116
  task_path: z.string().optional(),
82
117
  task: taskFileSchema.optional(),
83
118
  envelope_ref: z
@@ -102,62 +137,134 @@ const runStageSchema = z
102
137
  .describe("Wait budget in ms when blocking is true (same bounds as wait_run)"),
103
138
  })
104
139
  .refine((data) => [data.task_path, data.task, data.envelope_ref].filter(Boolean).length === 1, { message: "Exactly one of task_path, task, or envelope_ref is required" });
105
- const runStatusSchema = z.enum(["created", "running", "succeeded", "failed"]);
140
+ const runStatusSchema = z.enum([
141
+ "created",
142
+ "queued",
143
+ "running",
144
+ "succeeded",
145
+ "failed",
146
+ "cancelled",
147
+ ]);
106
148
  export function registerCatalogTools(server, deps) {
107
- const { manager, store, cwd } = deps;
108
- server.registerTool("list_pipelines", {
109
- description: "List manifest-declared pipeline paths across every project this host knows about (this host's own project plus any project a run has ever been recorded for). Each entry is tagged with project_root. A project with no runs yet won't appear until its first run exists.",
110
- inputSchema: z.object({}),
111
- }, async () => {
112
- const roots = await catalogRootsFor(deps);
113
- const pipelines = [];
114
- for (const root of roots) {
115
- try {
116
- const catalog = await browseCatalog(root);
117
- for (const p of catalog.pipelines) {
118
- pipelines.push({ ...p, project_root: root });
119
- }
149
+ const { manager, store, cwd, providerAuthContext, providerBoot } = deps;
150
+ const agentDir = deps.agentDir ?? getAgentDir();
151
+ server.registerTool("list_skills", {
152
+ description: "List skills with name, description, and origin (run|checkout|host). Optional runId scopes to that run's resolution view (run-tier skills first, then checkout .pi/skills, then host).",
153
+ inputSchema: z.object({
154
+ runId: z.string().optional(),
155
+ }),
156
+ }, async ({ runId }) => {
157
+ try {
158
+ let runSkills;
159
+ let checkoutRoot;
160
+ if (runId !== undefined) {
161
+ const meta = await store.readRunMeta(runId);
162
+ runSkills = runSkillsDir(store.getWorkspaceDir(runId));
163
+ checkoutRoot = meta.checkout_root;
120
164
  }
121
- catch {
122
- // stale/unreadable project root recorded on an old run; skip it
165
+ const catalog = await listSkillsWithOrigin({
166
+ cwd,
167
+ agentDir,
168
+ ...(runSkills !== undefined ? { runSkillsDir: runSkills } : {}),
169
+ ...(checkoutRoot !== undefined ? { checkoutRoot } : {}),
170
+ });
171
+ return textResult({
172
+ skills: catalog.skills,
173
+ diagnostics: catalog.diagnostics,
174
+ });
175
+ }
176
+ catch (err) {
177
+ if (runId !== undefined) {
178
+ const mapped = mapStoreLookupError(err, { policy: "run" });
179
+ return textResult({ error: mapped.error, status: mapped.status }, true);
123
180
  }
181
+ throw err;
124
182
  }
125
- return textResult({ pipelines });
183
+ });
184
+ server.registerTool("list_pipelines", {
185
+ description: "List manifest-declared pipeline paths across every project this host knows about (registered store roots and seeded roots). Each entry is tagged with project_root. Optional project_root filter narrows; unknown value returns unknown_project_root.",
186
+ inputSchema: z.object({
187
+ project_root: z.string().optional(),
188
+ }),
189
+ }, async ({ project_root }) => {
190
+ const result = await listPipelinesMultiProject({
191
+ store,
192
+ bootCwd: cwd,
193
+ projectRootFilter: project_root,
194
+ });
195
+ if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
196
+ result.items.length === 0) {
197
+ return textResult({
198
+ error: result.root_errors[0].message,
199
+ code: "unknown_project_root",
200
+ root_errors: result.root_errors,
201
+ }, true);
202
+ }
203
+ return textResult({
204
+ pipelines: result.items,
205
+ root_errors: result.root_errors,
206
+ ...(result.tip !== undefined ? { tip: result.tip } : {}),
207
+ });
126
208
  });
127
209
  server.registerTool("list_tasks", {
128
- description: "List manifest-declared task paths across every project this host knows about (this host's own project plus any project a run has ever been recorded for). Each entry is tagged with project_root. A project with no runs yet won't appear until its first run exists.",
129
- inputSchema: z.object({}),
130
- }, async () => {
131
- const roots = await catalogRootsFor(deps);
132
- const tasks = [];
133
- for (const root of roots) {
134
- try {
135
- const catalog = await browseCatalog(root);
136
- for (const t of catalog.tasks) {
137
- tasks.push({ ...t, project_root: root });
138
- }
139
- }
140
- catch {
141
- // stale/unreadable project root recorded on an old run; skip it
142
- }
210
+ description: "List manifest-declared task paths across every project this host knows about (registered store roots and seeded roots). Each entry is tagged with project_root. Optional project_root filter narrows; unknown value returns unknown_project_root.",
211
+ inputSchema: z.object({
212
+ project_root: z.string().optional(),
213
+ }),
214
+ }, async ({ project_root }) => {
215
+ const result = await listTasksMultiProject({
216
+ store,
217
+ bootCwd: cwd,
218
+ projectRootFilter: project_root,
219
+ });
220
+ if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
221
+ result.items.length === 0) {
222
+ return textResult({
223
+ error: result.root_errors[0].message,
224
+ code: "unknown_project_root",
225
+ root_errors: result.root_errors,
226
+ }, true);
143
227
  }
144
- return textResult({ tasks });
228
+ return textResult({
229
+ tasks: result.items,
230
+ root_errors: result.root_errors,
231
+ ...(result.tip !== undefined ? { tip: result.tip } : {}),
232
+ });
145
233
  });
146
234
  server.registerTool("list_models", {
147
- description: "List catalog model ids from the project catalog (same source as GET /api/models)",
148
- inputSchema: z.object({}),
149
- }, async () => {
150
- const catalog = await browseCatalog(cwd);
151
- return textResult({ models: catalog.models });
235
+ description: "List catalog model ids across every project this host knows about (same multi-root source as GET /api/models). Optional project_root filter narrows.",
236
+ inputSchema: z.object({
237
+ project_root: z.string().optional(),
238
+ }),
239
+ }, async ({ project_root }) => {
240
+ const result = await listModelsMultiProject({
241
+ store,
242
+ bootCwd: cwd,
243
+ projectRootFilter: project_root,
244
+ });
245
+ if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
246
+ result.items.length === 0) {
247
+ return textResult({
248
+ error: result.root_errors[0].message,
249
+ code: "unknown_project_root",
250
+ root_errors: result.root_errors,
251
+ }, true);
252
+ }
253
+ return textResult({
254
+ models: result.models,
255
+ entries: result.items,
256
+ root_errors: result.root_errors,
257
+ });
152
258
  });
153
259
  server.registerTool("list_runs", {
154
- description: "List known pipeline runs. Optional filters: status, since (ISO created_at lower bound), pipeline (id or path).",
260
+ description: "List known pipeline runs. Optional filters: status, since (ISO created_at lower bound), pipeline (id or path), caller_id.",
155
261
  inputSchema: z.object({
156
262
  status: runStatusSchema.optional(),
157
263
  since: z.string().optional(),
158
264
  pipeline: z.string().optional(),
265
+ caller_id: z.string().optional(),
159
266
  }),
160
- }, async ({ status, since, pipeline }) => {
267
+ }, async ({ status, since, pipeline, caller_id }) => {
161
268
  const filter = {};
162
269
  if (status !== undefined)
163
270
  filter.status = status;
@@ -169,17 +276,137 @@ export function registerCatalogTools(server, deps) {
169
276
  }
170
277
  if (pipeline !== undefined)
171
278
  filter.pipeline = pipeline;
279
+ if (caller_id !== undefined)
280
+ filter.caller_id = caller_id;
172
281
  const runs = await store.listRuns(Object.keys(filter).length > 0 ? filter : undefined);
173
282
  return textResult({ runs });
174
283
  });
175
284
  server.registerTool("get_health", {
176
- description: "Server health and soft-max run capacity: activeRunIds, activeCount, maxConcurrent, slotsAvailable, version. Start until slotsAvailable is 0; then wait for a run to finish or raise STAGEFLOW_MAX_CONCURRENT_RUNS.",
285
+ description: "Server health and soft-max run capacity: activeRunIds, activeCount, maxConcurrent, slotsAvailable, activeStageProcesses, version, stageflow_home, boot_providers (Host boot snapshot), providers_live (or pointer to list_providers), plus disk breakdown for the durable root. Start until slotsAvailable is 0; then wait for a run to finish or raise STAGEFLOW_MAX_CONCURRENT_RUNS.",
177
286
  inputSchema: z.object({}),
178
- }, async () => textResult({ ...manager.getHealth(), version: PACKAGE_VERSION }));
287
+ }, async () => {
288
+ const boot_providers = providerBoot
289
+ ? {
290
+ configured: providerBoot.configured,
291
+ failures: providerBoot.failures,
292
+ }
293
+ : { configured: [], failures: [] };
294
+ let providers_live = {
295
+ configured: [],
296
+ note: "Live auth inspect — prefer list_providers / sf providers status. boot_providers is Host boot env only and may be empty when CLI credentials are configured.",
297
+ };
298
+ if (providerAuthContext !== undefined) {
299
+ try {
300
+ const status = await getAuthStatus(cwd, undefined, providerAuthContext);
301
+ const rows = Array.isArray(status) ? status : [status];
302
+ providers_live = {
303
+ configured: rows
304
+ .filter((r) => r.configured)
305
+ .map((r) => r.providerId),
306
+ note: providers_live.note,
307
+ };
308
+ }
309
+ catch {
310
+ /* keep empty configured + note */
311
+ }
312
+ }
313
+ return textResult({
314
+ ...(await manager.getHealthWithDisk()),
315
+ version: PACKAGE_VERSION,
316
+ build_sha: BUILD_SHA,
317
+ toolchain: toolchainHealthMap(),
318
+ stageflow_home: globalStageflowHome(),
319
+ boot_providers,
320
+ providers_live,
321
+ providers: boot_providers,
322
+ });
323
+ });
324
+ server.registerTool("preflight", {
325
+ description: "Check pipeline requires:/secrets:/mcp against the Host toolchain manifest and curated stage env before start_run. Accepts pipeline path or inline definition (same union as start_run). Returns { ok, checks } with status ok|missing_tool|tool_version_mismatch|unknown_version|secret_unavailable|unresolved_var. Does not create a Run. unknown_version is ok unless strict:true.",
326
+ inputSchema: z.object({
327
+ pipeline: z
328
+ .union([z.string(), inlinePipelineSchema])
329
+ .describe("Catalog-relative pipeline path, or an inline pipeline definition object"),
330
+ project_root: z.string().optional(),
331
+ strict: z
332
+ .boolean()
333
+ .optional()
334
+ .describe("When true, unknown_version fails (default false)"),
335
+ }),
336
+ }, async ({ pipeline, project_root, strict }) => {
337
+ const roots = await resolveCatalogRoots({
338
+ store: deps.store,
339
+ bootCwd: deps.cwd,
340
+ });
341
+ let loaded;
342
+ let projectRoot;
343
+ try {
344
+ const wireRoot = selectCatalogRootForStart(roots, project_root);
345
+ projectRoot = wireRoot.project_root;
346
+ if (typeof pipeline === "string") {
347
+ const resolved = resolveCatalogRelativePath({
348
+ inputPath: pipeline,
349
+ projectRoot: project_root,
350
+ roots,
351
+ fieldName: "pipeline",
352
+ });
353
+ projectRoot = resolved.root.project_root;
354
+ const outcome = await loadPipelineOutcome(resolved.absolutePath, {
355
+ cwd: deps.cwd,
356
+ projectRoot,
357
+ });
358
+ if (!outcome.ok) {
359
+ return textResult({
360
+ ok: false,
361
+ error: outcome.issues[0]?.message ?? "pipeline load failed",
362
+ code: outcome.issues[0]?.code ?? "config_invalid",
363
+ issues: outcome.issues,
364
+ }, true);
365
+ }
366
+ loaded = outcome.value;
367
+ }
368
+ else {
369
+ const outcome = await loadPipelineFromObjectOutcome(pipeline, {
370
+ cwd: deps.cwd,
371
+ projectRoot,
372
+ });
373
+ if (!outcome.ok) {
374
+ return textResult({
375
+ ok: false,
376
+ error: outcome.issues[0]?.message ?? "pipeline load failed",
377
+ code: outcome.issues[0]?.code ?? "config_invalid",
378
+ issues: outcome.issues,
379
+ }, true);
380
+ }
381
+ loaded = outcome.value;
382
+ }
383
+ }
384
+ catch (err) {
385
+ if (err instanceof CatalogPathError) {
386
+ return textResult(catalogPathErrorBody(err), true);
387
+ }
388
+ throw err;
389
+ }
390
+ const result = await runPipelinePreflight(loaded, {
391
+ projectRoot,
392
+ strict: strict === true,
393
+ });
394
+ const code = preflightFailureCode(result, { strict: strict === true });
395
+ return textResult({
396
+ ok: result.ok,
397
+ checks: result.checks,
398
+ ...(code !== undefined ? { code } : {}),
399
+ });
400
+ });
179
401
  server.registerTool("start_run", {
180
- description: "Start a pipeline run using a filesystem pipeline path or an inline pipeline definition ({ id, stages: [...] }, each stage the same shape as a YAML stage body — no uses: refs), and either task_path (catalog task file) or an inline task object. Returns { runId }. On conflict returns isError with code busy_capacity (soft max full) or busy_checkout (same checkout leased), plus activeCount/maxConcurrent/activeRunIds and optional conflictingRunId/conflictingCheckout.",
402
+ description: "Start a pipeline run. Accepted params: pipeline (catalog-relative path or inline { id, stages: [...] } — stages are YAML stage bodies, no uses: refs), task_path XOR task (inline task may include repository/ref or checkout; repository XOR checkout with code task.binding_conflict), project_root, checkout (catalog-relative; prefer this name; absolute → absolute_path_not_allowed), checkout_override (alias of checkout), skip_gates, git_sha, ci_pr_url, ci_job_url, skills (name → { relativePath: utf-8 contents }; requires SKILL.md; materialised under runs/<runId>/skills/, never the worktree). REST POST /api/runs accepts path pipelines only (no inline pipeline). Returns { runId } or { runId, queued: true, queuePosition }. Errors: busy_capacity, busy_checkout, insufficient_disk, start.token_rejected, skills_*, inline_pipeline_too_large, catalog path-contract codes.",
181
403
  inputSchema: startRunSchema,
182
- }, async ({ pipeline, task_path, task }) => {
404
+ }, async (args) => {
405
+ const tokenField = findTokenShapedField(args);
406
+ if (tokenField !== undefined) {
407
+ return textResult(tokenRejectedPayload(tokenField), true);
408
+ }
409
+ const { pipeline, task_path, task, project_root, checkout, checkout_override, skip_gates, git_sha, ci_pr_url, ci_job_url, skills, } = args;
183
410
  if (typeof pipeline === "string" && !pipeline.trim()) {
184
411
  return textResult({ error: "pipeline is required" }, true);
185
412
  }
@@ -187,26 +414,130 @@ export function registerCatalogTools(server, deps) {
187
414
  if (taskInput === undefined) {
188
415
  return textResult({ error: "Exactly one of task_path or task is required" }, true);
189
416
  }
417
+ let wireRoot;
418
+ let roots;
419
+ try {
420
+ ({ wireRoot, roots } = await resolveCatalogStartInput({ store: deps.store, bootCwd: deps.cwd }, project_root));
421
+ }
422
+ catch (err) {
423
+ if (err instanceof CatalogPathError) {
424
+ return textResult(catalogPathErrorBody(err), true);
425
+ }
426
+ throw err;
427
+ }
428
+ const wireProjectRoot = wireRoot.project_root;
429
+ let resolvedPipeline = pipeline;
430
+ let resolvedTask = taskInput;
431
+ let resolvedCheckout;
432
+ try {
433
+ if (typeof pipeline === "string") {
434
+ resolvedPipeline = resolveCatalogRelativePath({
435
+ inputPath: pipeline,
436
+ projectRoot: wireProjectRoot,
437
+ roots,
438
+ fieldName: "pipeline",
439
+ }).absolutePath;
440
+ }
441
+ if (typeof task_path === "string") {
442
+ resolvedTask = resolveCatalogRelativePath({
443
+ inputPath: task_path,
444
+ projectRoot: wireProjectRoot,
445
+ roots,
446
+ fieldName: "task_path",
447
+ }).absolutePath;
448
+ }
449
+ const rawCheckout = pickCheckoutOverride({ checkout, checkout_override });
450
+ if (rawCheckout !== undefined) {
451
+ resolvedCheckout = resolveCatalogRelativePath({
452
+ inputPath: rawCheckout,
453
+ projectRoot: wireProjectRoot,
454
+ roots,
455
+ fieldName: "checkout",
456
+ }).absolutePath;
457
+ }
458
+ }
459
+ catch (err) {
460
+ if (err instanceof CatalogPathError) {
461
+ return textResult(catalogPathErrorBody(err), true);
462
+ }
463
+ throw err;
464
+ }
465
+ const callerId = callerIdFromRequestAuth();
190
466
  let result;
191
467
  try {
192
- result = await manager.startRun({ pipeline, task: taskInput });
468
+ result = await manager.startRun({
469
+ pipeline: resolvedPipeline,
470
+ task: resolvedTask,
471
+ projectRoot: wireRoot.path,
472
+ ...(resolvedCheckout !== undefined
473
+ ? { checkoutOverride: resolvedCheckout }
474
+ : {}),
475
+ ...(skip_gates !== undefined ? { skipGates: skip_gates } : {}),
476
+ ...(git_sha !== undefined ? { gitSha: git_sha } : {}),
477
+ ...(ci_pr_url !== undefined ? { ciPrUrl: ci_pr_url } : {}),
478
+ ...(ci_job_url !== undefined ? { ciJobUrl: ci_job_url } : {}),
479
+ ...(skills !== undefined ? { skills } : {}),
480
+ callerId,
481
+ });
193
482
  }
194
483
  catch (err) {
195
484
  if (err instanceof PipelineValidationError) {
485
+ writeAudit(auditLog, {
486
+ caller_id: callerId,
487
+ surface: getRequestAuth()?.surface ?? "mcp",
488
+ action: "start_run",
489
+ outcome: "error",
490
+ error_code: "pipeline_validation",
491
+ });
196
492
  return textResult({ error: "Pipeline validation failed", validation: err.result }, true);
197
493
  }
494
+ if (err instanceof PipelinePreflightError) {
495
+ writeAudit(auditLog, {
496
+ caller_id: callerId,
497
+ surface: getRequestAuth()?.surface ?? "mcp",
498
+ action: "start_run",
499
+ outcome: "error",
500
+ error_code: err.code,
501
+ });
502
+ return textResult(err.toNetworkBody(), true);
503
+ }
198
504
  throw err;
199
505
  }
200
506
  if (!result.ok) {
507
+ writeAudit(auditLog, {
508
+ caller_id: callerId,
509
+ surface: getRequestAuth()?.surface ?? "mcp",
510
+ action: "start_run",
511
+ outcome: "error",
512
+ error_code: result.code,
513
+ });
201
514
  const { ok: _ok, reason, ...rest } = result;
202
515
  return textResult({ error: reason, ...rest }, true);
203
516
  }
204
- return textResult({ runId: result.runId });
517
+ writeAudit(auditLog, {
518
+ caller_id: callerId,
519
+ surface: getRequestAuth()?.surface ?? "mcp",
520
+ action: "start_run",
521
+ target_run_id: result.runId,
522
+ outcome: "ok",
523
+ });
524
+ return textResult({
525
+ runId: result.runId,
526
+ ...(result.queued === true
527
+ ? {
528
+ queued: true,
529
+ queuePosition: result.queuePosition,
530
+ ...(result.queuedCode !== undefined
531
+ ? { queuedCode: result.queuedCode }
532
+ : {}),
533
+ }
534
+ : {}),
535
+ });
205
536
  });
206
537
  server.registerTool("run_stage", {
207
538
  description: "Run a single stage directly, without authoring a pipeline. `stage` is a filesystem path to a stage YAML file, or a bare inline stage body ({ id, system_prompt, io, model?, gate_kinds?, mcp?, verify?, timeout_ms? } — no uses:/route/pipeline wrapper), and exactly one of task_path, an inline task, or envelope_ref ({ runId, stageId, attempt? }) to resolve a previously stored envelope — from another run_stage call or any stage in a full pipeline run — as this stage's input. Internally this synthesizes a one-stage pipeline and executes it through the normal run path, so it shows up in list_runs/get_run and is polled with wait_run / get_envelope exactly like any other run. By default returns { runId, stageId } immediately (async); pass blocking:true to wait in this same call and get back { runId, stageId, status: \"completed\"|\"needs_input\"|\"timeout\", envelope? , pending_prompt? }.",
208
539
  inputSchema: runStageSchema,
209
- }, async ({ stage, task_path, task, envelope_ref, checkout, model, blocking, timeout_ms }) => {
540
+ }, async ({ stage, project_root, task_path, task, envelope_ref, checkout, model, blocking, timeout_ms }) => {
210
541
  let taskInput = task_path ?? task;
211
542
  if (envelope_ref) {
212
543
  try {
@@ -223,11 +554,28 @@ export function registerCatalogTools(server, deps) {
223
554
  return textResult({ error: "Exactly one of task_path, task, or envelope_ref is required" }, true);
224
555
  }
225
556
  let stageBody;
557
+ let stageProjectRoot;
226
558
  if (typeof stage === "string") {
227
559
  if (!stage.trim()) {
228
560
  return textResult({ error: "stage is required" }, true);
229
561
  }
230
- const absPath = path.resolve(cwd, stage);
562
+ let absPath = "";
563
+ try {
564
+ const { wireRoot, roots } = await resolveCatalogStartInput({ store: deps.store, bootCwd: deps.cwd }, project_root);
565
+ stageProjectRoot = wireRoot.path;
566
+ absPath = resolveCatalogRelativePath({
567
+ inputPath: stage,
568
+ projectRoot: wireRoot.project_root,
569
+ roots,
570
+ fieldName: "stage",
571
+ }).absolutePath;
572
+ }
573
+ catch (err) {
574
+ if (err instanceof CatalogPathError) {
575
+ return textResult(catalogPathErrorBody(err), true);
576
+ }
577
+ throw err;
578
+ }
231
579
  try {
232
580
  stageBody = await readYamlObject(absPath);
233
581
  }
@@ -254,7 +602,11 @@ export function registerCatalogTools(server, deps) {
254
602
  };
255
603
  let result;
256
604
  try {
257
- result = await manager.startRun({ pipeline, task: taskInput });
605
+ result = await manager.startRun({
606
+ pipeline,
607
+ task: taskInput,
608
+ ...(stageProjectRoot !== undefined ? { projectRoot: stageProjectRoot } : {}),
609
+ });
258
610
  }
259
611
  catch (err) {
260
612
  if (err instanceof PipelineValidationError) {
@@ -308,7 +660,25 @@ export function registerCatalogTools(server, deps) {
308
660
  }, async ({ runId }) => {
309
661
  try {
310
662
  const detail = await store.readRun(runId);
311
- return textResult(projectRunForMcp(detail));
663
+ return textResult({
664
+ ...projectRunForMcp(detail),
665
+ run_manifest: redactRunManifestForRead(detail.run_manifest),
666
+ });
667
+ }
668
+ catch (err) {
669
+ const mapped = mapStoreLookupError(err, { policy: "run" });
670
+ return textResult({ error: mapped.error, status: mapped.status }, true);
671
+ }
672
+ });
673
+ server.registerTool("export_run", {
674
+ description: "Export a single run as projectRun projection plus run_manifest. Works for running, cancelled, and terminal runs. Prefer over CLI sf export-run when the Host is reachable.",
675
+ inputSchema: z.object({
676
+ runId: z.string(),
677
+ }),
678
+ }, async ({ runId }) => {
679
+ try {
680
+ const detail = await store.readRun(runId);
681
+ return textResult(buildRunExportPayload(detail));
312
682
  }
313
683
  catch (err) {
314
684
  const mapped = mapStoreLookupError(err, { policy: "run" });
@@ -361,14 +731,21 @@ export function registerCatalogTools(server, deps) {
361
731
  else if (task !== undefined && task.trim())
362
732
  scope = "task";
363
733
  if (scope === "full") {
364
- const roots = await catalogRootsFor(deps);
734
+ const roots = await resolveCatalogRoots({
735
+ store: deps.store,
736
+ bootCwd: deps.cwd,
737
+ });
365
738
  const results = [];
366
739
  for (const root of roots) {
367
740
  try {
368
- results.push(await validateCatalog({ cwd: root, scope: "full", strict: strict ?? false }));
741
+ results.push(await validateCatalog({
742
+ cwd: root.path,
743
+ scope: "full",
744
+ strict: strict ?? false,
745
+ }));
369
746
  }
370
747
  catch {
371
- // stale/unreadable project root recorded on an old run; skip it
748
+ // unreadable root; skip
372
749
  }
373
750
  }
374
751
  const merged = {
@@ -383,13 +760,33 @@ export function registerCatalogTools(server, deps) {
383
760
  return textResult(merged);
384
761
  }
385
762
  const target = scope === "pipeline" ? pipeline.trim() : task.trim();
386
- const projectRoot = projectRootForPath(deps, target);
763
+ const roots = await resolveCatalogRoots({
764
+ store: deps.store,
765
+ bootCwd: deps.cwd,
766
+ });
767
+ let resolvedTarget = target;
768
+ let projectRoot = deps.cwd;
769
+ try {
770
+ const resolved = resolveCatalogRelativePath({
771
+ inputPath: target,
772
+ roots,
773
+ fieldName: scope === "pipeline" ? "pipeline" : "task",
774
+ });
775
+ resolvedTarget = resolved.absolutePath;
776
+ projectRoot = resolved.root.path;
777
+ }
778
+ catch (err) {
779
+ if (err instanceof CatalogPathError) {
780
+ return textResult(catalogPathErrorBody(err), true);
781
+ }
782
+ throw err;
783
+ }
387
784
  const result = await validateCatalog({
388
785
  cwd: projectRoot,
389
786
  scope,
390
787
  projectRoot,
391
- ...(scope === "pipeline" ? { pipeline: target } : {}),
392
- ...(scope === "task" ? { task: target } : {}),
788
+ ...(scope === "pipeline" ? { pipeline: resolvedTarget } : {}),
789
+ ...(scope === "task" ? { task: resolvedTarget } : {}),
393
790
  strict: strict ?? false,
394
791
  });
395
792
  return textResult(result);
@@ -400,23 +797,37 @@ export function registerCatalogTools(server, deps) {
400
797
  }
401
798
  });
402
799
  server.registerTool("describe_pipeline", {
403
- description: "Describe a pipeline DAG from a filesystem path (same as start_run): stages with inbound needs (id, on, optional if), fork, gate_kinds, Clone Chain clone_cap and clone_mode, and feedback_loop, entry, and replay_safe when set.",
800
+ description: "Describe a pipeline DAG from a catalog-relative path (same path contract as start_run): stages with inbound needs (id, on, optional if), fork, gate_kinds, Clone Chain clone_cap and clone_mode, and feedback_loop, entry, and replay_safe when set.",
404
801
  inputSchema: z.object({
405
802
  pipeline: z.string(),
803
+ project_root: z.string().optional(),
406
804
  }),
407
- }, async ({ pipeline }) => {
805
+ }, async ({ pipeline, project_root }) => {
408
806
  if (!pipeline.trim()) {
409
807
  return textResult({ error: "pipeline is required", status: 400 }, true);
410
808
  }
411
809
  try {
412
- const loaded = await loadPipeline(pipeline.trim(), {
413
- cwd: projectRootForPath(deps, pipeline.trim()),
810
+ const roots = await resolveCatalogRoots({
811
+ store: deps.store,
812
+ bootCwd: deps.cwd,
813
+ });
814
+ const resolved = resolveCatalogRelativePath({
815
+ inputPath: pipeline.trim(),
816
+ projectRoot: project_root,
817
+ roots,
818
+ fieldName: "pipeline",
819
+ });
820
+ const loaded = await loadPipeline(resolved.absolutePath, {
821
+ projectRoot: resolved.root.path,
414
822
  });
415
823
  return textResult(describePipeline(loaded));
416
824
  }
417
825
  catch (err) {
826
+ if (err instanceof CatalogPathError) {
827
+ return textResult(catalogPathErrorBody(err), true);
828
+ }
418
829
  const message = err instanceof Error ? err.message : String(err);
419
- return textResult({ error: message, status: 404 }, true);
830
+ return textResult({ error: message, status: 400 }, true);
420
831
  }
421
832
  });
422
833
  }