stageflow 0.25.0 → 0.27.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 (501) hide show
  1. package/README.md +10 -3
  2. package/dist/a2a/contracts.d.ts +1 -0
  3. package/dist/a2a/contracts.js +1 -0
  4. package/dist/a2a/registry.d.ts +2 -0
  5. package/dist/a2a/registry.js +20 -1
  6. package/dist/a2a/server.d.ts +7 -0
  7. package/dist/a2a/server.js +5 -2
  8. package/dist/a2a/service.d.ts +1 -1
  9. package/dist/a2a/service.js +57 -8
  10. package/dist/a2a/store.d.ts +8 -5
  11. package/dist/a2a/store.js +24 -67
  12. package/dist/agent/activity.d.ts +3 -0
  13. package/dist/agent/bootProviderConfig.d.ts +21 -0
  14. package/dist/agent/bootProviderConfig.js +74 -0
  15. package/dist/agent/piAdapter.d.ts +9 -1
  16. package/dist/agent/piAdapter.js +58 -3
  17. package/dist/agent/piIsolatedMcp.d.ts +2 -0
  18. package/dist/agent/piIsolatedMcp.js +10 -2
  19. package/dist/agent/port.d.ts +6 -0
  20. package/dist/agent/streamLogRedact.d.ts +1 -1
  21. package/dist/agent/streamLogRedact.js +4 -11
  22. package/dist/cli/artifactCommand.js +9 -16
  23. package/dist/cli/backupCommand.d.ts +9 -0
  24. package/dist/cli/backupCommand.js +111 -0
  25. package/dist/cli/debugRunCommand.d.ts +10 -0
  26. package/dist/cli/debugRunCommand.js +109 -0
  27. package/dist/cli/doctorCommand.d.ts +32 -0
  28. package/dist/cli/doctorCommand.js +453 -0
  29. package/dist/cli/envelopeCommand.js +9 -2
  30. package/dist/cli/exportAllCommand.d.ts +55 -0
  31. package/dist/cli/exportAllCommand.js +218 -0
  32. package/dist/cli/exportRunCommand.js +23 -21
  33. package/dist/cli/hostClient.d.ts +21 -3
  34. package/dist/cli/hostClient.js +93 -12
  35. package/dist/cli/initTemplates.d.ts +1 -1
  36. package/dist/cli/initTemplates.js +8 -1
  37. package/dist/cli/resolveSafeOutPath.d.ts +2 -0
  38. package/dist/cli/resolveSafeOutPath.js +40 -0
  39. package/dist/cli/restoreCommand.d.ts +10 -0
  40. package/dist/cli/restoreCommand.js +90 -0
  41. package/dist/cli/runCommand.d.ts +3 -2
  42. package/dist/cli/runCommand.js +93 -11
  43. package/dist/cli/runOutput.d.ts +4 -0
  44. package/dist/cli/runOutput.js +33 -7
  45. package/dist/cli/runStageCommand.d.ts +1 -0
  46. package/dist/cli/runStageCommand.js +44 -25
  47. package/dist/cli/runsCommand.d.ts +1 -1
  48. package/dist/cli/runsCommand.js +162 -8
  49. package/dist/cli.js +171 -30
  50. package/dist/config/catalogRelativePath.d.ts +62 -0
  51. package/dist/config/catalogRelativePath.js +118 -0
  52. package/dist/config/configOrigin.d.ts +27 -0
  53. package/dist/config/configOrigin.js +59 -0
  54. package/dist/config/hostConfig.d.ts +55 -0
  55. package/dist/config/hostConfig.js +333 -0
  56. package/dist/config/listSkills.d.ts +26 -0
  57. package/dist/config/listSkills.js +190 -3
  58. package/dist/config/loadOutcome.d.ts +1 -1
  59. package/dist/config/loadPipeline.js +23 -2
  60. package/dist/config/loadStage.js +18 -0
  61. package/dist/config/loadTask.d.ts +2 -0
  62. package/dist/config/loadTask.js +57 -18
  63. package/dist/config/materializeStageModels.js +5 -1
  64. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  65. package/dist/config/mergePipelineIncludes.js +19 -0
  66. package/dist/config/migrateYaml.js +6 -11
  67. package/dist/config/multiProjectCatalog.d.ts +30 -0
  68. package/dist/config/multiProjectCatalog.js +142 -0
  69. package/dist/config/normalizePipelineStageEntry.js +20 -1
  70. package/dist/config/pipelineStageKeys.js +2 -0
  71. package/dist/config/resolveCatalogRoots.d.ts +27 -0
  72. package/dist/config/resolveCatalogRoots.js +76 -0
  73. package/dist/config/resolveModel.d.ts +7 -1
  74. package/dist/config/resolveModel.js +11 -1
  75. package/dist/config/resolveStageMcpServers.d.ts +9 -1
  76. package/dist/config/resolveStageMcpServers.js +36 -9
  77. package/dist/config/secretFromEnvOrFile.d.ts +9 -0
  78. package/dist/config/secretFromEnvOrFile.js +34 -0
  79. package/dist/config/seededCatalog.d.ts +11 -0
  80. package/dist/config/seededCatalog.js +29 -0
  81. package/dist/config/toolRequires.d.ts +24 -0
  82. package/dist/config/toolRequires.js +115 -0
  83. package/dist/config/validateCatalog.d.ts +5 -1
  84. package/dist/config/validateCatalog.js +140 -1
  85. package/dist/diagnostics/checks.d.ts +39 -0
  86. package/dist/diagnostics/checks.js +135 -0
  87. package/dist/errors/codes.d.ts +14 -0
  88. package/dist/errors/codes.js +59 -0
  89. package/dist/git/cache.d.ts +14 -0
  90. package/dist/git/cache.js +150 -0
  91. package/dist/git/credentials.d.ts +9 -0
  92. package/dist/git/credentials.js +88 -0
  93. package/dist/git/errors.d.ts +20 -0
  94. package/dist/git/errors.js +94 -0
  95. package/dist/git/exec.d.ts +16 -0
  96. package/dist/git/exec.js +135 -0
  97. package/dist/git/operations.d.ts +29 -0
  98. package/dist/git/operations.js +153 -0
  99. package/dist/git/version.d.ts +1 -0
  100. package/dist/git/version.js +10 -0
  101. package/dist/logging/audit.d.ts +16 -0
  102. package/dist/logging/audit.js +19 -0
  103. package/dist/logging/commonWords.d.ts +2 -0
  104. package/dist/logging/commonWords.js +13 -0
  105. package/dist/logging/logger.d.ts +49 -0
  106. package/dist/logging/logger.js +193 -0
  107. package/dist/logging/namedSecrets.d.ts +6 -0
  108. package/dist/logging/namedSecrets.js +58 -0
  109. package/dist/logging/redact.d.ts +13 -0
  110. package/dist/logging/redact.js +88 -0
  111. package/dist/mcp/catalogTools.js +456 -80
  112. package/dist/mcp/checkoutTools.d.ts +52 -0
  113. package/dist/mcp/checkoutTools.js +332 -0
  114. package/dist/mcp/controlTools.js +179 -5
  115. package/dist/mcp/deps.d.ts +1 -0
  116. package/dist/mcp/getStartedTool.d.ts +3 -0
  117. package/dist/mcp/getStartedTool.js +62 -0
  118. package/dist/mcp/readArtifact.d.ts +11 -0
  119. package/dist/mcp/readArtifact.js +46 -30
  120. package/dist/mcp/server.js +1 -0
  121. package/dist/mcp/tools.js +4 -0
  122. package/dist/net/proxy.d.ts +14 -0
  123. package/dist/net/proxy.js +78 -0
  124. package/dist/package-meta.d.ts +2 -1
  125. package/dist/package-meta.js +2 -1
  126. package/dist/preflight/bash.d.ts +8 -0
  127. package/dist/preflight/bash.js +34 -0
  128. package/dist/preflight/claudeRoot.d.ts +11 -0
  129. package/dist/preflight/claudeRoot.js +23 -0
  130. package/dist/preflight/mcpCommands.d.ts +8 -0
  131. package/dist/preflight/mcpCommands.js +36 -0
  132. package/dist/preflight/pipelinePreflight.d.ts +40 -0
  133. package/dist/preflight/pipelinePreflight.js +192 -0
  134. package/dist/preflight/tls.d.ts +6 -0
  135. package/dist/preflight/tls.js +18 -0
  136. package/dist/preflight/toolchain.d.ts +45 -0
  137. package/dist/preflight/toolchain.js +219 -0
  138. package/dist/project/findProjectRoot.js +3 -4
  139. package/dist/project/globalHome.d.ts +7 -0
  140. package/dist/project/globalHome.js +63 -2
  141. package/dist/project/resolveProjectContext.js +2 -2
  142. package/dist/project/resolveStageflowContext.js +2 -2
  143. package/dist/projection/projectRun.d.ts +2 -1
  144. package/dist/projection/projectRun.js +1 -0
  145. package/dist/runstore/assertTmpdir.d.ts +1 -0
  146. package/dist/runstore/assertTmpdir.js +21 -0
  147. package/dist/runstore/backup.d.ts +52 -0
  148. package/dist/runstore/backup.js +292 -0
  149. package/dist/runstore/createStore.d.ts +18 -1
  150. package/dist/runstore/createStore.js +64 -5
  151. package/dist/runstore/debugBundle.d.ts +60 -0
  152. package/dist/runstore/debugBundle.js +143 -0
  153. package/dist/runstore/diskUsage.d.ts +50 -0
  154. package/dist/runstore/diskUsage.js +214 -0
  155. package/dist/runstore/exportRunPayload.d.ts +8 -0
  156. package/dist/runstore/exportRunPayload.js +23 -0
  157. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  158. package/dist/runstore/normalizeCatalogPath.js +10 -0
  159. package/dist/runstore/paths.d.ts +5 -0
  160. package/dist/runstore/paths.js +145 -1
  161. package/dist/runstore/port.d.ts +111 -13
  162. package/dist/runstore/port.js +8 -1
  163. package/dist/runstore/restore.d.ts +81 -0
  164. package/dist/runstore/restore.js +355 -0
  165. package/dist/runstore/retention.d.ts +27 -0
  166. package/dist/runstore/retention.js +74 -0
  167. package/dist/runstore/runManifest.d.ts +146 -0
  168. package/dist/runstore/runManifest.js +288 -0
  169. package/dist/runstore/runProjection.d.ts +3 -1
  170. package/dist/runstore/runProjection.js +63 -1
  171. package/dist/runstore/sqlite/SqliteRunStore.d.ts +28 -3
  172. package/dist/runstore/sqlite/SqliteRunStore.js +352 -219
  173. package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
  174. package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
  175. package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
  176. package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
  177. package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
  178. package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
  179. package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
  180. package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
  181. package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
  182. package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
  183. package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
  184. package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
  185. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
  186. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
  187. package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
  188. package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
  189. package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
  190. package/dist/runstore/sqlite/migrations/index.js +72 -0
  191. package/dist/runstore/sqlite/schema.d.ts +20 -1
  192. package/dist/runstore/sqlite/schema.js +277 -1
  193. package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
  194. package/dist/runstore/sqlite/storeOpenError.js +11 -0
  195. package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
  196. package/dist/runstore/sqlite/storeSchemaError.js +8 -0
  197. package/dist/runstore/stageExecution.js +3 -0
  198. package/dist/runstore/storeFilesystem.d.ts +32 -0
  199. package/dist/runstore/storeFilesystem.js +148 -0
  200. package/dist/runstore/trackProjection.js +2 -0
  201. package/dist/runstore/workspaceLayout.d.ts +13 -0
  202. package/dist/runstore/workspaceLayout.js +76 -0
  203. package/dist/runtime/completionCheckRunner.d.ts +3 -0
  204. package/dist/runtime/completionCheckRunner.js +45 -7
  205. package/dist/runtime/containerLimits.d.ts +16 -0
  206. package/dist/runtime/containerLimits.js +84 -0
  207. package/dist/runtime/credentialMaterialisation.d.ts +28 -0
  208. package/dist/runtime/credentialMaterialisation.js +128 -0
  209. package/dist/runtime/gitCheckoutCapability.js +7 -13
  210. package/dist/runtime/pipelineRunner.d.ts +36 -1
  211. package/dist/runtime/pipelineRunner.js +178 -17
  212. package/dist/runtime/pipelineScheduler.d.ts +15 -0
  213. package/dist/runtime/pipelineScheduler.js +135 -27
  214. package/dist/runtime/reloadRunCatalog.js +6 -1
  215. package/dist/runtime/repositoryMaterialize.d.ts +47 -0
  216. package/dist/runtime/repositoryMaterialize.js +235 -0
  217. package/dist/runtime/resumeTimedOut.d.ts +1 -1
  218. package/dist/runtime/resumeTimedOut.js +5 -2
  219. package/dist/runtime/runChangeBus.js +9 -0
  220. package/dist/runtime/runDeletion.d.ts +7 -0
  221. package/dist/runtime/runDeletion.js +37 -0
  222. package/dist/runtime/runManager.d.ts +158 -4
  223. package/dist/runtime/runManager.js +1596 -79
  224. package/dist/runtime/runRetentionSweep.d.ts +31 -0
  225. package/dist/runtime/runRetentionSweep.js +328 -0
  226. package/dist/runtime/runRetryCoordinator.d.ts +2 -0
  227. package/dist/runtime/runRetryCoordinator.js +19 -2
  228. package/dist/runtime/runSkills.d.ts +40 -0
  229. package/dist/runtime/runSkills.js +173 -0
  230. package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
  231. package/dist/runtime/stageAttemptBootstrap.js +195 -24
  232. package/dist/runtime/stageCacheEnv.d.ts +6 -0
  233. package/dist/runtime/stageCacheEnv.js +34 -0
  234. package/dist/runtime/stageConcurrency.d.ts +2 -1
  235. package/dist/runtime/stageConcurrency.js +4 -2
  236. package/dist/runtime/stageEnvironment.d.ts +38 -0
  237. package/dist/runtime/stageEnvironment.js +193 -0
  238. package/dist/runtime/stageProcessLauncher.d.ts +18 -0
  239. package/dist/runtime/stageProcessLauncher.js +194 -38
  240. package/dist/runtime/stageRecovery.d.ts +3 -1
  241. package/dist/runtime/stageRecovery.js +19 -4
  242. package/dist/runtime/stageRoots.d.ts +38 -1
  243. package/dist/runtime/stageRoots.js +118 -0
  244. package/dist/runtime/stageRunner.d.ts +1 -0
  245. package/dist/runtime/stageRunner.js +3 -1
  246. package/dist/runtime/stageSecretDecl.d.ts +9 -0
  247. package/dist/runtime/stageSecretDecl.js +102 -0
  248. package/dist/runtime/stageSecrets.d.ts +40 -0
  249. package/dist/runtime/stageSecrets.js +181 -0
  250. package/dist/runtime/stageWorker.d.ts +3 -2
  251. package/dist/runtime/stageWorker.js +58 -10
  252. package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
  253. package/dist/runtime/stageWorkerProtocol.js +8 -0
  254. package/dist/runtime/startPayload.d.ts +32 -0
  255. package/dist/runtime/startPayload.js +59 -0
  256. package/dist/runtime/taskInput.js +14 -5
  257. package/dist/runtime/verifiedStageExecution.d.ts +1 -0
  258. package/dist/runtime/verifiedStageExecution.js +2 -1
  259. package/dist/runtime/workspaceBinding.d.ts +20 -0
  260. package/dist/runtime/workspaceBinding.js +60 -0
  261. package/dist/server/allowedHosts.d.ts +19 -0
  262. package/dist/server/allowedHosts.js +179 -0
  263. package/dist/server/bootstrap.d.ts +36 -2
  264. package/dist/server/bootstrap.js +209 -5
  265. package/dist/server/controlToken.d.ts +47 -0
  266. package/dist/server/controlToken.js +241 -0
  267. package/dist/server/createHttpHost.d.ts +11 -2
  268. package/dist/server/createHttpHost.js +103 -10
  269. package/dist/server/ensureGlobalService.d.ts +5 -1
  270. package/dist/server/ensureGlobalService.js +35 -1
  271. package/dist/server/healthSurfaces.d.ts +6 -0
  272. package/dist/server/healthSurfaces.js +98 -0
  273. package/dist/server/http.d.ts +12 -1
  274. package/dist/server/http.js +1085 -485
  275. package/dist/server/listenHost.d.ts +5 -0
  276. package/dist/server/listenHost.js +56 -0
  277. package/dist/server/mcpHost.d.ts +10 -1
  278. package/dist/server/mcpHost.js +36 -6
  279. package/dist/server/operatorResults.d.ts +2 -2
  280. package/dist/server/operatorResults.js +40 -29
  281. package/dist/server/requestAuthContext.d.ts +12 -0
  282. package/dist/server/requestAuthContext.js +21 -0
  283. package/dist/server/shutdown.d.ts +69 -0
  284. package/dist/server/shutdown.js +219 -0
  285. package/dist/types/pipeline.d.ts +7 -0
  286. package/dist/types/stage.d.ts +8 -0
  287. package/dist/types/task.d.ts +8 -0
  288. package/dist/ui/assets/index-B6hlSXXn.js +120 -0
  289. package/dist/ui/index.html +1 -1
  290. package/examples/README.md +98 -0
  291. package/examples/archify-on-pr/README.md +213 -0
  292. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
  293. package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
  294. package/examples/archify-on-pr/author-diagrams.yaml +106 -0
  295. package/examples/archify-on-pr/detect-changes.yaml +89 -0
  296. package/examples/ci-validate/README.md +35 -0
  297. package/examples/ci-validate/check.yaml +13 -0
  298. package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
  299. package/examples/ci-validate/validate.sh +5 -0
  300. package/examples/compliance-review-demo/README.md +125 -0
  301. package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
  302. package/examples/compliance-review-demo/connect-account.yaml +47 -0
  303. package/examples/compliance-review-demo/map-to-control.yaml +123 -0
  304. package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
  305. package/examples/compliance-review-demo/publish-report.yaml +79 -0
  306. package/examples/compliance-review-demo/review-verdict.yaml +122 -0
  307. package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
  308. package/examples/compliance-review-demo/store-evidence.yaml +143 -0
  309. package/examples/conditional-fork/README.md +89 -0
  310. package/examples/conditional-fork/branch-a.yaml +13 -0
  311. package/examples/conditional-fork/branch-b.yaml +13 -0
  312. package/examples/conditional-fork/decide.yaml +35 -0
  313. package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
  314. package/examples/conditional-fork/fork-demo.task.yaml +8 -0
  315. package/examples/context7-mcp/README.md +42 -0
  316. package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
  317. package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
  318. package/examples/context7-mcp/fetch-docs.yaml +52 -0
  319. package/examples/context7-mcp/resolve-library.yaml +31 -0
  320. package/examples/context7-mcp/write-brief.yaml +52 -0
  321. package/examples/feature-loop/README.md +104 -0
  322. package/examples/feature-loop/address-feedback.yaml +148 -0
  323. package/examples/feature-loop/align.yaml +116 -0
  324. package/examples/feature-loop/decompose.yaml +86 -0
  325. package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
  326. package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
  327. package/examples/feature-loop/feature-loop.task.yaml +25 -0
  328. package/examples/feature-loop/implement.yaml +128 -0
  329. package/examples/feature-loop/plan.yaml +111 -0
  330. package/examples/feature-loop/publish.yaml +167 -0
  331. package/examples/feature-loop/review.yaml +146 -0
  332. package/examples/feature-loop/verify.yaml +106 -0
  333. package/examples/feedback-loop/README.md +72 -0
  334. package/examples/feedback-loop/VERIFY.md +208 -0
  335. package/examples/feedback-loop/continue-only.task.yaml +4 -0
  336. package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
  337. package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
  338. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
  339. package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
  340. package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
  341. package/examples/feedback-loop/implement.yaml +14 -0
  342. package/examples/feedback-loop/plan.yaml +14 -0
  343. package/examples/feedback-loop/review.yaml +15 -0
  344. package/examples/feedback-loop/send-back-once.task.yaml +6 -0
  345. package/examples/feedback-loop/submit.yaml +12 -0
  346. package/examples/generic-fan-in/README.md +151 -0
  347. package/examples/generic-fan-in/clarify.yaml +18 -0
  348. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
  349. package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
  350. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
  351. package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
  352. package/examples/generic-fan-in/research.yaml +45 -0
  353. package/examples/generic-fan-in/synthesize.yaml +66 -0
  354. package/examples/generic-fan-in/validation.yaml +45 -0
  355. package/examples/github-release/README.md +78 -0
  356. package/examples/github-release/draft-release-notes.yaml +64 -0
  357. package/examples/github-release/github-release.pipeline.yaml +11 -0
  358. package/examples/github-release/github-release.task.yaml +13 -0
  359. package/examples/github-release/publish-github-release.yaml +64 -0
  360. package/examples/hello-world/README.md +28 -0
  361. package/examples/hello-world/hello.pipeline.yaml +4 -0
  362. package/examples/hello-world/my-task.task.yaml +6 -0
  363. package/examples/hello-world/research.yaml +18 -0
  364. package/examples/mcp-hitl-tour/README.md +113 -0
  365. package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
  366. package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
  367. package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
  368. package/examples/mcp-hitl-tour/gather.yaml +31 -0
  369. package/examples/mcp-hitl-tour/intake.yaml +62 -0
  370. package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
  371. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
  372. package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
  373. package/examples/mcp-hitl-tour/polish.yaml +33 -0
  374. package/examples/mcp-hitl-tour/review.yaml +17 -0
  375. package/examples/mcp-hitl-tour/ship.yaml +25 -0
  376. package/examples/oss-issue-contribution/README.md +218 -0
  377. package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
  378. package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
  379. package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
  380. package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
  381. package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
  382. package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
  383. package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
  384. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
  385. package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
  386. package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
  387. package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
  388. package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
  389. package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
  390. package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
  391. package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
  392. package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
  393. package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
  394. package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
  395. package/examples/oss-quick-fix/README.md +65 -0
  396. package/examples/oss-quick-fix/implement-fix.yaml +84 -0
  397. package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
  398. package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
  399. package/examples/oss-quick-fix/ship-fix.yaml +81 -0
  400. package/examples/oss-quick-fix/understand-issue.yaml +67 -0
  401. package/examples/oss-quick-fix/verify-fix.yaml +73 -0
  402. package/examples/plan-review/README.md +37 -0
  403. package/examples/plan-review/plan-review-followup.yaml +13 -0
  404. package/examples/plan-review/plan-review.pipeline.yaml +9 -0
  405. package/examples/plan-review/plan-review.task.yaml +9 -0
  406. package/examples/plan-review/plan-review.yaml +25 -0
  407. package/examples/playwright-mcp/README.md +39 -0
  408. package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
  409. package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
  410. package/examples/playwright-mcp/screenshot.yaml +40 -0
  411. package/examples/retry-tour/README.md +75 -0
  412. package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
  413. package/examples/retry-tour/retry-tour.task.yaml +9 -0
  414. package/examples/route-if-tour/README.md +202 -0
  415. package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
  416. package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
  417. package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
  418. package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
  419. package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
  420. package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
  421. package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
  422. package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
  423. package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
  424. package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
  425. package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
  426. package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
  427. package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
  428. package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
  429. package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
  430. package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
  431. package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
  432. package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
  433. package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
  434. package/examples/route-wiring-smoke-test/README.md +377 -0
  435. package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
  436. package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
  437. package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
  438. package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
  439. package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
  440. package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
  441. package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
  442. package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
  443. package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
  444. package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
  445. package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
  446. package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
  447. package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
  448. package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
  449. package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
  450. package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
  451. package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
  452. package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
  453. package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
  454. package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
  455. package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
  456. package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
  457. package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
  458. package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
  459. package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
  460. package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
  461. package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
  462. package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
  463. package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
  464. package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
  465. package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
  466. package/examples/ship-feature/README.md +190 -0
  467. package/examples/ship-feature/feat-address-feedback.yaml +119 -0
  468. package/examples/ship-feature/feat-implement.yaml +180 -0
  469. package/examples/ship-feature/feat-plan.yaml +120 -0
  470. package/examples/ship-feature/feat-review.yaml +109 -0
  471. package/examples/ship-feature/feat-ship.yaml +203 -0
  472. package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
  473. package/examples/ship-feature/ship-feature.task.yaml +78 -0
  474. package/examples/stage-mcp/README.md +144 -0
  475. package/examples/stage-mcp/echo-mcp.mjs +20 -0
  476. package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
  477. package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
  478. package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
  479. package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
  480. package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
  481. package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
  482. package/examples/stage-mcp/use-echo.yaml +20 -0
  483. package/examples/verify-tour/README.md +80 -0
  484. package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
  485. package/examples/verify-tour/verify-tour.task.yaml +11 -0
  486. package/package.json +5 -1
  487. package/skills/stageflow/SKILL.md +6 -6
  488. package/skills/stageflow/references/control-surface.md +11 -5
  489. package/skills/stageflow/scripts/detect-host.mjs +14 -1
  490. package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
  491. package/skills/stageflow-author/SKILL.md +4 -3
  492. package/skills/stageflow-author/references/catalog-mapping.md +16 -0
  493. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  494. package/skills/stageflow-run/SKILL.md +20 -12
  495. package/skills/stageflow-run/references/mcp-call.md +9 -1
  496. package/skills/stageflow-run/references/task-and-pipeline-selection.md +16 -5
  497. package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
  498. package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
  499. package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
  500. package/skills/stageflow-setup/SKILL.md +40 -8
  501. package/dist/ui/assets/index-Da5EHU6M.js +0 -119
