stageflow 0.32.0 → 0.35.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 (335) hide show
  1. package/README.md +4 -3
  2. package/dist/agent/adapterSpill.d.ts +14 -0
  3. package/dist/agent/adapterSpill.js +83 -0
  4. package/dist/agent/agentBackend.d.ts +2 -2
  5. package/dist/agent/agentBackend.js +2 -2
  6. package/dist/agent/claudeAdapter.d.ts +13 -2
  7. package/dist/agent/claudeAdapter.js +50 -6
  8. package/dist/agent/cursorProvider.d.ts +3 -0
  9. package/dist/agent/cursorProvider.js +23 -6
  10. package/dist/agent/fakeAgent.d.ts +3 -3
  11. package/dist/agent/fakeAgent.js +0 -6
  12. package/dist/agent/piAdapter.d.ts +2 -2
  13. package/dist/agent/piAdapter.js +116 -15
  14. package/dist/agent/piIsolatedMcp.d.ts +1 -0
  15. package/dist/agent/piIsolatedMcp.js +19 -1
  16. package/dist/agent/piIsolatedMcpProbe.d.ts +11 -0
  17. package/dist/agent/piIsolatedMcpProbe.js +20 -0
  18. package/dist/agent/port.d.ts +2 -2
  19. package/dist/agent/providerAuth.d.ts +6 -0
  20. package/dist/agent/providerAuth.js +86 -17
  21. package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -6
  22. package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +13 -9
  23. package/dist/agent/stageTurnDriver.d.ts +33 -0
  24. package/dist/agent/stageTurnDriver.js +64 -0
  25. package/dist/agent/toolOutputBudget.d.ts +46 -0
  26. package/dist/agent/toolOutputBudget.js +97 -0
  27. package/dist/agent/toolOutputBudgetExtension.d.ts +22 -0
  28. package/dist/agent/toolOutputBudgetExtension.js +141 -0
  29. package/dist/agent/toolOutputSpill.d.ts +34 -0
  30. package/dist/agent/toolOutputSpill.js +85 -0
  31. package/dist/browser/agentBrowserLiveViewRelay.d.ts +41 -0
  32. package/dist/browser/agentBrowserLiveViewRelay.js +801 -0
  33. package/dist/browser/anchor.d.ts +2 -0
  34. package/dist/browser/anchor.js +2 -1
  35. package/dist/browser/auditSink.d.ts +8 -0
  36. package/dist/browser/browserHost.d.ts +29 -0
  37. package/dist/browser/browserSweep.d.ts +4 -1
  38. package/dist/browser/browserSweep.js +7 -0
  39. package/dist/browser/browserTeardown.d.ts +1 -0
  40. package/dist/browser/browserTeardown.js +32 -2
  41. package/dist/browser/containerBrowserEndpoint.d.ts +11 -0
  42. package/dist/browser/containerBrowserEndpoint.js +57 -0
  43. package/dist/browser/containerBrowserHost.d.ts +24 -0
  44. package/dist/browser/containerBrowserHost.js +147 -0
  45. package/dist/browser/dockerSandboxOrchestrator.d.ts +26 -0
  46. package/dist/browser/dockerSandboxOrchestrator.js +142 -0
  47. package/dist/browser/fakeLiveViewRelay.d.ts +15 -0
  48. package/dist/browser/fakeLiveViewRelay.js +94 -0
  49. package/dist/browser/fakeLiveViewSource.d.ts +6 -0
  50. package/dist/browser/fakeLiveViewSource.js +16 -0
  51. package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -1
  52. package/dist/browser/fakeRemoteBrowserHost.js +2 -1
  53. package/dist/browser/fakeSandboxOrchestrator.d.ts +9 -0
  54. package/dist/browser/fakeSandboxOrchestrator.js +44 -0
  55. package/dist/browser/gateHandoff.d.ts +0 -2
  56. package/dist/browser/gateHandoff.js +5 -11
  57. package/dist/browser/hostCapabilities.d.ts +23 -0
  58. package/dist/browser/hostCapabilities.js +23 -0
  59. package/dist/browser/humanLogin.d.ts +2 -2
  60. package/dist/browser/humanLogin.js +11 -2
  61. package/dist/browser/liveViewPersisted.d.ts +11 -0
  62. package/dist/browser/liveViewPersisted.js +22 -0
  63. package/dist/browser/liveViewRelay.d.ts +76 -0
  64. package/dist/browser/liveViewRelay.js +1 -0
  65. package/dist/browser/liveViewSessions.d.ts +25 -0
  66. package/dist/browser/liveViewSessions.js +139 -0
  67. package/dist/browser/liveViewSource.d.ts +25 -0
  68. package/dist/browser/liveViewSource.js +7 -0
  69. package/dist/browser/liveViewTickets.d.ts +46 -0
  70. package/dist/browser/liveViewTickets.js +122 -0
  71. package/dist/browser/localBrowserHost.d.ts +10 -0
  72. package/dist/browser/localBrowserHost.js +53 -7
  73. package/dist/browser/ownerScope.d.ts +10 -0
  74. package/dist/browser/ownerScope.js +6 -0
  75. package/dist/browser/profileStore.d.ts +5 -2
  76. package/dist/browser/profileStore.js +3 -5
  77. package/dist/browser/sandboxOrchestrator.d.ts +60 -0
  78. package/dist/browser/sandboxOrchestrator.js +8 -0
  79. package/dist/browser/sessionApiSandboxOrchestrator.d.ts +34 -0
  80. package/dist/browser/sessionApiSandboxOrchestrator.js +108 -0
  81. package/dist/browser/stageBrowserEnv.d.ts +7 -0
  82. package/dist/browser/stageBrowserEnv.js +53 -15
  83. package/dist/browser/stageHandoff.d.ts +47 -0
  84. package/dist/browser/stageHandoff.js +101 -0
  85. package/dist/browser/stageProfileLock.d.ts +1 -0
  86. package/dist/browser/stageProfileLock.js +1 -3
  87. package/dist/browser/volumeProfileStore.d.ts +7 -0
  88. package/dist/browser/volumeProfileStore.js +35 -0
  89. package/dist/cli/browserCommand.d.ts +3 -1
  90. package/dist/cli/browserCommand.js +25 -20
  91. package/dist/cli/resolveCliProjectRoot.d.ts +7 -0
  92. package/dist/cli/resolveCliProjectRoot.js +27 -0
  93. package/dist/cli/runCommand.d.ts +1 -1
  94. package/dist/cli/runCommand.js +59 -17
  95. package/dist/cli/skillsCommand.d.ts +20 -0
  96. package/dist/cli/skillsCommand.js +74 -31
  97. package/dist/cli/validateCommand.d.ts +1 -1
  98. package/dist/cli/validateCommand.js +22 -4
  99. package/dist/cli.js +4 -4
  100. package/dist/config/browseCatalog.d.ts +2 -0
  101. package/dist/config/browseCatalog.js +6 -0
  102. package/dist/config/catalogRelativePath.d.ts +4 -0
  103. package/dist/config/catalogRelativePath.js +37 -9
  104. package/dist/config/createStage.d.ts +1 -0
  105. package/dist/config/createStage.js +11 -2
  106. package/dist/config/createTask.d.ts +30 -0
  107. package/dist/config/createTask.js +161 -0
  108. package/dist/config/createTrigger.d.ts +15 -0
  109. package/dist/config/createTrigger.js +32 -25
  110. package/dist/config/draftPackage.d.ts +41 -0
  111. package/dist/config/draftPackage.js +216 -23
  112. package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
  113. package/dist/config/ensureCatalogScanRoot.js +6 -2
  114. package/dist/config/findTaskInCatalog.d.ts +33 -0
  115. package/dist/config/findTaskInCatalog.js +69 -0
  116. package/dist/config/hostConfig.d.ts +21 -0
  117. package/dist/config/hostConfig.js +113 -1
  118. package/dist/config/importTask.d.ts +19 -0
  119. package/dist/config/importTask.js +133 -0
  120. package/dist/config/installSkillRequest.d.ts +40 -0
  121. package/dist/config/installSkillRequest.js +286 -0
  122. package/dist/config/listConfig.d.ts +0 -16
  123. package/dist/config/listConfig.js +0 -3
  124. package/dist/config/loadOutcome.d.ts +11 -6
  125. package/dist/config/loadPipeline.js +0 -1
  126. package/dist/config/loadStage.js +2 -0
  127. package/dist/config/loadStageflowManifest.js +4 -1
  128. package/dist/config/loadTask.js +2 -0
  129. package/dist/config/loadTrigger.js +2 -0
  130. package/dist/config/mergePipelineIncludes.js +3 -0
  131. package/dist/config/normalizePipelineStageEntry.js +10 -1
  132. package/dist/config/printTargetYaml.js +0 -1
  133. package/dist/config/publishDraftPackage.d.ts +5 -1
  134. package/dist/config/publishDraftPackage.js +4 -1
  135. package/dist/config/resolveCatalogRoots.d.ts +4 -1
  136. package/dist/config/resolveCatalogRoots.js +18 -1
  137. package/dist/config/skillUsageIndex.d.ts +6 -0
  138. package/dist/config/skillUsageIndex.js +39 -0
  139. package/dist/config/stageBrowser.js +13 -0
  140. package/dist/config/triggerAdapterStatus.d.ts +11 -0
  141. package/dist/config/triggerAdapterStatus.js +90 -0
  142. package/dist/config/triggerCatalog.d.ts +41 -2
  143. package/dist/config/triggerCatalog.js +107 -15
  144. package/dist/config/updateTask.d.ts +30 -0
  145. package/dist/config/updateTask.js +119 -0
  146. package/dist/config/updateTrigger.d.ts +38 -0
  147. package/dist/config/updateTrigger.js +220 -0
  148. package/dist/config/validateCatalog.d.ts +6 -2
  149. package/dist/config/validateCatalog.js +48 -7
  150. package/dist/config/workshopCatalogFilenames.d.ts +37 -0
  151. package/dist/config/workshopCatalogFilenames.js +125 -0
  152. package/dist/config/workshopCatalogRepair.d.ts +7 -0
  153. package/dist/config/workshopCatalogRepair.js +144 -0
  154. package/dist/config/yamlParsePosition.d.ts +4 -0
  155. package/dist/config/yamlParsePosition.js +9 -0
  156. package/dist/hosted/containment.d.ts +3 -0
  157. package/dist/hosted/containment.js +36 -0
  158. package/dist/hosted/errors.d.ts +21 -0
  159. package/dist/hosted/errors.js +30 -0
  160. package/dist/hosted/packageSkills.d.ts +3 -0
  161. package/dist/hosted/packageSkills.js +80 -0
  162. package/dist/hosted/runtime.d.ts +12 -0
  163. package/dist/hosted/runtime.js +596 -0
  164. package/dist/hosted/sequencer.d.ts +28 -0
  165. package/dist/hosted/sequencer.js +129 -0
  166. package/dist/hosted/translate.d.ts +3 -0
  167. package/dist/hosted/translate.js +43 -0
  168. package/dist/hosted/types.d.ts +108 -0
  169. package/dist/hosted/types.js +10 -0
  170. package/dist/index.d.ts +9 -1
  171. package/dist/index.js +6 -0
  172. package/dist/mcp/getStartedTool.js +15 -6
  173. package/dist/mcp/triggerTools.js +2 -8
  174. package/dist/operatorAgent/agentPort.d.ts +11 -0
  175. package/dist/operatorAgent/agentPort.js +12 -0
  176. package/dist/operatorAgent/index.d.ts +1 -0
  177. package/dist/operatorAgent/index.js +1 -0
  178. package/dist/operatorAgent/piModel.js +26 -6
  179. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
  180. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +4 -2
  181. package/dist/operatorAgent/profiles/workshopAuthorTools.js +103 -16
  182. package/dist/package-meta.d.ts +1 -1
  183. package/dist/package-meta.js +1 -1
  184. package/dist/project/ensureProjectRootsFromEnv.d.ts +3 -0
  185. package/dist/project/ensureProjectRootsFromEnv.js +22 -0
  186. package/dist/project/globalHome.d.ts +1 -0
  187. package/dist/project/globalHome.js +18 -0
  188. package/dist/project/workspaceCatalog.d.ts +10 -0
  189. package/dist/project/workspaceCatalog.js +91 -0
  190. package/dist/projection/projectRun.d.ts +0 -1
  191. package/dist/projection/projectRun.js +0 -1
  192. package/dist/runstore/backup.js +14 -4
  193. package/dist/runstore/port.d.ts +11 -1
  194. package/dist/runstore/restore.js +5 -2
  195. package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -0
  196. package/dist/runstore/sqlite/SqliteRunStore.js +29 -9
  197. package/dist/runstore/sqlite/migrations/012-trigger-fires.d.ts +7 -0
  198. package/dist/runstore/sqlite/migrations/012-trigger-fires.js +18 -0
  199. package/dist/runstore/sqlite/migrations/index.js +2 -0
  200. package/dist/runstore/stageSnapshot.d.ts +3 -1
  201. package/dist/runstore/stageSnapshot.js +19 -0
  202. package/dist/runstore/workspaceLayout.js +27 -0
  203. package/dist/runstore/writeContainedArtifact.d.ts +1 -0
  204. package/dist/runstore/writeContainedArtifact.js +52 -0
  205. package/dist/runtime/containerLimits.d.ts +0 -3
  206. package/dist/runtime/containerLimits.js +0 -5
  207. package/dist/runtime/credentialBinding.d.ts +3 -0
  208. package/dist/runtime/credentialBinding.js +23 -6
  209. package/dist/runtime/emailSource.js +20 -28
  210. package/dist/runtime/githubPollSource.js +20 -28
  211. package/dist/runtime/pipelineRunner.d.ts +4 -4
  212. package/dist/runtime/pipelineScheduler.d.ts +2 -2
  213. package/dist/runtime/pipelineScheduler.js +3 -0
  214. package/dist/runtime/resumeReconstruct.d.ts +2 -2
  215. package/dist/runtime/resumeTimedOut.d.ts +2 -2
  216. package/dist/runtime/runManager.d.ts +18 -2
  217. package/dist/runtime/runManager.js +95 -30
  218. package/dist/runtime/runRetentionSweep.d.ts +0 -2
  219. package/dist/runtime/runRetentionSweep.js +0 -8
  220. package/dist/runtime/runRetryCoordinator.d.ts +2 -2
  221. package/dist/runtime/scheduleSource.js +15 -24
  222. package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
  223. package/dist/runtime/stageAttemptBootstrap.js +10 -1
  224. package/dist/runtime/stageProcessLauncher.js +2 -2
  225. package/dist/runtime/stageRoots.js +12 -1
  226. package/dist/runtime/stageRunner.d.ts +2 -2
  227. package/dist/runtime/stageRunner.js +8 -2
  228. package/dist/runtime/stageWorker.js +2 -2
  229. package/dist/runtime/triggerPort.d.ts +5 -3
  230. package/dist/runtime/triggerRunner.d.ts +1 -0
  231. package/dist/runtime/triggerRunner.js +27 -20
  232. package/dist/runtime/webhookAccept.d.ts +25 -0
  233. package/dist/runtime/webhookAccept.js +56 -0
  234. package/dist/server/bootstrap.d.ts +7 -2
  235. package/dist/server/bootstrap.js +15 -1
  236. package/dist/server/controlToken.d.ts +1 -1
  237. package/dist/server/controlToken.js +18 -2
  238. package/dist/server/healthSurfaces.d.ts +12 -0
  239. package/dist/server/healthSurfaces.js +27 -6
  240. package/dist/server/http.d.ts +19 -10
  241. package/dist/server/http.js +605 -85
  242. package/dist/server/liveViewPath.d.ts +9 -0
  243. package/dist/server/liveViewPath.js +8 -0
  244. package/dist/server/liveViewRoutes.d.ts +58 -0
  245. package/dist/server/liveViewRoutes.js +565 -0
  246. package/dist/server/mcpHost.d.ts +4 -2
  247. package/dist/server/mcpHost.js +2 -0
  248. package/dist/server/readCatalogFile.d.ts +29 -0
  249. package/dist/server/readCatalogFile.js +215 -0
  250. package/dist/server/triggerRoutes.d.ts +1 -0
  251. package/dist/server/triggerRoutes.js +200 -73
  252. package/dist/tools/readEmail.d.ts +3 -3
  253. package/dist/tools/writeStageArtifact.d.ts +9 -0
  254. package/dist/tools/writeStageArtifact.js +2 -47
  255. package/dist/types/pipeline.d.ts +1 -1
  256. package/dist/types/stage.d.ts +1 -1
  257. package/dist/types/stageflowManifest.d.ts +1 -1
  258. package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  259. package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  260. package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  261. package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  262. package/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  263. package/dist/ui/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  264. package/dist/ui/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  265. package/dist/ui/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  266. package/dist/ui/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  267. package/dist/ui/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  268. package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  269. package/dist/ui/assets/index-BoFPkKFg.js +256 -0
  270. package/dist/ui/assets/{index-Bv4p1aPK.css → index-CIPbbBUi.css} +1 -1
  271. package/dist/ui/index.html +4 -4
  272. package/dist/workshop/autosave.d.ts +2 -2
  273. package/dist/workshop/autosave.js +4 -6
  274. package/dist/workshop/buildStore.d.ts +2 -0
  275. package/dist/workshop/chatAttachments.d.ts +27 -0
  276. package/dist/workshop/chatAttachments.js +98 -0
  277. package/dist/workshop/chatTurn.d.ts +5 -2
  278. package/dist/workshop/chatTurn.js +22 -18
  279. package/dist/workshop/sessionMutations.d.ts +17 -0
  280. package/dist/workshop/sessionMutations.js +107 -0
  281. package/dist/workshop/sessionStore.d.ts +10 -0
  282. package/dist/workshop/sessionStore.js +52 -0
  283. package/dist/workshop/workshopPin.d.ts +4 -3
  284. package/dist/workshop/workshopPin.js +26 -6
  285. package/dist/workshop/workshopTranscriptTurn.d.ts +8 -0
  286. package/dist/workshop/workshopTranscriptTurn.js +46 -0
  287. package/examples/README.md +1 -1
  288. package/examples/archify-on-pr/README.md +1 -1
  289. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +0 -1
  290. package/examples/archify-on-pr/author-diagrams.yaml +1 -0
  291. package/examples/conditional-fork/branch-a.yaml +1 -1
  292. package/examples/conditional-fork/decide.yaml +2 -1
  293. package/examples/feature-loop/{implement.yaml → feature-implement.yaml} +1 -1
  294. package/examples/feature-loop/feature-loop.pipeline.yaml +10 -10
  295. package/examples/feature-loop/{plan.yaml → feature-plan.yaml} +1 -1
  296. package/examples/feature-loop/{review.yaml → feature-review.yaml} +1 -1
  297. package/examples/feedback-loop/{implement.yaml → feedback-implement.yaml} +1 -1
  298. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +9 -9
  299. package/examples/feedback-loop/feedback-loop.pipeline.yaml +9 -9
  300. package/examples/feedback-loop/{plan.yaml → feedback-plan.yaml} +1 -1
  301. package/examples/feedback-loop/{review.yaml → feedback-review.yaml} +1 -1
  302. package/examples/generic-fan-in/{research.yaml → fan-in-research.yaml} +1 -1
  303. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +3 -3
  304. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +3 -3
  305. package/examples/hello-world/{research.yaml → hello-research.yaml} +1 -1
  306. package/examples/hello-world/hello.pipeline.yaml +2 -2
  307. package/examples/mcp-hitl-tour/{review.yaml → mcp-hitl-review.yaml} +1 -1
  308. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +3 -3
  309. package/examples/oss-issue-contribution/oss-explain-fix.yaml +1 -0
  310. package/examples/oss-issue-contribution/oss-explain-issue.yaml +1 -0
  311. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +0 -2
  312. package/examples/stageflow.yaml +6 -0
  313. package/examples/triggers/sample-github-pr.trigger.yaml +12 -0
  314. package/examples/triggers/sample-inbox-email.trigger.yaml +14 -0
  315. package/examples/triggers/sample-manual-hello.trigger.yaml +5 -0
  316. package/examples/triggers/sample-nightly-hello.trigger.yaml +8 -0
  317. package/examples/triggers/sample-signed-webhook.trigger.yaml +11 -0
  318. package/examples/triggers-readiness/README.md +48 -0
  319. package/examples/triggers-readiness/readiness-emit.yaml +18 -0
  320. package/examples/triggers-readiness/readiness.pipeline.yaml +4 -0
  321. package/examples/triggers-readiness/readiness.task.yaml +6 -0
  322. package/examples/triggers-readiness/stageflow.yaml +13 -0
  323. package/examples/triggers-readiness/triggers/readiness-dynamic-manual.trigger.yaml +4 -0
  324. package/examples/triggers-readiness/triggers/readiness-email.trigger.yaml +12 -0
  325. package/examples/triggers-readiness/triggers/readiness-github-pr.trigger.yaml +12 -0
  326. package/examples/triggers-readiness/triggers/readiness-manual.trigger.yaml +5 -0
  327. package/examples/triggers-readiness/triggers/readiness-schedule.trigger.yaml +8 -0
  328. package/examples/triggers-readiness/triggers/readiness-webhook.trigger.yaml +11 -0
  329. package/package.json +9 -1
  330. package/skills/stageflow/references/control-surface.md +1 -1
  331. package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
  332. package/skills/stageflow-run/SKILL.md +1 -1
  333. package/skills/stageflow-run/references/mcp-call.md +1 -1
  334. package/skills/stageflow-setup/SKILL.md +1 -1
  335. package/dist/ui/assets/index-59cjF0OA.js +0 -133
