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
@@ -13,8 +13,8 @@
13
13
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Figtree:wght@400;500;600;700&display=swap" />
14
14
  <link rel="icon" type="image/svg+xml" href="/stageflow-icon.svg" />
15
15
  <title>Stageflow</title>
16
- <script type="module" crossorigin src="/assets/index-Da5EHU6M.js"></script>
17
- <link rel="stylesheet" crossorigin href="/assets/index-CSsDued1.css">
16
+ <script type="module" crossorigin src="/assets/index-CntB4bZR.js"></script>
17
+ <link rel="stylesheet" crossorigin href="/assets/index-Bv4p1aPK.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -0,0 +1,58 @@
1
+ import type { DraftPackage } from "../config/draftPackage.js";
2
+ export declare const WORKSHOP_UNTITLED_AUTOSAVE_KEY = "__untitled__";
3
+ export type WorkshopAutosaveChatMessage = {
4
+ id: string;
5
+ role: "assistant" | "user" | "system";
6
+ text: string;
7
+ artifacts?: unknown;
8
+ };
9
+ export type WorkshopAutosaveDestination = {
10
+ directory: string;
11
+ pipelineFilename?: string;
12
+ };
13
+ export type WorkshopAutosaveRecord = {
14
+ version: 1;
15
+ key: string;
16
+ updatedAt: string;
17
+ draft: DraftPackage;
18
+ messages: WorkshopAutosaveChatMessage[];
19
+ autoApply: boolean;
20
+ sessionModelOverride?: string | null;
21
+ destination?: WorkshopAutosaveDestination | null;
22
+ savedPath?: string | null;
23
+ savedTaskPath?: string | null;
24
+ diskFingerprints?: Record<string, string>;
25
+ };
26
+ export declare function workshopAutosaveSlotKey(pipelinePath: string | null | undefined): string;
27
+ export declare function resolveWorkshopAutosaveStoreRoot(options: {
28
+ projectRoot?: string | null;
29
+ isGitProject?: boolean;
30
+ }): string;
31
+ export declare function workshopAutosaveDir(storeRoot: string): string;
32
+ export declare function workshopAutosaveFilePath(storeRoot: string, key: string): string;
33
+ export declare function parseWorkshopAutosaveRecord(value: unknown): WorkshopAutosaveRecord | null;
34
+ export declare function readWorkshopAutosave(storeRoot: string, key: string): WorkshopAutosaveRecord | null;
35
+ export declare function writeWorkshopAutosave(storeRoot: string, record: WorkshopAutosaveRecord): WorkshopAutosaveRecord;
36
+ export declare function clearWorkshopAutosave(storeRoot: string, key: string): boolean;
37
+ export declare function fingerprintPath(filePath: string): string | null;
38
+ export declare function draftPackageDiskRelativePaths(input: {
39
+ pipelinePath: string;
40
+ draft: DraftPackage;
41
+ taskPath?: string | null;
42
+ }): string[];
43
+ export declare function fingerprintPackageFiles(projectRoot: string, relativePaths: readonly string[]): Record<string, string>;
44
+ export declare function detectDiskChange(input: {
45
+ baseline?: Record<string, string> | null;
46
+ current: Record<string, string>;
47
+ }): {
48
+ changed: boolean;
49
+ changedPaths: string[];
50
+ };
51
+ export type DiskChangeDecision = "reload" | "keep";
52
+ export declare function applyDiskChangeDecision(input: {
53
+ decision: DiskChangeDecision;
54
+ currentFingerprints: Record<string, string>;
55
+ }): {
56
+ clearAutosave: boolean;
57
+ nextFingerprints: Record<string, string>;
58
+ };
@@ -0,0 +1,222 @@
1
+ import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
2
+ import path from "node:path";
3
+ import { globalStageflowHome } from "../project/globalHome.js";
4
+ import { storeRootFor } from "../runstore/paths.js";
5
+ export const WORKSHOP_UNTITLED_AUTOSAVE_KEY = "__untitled__";
6
+ export function workshopAutosaveSlotKey(pipelinePath) {
7
+ const trimmed = pipelinePath?.trim();
8
+ if (!trimmed)
9
+ return WORKSHOP_UNTITLED_AUTOSAVE_KEY;
10
+ return trimmed.replace(/\\/g, "/");
11
+ }
12
+ export function resolveWorkshopAutosaveStoreRoot(options) {
13
+ const root = options.projectRoot?.trim();
14
+ if (root && options.isGitProject !== false) {
15
+ return storeRootFor(path.resolve(root));
16
+ }
17
+ return globalStageflowHome();
18
+ }
19
+ export function workshopAutosaveDir(storeRoot) {
20
+ return path.join(storeRoot, "workshop", "autosave");
21
+ }
22
+ export function workshopAutosaveFilePath(storeRoot, key) {
23
+ const safe = Buffer.from(workshopAutosaveSlotKey(key), "utf8").toString("base64url");
24
+ return path.join(workshopAutosaveDir(storeRoot), `${safe}.json`);
25
+ }
26
+ function isPlainObject(value) {
27
+ return value !== null && typeof value === "object" && !Array.isArray(value);
28
+ }
29
+ function parseChatMessage(value) {
30
+ if (!isPlainObject(value))
31
+ return null;
32
+ if (typeof value.id !== "string" || !value.id)
33
+ return null;
34
+ if (value.role !== "assistant" &&
35
+ value.role !== "user" &&
36
+ value.role !== "system") {
37
+ return null;
38
+ }
39
+ if (typeof value.text !== "string")
40
+ return null;
41
+ const msg = {
42
+ id: value.id,
43
+ role: value.role,
44
+ text: value.text,
45
+ };
46
+ if (value.artifacts !== undefined) {
47
+ msg.artifacts = value.artifacts;
48
+ }
49
+ return msg;
50
+ }
51
+ export function parseWorkshopAutosaveRecord(value) {
52
+ if (!isPlainObject(value))
53
+ return null;
54
+ if (value.version !== 1)
55
+ return null;
56
+ if (typeof value.key !== "string" || !value.key)
57
+ return null;
58
+ if (typeof value.updatedAt !== "string" || !value.updatedAt)
59
+ return null;
60
+ if (!isPlainObject(value.draft))
61
+ return null;
62
+ if (!isPlainObject(value.draft.pipeline))
63
+ return null;
64
+ if (!Array.isArray(value.messages))
65
+ return null;
66
+ if (typeof value.autoApply !== "boolean")
67
+ return null;
68
+ const messages = [];
69
+ for (const entry of value.messages) {
70
+ const msg = parseChatMessage(entry);
71
+ if (!msg)
72
+ return null;
73
+ messages.push(msg);
74
+ }
75
+ const record = {
76
+ version: 1,
77
+ key: value.key,
78
+ updatedAt: value.updatedAt,
79
+ draft: value.draft,
80
+ messages,
81
+ autoApply: value.autoApply,
82
+ };
83
+ if (value.sessionModelOverride === null ||
84
+ typeof value.sessionModelOverride === "string") {
85
+ record.sessionModelOverride = value.sessionModelOverride;
86
+ }
87
+ if (value.destination === null) {
88
+ record.destination = null;
89
+ }
90
+ else if (isPlainObject(value.destination)) {
91
+ if (typeof value.destination.directory !== "string")
92
+ return null;
93
+ record.destination = {
94
+ directory: value.destination.directory,
95
+ ...(typeof value.destination.pipelineFilename === "string"
96
+ ? { pipelineFilename: value.destination.pipelineFilename }
97
+ : {}),
98
+ };
99
+ }
100
+ if (value.savedPath === null || typeof value.savedPath === "string") {
101
+ record.savedPath = value.savedPath;
102
+ }
103
+ if (value.savedTaskPath === null || typeof value.savedTaskPath === "string") {
104
+ record.savedTaskPath = value.savedTaskPath;
105
+ }
106
+ if (value.diskFingerprints !== undefined) {
107
+ if (!isPlainObject(value.diskFingerprints))
108
+ return null;
109
+ const fps = {};
110
+ for (const [k, v] of Object.entries(value.diskFingerprints)) {
111
+ if (typeof v !== "string")
112
+ return null;
113
+ fps[k] = v;
114
+ }
115
+ record.diskFingerprints = fps;
116
+ }
117
+ return record;
118
+ }
119
+ export function readWorkshopAutosave(storeRoot, key) {
120
+ const filePath = workshopAutosaveFilePath(storeRoot, key);
121
+ if (!existsSync(filePath))
122
+ return null;
123
+ try {
124
+ const raw = JSON.parse(readFileSync(filePath, "utf8"));
125
+ const parsed = parseWorkshopAutosaveRecord(raw);
126
+ if (!parsed)
127
+ return null;
128
+ if (parsed.key !== workshopAutosaveSlotKey(key))
129
+ return null;
130
+ return parsed;
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ }
136
+ export function writeWorkshopAutosave(storeRoot, record) {
137
+ const key = workshopAutosaveSlotKey(record.key);
138
+ const next = {
139
+ ...record,
140
+ version: 1,
141
+ key,
142
+ updatedAt: record.updatedAt || new Date().toISOString(),
143
+ };
144
+ const dir = workshopAutosaveDir(storeRoot);
145
+ mkdirSync(dir, { recursive: true });
146
+ writeFileSync(workshopAutosaveFilePath(storeRoot, key), `${JSON.stringify(next, null, 2)}\n`, "utf8");
147
+ return next;
148
+ }
149
+ export function clearWorkshopAutosave(storeRoot, key) {
150
+ const filePath = workshopAutosaveFilePath(storeRoot, key);
151
+ if (!existsSync(filePath))
152
+ return false;
153
+ unlinkSync(filePath);
154
+ return true;
155
+ }
156
+ export function fingerprintPath(filePath) {
157
+ if (!existsSync(filePath))
158
+ return null;
159
+ const st = statSync(filePath);
160
+ return `${st.size}:${Math.trunc(st.mtimeMs)}`;
161
+ }
162
+ export function draftPackageDiskRelativePaths(input) {
163
+ const pipelinePath = input.pipelinePath.trim().replace(/\\/g, "/");
164
+ const paths = [pipelinePath];
165
+ const packageDir = path.posix.dirname(pipelinePath);
166
+ for (const stage of input.draft.stages ?? []) {
167
+ if (typeof stage.path !== "string" || !stage.path.trim())
168
+ continue;
169
+ const joined = path.posix
170
+ .normalize(path.posix.join(packageDir, stage.path.trim().replace(/\\/g, "/")))
171
+ .replace(/^\.\//, "");
172
+ paths.push(joined);
173
+ }
174
+ if (input.taskPath?.trim()) {
175
+ paths.push(input.taskPath.trim().replace(/\\/g, "/"));
176
+ }
177
+ return [...new Set(paths)];
178
+ }
179
+ export function fingerprintPackageFiles(projectRoot, relativePaths) {
180
+ const out = {};
181
+ const root = path.resolve(projectRoot);
182
+ for (const rel of relativePaths) {
183
+ const abs = path.resolve(root, rel);
184
+ const relToRoot = path.relative(root, abs);
185
+ if (relToRoot.startsWith("..") || path.isAbsolute(relToRoot)) {
186
+ out[rel] = "escaped";
187
+ continue;
188
+ }
189
+ out[rel] = fingerprintPath(abs) ?? "missing";
190
+ }
191
+ return out;
192
+ }
193
+ export function detectDiskChange(input) {
194
+ const baseline = input.baseline;
195
+ if (!baseline || Object.keys(baseline).length === 0) {
196
+ return { changed: false, changedPaths: [] };
197
+ }
198
+ const keys = new Set([
199
+ ...Object.keys(baseline),
200
+ ...Object.keys(input.current),
201
+ ]);
202
+ const changedPaths = [];
203
+ for (const key of keys) {
204
+ if ((baseline[key] ?? "missing") !== (input.current[key] ?? "missing")) {
205
+ changedPaths.push(key);
206
+ }
207
+ }
208
+ changedPaths.sort();
209
+ return { changed: changedPaths.length > 0, changedPaths };
210
+ }
211
+ export function applyDiskChangeDecision(input) {
212
+ if (input.decision === "reload") {
213
+ return {
214
+ clearAutosave: true,
215
+ nextFingerprints: input.currentFingerprints,
216
+ };
217
+ }
218
+ return {
219
+ clearAutosave: false,
220
+ nextFingerprints: input.currentFingerprints,
221
+ };
222
+ }
@@ -0,0 +1,79 @@
1
+ import { type DraftPackage } from "../config/draftPackage.js";
2
+ export type WorkshopBuildRecord = {
3
+ version: 1;
4
+ id: string;
5
+ createdAt: string;
6
+ updatedAt: string;
7
+ draft: DraftPackage;
8
+ projectRoot: string | null;
9
+ relativePath: string | null;
10
+ };
11
+ export type WorkshopBuildSummary = {
12
+ id: string;
13
+ createdAt: string;
14
+ updatedAt: string;
15
+ projectRoot: string | null;
16
+ relativePath: string | null;
17
+ };
18
+ export type WorkshopBuildCreateInput = {
19
+ draft: DraftPackage;
20
+ id?: string;
21
+ now?: Date;
22
+ projectRoot?: string | null;
23
+ relativePath?: string | null;
24
+ };
25
+ export type WorkshopBuildUpdate = {
26
+ draft?: DraftPackage;
27
+ projectRoot?: string | null;
28
+ relativePath?: string | null;
29
+ };
30
+ export type WorkshopBuildStoreErrorCode = "workshop_build_not_found";
31
+ export declare class WorkshopBuildStoreError extends Error {
32
+ readonly code: WorkshopBuildStoreErrorCode;
33
+ readonly buildId?: string;
34
+ constructor(message: string, code: WorkshopBuildStoreErrorCode, buildId?: string);
35
+ }
36
+ export declare function resolveWorkshopBuildStoreRoot(): string;
37
+ export declare function workshopBuildsDir(storeRoot: string): string;
38
+ export declare function workshopBuildFilePath(storeRoot: string, buildId: string): string;
39
+ export declare function parseWorkshopBuildRecord(value: unknown): WorkshopBuildRecord | null;
40
+ export declare function readWorkshopBuild(storeRoot: string, buildId: string): WorkshopBuildRecord | null;
41
+ export declare function createWorkshopBuild(storeRoot: string, input: WorkshopBuildCreateInput): WorkshopBuildRecord;
42
+ export declare function getWorkshopBuild(storeRoot: string, buildId: string): WorkshopBuildRecord;
43
+ export declare function listWorkshopBuilds(storeRoot: string): WorkshopBuildSummary[];
44
+ export type WorkshopPickerCatalogPipeline = {
45
+ project_root: string;
46
+ path: string;
47
+ id: string;
48
+ };
49
+ export declare function resolvePickerCatalogPipelines(items: readonly WorkshopPickerCatalogPipeline[], roots: readonly {
50
+ project_root: string;
51
+ path: string;
52
+ }[]): WorkshopPickerCatalogPipeline[];
53
+ export type WorkshopPickerRow = {
54
+ id: string | null;
55
+ name: string;
56
+ projectRoot: string | null;
57
+ relativePath: string | null;
58
+ };
59
+ export type FocusUnboundWorkshopBuildInput = {
60
+ projectRoot: string;
61
+ relativePath: string;
62
+ };
63
+ export type FocusUnboundWorkshopBuildResult = {
64
+ ok: true;
65
+ created: boolean;
66
+ build: WorkshopBuildRecord;
67
+ } | {
68
+ ok: false;
69
+ status: 400 | 404;
70
+ error: string;
71
+ };
72
+ export declare function listWorkshopPickerRows(storeRoot: string, pipelines: ReadonlyArray<WorkshopPickerCatalogPipeline>, roots?: readonly {
73
+ project_root: string;
74
+ path: string;
75
+ }[]): WorkshopPickerRow[];
76
+ export declare function focusUnboundWorkshopBuild(storeRoot: string, input: FocusUnboundWorkshopBuildInput): Promise<FocusUnboundWorkshopBuildResult>;
77
+ export declare function updateWorkshopBuild(storeRoot: string, buildId: string, patch: WorkshopBuildUpdate, options?: {
78
+ now?: Date;
79
+ }): WorkshopBuildRecord;
@@ -0,0 +1,326 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, } from "node:fs";
3
+ import path from "node:path";
4
+ import { loadDraftPackage, parseDraftPackageBody, } from "../config/draftPackage.js";
5
+ import { globalStageflowHome } from "../project/globalHome.js";
6
+ export class WorkshopBuildStoreError extends Error {
7
+ code;
8
+ buildId;
9
+ constructor(message, code, buildId) {
10
+ super(message);
11
+ this.name = "WorkshopBuildStoreError";
12
+ this.code = code;
13
+ if (buildId !== undefined)
14
+ this.buildId = buildId;
15
+ }
16
+ }
17
+ export function resolveWorkshopBuildStoreRoot() {
18
+ return globalStageflowHome();
19
+ }
20
+ export function workshopBuildsDir(storeRoot) {
21
+ return path.join(storeRoot, "workshop", "builds");
22
+ }
23
+ export function workshopBuildFilePath(storeRoot, buildId) {
24
+ return path.join(workshopBuildsDir(storeRoot), `${guardBuildId(buildId)}.json`);
25
+ }
26
+ function guardBuildId(buildId) {
27
+ const trimmed = buildId.trim();
28
+ if (!trimmed ||
29
+ trimmed.includes("/") ||
30
+ trimmed.includes("\\") ||
31
+ trimmed.includes("..") ||
32
+ trimmed === ".") {
33
+ throw new Error(`invalid workshop build id: ${buildId}`);
34
+ }
35
+ return trimmed;
36
+ }
37
+ function isPlainObject(value) {
38
+ return value !== null && typeof value === "object" && !Array.isArray(value);
39
+ }
40
+ function normalizeTie(value) {
41
+ if (value == null)
42
+ return null;
43
+ const trimmed = value.trim();
44
+ return trimmed ? trimmed : null;
45
+ }
46
+ function parseTieField(value) {
47
+ if (value === undefined || value === null)
48
+ return null;
49
+ if (typeof value !== "string")
50
+ return undefined;
51
+ return normalizeTie(value);
52
+ }
53
+ function parseStoredDraft(value) {
54
+ const parsed = parseDraftPackageBody(value);
55
+ if ("ok" in parsed)
56
+ return null;
57
+ return parsed;
58
+ }
59
+ export function parseWorkshopBuildRecord(value) {
60
+ if (!isPlainObject(value))
61
+ return null;
62
+ if (value.version !== 1)
63
+ return null;
64
+ if (typeof value.id !== "string" || !value.id)
65
+ return null;
66
+ if (typeof value.createdAt !== "string" || !value.createdAt)
67
+ return null;
68
+ if (typeof value.updatedAt !== "string" || !value.updatedAt)
69
+ return null;
70
+ const draft = parseStoredDraft(value.draft);
71
+ if (!draft)
72
+ return null;
73
+ const projectRoot = parseTieField(value.projectRoot);
74
+ if (projectRoot === undefined)
75
+ return null;
76
+ const relativePath = parseTieField(value.relativePath);
77
+ if (relativePath === undefined)
78
+ return null;
79
+ return {
80
+ version: 1,
81
+ id: value.id,
82
+ createdAt: value.createdAt,
83
+ updatedAt: value.updatedAt,
84
+ draft,
85
+ projectRoot,
86
+ relativePath,
87
+ };
88
+ }
89
+ function writeBuild(storeRoot, record) {
90
+ const dir = workshopBuildsDir(storeRoot);
91
+ mkdirSync(dir, { recursive: true });
92
+ const payload = {
93
+ version: 1,
94
+ id: record.id,
95
+ createdAt: record.createdAt,
96
+ updatedAt: record.updatedAt,
97
+ draft: record.draft,
98
+ projectRoot: record.projectRoot,
99
+ relativePath: record.relativePath,
100
+ };
101
+ writeFileSync(workshopBuildFilePath(storeRoot, record.id), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
102
+ }
103
+ export function readWorkshopBuild(storeRoot, buildId) {
104
+ let id;
105
+ try {
106
+ id = guardBuildId(buildId);
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ const filePath = workshopBuildFilePath(storeRoot, id);
112
+ if (!existsSync(filePath))
113
+ return null;
114
+ try {
115
+ const raw = JSON.parse(readFileSync(filePath, "utf8"));
116
+ const parsed = parseWorkshopBuildRecord(raw);
117
+ if (!parsed || parsed.id !== id)
118
+ return null;
119
+ return parsed;
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ export function createWorkshopBuild(storeRoot, input) {
126
+ const draft = parseStoredDraft(input.draft);
127
+ if (!draft) {
128
+ throw new Error("draft.pipeline is required");
129
+ }
130
+ const id = input.id?.trim() || randomUUID();
131
+ guardBuildId(id);
132
+ if (readWorkshopBuild(storeRoot, id)) {
133
+ throw new Error(`workshop build already exists: ${id}`);
134
+ }
135
+ const now = (input.now ?? new Date()).toISOString();
136
+ const record = {
137
+ version: 1,
138
+ id,
139
+ createdAt: now,
140
+ updatedAt: now,
141
+ draft,
142
+ projectRoot: normalizeTie(input.projectRoot),
143
+ relativePath: normalizeTie(input.relativePath),
144
+ };
145
+ writeBuild(storeRoot, record);
146
+ return record;
147
+ }
148
+ export function getWorkshopBuild(storeRoot, buildId) {
149
+ const record = readWorkshopBuild(storeRoot, buildId);
150
+ if (!record) {
151
+ throw new WorkshopBuildStoreError(`workshop_build_not_found: ${buildId}`, "workshop_build_not_found", buildId);
152
+ }
153
+ return record;
154
+ }
155
+ function listWorkshopBuildRecords(storeRoot) {
156
+ const dir = workshopBuildsDir(storeRoot);
157
+ if (!existsSync(dir))
158
+ return [];
159
+ const records = [];
160
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
161
+ if (!entry.isFile() || !entry.name.endsWith(".json"))
162
+ continue;
163
+ const id = entry.name.slice(0, -".json".length);
164
+ const record = readWorkshopBuild(storeRoot, id);
165
+ if (!record)
166
+ continue;
167
+ records.push(record);
168
+ }
169
+ records.sort((a, b) => {
170
+ if (a.updatedAt !== b.updatedAt) {
171
+ return a.updatedAt < b.updatedAt ? 1 : -1;
172
+ }
173
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
174
+ });
175
+ return records;
176
+ }
177
+ export function listWorkshopBuilds(storeRoot) {
178
+ return listWorkshopBuildRecords(storeRoot).map((record) => ({
179
+ id: record.id,
180
+ createdAt: record.createdAt,
181
+ updatedAt: record.updatedAt,
182
+ projectRoot: record.projectRoot,
183
+ relativePath: record.relativePath,
184
+ }));
185
+ }
186
+ export function resolvePickerCatalogPipelines(items, roots) {
187
+ const byWire = new Map(roots.map((root) => [root.project_root, root.path]));
188
+ return items.map((item) => {
189
+ const resolved = byWire.get(item.project_root);
190
+ return resolved ? { ...item, project_root: resolved } : item;
191
+ });
192
+ }
193
+ function normalizeProjectRoot(value) {
194
+ if (value == null)
195
+ return null;
196
+ const trimmed = value.trim();
197
+ if (!trimmed)
198
+ return null;
199
+ if (path.isAbsolute(trimmed))
200
+ return path.resolve(trimmed);
201
+ return trimmed.replace(/\\/g, "/");
202
+ }
203
+ function normalizeRelativePath(value) {
204
+ if (value == null)
205
+ return null;
206
+ let trimmed = value.trim().replace(/\\/g, "/");
207
+ if (!trimmed)
208
+ return null;
209
+ while (trimmed.startsWith("./"))
210
+ trimmed = trimmed.slice(2);
211
+ return trimmed || null;
212
+ }
213
+ function tieKey(projectRoot, relativePath) {
214
+ if (!projectRoot || !relativePath)
215
+ return null;
216
+ return `${projectRoot}\0${relativePath}`;
217
+ }
218
+ function pickerName(id) {
219
+ const trimmed = id?.trim() ?? "";
220
+ return trimmed ? trimmed : "Untitled";
221
+ }
222
+ function findTiedBuild(storeRoot, projectRoot, relativePath) {
223
+ const key = tieKey(projectRoot, relativePath);
224
+ if (!key)
225
+ return null;
226
+ for (const record of listWorkshopBuildRecords(storeRoot)) {
227
+ const recordKey = tieKey(normalizeProjectRoot(record.projectRoot), normalizeRelativePath(record.relativePath));
228
+ if (recordKey === key)
229
+ return record;
230
+ }
231
+ return null;
232
+ }
233
+ export function listWorkshopPickerRows(storeRoot, pipelines, roots = []) {
234
+ const byWire = new Map(roots.map((root) => [root.project_root, root.path]));
235
+ const canonicalRoot = (value) => {
236
+ const normalized = normalizeProjectRoot(value);
237
+ if (!normalized)
238
+ return null;
239
+ return byWire.get(normalized) ?? normalized;
240
+ };
241
+ const rows = [];
242
+ const tied = new Set();
243
+ for (const record of listWorkshopBuildRecords(storeRoot)) {
244
+ const projectRoot = canonicalRoot(record.projectRoot);
245
+ const key = tieKey(projectRoot, normalizeRelativePath(record.relativePath));
246
+ if (key)
247
+ tied.add(key);
248
+ rows.push({
249
+ id: record.id,
250
+ name: pickerName(record.draft.pipeline.id),
251
+ projectRoot,
252
+ relativePath: record.relativePath,
253
+ });
254
+ }
255
+ for (const pipeline of pipelines) {
256
+ const projectRoot = canonicalRoot(pipeline.project_root);
257
+ const relativePath = normalizeRelativePath(pipeline.path);
258
+ if (!projectRoot || !relativePath)
259
+ continue;
260
+ const key = tieKey(projectRoot, relativePath);
261
+ if (key && tied.has(key))
262
+ continue;
263
+ rows.push({
264
+ id: null,
265
+ name: pickerName(pipeline.id),
266
+ projectRoot,
267
+ relativePath,
268
+ });
269
+ }
270
+ return rows;
271
+ }
272
+ export async function focusUnboundWorkshopBuild(storeRoot, input) {
273
+ const projectRoot = normalizeProjectRoot(input.projectRoot);
274
+ const relativePath = normalizeRelativePath(input.relativePath);
275
+ if (!projectRoot || !relativePath) {
276
+ return {
277
+ ok: false,
278
+ status: 400,
279
+ error: "project root and path are required",
280
+ };
281
+ }
282
+ const existing = findTiedBuild(storeRoot, projectRoot, relativePath);
283
+ if (existing) {
284
+ return { ok: true, created: false, build: existing };
285
+ }
286
+ const loaded = await loadDraftPackage(projectRoot, relativePath);
287
+ if (!loaded.ok) {
288
+ return { ok: false, status: loaded.status, error: loaded.error };
289
+ }
290
+ const again = findTiedBuild(storeRoot, projectRoot, relativePath);
291
+ if (again) {
292
+ return { ok: true, created: false, build: again };
293
+ }
294
+ const build = createWorkshopBuild(storeRoot, {
295
+ draft: loaded.draft,
296
+ projectRoot,
297
+ relativePath,
298
+ });
299
+ return { ok: true, created: true, build };
300
+ }
301
+ export function updateWorkshopBuild(storeRoot, buildId, patch, options) {
302
+ const record = getWorkshopBuild(storeRoot, buildId);
303
+ let draft = record.draft;
304
+ if (patch.draft !== undefined) {
305
+ const parsed = parseStoredDraft(patch.draft);
306
+ if (!parsed) {
307
+ throw new Error("draft.pipeline is required");
308
+ }
309
+ draft = parsed;
310
+ }
311
+ const next = {
312
+ ...record,
313
+ id: record.id,
314
+ version: 1,
315
+ updatedAt: (options?.now ?? new Date()).toISOString(),
316
+ draft,
317
+ projectRoot: patch.projectRoot === undefined
318
+ ? record.projectRoot
319
+ : normalizeTie(patch.projectRoot),
320
+ relativePath: patch.relativePath === undefined
321
+ ? record.relativePath
322
+ : normalizeTie(patch.relativePath),
323
+ };
324
+ writeBuild(storeRoot, next);
325
+ return next;
326
+ }