@@ -0,0 +1,72 @@
1
+ # feedback-loop
2
+
3
+ Source-owned feedback loop: `review` may `continue` or `send_back` to `implement`.
4
+ `submit` is `replay_safe: false` so it is never on a replay route.
5
+
6
+ Catalog policy is a `{ type: loop }` entry on `route` (not a top-level `feedback_loop:` key). The envelope field is still `feedback_loop`. See [YAML catalog — Feedback loops](../../docs/yaml-catalog.md#feedback-loops) and [`feedback-loop.pipeline.yaml`](../../tests/fixtures/pipelines/feedback-loop.pipeline.yaml).
7
+
8
+ Domain-neutral — the same wiring works for release notes, research digests, content review, or an SDLC-style plan/implement pass.
9
+
10
+ ## Prerequisites
11
+
12
+ - Node.js ≥ 20, Stageflow installed (`npm i -g stageflow`), **or** this repo built (`npm run build`)
13
+ - Provider auth connected (`sf ui` → Settings → Providers, or `sf providers login …`)
14
+
15
+ ## Manual verification (recommended)
16
+
17
+ Step-by-step scenarios A–D (continue, one send_back, require_continue exhaust, wait_for_human decide):
18
+
19
+ → **[VERIFY.md](./VERIFY.md)**
20
+
21
+ ## Commands
22
+
23
+ From the **repository git root**:
24
+
25
+ ```bash
26
+ sf validate --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml --strict
27
+ sf run \
28
+ --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml \
29
+ --task examples/feedback-loop/feedback-loop.task.yaml
30
+ ```
31
+
32
+ Wait-for-human policy (`max_replays: 1`):
33
+
34
+ ```bash
35
+ sf run \
36
+ --pipeline examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml \
37
+ --task examples/feedback-loop/exhaust-wait-human.task.yaml
38
+ ```
39
+
40
+ Optional console (any subdirectory):
41
+
42
+ ```bash
43
+ cd examples/feedback-loop && sf ui
44
+ ```
45
+
46
+ ### From the Stageflow repo (no global install)
47
+
48
+ ```bash
49
+ npm run build
50
+ npm run dev -- validate --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml --strict
51
+ npm run dev -- run \
52
+ --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml \
53
+ --task examples/feedback-loop/feedback-loop.task.yaml
54
+ ```
55
+
56
+ ## Layout
57
+
58
+ ```
59
+ examples/feedback-loop/
60
+ VERIFY.md # manual scenarios A–D
61
+ feedback-loop.pipeline.yaml # require_continue, max_replays 2
62
+ feedback-loop-wait-human.pipeline.yaml
63
+ feedback-loop.task.yaml
64
+ continue-only / send-back-once / exhaust-*.task.yaml
65
+ plan.yaml | implement.yaml | review.yaml | submit.yaml
66
+ ```
67
+
68
+ ## References
69
+
70
+ - [YAML catalog — Feedback loops](../../docs/yaml-catalog.md#feedback-loops)
71
+ - [Envelopes — Feedback loops](../../docs/envelopes.md#feedback-loops)
72
+ - [CLI — feedback-decide](../../docs/cli-reference.md#sf-runs-feedback-decide)
@@ -0,0 +1,208 @@
1
+ # Feedback-loop manual verification
2
+
3
+ Simple runs to exercise the feedback-loop work from this repo. Uses a real provider (not FakeAgent).
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ cd /path/to/software-factory
9
+ npm i
10
+ npm run build
11
+ # Provider auth once (example stages use omniroute/auto)
12
+ # Connect via: npm run dev -- ui → Settings → Providers
13
+ ```
14
+
15
+ Use `npm run dev -- …` as `sf` from this worktree. Run state lives in `<repo>/.stageflow/`.
16
+
17
+ Optional console:
18
+
19
+ ```bash
20
+ npm run dev -- ui
21
+ ```
22
+
23
+ If `sf ui` is up on `:3847`, mutating CLI (`runs feedback-decide`) is refused — decide in the UI panel, or stop the host and use CLI.
24
+
25
+ Validate once:
26
+
27
+ ```bash
28
+ npm run dev -- validate --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml --strict
29
+ npm run dev -- validate --pipeline examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml --strict
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Scenario A — Continue only (happy path)
35
+
36
+ **Expect:** `plan → implement → review → submit`, no replay.
37
+
38
+ ```bash
39
+ npm run dev -- run \
40
+ --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml \
41
+ --task examples/feedback-loop/continue-only.task.yaml \
42
+ --json > /tmp/fb-a.json
43
+ ```
44
+
45
+ **Pass:** exit `0`; all four stages `succeeded`; `submit` ran once.
46
+
47
+ ```bash
48
+ RUN=$(jq -r .runId /tmp/fb-a.json)
49
+ npm run dev -- runs show --run "$RUN" --json | jq '{
50
+ status,
51
+ stages: [.stages[] | {id: .stage_id, status}],
52
+ active: .active_feedback_loop,
53
+ loops: [.feedback_loops[]?.loop.state]
54
+ }'
55
+ ```
56
+
57
+ **Fail:** any `send_back`, or `submit` never runs.
58
+
59
+ ---
60
+
61
+ ## Scenario B — One send_back, then continue
62
+
63
+ **Expect:** review sends back to `implement` once; replay includes Feedback Loop Context; then continue → submit.
64
+
65
+ ```bash
66
+ npm run dev -- run \
67
+ --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml \
68
+ --task examples/feedback-loop/send-back-once.task.yaml \
69
+ --json > /tmp/fb-b.json
70
+ ```
71
+
72
+ **Pass:**
73
+
74
+ - Stage path roughly `plan → implement → review → implement → review → submit`
75
+ - One replay in history; loop ends `continued`
76
+ - On the replayed stages, the agent prompt shows a **Feedback Loop Context** block
77
+
78
+ ```bash
79
+ RUN=$(jq -r .runId /tmp/fb-b.json)
80
+ npm run dev -- runs show --run "$RUN" --json | jq '{
81
+ status,
82
+ stages: [.stages[] | {id: .stage_id, status}],
83
+ replays: [.feedback_loops[0].replays[] | {
84
+ n: .replay.replay_number,
85
+ target: .replay.target_stage_id,
86
+ status: .replay.status
87
+ }],
88
+ loop: .feedback_loops[0].loop.state
89
+ }'
90
+ ```
91
+
92
+ UI: Feedback Loop panel shows budget / route / replay timeline.
93
+
94
+ **Fail:** submit before continue; no replay recorded; no Feedback Loop Context on replay.
95
+
96
+ ---
97
+
98
+ ## Scenario C — Exhaust `require_continue` (over-limit send_back fails)
99
+
100
+ Pipeline: `max_replays: 2`, `on_max_replays: require_continue`.
101
+
102
+ **Expect:** two accepted send_backs, third rejected; `submit` never succeeds.
103
+
104
+ ```bash
105
+ npm run dev -- run \
106
+ --pipeline examples/feedback-loop/feedback-loop.pipeline.yaml \
107
+ --task examples/feedback-loop/exhaust-require-continue.task.yaml \
108
+ --json > /tmp/fb-c.json
109
+ ```
110
+
111
+ **Pass:** run failed; ~2 replays; failure mentions `max_replays` / `require_continue`; `submit` not succeeded.
112
+
113
+ ```bash
114
+ RUN=$(jq -r .runId /tmp/fb-c.json)
115
+ npm run dev -- runs show --run "$RUN" --json | jq '{
116
+ status,
117
+ failed_stage_id,
118
+ failed_reason,
119
+ replay_count: (.feedback_loops[0].replays | length),
120
+ submit: [.stages[] | select(.stage_id=="submit") | .status]
121
+ }'
122
+ ```
123
+
124
+ **Fail:** third send_back accepted; run succeeds; or parks for human (wrong policy).
125
+
126
+ ---
127
+
128
+ ## Scenario D — Exhaust `wait_for_human`, then decide
129
+
130
+ Pipeline: `feedback-loop-wait-human.pipeline.yaml` (`max_replays: 1`, `on_max_replays: wait_for_human`).
131
+
132
+ **Pairing:** You **must** use `feedback-loop-wait-human.pipeline.yaml` with `exhaust-wait-human.task.yaml`. The default `feedback-loop.pipeline.yaml` uses `require_continue` — wrong pipeline means **no human ask** (run fails on over-limit send_back instead of parking). Every review success until park must `send_back` (never `continue`).
133
+
134
+ **Expect:** second send_back parks the run; you choose extend / continue / abandon.
135
+
136
+ Prefer **no** `sf ui` on `:3847` if you will use CLI decide.
137
+
138
+ ```bash
139
+ npm run dev -- run \
140
+ --pipeline examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml \
141
+ --task examples/feedback-loop/exhaust-wait-human.task.yaml \
142
+ --json > /tmp/fb-d.json
143
+ # Exit 2 when parked waiting is normal
144
+ ```
145
+
146
+ Inspect the park:
147
+
148
+ ```bash
149
+ RUN=$(jq -r .runId /tmp/fb-d.json)
150
+ npm run dev -- runs waiting --run "$RUN" --json
151
+ npm run dev -- runs show --run "$RUN" --json | jq '.active_feedback_loop | {
152
+ state, policy, deferred_send_back
153
+ }'
154
+ ```
155
+
156
+ Expect `waiting_kind: "feedback_loop_decision"`, `state: "waiting_for_human"`, deferred target `implement`.
157
+
158
+ Pick **one** decision (host down for CLI):
159
+
160
+ ```bash
161
+ # Extra replay budget, then agent should continue later
162
+ npm run dev -- runs feedback-decide --run "$RUN" --stage review --decision extend --json
163
+
164
+ # Or release downstream without another replay
165
+ npm run dev -- runs feedback-decide --run "$RUN" --stage review --decision continue --json
166
+
167
+ # Or fail the run
168
+ npm run dev -- runs feedback-decide --run "$RUN" --stage review --decision abandon --reason "stop" --json
169
+ ```
170
+
171
+ With `sf ui` instead: open the run → FeedbackDecidePanel → Extend / Continue / Abandon.
172
+
173
+ After decide, wait for terminal if needed:
174
+
175
+ ```bash
176
+ npm run dev -- runs wait --run "$RUN" --until terminal --timeout-ms 240000 --json
177
+ ```
178
+
179
+ **Pass:**
180
+
181
+ | Decision | Expect |
182
+ |----------|--------|
183
+ | `extend` | `effect: extended`; another implement→review; then continue → submit; `max_replays` bumped by 1 |
184
+ | `continue` | `effect: continued`; submit runs; no further replay |
185
+ | `abandon` | run `failed`; submit never runs |
186
+
187
+ **Fail:** second send_back rejected instead of parking; decide refused while host is still up.
188
+
189
+ ---
190
+
191
+ ## Quick matrix
192
+
193
+ | Scenario | Pipeline | Task | Cost note |
194
+ |----------|----------|------|-----------|
195
+ | A Continue | `feedback-loop.pipeline.yaml` | `continue-only.task.yaml` | ~4 stages |
196
+ | B One send_back | `feedback-loop.pipeline.yaml` | `send-back-once.task.yaml` | ~6 stage runs |
197
+ | C require_continue exhaust | `feedback-loop.pipeline.yaml` | `exhaust-require-continue.task.yaml` | ~7+ stage runs, expects failure |
198
+ | D wait_for_human | `feedback-loop-wait-human.pipeline.yaml` | `exhaust-wait-human.task.yaml` | parks; then decide |
199
+
200
+ Clone-chain Loop from Join is covered by fixture
201
+ [`tests/fixtures/pipelines/clone-chain-loop-from-join.pipeline.yaml`](../../tests/fixtures/pipelines/clone-chain-loop-from-join.pipeline.yaml),
202
+ not this walkthrough.
203
+
204
+ ## References
205
+
206
+ - [YAML catalog — Feedback loops](../../docs/yaml-catalog.md#feedback-loops)
207
+ - [CLI — feedback-decide](../../docs/cli-reference.md#sf-runs-feedback-decide)
208
+ - [Envelopes — Feedback loops](../../docs/envelopes.md#feedback-loops)
@@ -0,0 +1,4 @@
1
+ id: feedback-loop-continue-only
2
+ goal: Draft a short brief and submit it after review continues on the first pass
3
+ context: Verification scenario — review must emit continue (no send_back)
4
+ constraints: Docs only. review must emit feedback_loop.action continue on the first success.
@@ -0,0 +1,6 @@
1
+ id: feedback-loop-exhaust-require-continue
2
+ goal: Keep sending work back from review until the loop rejects further send_back
3
+ context: Verification scenario — force require_continue max_replays exhaustion
4
+ constraints: |
5
+ Docs only. Every successful review must emit feedback_loop send_back target implement.
6
+ Never emit continue. Expect the third send_back to fail after max_replays 2.
@@ -0,0 +1,11 @@
1
+ id: feedback-loop-exhaust-wait-human
2
+ goal: Send work back twice so the loop parks for a human decision
3
+ context: Verification scenario — wait_for_human after max_replays 1
4
+ constraints: |
5
+ MUST pair with pipeline feedback-loop-wait-human.pipeline.yaml
6
+ (on_max_replays: wait_for_human, max_replays: 1). Do NOT use
7
+ feedback-loop.pipeline.yaml (require_continue) — that never asks a human.
8
+ Docs only. Every review success until the run parks MUST emit send_back
9
+ target implement — never emit continue. First review: send_back implement;
10
+ after replay, second review: send_back implement again so the loop parks
11
+ for feedback-decide.
@@ -0,0 +1,23 @@
1
+ id: feedback-loop-wait-human
2
+ stages:
3
+ - id: plan
4
+ entry: true
5
+ route:
6
+ - to: implement
7
+ uses: ./plan.yaml
8
+ - id: implement
9
+ route:
10
+ - to: review
11
+ uses: ./implement.yaml
12
+ - id: review
13
+ route:
14
+ - to: submit
15
+ - type: loop
16
+ to: implement
17
+ max_replays: 1
18
+ on_max_replays: wait_for_human
19
+ replay_session: resume
20
+ uses: ./review.yaml
21
+ - id: submit
22
+ uses: ./submit.yaml
23
+ replay_safe: false
@@ -0,0 +1,23 @@
1
+ id: feedback-loop
2
+ stages:
3
+ - id: plan
4
+ entry: true
5
+ route:
6
+ - to: implement
7
+ uses: ./plan.yaml
8
+ - id: implement
9
+ route:
10
+ - to: review
11
+ uses: ./implement.yaml
12
+ - id: review
13
+ route:
14
+ - to: submit
15
+ - type: loop
16
+ to: implement
17
+ max_replays: 2
18
+ on_max_replays: require_continue
19
+ replay_session: resume
20
+ uses: ./review.yaml
21
+ - id: submit
22
+ uses: ./submit.yaml
23
+ replay_safe: false
@@ -0,0 +1,4 @@
1
+ id: feedback-loop
2
+ goal: Draft a short brief, revise it until a review stage continues, then submit
3
+ context: Domain-neutral feedback-loop walkthrough — plan → implement → review → submit
4
+ constraints: Docs only; no implementation code. Prefer one send_back then continue.
@@ -0,0 +1,14 @@
1
+ id: implement
2
+ system_prompt: |
3
+ Produce the work described by the upstream plan envelope.
4
+ Keep the deliverable short (a brief outline or draft).
5
+ Emit a success envelope summarizing what you produced.
6
+ On a feedback replay, read Feedback Loop Context and address the review feedback.
7
+ model: omniroute/auto
8
+ io:
9
+ input:
10
+ schema:
11
+ type: object
12
+ output:
13
+ schema:
14
+ type: object
@@ -0,0 +1,14 @@
1
+ id: plan
2
+ system_prompt: |
3
+ Create a short plan for the task goal.
4
+ List the sections you will produce and any open questions.
5
+ Emit a success envelope with a clear summary when done.
6
+ On a feedback replay, read Feedback Loop Context and revise the plan to address the send-back.
7
+ model: omniroute/auto
8
+ io:
9
+ input:
10
+ schema:
11
+ type: object
12
+ output:
13
+ schema:
14
+ type: object
@@ -0,0 +1,15 @@
1
+ id: review
2
+ system_prompt: |
3
+ Review the upstream work against the task goal.
4
+ On success you MUST include feedback_loop in emit_stage_envelope:
5
+ - {"action":"continue"} when the work is good enough to submit
6
+ - {"action":"send_back","target":"implement"} when another pass is needed
7
+ Prefer at most one send_back in this walkthrough, then continue.
8
+ model: omniroute/auto
9
+ io:
10
+ input:
11
+ schema:
12
+ type: object
13
+ output:
14
+ schema:
15
+ type: object
@@ -0,0 +1,6 @@
1
+ id: feedback-loop-send-back-once
2
+ goal: Draft a short brief, send it back once from review, then continue and submit
3
+ context: Verification scenario — exactly one send_back to implement, then continue
4
+ constraints: |
5
+ Docs only. On the first review success, emit feedback_loop send_back target implement.
6
+ On the second review success, emit feedback_loop continue. Do not send_back twice.
@@ -0,0 +1,12 @@
1
+ id: submit
2
+ system_prompt: |
3
+ Submit the approved work. Summarize the final brief in the envelope.
4
+ This stage is replay_safe: false — it runs only after review continues.
5
+ model: omniroute/auto
6
+ io:
7
+ input:
8
+ schema:
9
+ type: object
10
+ output:
11
+ schema:
12
+ type: object
@@ -0,0 +1,151 @@
1
+ # generic-fan-in
2
+
3
+ Dummy catalog for **manual operator-console testing** of generic multi-parent
4
+ fan-in. `research` and `validation` run in parallel after `clarify`, pause on
5
+ a free-text gate, then emit distinct payloads. `synthesize` waits for both and
6
+ must copy `priorEnvelopesByStage` into `payload.received` so you can inspect
7
+ what was handed across the join.
8
+
9
+ Catalog wiring is outbound `route`: `research` and `validation` each list `to: synthesize`. Join rules (shipped runtime): the child waits until every parent is terminal; it **runs** if at least one parent succeeded (skipped siblings do not block); it stays **pending** if any parent failed (even when `on` lists `failed`); it force-skips only if every parent skipped. Including `failed` or `skipped` in `on:` opts that edge out of skip-cascade; it does not launch the Join from a failed parent.
10
+
11
+ Wiring matches the fixture twins: [`diamond-fan-in.pipeline.yaml`](../../tests/fixtures/pipelines/diamond-fan-in.pipeline.yaml) and [`diamond-fan-in-accepted.pipeline.yaml`](../../tests/fixtures/pipelines/diamond-fan-in-accepted.pipeline.yaml). See [`docs/yaml-catalog.md#generic-fan-in`](../../docs/yaml-catalog.md#generic-fan-in).
12
+
13
+ Two pipelines:
14
+
15
+ | Pipeline | What it exercises |
16
+ |----------|-------------------|
17
+ | `generic-fan-in` | Default succeeded-only edges into `synthesize` |
18
+ | `generic-fan-in-accepted` | Research edge `on: [succeeded, failed, skipped]` — still does **not** run the Join after research fails |
19
+
20
+ ## Prerequisites
21
+
22
+ Use this repo's CLI (`npm run build` / `npm run dev`) or a Stageflow release
23
+ that includes generic fan-in. A globally installed `sf` from npm may lag.
24
+
25
+ - Node.js ≥ 20
26
+ - From repo root: `npm run build` and `npm run ui:build`
27
+ - Provider auth connected (`sf ui` → Settings → Providers). Stages use `cursor/auto`.
28
+
29
+ Run state lives in `<repo>/.stageflow` even if you start the console from a subdirectory.
30
+
31
+ ## Terminal 1 — operator console
32
+
33
+ From the **repository git root**:
34
+
35
+ ```bash
36
+ npm run build
37
+ npm run ui:build
38
+ PI_CURSOR_SETTING_SOURCES=all STAGEFLOW_ACTIVITY_VERBOSE=1 node dist/cli.js ui
39
+ ```
40
+
41
+ `npm run dev -- ui` runs the TypeScript CLI via tsx; use `node dist/cli.js ui` after `ui:build` so the console is served from `dist/ui`. Do not use a globally installed `sf` — Homebrew `sf` is an older build that cannot load this catalog.
42
+
43
+ Open `http://127.0.0.1:3847`. Browse should list **generic-fan-in** and **generic-fan-in-accepted** (same names as the YAML files).
44
+
45
+ ## Terminal 2 — start a run (repo root)
46
+
47
+ ```bash
48
+ node dist/cli.js validate --pipeline examples/generic-fan-in/generic-fan-in.pipeline.yaml --strict
49
+ node dist/cli.js run \
50
+ --pipeline examples/generic-fan-in/generic-fan-in.pipeline.yaml \
51
+ --task examples/generic-fan-in/generic-fan-in.task.yaml
52
+ ```
53
+
54
+ Exit code `2` means waiting on operator input. Leave this terminal; do the rest in the console.
55
+
56
+ Start a **new run** for each scenario below. Do not reuse a finished run.
57
+
58
+ ---
59
+
60
+ ## Scenario A — both parents succeed (main envelope check)
61
+
62
+ At **research**, answer exactly:
63
+
64
+ ```
65
+ ok glaciers
66
+ ```
67
+
68
+ At **validation**, answer exactly:
69
+
70
+ ```
71
+ ok citations
72
+ ```
73
+
74
+ Order of answers does not matter. `synthesize` starts only after both succeed.
75
+
76
+ ### What to verify
77
+
78
+ 1. Track is a diamond: `clarify` fans out to **research** and **validation**, then both wires inbound into **synthesize**.
79
+ 2. While only one parent is answered, select **synthesize**. It stays blocked. Copy / `blocked_by` lists the remaining parent, not only the first YAML parent.
80
+ 3. After `research` succeeds, select it and open **Files → Handoff envelope** (or `#/runs/<runId>/stages/research/envelope`). Payload should have `finding: glaciers`.
81
+ 4. After `validation` succeeds, open its handoff envelope. Payload should have `finding: citations`.
82
+ 5. **synthesize** runs once both parents succeeded. Open its handoff envelope. Confirm:
83
+ - `payload.received` has keys `research` then `validation` (YAML declaration order, not the order you answered).
84
+ - `received.research.finding` is `glaciers` and `received.validation.finding` is `citations`.
85
+ - Summary mentions both parent keys and their success status.
86
+ 6. From the repo root, you can also print the same records:
87
+
88
+ ```bash
89
+ node dist/cli.js envelope get --run <runId> --stage research --json
90
+ node dist/cli.js envelope get --run <runId> --stage validation --json
91
+ node dist/cli.js envelope get --run <runId> --stage synthesize --json
92
+ ```
93
+
94
+ `<runId>` is on the run detail URL (`#/runs/<runId>/…`) and in the run list.
95
+
96
+ The synthesize payload is the join copy of `priorEnvelopesByStage`. That field is keyed; it is not a clone-list `priorEnvelopes` array, and `priorEnvelope` is null on the join.
97
+
98
+ ---
99
+
100
+ ## Scenario B — failed parent leaves the join pending
101
+
102
+ New run of **generic-fan-in**. At research, answer:
103
+
104
+ ```
105
+ fail
106
+ ```
107
+
108
+ At validation, answer:
109
+
110
+ ```
111
+ ok citations
112
+ ```
113
+
114
+ ### What to verify
115
+
116
+ 1. **research** is failed (open its handoff envelope — failure status, no finding).
117
+ 2. **validation** still finishes; its envelope is success with `citations`.
118
+ 3. **synthesize** stays **pending** (not skip-cascaded). A failed parent blocks the Join.
119
+ 4. Run outcome **failed**.
120
+ 5. Open synthesize anyway: there is no join envelope. The Join did not receive `priorEnvelopesByStage`.
121
+
122
+ ---
123
+
124
+ ## Scenario C — listing `failed` on `on:` still does not open the join
125
+
126
+ New run:
127
+
128
+ ```bash
129
+ node dist/cli.js run \
130
+ --pipeline examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml \
131
+ --task examples/generic-fan-in/generic-fan-in-accepted.task.yaml
132
+ ```
133
+
134
+ At research, answer `fail`. At validation, answer `ok citations`.
135
+
136
+ ### What to verify
137
+
138
+ 1. **research** stays visibly **failed**. **validation** succeeds.
139
+ 2. **synthesize** stays **pending**. Listing `failed` on the research edge only opts that edge out of skip-cascade; it does not launch `synthesize`.
140
+ 3. Run outcome **failed**. Skipped siblings would not block a Join that has a succeeded parent; a **failed** parent still does.
141
+
142
+ ---
143
+
144
+ ## Envelope inspector (any scenario)
145
+
146
+ On a completed stage, the first Files row is **Handoff envelope**. It opens the
147
+ inspector (`#/runs/<runId>/stages/<stageId>/envelope`) with `summary`, `payload`,
148
+ and artifact paths. Use that for the parent envelopes; use **synthesize** for the
149
+ keyed join copy.
150
+
151
+ CLI equivalent: `node dist/cli.js envelope get --run <runId> --stage <stageId> --json`.
@@ -0,0 +1,18 @@
1
+ id: clarify
2
+ system_prompt: |
3
+ You are the root of a diamond pipeline. Call emit_stage_envelope exactly once.
4
+
5
+ Emit status success, artifacts [], payload { "brief": "diamond start" },
6
+ model: cursor/auto
7
+ io:
8
+ input:
9
+ schema:
10
+ type: object
11
+ output:
12
+ schema:
13
+ type: object
14
+ required:
15
+ - brief
16
+ properties:
17
+ brief:
18
+ type: string
@@ -0,0 +1,19 @@
1
+ id: generic-fan-in-accepted
2
+ stages:
3
+ - id: clarify
4
+ entry: true
5
+ route:
6
+ - to: research
7
+ - to: validation
8
+ uses: ./clarify.yaml
9
+ - id: research
10
+ route:
11
+ - to: synthesize
12
+ on: [succeeded, failed, skipped]
13
+ uses: ./research.yaml
14
+ - id: validation
15
+ route:
16
+ - to: synthesize
17
+ uses: ./validation.yaml
18
+ - id: synthesize
19
+ uses: ./synthesize.yaml
@@ -0,0 +1,8 @@
1
+ id: generic-fan-in-accepted
2
+ goal: |
3
+ Dummy walkthrough for an accepted-failure diamond. research may succeed or
4
+ fail. validation must succeed. synthesize still runs when research fails and
5
+ must copy that failure envelope under received.research.
6
+ context: |
7
+ Manual operator-console test. Reply fail at research and ok citations at
8
+ validation, then open synthesize to see the keyed failure + success pair.
@@ -0,0 +1,18 @@
1
+ id: generic-fan-in
2
+ stages:
3
+ - id: clarify
4
+ entry: true
5
+ route:
6
+ - to: research
7
+ - to: validation
8
+ uses: ./clarify.yaml
9
+ - id: research
10
+ route:
11
+ - to: synthesize
12
+ uses: ./research.yaml
13
+ - id: validation
14
+ route:
15
+ - to: synthesize
16
+ uses: ./validation.yaml
17
+ - id: synthesize
18
+ uses: ./synthesize.yaml
@@ -0,0 +1,9 @@
1
+ id: generic-fan-in
2
+ goal: |
3
+ Dummy walkthrough for generic multi-parent fan-in. research and validation
4
+ run in parallel after clarify. Reply to each with ok <finding> or fail.
5
+ synthesize waits for both and must copy priorEnvelopesByStage into payload.received.
6
+ context: |
7
+ Manual operator-console test. Distinct findings (for example glaciers and
8
+ citations) make it obvious which parent envelope landed under which key.
9
+ On fail of either parent, synthesize is skipped and the run fails.