@@ -21,6 +21,7 @@ import { hydrateScheduleFromStore, hydratedScheduleHasRunnableWork, resumeRun, r
21
21
  import { resolveFeedbackLoopDecision, } from "./feedbackLoopDecision.js";
22
22
  import { RunRetryCoordinator, readRetryRootWaitTimeoutMs, } from "./runRetryCoordinator.js";
23
23
  import { readMaxActiveStageProcesses, readMaxActiveStagesPerRun, readStageExecutionMode, } from "./stageConcurrency.js";
24
+ import { runOwnerScope } from "../browser/ownerScope.js";
24
25
  import { isHumanLoginStage } from "../browser/humanLogin.js";
25
26
  import { defaultStageBrowserSupport, resolveStageBrowserEnv, } from "../browser/stageBrowserEnv.js";
26
27
  import { teardownRunBrowsers, teardownStageBrowser, } from "../browser/browserTeardown.js";
@@ -267,6 +268,9 @@ export class RunManager {
267
268
  queuedDone = new Map();
268
269
  admissionDrainInFlight = false;
269
270
  resumeInFlight = new Set();
271
+ gateClosedListeners = new Set();
272
+ beforeBrowserTeardownListeners = new Set();
273
+ shutdownListeners = new Set();
270
274
  retryInFlight = new Set();
271
275
  retryStartOwner = new Map();
272
276
  retryStartWaiters = new Map();
@@ -357,7 +361,18 @@ export class RunManager {
357
361
  return this.active.size;
358
362
  }
359
363
  stopAcceptingWork() {
364
+ const wasAccepting = this.acceptingWork;
360
365
  this.acceptingWork = false;
366
+ if (wasAccepting) {
367
+ for (const listener of [...this.shutdownListeners]) {
368
+ try {
369
+ listener();
370
+ }
371
+ catch {
372
+ // listeners must not affect shutdown
373
+ }
374
+ }
375
+ }
361
376
  for (const halt of this.schedulingHalts.values()) {
362
377
  halt.halted = true;
363
378
  halt.hostShutdown = true;
@@ -592,13 +607,14 @@ export class RunManager {
592
607
  .some((entry) => entry.runId === runId && entry.stageId === stageId);
593
608
  }
594
609
  async sweepBrowserSessions() {
595
- const support = this.options.browser ?? defaultStageBrowserSupport();
610
+ const support = this.browserSupport();
596
611
  const isRunLive = createRunLiveness(this.options.store);
597
612
  await stageProfileLock(support)
598
613
  .reclaimStale(isRunLive)
599
614
  .catch(() => 0);
600
615
  return sweepOrphanBrowserSessions({
601
616
  isRunLive,
617
+ host: support.host,
602
618
  ...(support.runner !== undefined ? { runner: support.runner } : {}),
603
619
  ...(support.closeWaitMs !== undefined
604
620
  ? { closeWaitMs: support.closeWaitMs }
@@ -833,6 +849,64 @@ export class RunManager {
833
849
  }
834
850
  await this.drainAdmissionQueue();
835
851
  }
852
+ /** Called when a stage's gate stops accepting operator input (answered, abandoned) or a run is cancelled (no stage id). */
853
+ onGateClosed(listener) {
854
+ this.gateClosedListeners.add(listener);
855
+ return () => {
856
+ this.gateClosedListeners.delete(listener);
857
+ };
858
+ }
859
+ /** Awaited (bounded by the browser support) before a stage's or run's browser is torn down; stageId absent means the whole run. */
860
+ beforeBrowserTeardown(listener) {
861
+ this.beforeBrowserTeardownListeners.add(listener);
862
+ return () => {
863
+ this.beforeBrowserTeardownListeners.delete(listener);
864
+ };
865
+ }
866
+ /** Called once the Host stops accepting work (drain start). */
867
+ onShutdown(listener) {
868
+ this.shutdownListeners.add(listener);
869
+ return () => {
870
+ this.shutdownListeners.delete(listener);
871
+ };
872
+ }
873
+ browserSupport() {
874
+ const base = this.options.browser ?? defaultStageBrowserSupport();
875
+ if (this.beforeBrowserTeardownListeners.size === 0)
876
+ return base;
877
+ return {
878
+ ...base,
879
+ beforeTeardown: async (input) => {
880
+ await Promise.all([
881
+ base.beforeTeardown?.(input),
882
+ ...[...this.beforeBrowserTeardownListeners].map(async (listener) => {
883
+ try {
884
+ await listener(input);
885
+ }
886
+ catch {
887
+ // listeners must not block teardown
888
+ }
889
+ }),
890
+ ]);
891
+ },
892
+ };
893
+ }
894
+ browserOption() {
895
+ if (this.options.browser === undefined && this.beforeBrowserTeardownListeners.size === 0) {
896
+ return {};
897
+ }
898
+ return { browser: this.browserSupport() };
899
+ }
900
+ notifyGateClosed(runId, stageId) {
901
+ for (const listener of [...this.gateClosedListeners]) {
902
+ try {
903
+ listener(runId, stageId);
904
+ }
905
+ catch {
906
+ // listeners must not affect run control
907
+ }
908
+ }
909
+ }
836
910
  async abandonStage(runId, stageId) {
837
911
  let detail;
838
912
  try {
@@ -863,6 +937,7 @@ export class RunManager {
863
937
  status: 409,
864
938
  };
865
939
  }
940
+ this.notifyGateClosed(runId, stageId);
866
941
  if (this.stageProcessLauncher !== undefined) {
867
942
  const hasActive = this.stageProcessLauncher
868
943
  .getActiveStageProcesses()
@@ -871,7 +946,7 @@ export class RunManager {
871
946
  await this.stageProcessLauncher.cancelRun(runId);
872
947
  }
873
948
  }
874
- await teardownStageBrowser(this.options.browser ?? defaultStageBrowserSupport(), {
949
+ await teardownStageBrowser(this.browserSupport(), {
875
950
  runId,
876
951
  runDir: this.options.store.getWorkspaceDir(runId),
877
952
  stageId,
@@ -893,7 +968,7 @@ export class RunManager {
893
968
  const hasWaiting = after.stages.some((s) => s.status === "waiting_for_input");
894
969
  if (!hasWaiting &&
895
970
  !(await createRunLiveness(this.options.store)(runId).catch(() => true))) {
896
- await teardownRunBrowsers(this.options.browser ?? defaultStageBrowserSupport(), {
971
+ await teardownRunBrowsers(this.browserSupport(), {
897
972
  runId,
898
973
  runDir: this.options.store.getWorkspaceDir(runId),
899
974
  events: (stageId) => this.options.store.listStageEvents(runId, stageId),
@@ -931,6 +1006,7 @@ export class RunManager {
931
1006
  };
932
1007
  }
933
1008
  await this.options.store.updateRunStatus(runId, "cancelled");
1009
+ this.notifyGateClosed(runId);
934
1010
  await this.options.store.setCancelReason(runId, trimmedReason);
935
1011
  await finaliseStoredRunManifest(this.options.store, runId).catch(() => undefined);
936
1012
  await this.refreshRunDiskBytes(runId).catch(() => undefined);
@@ -950,7 +1026,7 @@ export class RunManager {
950
1026
  if (this.stageProcessLauncher !== undefined) {
951
1027
  await this.stageProcessLauncher.cancelRun(runId);
952
1028
  }
953
- await teardownRunBrowsers(this.options.browser ?? defaultStageBrowserSupport(), {
1029
+ await teardownRunBrowsers(this.browserSupport(), {
954
1030
  runId,
955
1031
  runDir: this.options.store.getWorkspaceDir(runId),
956
1032
  events: (stageId) => this.options.store.listStageEvents(runId, stageId),
@@ -1530,9 +1606,7 @@ export class RunManager {
1530
1606
  agent: this.options.agent,
1531
1607
  cwd: meta.project_root ?? this.projectRoot,
1532
1608
  operatorCatalog: this.options.operatorCatalog,
1533
- ...(this.options.browser !== undefined
1534
- ? { browser: this.options.browser }
1535
- : {}),
1609
+ ...this.browserOption(),
1536
1610
  maxActiveStagesPerRun: this.maxActiveStagesPerRun,
1537
1611
  executionMode: this.executionMode,
1538
1612
  stageProcessLauncher: this.stageProcessLauncher,
@@ -1757,6 +1831,7 @@ export class RunManager {
1757
1831
  }
1758
1832
  return prefix;
1759
1833
  }
1834
+ this.notifyGateClosed(runId, stageId);
1760
1835
  return await orchestrateAnswerResume({
1761
1836
  prefixMode: prefix.mode,
1762
1837
  executionMode: this.executionMode,
@@ -1896,9 +1971,7 @@ export class RunManager {
1896
1971
  checkoutRoot: meta.checkout_root,
1897
1972
  hitl: this.hitl,
1898
1973
  operatorCatalog: this.options.operatorCatalog,
1899
- ...(this.options.browser !== undefined
1900
- ? { browser: this.options.browser }
1901
- : {}),
1974
+ ...this.browserOption(),
1902
1975
  },
1903
1976
  maxActiveStagesPerRun: this.maxActiveStagesPerRun,
1904
1977
  executionMode: this.executionMode,
@@ -1957,7 +2030,8 @@ export class RunManager {
1957
2030
  });
1958
2031
  const resumedStage = loaded.stages.find((s) => s.id === definitionIdForInstance(meta.pipeline_dag, stageId));
1959
2032
  if (resumedStage?.browser?.profile !== undefined) {
1960
- await acquireStageProfile(this.options.browser ?? defaultStageBrowserSupport(), {
2033
+ await acquireStageProfile(this.browserSupport(), {
2034
+ scope: runOwnerScope(this.browserSupport(), { runId }),
1961
2035
  profile: resumedStage.browser.profile,
1962
2036
  owner: { runId, stageId },
1963
2037
  isRunLive: createRunLiveness(store),
@@ -1968,9 +2042,10 @@ export class RunManager {
1968
2042
  }
1969
2043
  });
1970
2044
  }
1971
- const browserEnv = await resolveStageBrowserEnv(this.options.browser ?? defaultStageBrowserSupport(), {
2045
+ const browserEnv = await resolveStageBrowserEnv(this.browserSupport(), {
1972
2046
  runId,
1973
2047
  stageId,
2048
+ scope: runOwnerScope(this.browserSupport(), { runId }),
1974
2049
  runDir: workspaceDir,
1975
2050
  browser: resumedStage?.browser,
1976
2051
  attempt,
@@ -1999,7 +2074,7 @@ export class RunManager {
1999
2074
  if (launchResult.type === "waiting") {
2000
2075
  return { ok: true };
2001
2076
  }
2002
- await teardownStageBrowser(this.options.browser ?? defaultStageBrowserSupport(), {
2077
+ await teardownStageBrowser(this.browserSupport(), {
2003
2078
  runId,
2004
2079
  runDir: workspaceDir,
2005
2080
  stageId,
@@ -2021,9 +2096,7 @@ export class RunManager {
2021
2096
  checkoutRoot: meta.checkout_root,
2022
2097
  hitl: this.hitl,
2023
2098
  operatorCatalog: this.options.operatorCatalog,
2024
- ...(this.options.browser !== undefined
2025
- ? { browser: this.options.browser }
2026
- : {}),
2099
+ ...this.browserOption(),
2027
2100
  },
2028
2101
  retryRoots: new Map([[stageId, nextRepairAttempt]]),
2029
2102
  maxActiveStagesPerRun: this.maxActiveStagesPerRun,
@@ -2041,7 +2114,7 @@ export class RunManager {
2041
2114
  reason: launchResult.reason,
2042
2115
  }, eventOptions);
2043
2116
  await store.updateRunStatus(runId, "failed");
2044
- await teardownRunBrowsers(this.options.browser ?? defaultStageBrowserSupport(), {
2117
+ await teardownRunBrowsers(this.browserSupport(), {
2045
2118
  runId,
2046
2119
  runDir: workspaceDir,
2047
2120
  events: (stageId) => store.listStageEvents(runId, stageId),
@@ -2067,9 +2140,7 @@ export class RunManager {
2067
2140
  checkoutRoot: meta.checkout_root,
2068
2141
  hitl: this.hitl,
2069
2142
  operatorCatalog: this.options.operatorCatalog,
2070
- ...(this.options.browser !== undefined
2071
- ? { browser: this.options.browser }
2072
- : {}),
2143
+ ...this.browserOption(),
2073
2144
  },
2074
2145
  maxActiveStagesPerRun: this.maxActiveStagesPerRun,
2075
2146
  resumeFromStageId: stageId,
@@ -2093,7 +2164,7 @@ export class RunManager {
2093
2164
  reason,
2094
2165
  }, eventOptions);
2095
2166
  await store.updateRunStatus(runId, "failed");
2096
- await teardownRunBrowsers(this.options.browser ?? defaultStageBrowserSupport(), {
2167
+ await teardownRunBrowsers(this.browserSupport(), {
2097
2168
  runId,
2098
2169
  runDir: store.getWorkspaceDir(runId),
2099
2170
  events: (stageId) => store.listStageEvents(runId, stageId),
@@ -2406,9 +2477,7 @@ export class RunManager {
2406
2477
  const started = await startPipeline({
2407
2478
  dispatchKey,
2408
2479
  submission,
2409
- ...(this.options.browser !== undefined
2410
- ? { browser: this.options.browser }
2411
- : {}),
2480
+ ...this.browserOption(),
2412
2481
  agent: this.options.agent,
2413
2482
  store: this.options.store,
2414
2483
  taskYaml,
@@ -2911,9 +2980,7 @@ export class RunManager {
2911
2980
  const schedulingHalt = this.ensureSchedulingHalt(runId);
2912
2981
  const started = await startPipeline({
2913
2982
  submission,
2914
- ...(this.options.browser !== undefined
2915
- ? { browser: this.options.browser }
2916
- : {}),
2983
+ ...this.browserOption(),
2917
2984
  agent: this.options.agent,
2918
2985
  store: this.options.store,
2919
2986
  taskYaml,
@@ -3018,9 +3085,7 @@ export class RunManager {
3018
3085
  checkoutRoot: loadedMeta.checkout_root,
3019
3086
  hitl: this.hitl,
3020
3087
  operatorCatalog: this.options.operatorCatalog,
3021
- ...(this.options.browser !== undefined
3022
- ? { browser: this.options.browser }
3023
- : {}),
3088
+ ...this.browserOption(),
3024
3089
  },
3025
3090
  maxActiveStagesPerRun: this.maxActiveStagesPerRun,
3026
3091
  executionMode: this.executionMode,
@@ -15,8 +15,6 @@ export type RunRetentionSweepOptions = {
15
15
  artifactMaxBytes?: number;
16
16
  bareCacheTtlMs?: number;
17
17
  };
18
- export declare function getSlimWalkCallCount(): number;
19
- export declare function resetSlimWalkCallCount(): void;
20
18
  /**
21
19
  * Walk attempt + legacy artifact trees and remove SLIM-eligible paths.
22
20
  * Never removes envelope.json, log.jsonl, or under-threshold artifacts.
@@ -7,13 +7,6 @@ import { reclaimWorkspaceBinding, worktreePathForRun, } from "./repositoryMateri
7
7
  import { deleteRunEverywhere } from "./runDeletion.js";
8
8
  const SLIM_ATTEMPT_FILES = ["pi-session.jsonl", "stream.log"];
9
9
  const SLIM_ATTEMPT_DIRS = [".pi-agent"];
10
- let slimWalkCallCount = 0;
11
- export function getSlimWalkCallCount() {
12
- return slimWalkCallCount;
13
- }
14
- export function resetSlimWalkCallCount() {
15
- slimWalkCallCount = 0;
16
- }
17
10
  async function pathExists(target) {
18
11
  try {
19
12
  await stat(target);
@@ -84,7 +77,6 @@ async function slimAttemptDir(attemptDir, maxBytes) {
84
77
  * Never removes envelope.json, log.jsonl, or under-threshold artifacts.
85
78
  */
86
79
  export async function slimRunWorkspaceArtifacts(workspaceDir, maxBytes) {
87
- slimWalkCallCount += 1;
88
80
  const stagesRoot = path.join(workspaceDir, "stages");
89
81
  if (!(await pathExists(stagesRoot)))
90
82
  return;
@@ -1,4 +1,4 @@
1
- import type { AgentPort } from "../agent/port.js";
1
+ import type { StagePort } from "../agent/port.js";
2
2
  import { type RunDetail, type RunPipelineDagSnapshot, type RunStatus, type RunStore, type StageSnapshot } from "../runstore/port.js";
3
3
  import type { PipelineRunResult } from "./pipelineRunner.js";
4
4
  import { type SchedulerPreparedPipeline } from "./pipelineScheduler.js";
@@ -56,7 +56,7 @@ export type RetryStageRequest = {
56
56
  runId: string;
57
57
  stageId: string;
58
58
  store: RunStore;
59
- agent: AgentPort;
59
+ agent: StagePort;
60
60
  cwd: string;
61
61
  operatorCatalog?: OperatorCatalog;
62
62
  browser?: StageBrowserSupport;
@@ -1,9 +1,5 @@
1
- import path from "node:path";
2
1
  import { Cron } from "croner";
3
- import { getCatalogScanPaths } from "../config/browseCatalog.js";
4
- import { loadTriggerOutcome } from "../config/loadTrigger.js";
5
- import { catalogContextFromStageflow } from "../config/resolveCatalogContext.js";
6
- import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
2
+ import { listCatalogTriggerMatches, readTriggerStoreRecord, triggerStoreId, } from "../config/triggerCatalog.js";
7
3
  export const DEFAULT_TRIGGER_TICK_INTERVAL_MS = 30_000;
8
4
  /** Parse `STAGEFLOW_TRIGGER_TICK_INTERVAL_MS`; default 30s; `0` disables. */
9
5
  export function triggerTickIntervalMsFromEnv(env = process.env) {
@@ -72,17 +68,14 @@ export class ScheduleSource {
72
68
  * against an injected clock instead of waiting on real interval timers.
73
69
  */
74
70
  async tick(onFire) {
75
- const ctx = catalogContextFromStageflow(await resolveStageflowContext(this.cwd));
76
- const scanPaths = await getCatalogScanPaths(ctx);
77
- if (!scanPaths)
78
- return;
79
71
  const now = this.now();
80
- const projectRoot = ctx.projectRoot ?? undefined;
81
- for (const triggerPath of scanPaths.triggerPaths) {
82
- const outcome = await loadTriggerOutcome(triggerPath);
83
- if (!outcome.ok)
84
- continue;
85
- const definition = outcome.value;
72
+ const catalogTriggers = await listCatalogTriggerMatches({
73
+ store: this.store,
74
+ bootCwd: this.cwd,
75
+ sourceRootsOnly: true,
76
+ });
77
+ for (const match of catalogTriggers) {
78
+ const definition = match.definition;
86
79
  if (definition.kind !== "schedule" || !definition.enabled || !definition.schedule) {
87
80
  continue;
88
81
  }
@@ -94,25 +87,23 @@ export class ScheduleSource {
94
87
  this.logError(`invalid schedule for trigger "${definition.id}": ${err instanceof Error ? err.message : String(err)}`);
95
88
  continue;
96
89
  }
97
- const definitionRef = projectRoot !== undefined
98
- ? path.relative(projectRoot, triggerPath).replace(/\\/g, "/")
99
- : triggerPath;
90
+ const storeId = triggerStoreId(match.project_root, definition.id);
100
91
  await this.store.upsertTrigger({
101
- id: definition.id,
102
- definitionRef,
92
+ id: storeId,
93
+ definitionRef: match.definition_ref,
103
94
  enabled: true,
104
95
  });
105
- const record = await this.store.getTrigger(definition.id);
96
+ const record = await readTriggerStoreRecord(this.store, match.project_root, definition.id);
106
97
  if (!record?.next_run_at) {
107
98
  if (next)
108
- await this.store.setTriggerNextRun(definition.id, next.toISOString());
99
+ await this.store.setTriggerNextRun(storeId, next.toISOString());
109
100
  continue;
110
101
  }
111
102
  const dueAt = new Date(record.next_run_at);
112
103
  if (dueAt.getTime() <= now.getTime()) {
113
- await onFire({ triggerId: definition.id });
104
+ await onFire({ triggerId: definition.id, project_root: match.project_root });
114
105
  if (next)
115
- await this.store.setTriggerNextRun(definition.id, next.toISOString());
106
+ await this.store.setTriggerNextRun(storeId, next.toISOString());
116
107
  }
117
108
  }
118
109
  }
@@ -1,4 +1,4 @@
1
- import type { AgentPort, FeedbackLoopContext, StageHandle, StageRunInput, StageSessionMode } from "../agent/port.js";
1
+ import type { StagePort, FeedbackLoopContext, StageHandle, StageRunInput, StageSessionMode } from "../agent/port.js";
2
2
  import { type StageStreamLogWriter } from "./stageStreamLog.js";
3
3
  import type { RunStore } from "../runstore/port.js";
4
4
  import type { StageEnvelope } from "../types/envelope.js";
@@ -12,7 +12,7 @@ export type OperatorCatalog = {
12
12
  agentDir?: string;
13
13
  };
14
14
  export type StageAttemptOpenInput = {
15
- agent: Pick<AgentPort, "openStage">;
15
+ agent: Pick<StagePort, "openStage">;
16
16
  store: RunStore;
17
17
  runId: string;
18
18
  stage: LoadedStageConfig;
@@ -2,6 +2,7 @@ import { emailHostFor, stageEmail, workerStageEmail, validateStageEmailAccounts
2
2
  import { EmailError } from "../email/port.js";
3
3
  import { bindingKindForOrigin, catalogOrSeededOrigin, decideWorkspaceConfigTrust, } from "../config/configOrigin.js";
4
4
  import { loginCheckPromptBlock, readStageLoginCheck, } from "../browser/loginCheck.js";
5
+ import { stageGateHandoff } from "../browser/stageHandoff.js";
5
6
  import { humanLoginPromptBlock, isHumanLoginStage } from "../browser/humanLogin.js";
6
7
  import { BROWSER_SKILL_NAME, resolveBuiltinSkillFile, } from "../config/builtinSkills.js";
7
8
  import { resolveSkillByName, } from "../config/listSkills.js";
@@ -239,12 +240,20 @@ async function openStageWithOperatorCatalog(agent, input, catalog, factoryCwd, a
239
240
  return { ok: false, reason: "browser login check result is missing" };
240
241
  }
241
242
  }
243
+ const humanLoginHandoff = humanLogin
244
+ ? await stageGateHandoff({
245
+ runDir: resolveOptions.workspaceDir,
246
+ runId: resolveOptions.runId,
247
+ stageId: input.stage.id,
248
+ dirStageId: stageIdForManifest,
249
+ })
250
+ : undefined;
242
251
  try {
243
252
  const handle = agent.openStage({
244
253
  ...input,
245
254
  stage: {
246
255
  ...input.stage,
247
- system_prompt: `${stampStagePromptArtifactsDir(input.stage.system_prompt, artifactsDir)}${loginCheck !== undefined ? `\n\n${loginCheckPromptBlock(loginCheck)}` : ""}${humanLogin ? `\n\n${humanLoginPromptBlock(input.stage.browser?.login_url ?? input.stage.browser?.check?.url)}` : ""}`,
256
+ system_prompt: `${stampStagePromptArtifactsDir(input.stage.system_prompt, artifactsDir)}${loginCheck !== undefined ? `\n\n${loginCheckPromptBlock(loginCheck)}` : ""}${humanLogin ? `\n\n${humanLoginPromptBlock(input.stage.browser?.login_url ?? input.stage.browser?.check?.url, humanLoginHandoff?.kind === "live_view" ? "live_view" : "local_window")}` : ""}`,
248
257
  ...(loginCheck !== undefined
249
258
  ? {
250
259
  pre_emit_checks: [
@@ -4,7 +4,7 @@ import { logger as rootLogger, resolveLogMaxLineBytes, } from "../logging/logger
4
4
  import { isCursorModelRef, readCursorApiKey } from "../agent/cursorProvider.js";
5
5
  import { BROWSER_ENV_PREFIX } from "../browser/browserHost.js";
6
6
  import { PACKAGE_VERSION } from "../package-meta.js";
7
- import { PI_HOME_AUTH_PATH_ENV, stageflowAgentAuthPath } from "./credentialBinding.js";
7
+ import { PI_HOME_AUTH_PATH_ENV, sfOwnedAuthPath } from "./credentialBinding.js";
8
8
  import { redactString } from "../logging/redact.js";
9
9
  import { getNamedSecrets } from "../logging/namedSecrets.js";
10
10
  import { readMaxActiveStageProcesses, } from "./stageConcurrency.js";
@@ -352,7 +352,7 @@ export class StageProcessLauncher {
352
352
  : overlaid;
353
353
  const childEnv = {
354
354
  ...withBrowser,
355
- [PI_HOME_AUTH_PATH_ENV]: stageflowAgentAuthPath(),
355
+ [PI_HOME_AUTH_PATH_ENV]: sfOwnedAuthPath(),
356
356
  };
357
357
  const cursorApiKey = readCursorApiKey(hostEnv);
358
358
  if (isCursorModelRef(input.model ?? "") &&
@@ -3,7 +3,8 @@ import path from "node:path";
3
3
  import { isCursorModelRef } from "../agent/cursorProvider.js";
4
4
  import { stageDir } from "../runstore/paths.js";
5
5
  import { noAttemptContext } from "./stageAttemptContext.js";
6
- import { resolveCredentialBinding } from "./credentialBinding.js";
6
+ import { resolveCredentialBinding, STAGEFLOW_AGENT_AUTH_PATH_ENV, currentExplicitAuthPath, } from "./credentialBinding.js";
7
+ import { SF_STAGE_WORKER } from "./stageWorkerProtocol.js";
7
8
  export const STAGEFLOW_CHECKOUT = "STAGEFLOW_CHECKOUT";
8
9
  export const STAGEFLOW_RUN_WORKSPACE = "STAGEFLOW_RUN_WORKSPACE";
9
10
  export const STAGEFLOW_REPOSITORY = "STAGEFLOW_REPOSITORY";
@@ -127,6 +128,16 @@ export function stageBindingEnvFromRun(options) {
127
128
  export function withResolvedAuthPath(roots, factoryCwd) {
128
129
  if (roots.authPath)
129
130
  return roots;
131
+ const explicit = currentExplicitAuthPath();
132
+ if (explicit !== undefined) {
133
+ return { ...roots, authPath: explicit };
134
+ }
135
+ if (process.env[SF_STAGE_WORKER] === "1") {
136
+ const stamped = process.env[STAGEFLOW_AGENT_AUTH_PATH_ENV]?.trim();
137
+ if (!stamped)
138
+ return roots;
139
+ return { ...roots, authPath: path.resolve(stamped) };
140
+ }
130
141
  const binding = resolveCredentialBinding(factoryCwd);
131
142
  return { ...roots, authPath: binding.authPath };
132
143
  }
@@ -1,4 +1,4 @@
1
- import type { AgentPort, FeedbackLoopContext, StageHandle, StageRunResult, StageSessionMode } from "../agent/port.js";
1
+ import type { StagePort, FeedbackLoopContext, StageHandle, StageRunResult, StageSessionMode } from "../agent/port.js";
2
2
  import { type HostGateContext } from "../browser/gateHandoff.js";
3
3
  import type { StageBrowserSupport } from "../browser/browserHost.js";
4
4
  import type { StageEnvelope } from "../types/envelope.js";
@@ -20,7 +20,7 @@ export declare function isRunStageWaiting(outcome: RunStageOutcome): outcome is
20
20
  waiting: true;
21
21
  };
22
22
  export type RunStageOptions = {
23
- agent: AgentPort;
23
+ agent: StagePort;
24
24
  store: RunStore;
25
25
  runId: string;
26
26
  stage: LoadedStageConfig;
@@ -1,4 +1,5 @@
1
- import { hostGateContextFor, stampGateRequest, } from "../browser/gateHandoff.js";
1
+ import { stampGateRequest } from "../browser/gateHandoff.js";
2
+ import { stageGateContext } from "../browser/stageHandoff.js";
2
3
  import { deriveExecutionPatchFromEvent } from "../runstore/stageExecution.js";
3
4
  import { buildStageRoots, withResolvedAuthPath, } from "./stageRoots.js";
4
5
  import { createDefaultHitlQaHooks, recordWaitEnter, } from "./stageHitl.js";
@@ -231,7 +232,12 @@ export async function runStage(options) {
231
232
  store: workerMode ? store : undefined,
232
233
  attemptCtx,
233
234
  skipGates,
234
- gateContext: hostGateContextFor(stage.browser),
235
+ gateContext: await stageGateContext({
236
+ runDir: workspaceDir ?? store.getWorkspaceDir(runId),
237
+ runId,
238
+ stageId,
239
+ browser: stage.browser,
240
+ }),
235
241
  });
236
242
  }
237
243
  catch (err) {
@@ -1,4 +1,4 @@
1
- import { resolveAgentPort } from "../agent/resolveAgentPort.js";
1
+ import { resolveStagePort } from "../agent/resolveStagePort.js";
2
2
  import { asAgentBackendId } from "../agent/agentBackend.js";
3
3
  import { loadStageflowManifestOutcome } from "../config/loadStageflowManifest.js";
4
4
  import { loadNamedSecretsFromAttemptDir } from "../logging/namedSecrets.js";
@@ -29,7 +29,7 @@ export async function runStageWorker(input) {
29
29
  }
30
30
  const dag = meta.pipeline_dag ?? loaded.dag;
31
31
  const manifestOutcome = await loadStageflowManifestOutcome(input.rootDir);
32
- const agent = resolveAgentPort({
32
+ const agent = resolveStagePort({
33
33
  global: manifestOutcome.ok
34
34
  ? asAgentBackendId(manifestOutcome.value.manifest.agent)
35
35
  : undefined,
@@ -1,12 +1,14 @@
1
1
  import type { TaskFile } from "../types/task.js";
2
2
  export type TriggerFireEvent = {
3
3
  triggerId: string;
4
+ project_root?: string;
4
5
  task?: TaskFile;
5
6
  };
6
7
  /**
7
- * Abstract seam for anything that decides "fire trigger X now" — a croner-backed
8
- * schedule loop, a GitHub/email poller, a webhook receiver. No adapter implements
9
- * this yet; it exists so those later adapters build against a locked contract.
8
+ * Long-running sources that decide "fire trigger X now". ScheduleSource,
9
+ * GithubPollSource, and EmailSource implement this. Webhook deliveries are
10
+ * request-driven: acceptWebhook shares TriggerFireEvent's optional task, and
11
+ * the HTTP route fires; a webhook is not a start/stop loop.
10
12
  */
11
13
  export interface TriggerSourcePort {
12
14
  start(onFire: (event: TriggerFireEvent) => Promise<void>): Promise<void>;
@@ -13,5 +13,6 @@ import type { TaskFile } from "../types/task.js";
13
13
  */
14
14
  export declare function fireTrigger(triggerId: string, store: RunStore, runManager: RunManager, options?: {
15
15
  cwd?: string;
16
+ project_root?: string;
16
17
  task?: TaskFile;
17
18
  }): Promise<StartRunResult>;