stageflow 0.23.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 (511) hide show
  1. package/README.md +24 -5
  2. package/dist/a2a/configDiscovery.d.ts +9 -0
  3. package/dist/a2a/configDiscovery.js +18 -0
  4. package/dist/a2a/contracts.d.ts +94 -0
  5. package/dist/a2a/contracts.js +164 -0
  6. package/dist/a2a/limits.d.ts +14 -0
  7. package/dist/a2a/limits.js +29 -0
  8. package/dist/a2a/registry.d.ts +46 -0
  9. package/dist/a2a/registry.js +178 -0
  10. package/dist/a2a/server.d.ts +36 -0
  11. package/dist/a2a/server.js +344 -0
  12. package/dist/a2a/service.d.ts +97 -0
  13. package/dist/a2a/service.js +545 -0
  14. package/dist/a2a/store.d.ts +109 -0
  15. package/dist/a2a/store.js +202 -0
  16. package/dist/agent/activity.d.ts +3 -0
  17. package/dist/agent/bootProviderConfig.d.ts +21 -0
  18. package/dist/agent/bootProviderConfig.js +74 -0
  19. package/dist/agent/piAdapter.d.ts +9 -1
  20. package/dist/agent/piAdapter.js +58 -3
  21. package/dist/agent/piIsolatedMcp.d.ts +2 -0
  22. package/dist/agent/piIsolatedMcp.js +10 -2
  23. package/dist/agent/port.d.ts +6 -0
  24. package/dist/agent/streamLogRedact.d.ts +1 -1
  25. package/dist/agent/streamLogRedact.js +4 -11
  26. package/dist/cli/a2aCommand.d.ts +8 -0
  27. package/dist/cli/a2aCommand.js +131 -0
  28. package/dist/cli/artifactCommand.js +9 -16
  29. package/dist/cli/backupCommand.d.ts +9 -0
  30. package/dist/cli/backupCommand.js +111 -0
  31. package/dist/cli/debugRunCommand.d.ts +10 -0
  32. package/dist/cli/debugRunCommand.js +109 -0
  33. package/dist/cli/doctorCommand.d.ts +32 -0
  34. package/dist/cli/doctorCommand.js +453 -0
  35. package/dist/cli/envelopeCommand.js +9 -2
  36. package/dist/cli/exportAllCommand.d.ts +55 -0
  37. package/dist/cli/exportAllCommand.js +218 -0
  38. package/dist/cli/exportRunCommand.js +23 -21
  39. package/dist/cli/hostClient.d.ts +21 -3
  40. package/dist/cli/hostClient.js +93 -12
  41. package/dist/cli/initTemplates.d.ts +1 -1
  42. package/dist/cli/initTemplates.js +8 -1
  43. package/dist/cli/resolveSafeOutPath.d.ts +2 -0
  44. package/dist/cli/resolveSafeOutPath.js +40 -0
  45. package/dist/cli/restoreCommand.d.ts +10 -0
  46. package/dist/cli/restoreCommand.js +90 -0
  47. package/dist/cli/runCommand.d.ts +3 -2
  48. package/dist/cli/runCommand.js +93 -11
  49. package/dist/cli/runOutput.d.ts +4 -0
  50. package/dist/cli/runOutput.js +33 -7
  51. package/dist/cli/runStageCommand.d.ts +34 -0
  52. package/dist/cli/runStageCommand.js +426 -0
  53. package/dist/cli/runsCommand.d.ts +1 -1
  54. package/dist/cli/runsCommand.js +162 -8
  55. package/dist/cli.js +190 -30
  56. package/dist/config/catalogRelativePath.d.ts +62 -0
  57. package/dist/config/catalogRelativePath.js +118 -0
  58. package/dist/config/configOrigin.d.ts +27 -0
  59. package/dist/config/configOrigin.js +59 -0
  60. package/dist/config/hostConfig.d.ts +55 -0
  61. package/dist/config/hostConfig.js +333 -0
  62. package/dist/config/listSkills.d.ts +26 -0
  63. package/dist/config/listSkills.js +190 -3
  64. package/dist/config/loadOutcome.d.ts +1 -1
  65. package/dist/config/loadPipeline.js +23 -2
  66. package/dist/config/loadStage.js +18 -0
  67. package/dist/config/loadTask.d.ts +2 -0
  68. package/dist/config/loadTask.js +57 -18
  69. package/dist/config/materializeStageModels.js +5 -1
  70. package/dist/config/mergePipelineIncludes.d.ts +3 -0
  71. package/dist/config/mergePipelineIncludes.js +19 -0
  72. package/dist/config/migrateYaml.js +6 -11
  73. package/dist/config/multiProjectCatalog.d.ts +30 -0
  74. package/dist/config/multiProjectCatalog.js +142 -0
  75. package/dist/config/normalizePipelineStageEntry.js +20 -1
  76. package/dist/config/pipelineStageKeys.js +2 -0
  77. package/dist/config/resolveCatalogRoots.d.ts +27 -0
  78. package/dist/config/resolveCatalogRoots.js +76 -0
  79. package/dist/config/resolveModel.d.ts +7 -1
  80. package/dist/config/resolveModel.js +11 -1
  81. package/dist/config/resolveStageMcpServers.d.ts +9 -1
  82. package/dist/config/resolveStageMcpServers.js +36 -9
  83. package/dist/config/secretFromEnvOrFile.d.ts +9 -0
  84. package/dist/config/secretFromEnvOrFile.js +34 -0
  85. package/dist/config/seededCatalog.d.ts +11 -0
  86. package/dist/config/seededCatalog.js +29 -0
  87. package/dist/config/toolRequires.d.ts +24 -0
  88. package/dist/config/toolRequires.js +115 -0
  89. package/dist/config/validateCatalog.d.ts +5 -1
  90. package/dist/config/validateCatalog.js +140 -1
  91. package/dist/diagnostics/checks.d.ts +39 -0
  92. package/dist/diagnostics/checks.js +135 -0
  93. package/dist/errors/codes.d.ts +14 -0
  94. package/dist/errors/codes.js +59 -0
  95. package/dist/git/cache.d.ts +14 -0
  96. package/dist/git/cache.js +150 -0
  97. package/dist/git/credentials.d.ts +9 -0
  98. package/dist/git/credentials.js +88 -0
  99. package/dist/git/errors.d.ts +20 -0
  100. package/dist/git/errors.js +94 -0
  101. package/dist/git/exec.d.ts +16 -0
  102. package/dist/git/exec.js +135 -0
  103. package/dist/git/operations.d.ts +29 -0
  104. package/dist/git/operations.js +153 -0
  105. package/dist/git/version.d.ts +1 -0
  106. package/dist/git/version.js +10 -0
  107. package/dist/logging/audit.d.ts +16 -0
  108. package/dist/logging/audit.js +19 -0
  109. package/dist/logging/commonWords.d.ts +2 -0
  110. package/dist/logging/commonWords.js +13 -0
  111. package/dist/logging/logger.d.ts +49 -0
  112. package/dist/logging/logger.js +193 -0
  113. package/dist/logging/namedSecrets.d.ts +6 -0
  114. package/dist/logging/namedSecrets.js +58 -0
  115. package/dist/logging/redact.d.ts +13 -0
  116. package/dist/logging/redact.js +88 -0
  117. package/dist/mcp/catalogTools.js +591 -76
  118. package/dist/mcp/checkoutTools.d.ts +52 -0
  119. package/dist/mcp/checkoutTools.js +332 -0
  120. package/dist/mcp/controlTools.js +179 -5
  121. package/dist/mcp/deps.d.ts +1 -0
  122. package/dist/mcp/getStartedTool.d.ts +3 -0
  123. package/dist/mcp/getStartedTool.js +62 -0
  124. package/dist/mcp/readArtifact.d.ts +11 -0
  125. package/dist/mcp/readArtifact.js +46 -30
  126. package/dist/mcp/server.js +1 -0
  127. package/dist/mcp/tools.js +4 -0
  128. package/dist/net/proxy.d.ts +14 -0
  129. package/dist/net/proxy.js +78 -0
  130. package/dist/package-meta.d.ts +2 -1
  131. package/dist/package-meta.js +2 -1
  132. package/dist/preflight/bash.d.ts +8 -0
  133. package/dist/preflight/bash.js +34 -0
  134. package/dist/preflight/claudeRoot.d.ts +11 -0
  135. package/dist/preflight/claudeRoot.js +23 -0
  136. package/dist/preflight/mcpCommands.d.ts +8 -0
  137. package/dist/preflight/mcpCommands.js +36 -0
  138. package/dist/preflight/pipelinePreflight.d.ts +40 -0
  139. package/dist/preflight/pipelinePreflight.js +192 -0
  140. package/dist/preflight/tls.d.ts +6 -0
  141. package/dist/preflight/tls.js +18 -0
  142. package/dist/preflight/toolchain.d.ts +45 -0
  143. package/dist/preflight/toolchain.js +219 -0
  144. package/dist/project/findProjectRoot.js +3 -4
  145. package/dist/project/globalHome.d.ts +7 -0
  146. package/dist/project/globalHome.js +63 -2
  147. package/dist/project/resolveProjectContext.js +2 -2
  148. package/dist/project/resolveStageflowContext.js +2 -2
  149. package/dist/projection/projectRun.d.ts +2 -1
  150. package/dist/projection/projectRun.js +1 -0
  151. package/dist/runstore/assertTmpdir.d.ts +1 -0
  152. package/dist/runstore/assertTmpdir.js +21 -0
  153. package/dist/runstore/backup.d.ts +52 -0
  154. package/dist/runstore/backup.js +292 -0
  155. package/dist/runstore/createStore.d.ts +27 -0
  156. package/dist/runstore/createStore.js +75 -7
  157. package/dist/runstore/debugBundle.d.ts +60 -0
  158. package/dist/runstore/debugBundle.js +143 -0
  159. package/dist/runstore/diskUsage.d.ts +50 -0
  160. package/dist/runstore/diskUsage.js +214 -0
  161. package/dist/runstore/exportRunPayload.d.ts +8 -0
  162. package/dist/runstore/exportRunPayload.js +23 -0
  163. package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
  164. package/dist/runstore/normalizeCatalogPath.js +10 -0
  165. package/dist/runstore/paths.d.ts +5 -0
  166. package/dist/runstore/paths.js +145 -1
  167. package/dist/runstore/port.d.ts +119 -8
  168. package/dist/runstore/port.js +8 -1
  169. package/dist/runstore/restore.d.ts +81 -0
  170. package/dist/runstore/restore.js +355 -0
  171. package/dist/runstore/retention.d.ts +27 -0
  172. package/dist/runstore/retention.js +74 -0
  173. package/dist/runstore/runManifest.d.ts +146 -0
  174. package/dist/runstore/runManifest.js +288 -0
  175. package/dist/runstore/runProjection.d.ts +3 -1
  176. package/dist/runstore/runProjection.js +63 -1
  177. package/dist/runstore/sqlite/SqliteRunStore.d.ts +37 -3
  178. package/dist/runstore/sqlite/SqliteRunStore.js +401 -227
  179. package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
  180. package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
  181. package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
  182. package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
  183. package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
  184. package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
  185. package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
  186. package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
  187. package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
  188. package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
  189. package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
  190. package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
  191. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
  192. package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
  193. package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
  194. package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
  195. package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
  196. package/dist/runstore/sqlite/migrations/index.js +72 -0
  197. package/dist/runstore/sqlite/schema.d.ts +20 -1
  198. package/dist/runstore/sqlite/schema.js +283 -1
  199. package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
  200. package/dist/runstore/sqlite/storeOpenError.js +11 -0
  201. package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
  202. package/dist/runstore/sqlite/storeSchemaError.js +8 -0
  203. package/dist/runstore/stageExecution.js +3 -0
  204. package/dist/runstore/storeFilesystem.d.ts +32 -0
  205. package/dist/runstore/storeFilesystem.js +148 -0
  206. package/dist/runstore/submission.d.ts +11 -0
  207. package/dist/runstore/submission.js +7 -0
  208. package/dist/runstore/trackProjection.js +2 -0
  209. package/dist/runstore/workspaceLayout.d.ts +13 -0
  210. package/dist/runstore/workspaceLayout.js +76 -0
  211. package/dist/runtime/completionCheckRunner.d.ts +3 -0
  212. package/dist/runtime/completionCheckRunner.js +45 -7
  213. package/dist/runtime/containerLimits.d.ts +16 -0
  214. package/dist/runtime/containerLimits.js +84 -0
  215. package/dist/runtime/credentialMaterialisation.d.ts +28 -0
  216. package/dist/runtime/credentialMaterialisation.js +128 -0
  217. package/dist/runtime/gitCheckoutCapability.js +7 -13
  218. package/dist/runtime/pipelineRunner.d.ts +38 -1
  219. package/dist/runtime/pipelineRunner.js +179 -15
  220. package/dist/runtime/pipelineScheduler.d.ts +15 -0
  221. package/dist/runtime/pipelineScheduler.js +167 -42
  222. package/dist/runtime/reloadRunCatalog.js +12 -1
  223. package/dist/runtime/repositoryMaterialize.d.ts +47 -0
  224. package/dist/runtime/repositoryMaterialize.js +235 -0
  225. package/dist/runtime/resolveEnvelopeRef.d.ts +30 -0
  226. package/dist/runtime/resolveEnvelopeRef.js +79 -0
  227. package/dist/runtime/resumeTimedOut.d.ts +1 -1
  228. package/dist/runtime/resumeTimedOut.js +5 -2
  229. package/dist/runtime/runChangeBus.js +9 -0
  230. package/dist/runtime/runDeletion.d.ts +7 -0
  231. package/dist/runtime/runDeletion.js +37 -0
  232. package/dist/runtime/runManager.d.ts +179 -4
  233. package/dist/runtime/runManager.js +1644 -83
  234. package/dist/runtime/runRetentionSweep.d.ts +31 -0
  235. package/dist/runtime/runRetentionSweep.js +328 -0
  236. package/dist/runtime/runRetryCoordinator.d.ts +2 -0
  237. package/dist/runtime/runRetryCoordinator.js +19 -2
  238. package/dist/runtime/runSkills.d.ts +40 -0
  239. package/dist/runtime/runSkills.js +173 -0
  240. package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
  241. package/dist/runtime/stageAttemptBootstrap.js +195 -24
  242. package/dist/runtime/stageCacheEnv.d.ts +6 -0
  243. package/dist/runtime/stageCacheEnv.js +34 -0
  244. package/dist/runtime/stageConcurrency.d.ts +2 -1
  245. package/dist/runtime/stageConcurrency.js +4 -2
  246. package/dist/runtime/stageEnvironment.d.ts +38 -0
  247. package/dist/runtime/stageEnvironment.js +193 -0
  248. package/dist/runtime/stageProcessLauncher.d.ts +18 -0
  249. package/dist/runtime/stageProcessLauncher.js +194 -38
  250. package/dist/runtime/stageRecovery.d.ts +3 -1
  251. package/dist/runtime/stageRecovery.js +19 -4
  252. package/dist/runtime/stageRoots.d.ts +38 -1
  253. package/dist/runtime/stageRoots.js +118 -0
  254. package/dist/runtime/stageRunner.d.ts +1 -0
  255. package/dist/runtime/stageRunner.js +3 -1
  256. package/dist/runtime/stageSecretDecl.d.ts +9 -0
  257. package/dist/runtime/stageSecretDecl.js +102 -0
  258. package/dist/runtime/stageSecrets.d.ts +40 -0
  259. package/dist/runtime/stageSecrets.js +181 -0
  260. package/dist/runtime/stageWorker.d.ts +3 -2
  261. package/dist/runtime/stageWorker.js +58 -10
  262. package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
  263. package/dist/runtime/stageWorkerProtocol.js +8 -0
  264. package/dist/runtime/startPayload.d.ts +32 -0
  265. package/dist/runtime/startPayload.js +59 -0
  266. package/dist/runtime/taskInput.js +14 -5
  267. package/dist/runtime/verifiedStageExecution.d.ts +1 -0
  268. package/dist/runtime/verifiedStageExecution.js +2 -1
  269. package/dist/runtime/workspaceBinding.d.ts +20 -0
  270. package/dist/runtime/workspaceBinding.js +60 -0
  271. package/dist/server/allowedHosts.d.ts +19 -0
  272. package/dist/server/allowedHosts.js +179 -0
  273. package/dist/server/bootstrap.d.ts +38 -2
  274. package/dist/server/bootstrap.js +219 -4
  275. package/dist/server/controlToken.d.ts +47 -0
  276. package/dist/server/controlToken.js +241 -0
  277. package/dist/server/createHttpHost.d.ts +11 -2
  278. package/dist/server/createHttpHost.js +109 -10
  279. package/dist/server/ensureGlobalService.d.ts +5 -1
  280. package/dist/server/ensureGlobalService.js +35 -1
  281. package/dist/server/healthSurfaces.d.ts +6 -0
  282. package/dist/server/healthSurfaces.js +98 -0
  283. package/dist/server/http.d.ts +12 -1
  284. package/dist/server/http.js +1085 -485
  285. package/dist/server/listenHost.d.ts +5 -0
  286. package/dist/server/listenHost.js +56 -0
  287. package/dist/server/mcpHost.d.ts +10 -1
  288. package/dist/server/mcpHost.js +36 -6
  289. package/dist/server/operatorResults.d.ts +2 -2
  290. package/dist/server/operatorResults.js +40 -29
  291. package/dist/server/requestAuthContext.d.ts +12 -0
  292. package/dist/server/requestAuthContext.js +21 -0
  293. package/dist/server/shutdown.d.ts +69 -0
  294. package/dist/server/shutdown.js +219 -0
  295. package/dist/types/pipeline.d.ts +7 -0
  296. package/dist/types/stage.d.ts +8 -0
  297. package/dist/types/task.d.ts +8 -0
  298. package/dist/ui/assets/index-B6hlSXXn.js +120 -0
  299. package/dist/ui/index.html +1 -1
  300. package/examples/README.md +98 -0
  301. package/examples/archify-on-pr/README.md +213 -0
  302. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
  303. package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
  304. package/examples/archify-on-pr/author-diagrams.yaml +106 -0
  305. package/examples/archify-on-pr/detect-changes.yaml +89 -0
  306. package/examples/ci-validate/README.md +35 -0
  307. package/examples/ci-validate/check.yaml +13 -0
  308. package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
  309. package/examples/ci-validate/validate.sh +5 -0
  310. package/examples/compliance-review-demo/README.md +125 -0
  311. package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
  312. package/examples/compliance-review-demo/connect-account.yaml +47 -0
  313. package/examples/compliance-review-demo/map-to-control.yaml +123 -0
  314. package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
  315. package/examples/compliance-review-demo/publish-report.yaml +79 -0
  316. package/examples/compliance-review-demo/review-verdict.yaml +122 -0
  317. package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
  318. package/examples/compliance-review-demo/store-evidence.yaml +143 -0
  319. package/examples/conditional-fork/README.md +89 -0
  320. package/examples/conditional-fork/branch-a.yaml +13 -0
  321. package/examples/conditional-fork/branch-b.yaml +13 -0
  322. package/examples/conditional-fork/decide.yaml +35 -0
  323. package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
  324. package/examples/conditional-fork/fork-demo.task.yaml +8 -0
  325. package/examples/context7-mcp/README.md +42 -0
  326. package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
  327. package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
  328. package/examples/context7-mcp/fetch-docs.yaml +52 -0
  329. package/examples/context7-mcp/resolve-library.yaml +31 -0
  330. package/examples/context7-mcp/write-brief.yaml +52 -0
  331. package/examples/feature-loop/README.md +104 -0
  332. package/examples/feature-loop/address-feedback.yaml +148 -0
  333. package/examples/feature-loop/align.yaml +116 -0
  334. package/examples/feature-loop/decompose.yaml +86 -0
  335. package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
  336. package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
  337. package/examples/feature-loop/feature-loop.task.yaml +25 -0
  338. package/examples/feature-loop/implement.yaml +128 -0
  339. package/examples/feature-loop/plan.yaml +111 -0
  340. package/examples/feature-loop/publish.yaml +167 -0
  341. package/examples/feature-loop/review.yaml +146 -0
  342. package/examples/feature-loop/verify.yaml +106 -0
  343. package/examples/feedback-loop/README.md +72 -0
  344. package/examples/feedback-loop/VERIFY.md +208 -0
  345. package/examples/feedback-loop/continue-only.task.yaml +4 -0
  346. package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
  347. package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
  348. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
  349. package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
  350. package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
  351. package/examples/feedback-loop/implement.yaml +14 -0
  352. package/examples/feedback-loop/plan.yaml +14 -0
  353. package/examples/feedback-loop/review.yaml +15 -0
  354. package/examples/feedback-loop/send-back-once.task.yaml +6 -0
  355. package/examples/feedback-loop/submit.yaml +12 -0
  356. package/examples/generic-fan-in/README.md +151 -0
  357. package/examples/generic-fan-in/clarify.yaml +18 -0
  358. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
  359. package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
  360. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
  361. package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
  362. package/examples/generic-fan-in/research.yaml +45 -0
  363. package/examples/generic-fan-in/synthesize.yaml +66 -0
  364. package/examples/generic-fan-in/validation.yaml +45 -0
  365. package/examples/github-release/README.md +78 -0
  366. package/examples/github-release/draft-release-notes.yaml +64 -0
  367. package/examples/github-release/github-release.pipeline.yaml +11 -0
  368. package/examples/github-release/github-release.task.yaml +13 -0
  369. package/examples/github-release/publish-github-release.yaml +64 -0
  370. package/examples/hello-world/README.md +28 -0
  371. package/examples/hello-world/hello.pipeline.yaml +4 -0
  372. package/examples/hello-world/my-task.task.yaml +6 -0
  373. package/examples/hello-world/research.yaml +18 -0
  374. package/examples/mcp-hitl-tour/README.md +113 -0
  375. package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
  376. package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
  377. package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
  378. package/examples/mcp-hitl-tour/gather.yaml +31 -0
  379. package/examples/mcp-hitl-tour/intake.yaml +62 -0
  380. package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
  381. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
  382. package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
  383. package/examples/mcp-hitl-tour/polish.yaml +33 -0
  384. package/examples/mcp-hitl-tour/review.yaml +17 -0
  385. package/examples/mcp-hitl-tour/ship.yaml +25 -0
  386. package/examples/oss-issue-contribution/README.md +218 -0
  387. package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
  388. package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
  389. package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
  390. package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
  391. package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
  392. package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
  393. package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
  394. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
  395. package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
  396. package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
  397. package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
  398. package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
  399. package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
  400. package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
  401. package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
  402. package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
  403. package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
  404. package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
  405. package/examples/oss-quick-fix/README.md +65 -0
  406. package/examples/oss-quick-fix/implement-fix.yaml +84 -0
  407. package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
  408. package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
  409. package/examples/oss-quick-fix/ship-fix.yaml +81 -0
  410. package/examples/oss-quick-fix/understand-issue.yaml +67 -0
  411. package/examples/oss-quick-fix/verify-fix.yaml +73 -0
  412. package/examples/plan-review/README.md +37 -0
  413. package/examples/plan-review/plan-review-followup.yaml +13 -0
  414. package/examples/plan-review/plan-review.pipeline.yaml +9 -0
  415. package/examples/plan-review/plan-review.task.yaml +9 -0
  416. package/examples/plan-review/plan-review.yaml +25 -0
  417. package/examples/playwright-mcp/README.md +39 -0
  418. package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
  419. package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
  420. package/examples/playwright-mcp/screenshot.yaml +40 -0
  421. package/examples/retry-tour/README.md +75 -0
  422. package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
  423. package/examples/retry-tour/retry-tour.task.yaml +9 -0
  424. package/examples/route-if-tour/README.md +202 -0
  425. package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
  426. package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
  427. package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
  428. package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
  429. package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
  430. package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
  431. package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
  432. package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
  433. package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
  434. package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
  435. package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
  436. package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
  437. package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
  438. package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
  439. package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
  440. package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
  441. package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
  442. package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
  443. package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
  444. package/examples/route-wiring-smoke-test/README.md +377 -0
  445. package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
  446. package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
  447. package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
  448. package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
  449. package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
  450. package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
  451. package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
  452. package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
  453. package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
  454. package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
  455. package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
  456. package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
  457. package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
  458. package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
  459. package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
  460. package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
  461. package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
  462. package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
  463. package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
  464. package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
  465. package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
  466. package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
  467. package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
  468. package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
  469. package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
  470. package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
  471. package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
  472. package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
  473. package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
  474. package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
  475. package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
  476. package/examples/ship-feature/README.md +190 -0
  477. package/examples/ship-feature/feat-address-feedback.yaml +119 -0
  478. package/examples/ship-feature/feat-implement.yaml +180 -0
  479. package/examples/ship-feature/feat-plan.yaml +120 -0
  480. package/examples/ship-feature/feat-review.yaml +109 -0
  481. package/examples/ship-feature/feat-ship.yaml +203 -0
  482. package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
  483. package/examples/ship-feature/ship-feature.task.yaml +78 -0
  484. package/examples/stage-mcp/README.md +144 -0
  485. package/examples/stage-mcp/echo-mcp.mjs +20 -0
  486. package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
  487. package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
  488. package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
  489. package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
  490. package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
  491. package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
  492. package/examples/stage-mcp/use-echo.yaml +20 -0
  493. package/examples/verify-tour/README.md +80 -0
  494. package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
  495. package/examples/verify-tour/verify-tour.task.yaml +11 -0
  496. package/package.json +6 -1
  497. package/skills/stageflow/SKILL.md +6 -6
  498. package/skills/stageflow/references/control-surface.md +11 -5
  499. package/skills/stageflow/scripts/detect-host.mjs +14 -1
  500. package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
  501. package/skills/stageflow-author/SKILL.md +4 -3
  502. package/skills/stageflow-author/references/catalog-mapping.md +16 -0
  503. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  504. package/skills/stageflow-run/SKILL.md +20 -12
  505. package/skills/stageflow-run/references/mcp-call.md +9 -1
  506. package/skills/stageflow-run/references/task-and-pipeline-selection.md +16 -5
  507. package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
  508. package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
  509. package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
  510. package/skills/stageflow-setup/SKILL.md +40 -8
  511. package/dist/ui/assets/index-Da5EHU6M.js +0 -119
@@ -1,189 +1,20 @@
1
1
  import Database from "better-sqlite3";
2
+ import { existsSync, statSync } from "node:fs";
2
3
  import { mkdir } from "node:fs/promises";
3
4
  import path from "node:path";
4
5
  import { projectRunDetail, projectRunSummary, orderStageSnapshots } from "../runProjection.js";
5
- import { normalizeCatalogPath } from "../normalizeCatalogPath.js";
6
+ import { normalizeCatalogPath, normalizeProjectRoot } from "../normalizeCatalogPath.js";
6
7
  import { buildStageSnapshotFromStore } from "../stageSnapshot.js";
7
8
  import { parsePipelineDagSnapshot } from "../pipelineDagSnapshot.js";
8
9
  import { newRunId, runWorkspaceDir } from "../paths.js";
9
10
  import { attemptAgentDir, attemptArtifactsDir, stageDir, } from "../workspaceLayout.js";
10
11
  import { importDiskRunsIfEmpty } from "./migrateFromDisk.js";
11
- import { SCHEMA_SQL } from "./schema.js";
12
+ import { applyPendingMigrations, assertSchemaVersion, } from "./migrations/index.js";
13
+ import { StoreSchemaError } from "./storeSchemaError.js";
14
+ import { applyStorePragmas } from "./applyStorePragmas.js";
15
+ import { RunSubmissionExistsError } from "../submission.js";
16
+ const EXECUTION_SELECT_COLS = `run_id, stage_id, attempt, status, verification_outcome, started_at, finished_at, envelope_json, cost_usd, usage_json, auto_resume_count`;
12
17
  const ensuredStageDirs = new Set();
13
- const DEFAULT_SQLITE_BUSY_TIMEOUT_MS = 5000;
14
- function readSqliteBusyTimeoutMs() {
15
- const raw = process.env.STAGEFLOW_SQLITE_BUSY_TIMEOUT_MS;
16
- if (raw === undefined || raw.trim() === "") {
17
- return DEFAULT_SQLITE_BUSY_TIMEOUT_MS;
18
- }
19
- const parsed = Number.parseInt(raw, 10);
20
- if (!Number.isFinite(parsed) || parsed < 0) {
21
- return DEFAULT_SQLITE_BUSY_TIMEOUT_MS;
22
- }
23
- return parsed;
24
- }
25
- function ensureCheckoutRootColumn(db) {
26
- const cols = db.prepare(`PRAGMA table_info(runs)`).all();
27
- if (!cols.some((c) => c.name === "checkout_root")) {
28
- db.exec(`ALTER TABLE runs ADD COLUMN checkout_root TEXT`);
29
- }
30
- }
31
- function ensureCiIdentityColumns(db) {
32
- const cols = db.prepare(`PRAGMA table_info(runs)`).all();
33
- const names = new Set(cols.map((c) => c.name));
34
- for (const name of ["git_sha", "ci_pr_url", "ci_job_url"]) {
35
- if (!names.has(name)) {
36
- db.exec(`ALTER TABLE runs ADD COLUMN ${name} TEXT`);
37
- }
38
- }
39
- }
40
- function ensurePipelineDagColumn(db) {
41
- const cols = db.prepare(`PRAGMA table_info(runs)`).all();
42
- if (!cols.some((c) => c.name === "pipeline_dag_json")) {
43
- db.exec(`ALTER TABLE runs ADD COLUMN pipeline_dag_json TEXT`);
44
- }
45
- }
46
- function ensureRunLocatorColumns(db) {
47
- const cols = db.prepare(`PRAGMA table_info(runs)`).all();
48
- const names = new Set(cols.map((c) => c.name));
49
- for (const name of ["pipeline_path", "task_path", "project_root"]) {
50
- if (!names.has(name)) {
51
- db.exec(`ALTER TABLE runs ADD COLUMN ${name} TEXT`);
52
- }
53
- }
54
- }
55
- function ensureStageExecutionsTable(db) {
56
- db.exec(`
57
- CREATE TABLE IF NOT EXISTS stage_executions (
58
- run_id TEXT NOT NULL,
59
- stage_id TEXT NOT NULL,
60
- attempt INTEGER NOT NULL,
61
- status TEXT NOT NULL,
62
- verification_outcome TEXT NOT NULL DEFAULT 'not_run',
63
- started_at TEXT,
64
- finished_at TEXT,
65
- envelope_json TEXT,
66
- PRIMARY KEY (run_id, stage_id, attempt),
67
- FOREIGN KEY (run_id) REFERENCES runs(run_id)
68
- );
69
- CREATE INDEX IF NOT EXISTS idx_stage_executions_run_stage
70
- ON stage_executions (run_id, stage_id, attempt);
71
- `);
72
- }
73
- function ensureStageExecutionVerificationOutcomeColumn(db) {
74
- const cols = db
75
- .prepare(`PRAGMA table_info(stage_executions)`)
76
- .all();
77
- if (!cols.some((c) => c.name === "verification_outcome")) {
78
- db.exec(`ALTER TABLE stage_executions ADD COLUMN verification_outcome TEXT NOT NULL DEFAULT 'not_run'`);
79
- }
80
- }
81
- function ensureStageExecutionCostColumns(db) {
82
- const cols = db
83
- .prepare(`PRAGMA table_info(stage_executions)`)
84
- .all();
85
- const names = new Set(cols.map((c) => c.name));
86
- if (!names.has("cost_usd")) {
87
- db.exec(`ALTER TABLE stage_executions ADD COLUMN cost_usd REAL`);
88
- }
89
- if (!names.has("usage_json")) {
90
- db.exec(`ALTER TABLE stage_executions ADD COLUMN usage_json TEXT`);
91
- }
92
- }
93
- function backfillVerificationOutcomes(db) {
94
- db.exec(`
95
- UPDATE stage_executions
96
- SET verification_outcome = CASE
97
- WHEN status = 'succeeded'
98
- AND EXISTS (
99
- SELECT 1 FROM verification_check_results AS check_result
100
- WHERE check_result.run_id = stage_executions.run_id
101
- AND check_result.stage_id = stage_executions.stage_id
102
- AND check_result.attempt = stage_executions.attempt
103
- )
104
- AND NOT EXISTS (
105
- SELECT 1 FROM verification_check_results AS check_result
106
- WHERE check_result.run_id = stage_executions.run_id
107
- AND check_result.stage_id = stage_executions.stage_id
108
- AND check_result.attempt = stage_executions.attempt
109
- AND check_result.status != 'passed'
110
- )
111
- THEN 'passed'
112
- WHEN status = 'failed'
113
- AND EXISTS (
114
- SELECT 1 FROM verification_check_results AS check_result
115
- WHERE check_result.run_id = stage_executions.run_id
116
- AND check_result.stage_id = stage_executions.stage_id
117
- AND check_result.attempt = stage_executions.attempt
118
- )
119
- THEN 'failed'
120
- ELSE verification_outcome
121
- END
122
- WHERE verification_outcome = 'not_run';
123
- `);
124
- }
125
- function ensureStageEventsAttemptColumn(db) {
126
- const cols = db
127
- .prepare(`PRAGMA table_info(stage_events)`)
128
- .all();
129
- if (!cols.some((c) => c.name === "attempt")) {
130
- db.exec(`ALTER TABLE stage_events ADD COLUMN attempt INTEGER NOT NULL DEFAULT 1`);
131
- db.exec(`
132
- CREATE INDEX IF NOT EXISTS idx_stage_events_run_stage_attempt_at
133
- ON stage_events (run_id, stage_id, attempt, at);
134
- `);
135
- }
136
- }
137
- function ensureVerificationCheckResultsTable(db) {
138
- db.exec(`
139
- CREATE TABLE IF NOT EXISTS verification_check_results (
140
- run_id TEXT NOT NULL,
141
- stage_id TEXT NOT NULL,
142
- attempt INTEGER NOT NULL,
143
- check_id TEXT NOT NULL,
144
- check_type TEXT NOT NULL,
145
- status TEXT NOT NULL,
146
- started_at TEXT,
147
- finished_at TEXT,
148
- evidence_json TEXT,
149
- PRIMARY KEY (run_id, stage_id, attempt, check_id),
150
- FOREIGN KEY (run_id, stage_id, attempt)
151
- REFERENCES stage_executions(run_id, stage_id, attempt)
152
- );
153
- CREATE INDEX IF NOT EXISTS idx_verification_check_results_execution
154
- ON verification_check_results (run_id, stage_id, attempt, check_id);
155
- `);
156
- }
157
- function ensureFeedbackReplayStagePassEnvelopeColumn(db) {
158
- const cols = db
159
- .prepare(`PRAGMA table_info(feedback_replay_stage_passes)`)
160
- .all();
161
- if (cols.length === 0)
162
- return;
163
- if (!cols.some((c) => c.name === "emitted_envelope_json")) {
164
- db.exec(`ALTER TABLE feedback_replay_stage_passes ADD COLUMN emitted_envelope_json TEXT`);
165
- }
166
- }
167
- function ensureFeedbackReplayStagePassSessionOriginColumn(db) {
168
- const cols = db
169
- .prepare(`PRAGMA table_info(feedback_replay_stage_passes)`)
170
- .all();
171
- if (cols.length === 0)
172
- return;
173
- if (!cols.some((c) => c.name === "session_origin_attempt")) {
174
- db.exec(`ALTER TABLE feedback_replay_stage_passes ADD COLUMN session_origin_attempt INTEGER`);
175
- }
176
- }
177
- function ensureFeedbackLoopDeferredSendBackColumn(db) {
178
- const cols = db
179
- .prepare(`PRAGMA table_info(feedback_loops)`)
180
- .all();
181
- if (cols.length === 0)
182
- return;
183
- if (!cols.some((c) => c.name === "deferred_send_back_json")) {
184
- db.exec(`ALTER TABLE feedback_loops ADD COLUMN deferred_send_back_json TEXT`);
185
- }
186
- }
187
18
  function executionFromRow(row) {
188
19
  return {
189
20
  run_id: row.run_id,
@@ -197,7 +28,10 @@ function executionFromRow(row) {
197
28
  ? JSON.parse(row.envelope_json)
198
29
  : null,
199
30
  ...(row.cost_usd != null ? { cost_usd: row.cost_usd } : {}),
200
- ...(row.usage_json != null ? { usage: JSON.parse(row.usage_json) } : {}),
31
+ ...(row.usage_json != null
32
+ ? { usage: JSON.parse(row.usage_json) }
33
+ : {}),
34
+ auto_resume_count: row.auto_resume_count ?? 0,
201
35
  };
202
36
  }
203
37
  function verificationCheckResultFromRow(row) {
@@ -293,38 +127,57 @@ export class SqliteRunStore {
293
127
  storeRoot;
294
128
  db;
295
129
  migratePromise;
296
- constructor(storeRoot) {
130
+ constructor(storeRoot, options) {
297
131
  this.storeRoot = storeRoot;
132
+ const openerMode = options?.openerMode ??
133
+ (process.env.VITEST === "true" ? "migrate" : "assert");
298
134
  const dbPath = path.join(storeRoot, "state.db");
135
+ if (openerMode === "assert") {
136
+ if (!existsSync(dbPath)) {
137
+ throw new StoreSchemaError("store_schema_migration_required: database file is missing", "store_schema_migration_required");
138
+ }
139
+ this.db = new Database(dbPath);
140
+ applyStorePragmas(this.db);
141
+ assertSchemaVersion(this.db);
142
+ this.migratePromise = Promise.resolve();
143
+ return;
144
+ }
299
145
  this.db = new Database(dbPath);
300
- this.db.pragma("journal_mode = WAL");
301
- this.db.pragma(`busy_timeout = ${readSqliteBusyTimeoutMs()}`);
302
- this.db.exec(SCHEMA_SQL);
303
- ensureCheckoutRootColumn(this.db);
304
- ensureCiIdentityColumns(this.db);
305
- ensurePipelineDagColumn(this.db);
306
- ensureRunLocatorColumns(this.db);
307
- ensureStageExecutionsTable(this.db);
308
- ensureStageExecutionVerificationOutcomeColumn(this.db);
309
- ensureStageExecutionCostColumns(this.db);
310
- ensureStageEventsAttemptColumn(this.db);
311
- ensureVerificationCheckResultsTable(this.db);
312
- ensureFeedbackReplayStagePassEnvelopeColumn(this.db);
313
- ensureFeedbackReplayStagePassSessionOriginColumn(this.db);
314
- ensureFeedbackLoopDeferredSendBackColumn(this.db);
315
- backfillVerificationOutcomes(this.db);
146
+ applyStorePragmas(this.db);
147
+ applyPendingMigrations(this.db);
316
148
  this.migratePromise = importDiskRunsIfEmpty(this.db, storeRoot).then(() => undefined);
317
149
  }
318
150
  /** Await one-shot disk import before catalog reads (create paths also wait). */
319
151
  async ready() {
320
152
  await this.migratePromise;
321
153
  }
154
+ async close() {
155
+ await this.ready();
156
+ this.db.pragma("wal_checkpoint(TRUNCATE)");
157
+ this.db.close();
158
+ }
159
+ async snapshotInto(destPath) {
160
+ await this.ready();
161
+ const userVersion = this.db.pragma("user_version", {
162
+ simple: true,
163
+ });
164
+ const escaped = destPath.replace(/'/g, "''");
165
+ this.db.exec(`VACUUM INTO '${escaped}'`);
166
+ return { userVersion };
167
+ }
168
+ /**
169
+ * The connection this store owns, for the one caller allowed to share it: the composition root
170
+ * wiring the A2A tables into the same `state.db` file. Not part of the `RunStore` interface.
171
+ */
172
+ get connection() {
173
+ return this.db;
174
+ }
322
175
  getWorkspaceDir(runId) {
323
176
  return runWorkspaceDir(this.storeRoot, runId);
324
177
  }
325
178
  async createRun(input) {
326
179
  await this.ready();
327
- const runId = newRunId();
180
+ const runId = input.runId ?? newRunId();
328
181
  const workspaceDir = this.getWorkspaceDir(runId);
329
182
  await mkdir(path.join(workspaceDir, "stages"), { recursive: true });
330
183
  const now = new Date().toISOString();
@@ -337,45 +190,265 @@ export class SqliteRunStore {
337
190
  const projectRoot = input.projectRoot
338
191
  ? normalizeCatalogPath(input.projectRoot)
339
192
  : null;
340
- this.db
341
- .prepare(`INSERT INTO runs
342
- (run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root)
193
+ const pipelineBody = input.pipelineBody ??
194
+ (input.inlinePipeline !== undefined
195
+ ? JSON.stringify(input.inlinePipeline)
196
+ : null);
197
+ const pipelineSource = input.pipelineSource ??
198
+ (pipelineBody != null && pipelinePath == null ? "inline" : null);
199
+ this.db.transaction(() => {
200
+ if (input.submission) {
201
+ const existing = this.readSubmission(input.submission.key);
202
+ if (existing)
203
+ throw new RunSubmissionExistsError(existing);
204
+ }
205
+ this.db
206
+ .prepare(`INSERT INTO runs
207
+ (run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root, repository, ref, resolved_sha, run_branch, git_author_name, git_author_email, pipeline_source, pipeline_body, caller_id, run_manifest, skip_gates)
343
208
  VALUES
344
- (@run_id, @pipeline_id, @task_id, @task_yaml, @status, @created_at, @updated_at, @checkout_root, @pipeline_dag_json, @git_sha, @ci_pr_url, @ci_job_url, @pipeline_path, @task_path, @project_root)`)
209
+ (@run_id, @pipeline_id, @task_id, @task_yaml, @status, @created_at, @updated_at, @checkout_root, @pipeline_dag_json, @git_sha, @ci_pr_url, @ci_job_url, @pipeline_path, @task_path, @project_root, @repository, @ref, @resolved_sha, @run_branch, @git_author_name, @git_author_email, @pipeline_source, @pipeline_body, @caller_id, @run_manifest, @skip_gates)`)
210
+ .run({
211
+ run_id: runId,
212
+ pipeline_id: input.pipelineId,
213
+ task_id: input.taskId ?? null,
214
+ task_yaml: input.taskYaml,
215
+ status: input.status ?? "running",
216
+ created_at: now,
217
+ updated_at: now,
218
+ checkout_root: input.checkoutRoot ?? null,
219
+ pipeline_dag_json: input.pipelineDag
220
+ ? JSON.stringify(input.pipelineDag)
221
+ : null,
222
+ git_sha: input.gitSha ?? null,
223
+ ci_pr_url: input.ciPrUrl ?? null,
224
+ ci_job_url: input.ciJobUrl ?? null,
225
+ pipeline_path: pipelinePath,
226
+ task_path: taskPath,
227
+ project_root: projectRoot,
228
+ repository: input.repository ?? null,
229
+ ref: input.ref ?? null,
230
+ resolved_sha: input.resolvedSha ?? null,
231
+ run_branch: input.runBranch ?? null,
232
+ git_author_name: input.gitAuthorName ?? null,
233
+ git_author_email: input.gitAuthorEmail ?? null,
234
+ pipeline_source: pipelineSource,
235
+ pipeline_body: pipelineBody,
236
+ caller_id: input.callerId ?? null,
237
+ run_manifest: input.runManifest !== undefined
238
+ ? JSON.stringify(input.runManifest)
239
+ : null,
240
+ skip_gates: input.skipGates === undefined ? null : input.skipGates ? 1 : 0,
241
+ });
242
+ if (input.submission) {
243
+ this.db.prepare("INSERT INTO run_submissions (submission_key, request_hash, run_id) VALUES (?, ?, ?)")
244
+ .run(input.submission.key, input.submission.requestHash, runId);
245
+ }
246
+ })();
247
+ return { runId, workspaceDir };
248
+ }
249
+ readSubmission(key) {
250
+ const row = this.db.prepare("SELECT submission_key AS key, request_hash AS requestHash, run_id AS runId FROM run_submissions WHERE submission_key = ?")
251
+ .get(key);
252
+ return row ?? null;
253
+ }
254
+ async getRunBySubmission(key) {
255
+ await this.ready();
256
+ return this.readSubmission(key);
257
+ }
258
+ async updateRunStatus(runId, status) {
259
+ await this.ready();
260
+ const now = new Date().toISOString();
261
+ const isTerminal = status === "succeeded" || status === "failed" || status === "cancelled";
262
+ const result = isTerminal
263
+ ? this.db
264
+ .prepare(`UPDATE runs SET status = @status, updated_at = @updated_at,
265
+ finished_at = COALESCE(finished_at, @finished_at)
266
+ WHERE run_id = @run_id`)
267
+ .run({
268
+ run_id: runId,
269
+ status,
270
+ updated_at: now,
271
+ finished_at: now,
272
+ })
273
+ : this.db
274
+ .prepare(`UPDATE runs SET status = @status, updated_at = @updated_at WHERE run_id = @run_id`)
275
+ .run({
276
+ run_id: runId,
277
+ status,
278
+ updated_at: now,
279
+ });
280
+ if (result.changes === 0) {
281
+ throw new Error(`Run not found: ${runId}`);
282
+ }
283
+ }
284
+ async tryUpdateRunStatus(runId, status, expectedStatus) {
285
+ await this.ready();
286
+ const now = new Date().toISOString();
287
+ const isTerminal = status === "succeeded" || status === "failed" || status === "cancelled";
288
+ const result = isTerminal
289
+ ? this.db
290
+ .prepare(`UPDATE runs SET status = @status, updated_at = @updated_at,
291
+ finished_at = COALESCE(finished_at, @finished_at)
292
+ WHERE run_id = @run_id AND status = @expected_status`)
293
+ .run({
294
+ run_id: runId,
295
+ status,
296
+ expected_status: expectedStatus,
297
+ updated_at: now,
298
+ finished_at: now,
299
+ })
300
+ : this.db
301
+ .prepare(`UPDATE runs SET status = @status, updated_at = @updated_at
302
+ WHERE run_id = @run_id AND status = @expected_status`)
303
+ .run({
304
+ run_id: runId,
305
+ status,
306
+ expected_status: expectedStatus,
307
+ updated_at: now,
308
+ });
309
+ if (result.changes > 0)
310
+ return true;
311
+ const exists = this.db
312
+ .prepare(`SELECT 1 AS ok FROM runs WHERE run_id = ?`)
313
+ .get(runId);
314
+ if (exists === undefined) {
315
+ throw new Error(`Run not found: ${runId}`);
316
+ }
317
+ return false;
318
+ }
319
+ async patchRunWorkspaceBinding(runId, patch) {
320
+ await this.ready();
321
+ const sets = ["updated_at = @updated_at"];
322
+ const params = {
323
+ run_id: runId,
324
+ updated_at: new Date().toISOString(),
325
+ };
326
+ if (patch.checkoutRoot !== undefined) {
327
+ sets.push("checkout_root = @checkout_root");
328
+ params.checkout_root = patch.checkoutRoot;
329
+ }
330
+ if (patch.repository !== undefined) {
331
+ sets.push("repository = @repository");
332
+ params.repository = patch.repository;
333
+ }
334
+ if (patch.ref !== undefined) {
335
+ sets.push("ref = @ref");
336
+ params.ref = patch.ref;
337
+ }
338
+ if (patch.resolvedSha !== undefined) {
339
+ sets.push("resolved_sha = @resolved_sha");
340
+ params.resolved_sha = patch.resolvedSha;
341
+ }
342
+ if (patch.runBranch !== undefined) {
343
+ sets.push("run_branch = @run_branch");
344
+ params.run_branch = patch.runBranch;
345
+ }
346
+ if (sets.length === 1) {
347
+ return;
348
+ }
349
+ const result = this.db
350
+ .prepare(`UPDATE runs SET ${sets.join(", ")} WHERE run_id = @run_id`)
351
+ .run(params);
352
+ if (result.changes === 0) {
353
+ throw new Error(`Run not found: ${runId}`);
354
+ }
355
+ }
356
+ async appendConfigOrigins(runId, origins) {
357
+ await this.ready();
358
+ if (origins.length === 0)
359
+ return;
360
+ const row = this.getRunRow(runId);
361
+ const existing = row.config_origins_json
362
+ ? JSON.parse(row.config_origins_json)
363
+ : [];
364
+ const keyOf = (o) => `${o.name}\0${o.origin}\0${o.path ?? ""}`;
365
+ const seen = new Set(existing.map(keyOf));
366
+ const merged = [...existing];
367
+ for (const origin of origins) {
368
+ const key = keyOf(origin);
369
+ if (seen.has(key))
370
+ continue;
371
+ seen.add(key);
372
+ merged.push(origin);
373
+ }
374
+ if (merged.length === existing.length)
375
+ return;
376
+ const result = this.db
377
+ .prepare(`UPDATE runs SET config_origins_json = @config_origins_json, updated_at = @updated_at WHERE run_id = @run_id`)
345
378
  .run({
346
379
  run_id: runId,
347
- pipeline_id: input.pipelineId,
348
- task_id: input.taskId ?? null,
349
- task_yaml: input.taskYaml,
350
- status: "running",
351
- created_at: now,
352
- updated_at: now,
353
- checkout_root: input.checkoutRoot ?? null,
354
- pipeline_dag_json: input.pipelineDag
355
- ? JSON.stringify(input.pipelineDag)
356
- : null,
357
- git_sha: input.gitSha ?? null,
358
- ci_pr_url: input.ciPrUrl ?? null,
359
- ci_job_url: input.ciJobUrl ?? null,
360
- pipeline_path: pipelinePath,
361
- task_path: taskPath,
362
- project_root: projectRoot,
380
+ config_origins_json: JSON.stringify(merged),
381
+ updated_at: new Date().toISOString(),
363
382
  });
364
- return { runId, workspaceDir };
383
+ if (result.changes === 0) {
384
+ throw new Error(`Run not found: ${runId}`);
385
+ }
365
386
  }
366
- async updateRunStatus(runId, status) {
387
+ async setCancelReason(runId, reason) {
367
388
  await this.ready();
368
389
  const result = this.db
369
- .prepare(`UPDATE runs SET status = @status, updated_at = @updated_at WHERE run_id = @run_id`)
390
+ .prepare(`UPDATE runs SET cancel_reason = @cancel_reason, updated_at = @updated_at WHERE run_id = @run_id`)
370
391
  .run({
371
392
  run_id: runId,
372
- status,
393
+ cancel_reason: reason,
373
394
  updated_at: new Date().toISOString(),
374
395
  });
375
396
  if (result.changes === 0) {
376
397
  throw new Error(`Run not found: ${runId}`);
377
398
  }
378
399
  }
400
+ async setRunDiskUsage(runId, diskBytes, measuredAt) {
401
+ await this.ready();
402
+ const result = this.db
403
+ .prepare(`UPDATE runs SET disk_bytes = @disk_bytes, disk_measured_at = @disk_measured_at
404
+ WHERE run_id = @run_id`)
405
+ .run({
406
+ run_id: runId,
407
+ disk_bytes: diskBytes,
408
+ disk_measured_at: measuredAt,
409
+ });
410
+ if (result.changes === 0) {
411
+ throw new Error(`Run not found: ${runId}`);
412
+ }
413
+ }
414
+ async setSlimmedAt(runId, slimmedAt) {
415
+ await this.ready();
416
+ const result = this.db
417
+ .prepare(`UPDATE runs SET slimmed_at = @slimmed_at WHERE run_id = @run_id`)
418
+ .run({
419
+ run_id: runId,
420
+ slimmed_at: slimmedAt,
421
+ });
422
+ if (result.changes === 0) {
423
+ throw new Error(`Run not found: ${runId}`);
424
+ }
425
+ }
426
+ async deleteRun(runId) {
427
+ await this.ready();
428
+ const deleteAll = this.db.transaction(() => {
429
+ const exists = this.db
430
+ .prepare(`SELECT 1 AS ok FROM runs WHERE run_id = ?`)
431
+ .get(runId);
432
+ if (exists === undefined) {
433
+ throw new Error(`Run not found: ${runId}`);
434
+ }
435
+ this.db.prepare(`DELETE FROM stage_events WHERE run_id = ?`).run(runId);
436
+ this.db
437
+ .prepare(`DELETE FROM verification_check_results WHERE run_id = ?`)
438
+ .run(runId);
439
+ this.db.prepare(`DELETE FROM stage_executions WHERE run_id = ?`).run(runId);
440
+ this.db
441
+ .prepare(`DELETE FROM feedback_replay_stage_passes WHERE run_id = ?`)
442
+ .run(runId);
443
+ this.db.prepare(`DELETE FROM fork_generations WHERE run_id = ?`).run(runId);
444
+ this.db.prepare(`DELETE FROM feedback_replays WHERE run_id = ?`).run(runId);
445
+ this.db.prepare(`DELETE FROM feedback_loops WHERE run_id = ?`).run(runId);
446
+ this.db.prepare(`DELETE FROM stages WHERE run_id = ?`).run(runId);
447
+ this.db.prepare(`DELETE FROM run_submissions WHERE run_id = ?`).run(runId);
448
+ this.db.prepare(`DELETE FROM runs WHERE run_id = ?`).run(runId);
449
+ });
450
+ deleteAll();
451
+ }
379
452
  async updatePipelineDag(runId, dag) {
380
453
  await this.ready();
381
454
  const result = this.db
@@ -397,6 +470,25 @@ export class SqliteRunStore {
397
470
  await this.ready();
398
471
  return this.getRunRow(runId).task_yaml;
399
472
  }
473
+ async readPipelineBody(runId) {
474
+ await this.ready();
475
+ return this.getRunRow(runId).pipeline_body;
476
+ }
477
+ async updateRunManifest(runId, manifest) {
478
+ await this.ready();
479
+ const result = this.db
480
+ .prepare(`UPDATE runs SET run_manifest = @run_manifest, updated_at = @updated_at WHERE run_id = @run_id`)
481
+ .run({
482
+ run_id: runId,
483
+ run_manifest: manifest === null || manifest === undefined
484
+ ? null
485
+ : JSON.stringify(manifest),
486
+ updated_at: new Date().toISOString(),
487
+ });
488
+ if (result.changes === 0) {
489
+ throw new Error(`Run not found: ${runId}`);
490
+ }
491
+ }
400
492
  async ensureStageWorkspace(runId, stageId) {
401
493
  await this.ready();
402
494
  this.getRunRow(runId);
@@ -447,7 +539,7 @@ export class SqliteRunStore {
447
539
  verification_outcome: "not_run",
448
540
  });
449
541
  const row = this.db
450
- .prepare(`SELECT run_id, stage_id, attempt, status, verification_outcome, started_at, finished_at, envelope_json, cost_usd, usage_json
542
+ .prepare(`SELECT ${EXECUTION_SELECT_COLS}
451
543
  FROM stage_executions
452
544
  WHERE run_id = ? AND stage_id = ? AND attempt = ?`)
453
545
  .get(runId, stageId, attempt);
@@ -457,7 +549,7 @@ export class SqliteRunStore {
457
549
  async listStageExecutions(runId, stageId) {
458
550
  await this.ready();
459
551
  const rows = this.db
460
- .prepare(`SELECT run_id, stage_id, attempt, status, verification_outcome, started_at, finished_at, envelope_json, cost_usd, usage_json
552
+ .prepare(`SELECT ${EXECUTION_SELECT_COLS}
461
553
  FROM stage_executions
462
554
  WHERE run_id = ? AND stage_id = ?
463
555
  ORDER BY attempt ASC`)
@@ -467,7 +559,7 @@ export class SqliteRunStore {
467
559
  async getLatestStageExecution(runId, stageId) {
468
560
  await this.ready();
469
561
  const row = this.db
470
- .prepare(`SELECT run_id, stage_id, attempt, status, verification_outcome, started_at, finished_at, envelope_json, cost_usd, usage_json
562
+ .prepare(`SELECT ${EXECUTION_SELECT_COLS}
471
563
  FROM stage_executions
472
564
  WHERE run_id = ? AND stage_id = ?
473
565
  ORDER BY attempt DESC
@@ -486,7 +578,7 @@ export class SqliteRunStore {
486
578
  async getStageExecution(runId, stageId, attempt) {
487
579
  await this.ready();
488
580
  const row = this.db
489
- .prepare(`SELECT run_id, stage_id, attempt, status, verification_outcome, started_at, finished_at, envelope_json, cost_usd, usage_json
581
+ .prepare(`SELECT ${EXECUTION_SELECT_COLS}
490
582
  FROM stage_executions
491
583
  WHERE run_id = ? AND stage_id = ? AND attempt = ?`)
492
584
  .get(runId, stageId, attempt);
@@ -495,6 +587,21 @@ export class SqliteRunStore {
495
587
  }
496
588
  return executionFromRow(row);
497
589
  }
590
+ async listInterruptedStageExecutions() {
591
+ await this.ready();
592
+ const rows = this.db
593
+ .prepare(`SELECT ${EXECUTION_SELECT_COLS}
594
+ FROM stage_executions e
595
+ WHERE e.status = 'interrupted'
596
+ AND e.attempt = (
597
+ SELECT MAX(e2.attempt)
598
+ FROM stage_executions e2
599
+ WHERE e2.run_id = e.run_id AND e2.stage_id = e.stage_id
600
+ )
601
+ ORDER BY e.run_id ASC, e.stage_id ASC, e.attempt ASC`)
602
+ .all();
603
+ return rows.map(executionFromRow);
604
+ }
498
605
  async updateStageExecution(runId, stageId, attempt, patch) {
499
606
  await this.ready();
500
607
  const sets = [];
@@ -532,6 +639,10 @@ export class SqliteRunStore {
532
639
  sets.push("usage_json = @usage_json");
533
640
  params.usage_json = JSON.stringify(patch.usage);
534
641
  }
642
+ if (patch.auto_resume_count !== undefined) {
643
+ sets.push("auto_resume_count = @auto_resume_count");
644
+ params.auto_resume_count = patch.auto_resume_count;
645
+ }
535
646
  if (sets.length === 0)
536
647
  return;
537
648
  const result = this.db
@@ -708,9 +819,13 @@ export class SqliteRunStore {
708
819
  clauses.push("(pipeline_id = ? OR pipeline_path = ? OR pipeline_path = ?)");
709
820
  params.push(pipeline, pipeline, normalized);
710
821
  }
822
+ if (filter?.caller_id !== undefined) {
823
+ clauses.push("caller_id = ?");
824
+ params.push(filter.caller_id);
825
+ }
711
826
  const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
712
827
  const rows = this.db
713
- .prepare(`SELECT run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root
828
+ .prepare(`SELECT run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root, repository, ref, resolved_sha, run_branch, git_author_name, git_author_email, cancel_reason, finished_at, slimmed_at, disk_bytes, disk_measured_at, config_origins_json, pipeline_source, pipeline_body, caller_id, run_manifest, skip_gates
714
829
  FROM runs ${where} ORDER BY created_at DESC`)
715
830
  .all(...params);
716
831
  const summaries = [];
@@ -724,10 +839,34 @@ export class SqliteRunStore {
724
839
  }
725
840
  return summaries;
726
841
  }
727
- async listProjectRoots() {
842
+ async ensureProject(absPath) {
843
+ await this.ready();
844
+ const resolved = path.resolve(absPath);
845
+ let st;
846
+ try {
847
+ st = statSync(resolved);
848
+ }
849
+ catch {
850
+ throw new Error(`project_root does not exist: ${resolved}`);
851
+ }
852
+ if (!st.isDirectory()) {
853
+ throw new Error(`project_root is not a directory: ${resolved}`);
854
+ }
855
+ const normalized = normalizeProjectRoot(absPath);
856
+ if (normalized === path.parse(normalized).root) {
857
+ throw new Error(`project_root must not be filesystem root: ${normalized}`);
858
+ }
859
+ const now = new Date().toISOString();
860
+ this.db
861
+ .prepare(`INSERT INTO projects (project_root, created_at) VALUES (?, ?)
862
+ ON CONFLICT(project_root) DO NOTHING`)
863
+ .run(normalized, now);
864
+ return normalized;
865
+ }
866
+ async listRegisteredProjects() {
728
867
  await this.ready();
729
868
  const rows = this.db
730
- .prepare(`SELECT DISTINCT project_root FROM runs WHERE project_root IS NOT NULL AND project_root != ''`)
869
+ .prepare(`SELECT project_root FROM projects ORDER BY project_root`)
731
870
  .all();
732
871
  return rows.map((row) => row.project_root);
733
872
  }
@@ -1138,12 +1277,47 @@ export class SqliteRunStore {
1138
1277
  ...(row.pipeline_path != null ? { pipeline_path: row.pipeline_path } : {}),
1139
1278
  ...(row.task_path != null ? { task_path: row.task_path } : {}),
1140
1279
  ...(row.project_root != null ? { project_root: row.project_root } : {}),
1280
+ ...(row.repository != null ? { repository: row.repository } : {}),
1281
+ ...(row.ref != null ? { ref: row.ref } : {}),
1282
+ ...(row.resolved_sha != null ? { resolved_sha: row.resolved_sha } : {}),
1283
+ ...(row.run_branch != null ? { run_branch: row.run_branch } : {}),
1284
+ ...(row.git_author_name != null
1285
+ ? { git_author_name: row.git_author_name }
1286
+ : {}),
1287
+ ...(row.git_author_email != null
1288
+ ? { git_author_email: row.git_author_email }
1289
+ : {}),
1290
+ ...(row.cancel_reason != null ? { cancel_reason: row.cancel_reason } : {}),
1291
+ ...(row.finished_at != null ? { finished_at: row.finished_at } : {}),
1292
+ ...(row.slimmed_at != null ? { slimmed_at: row.slimmed_at } : {}),
1293
+ ...(row.disk_bytes != null ? { disk_bytes: row.disk_bytes } : {}),
1294
+ ...(row.disk_measured_at != null
1295
+ ? { disk_measured_at: row.disk_measured_at }
1296
+ : {}),
1297
+ ...(row.config_origins_json
1298
+ ? {
1299
+ config_origins: JSON.parse(row.config_origins_json),
1300
+ }
1301
+ : {}),
1302
+ ...(row.pipeline_source === "inline" || row.pipeline_source === "path"
1303
+ ? { pipeline_source: row.pipeline_source }
1304
+ : {}),
1305
+ ...(row.caller_id != null ? { caller_id: row.caller_id } : {}),
1306
+ ...(row.run_manifest
1307
+ ? { run_manifest: JSON.parse(row.run_manifest) }
1308
+ : {}),
1309
+ ...(row.skip_gates != null ? { skip_gates: row.skip_gates !== 0 } : {}),
1141
1310
  ...(pipeline_dag ? { pipeline_dag } : {}),
1311
+ ...(row.pipeline_body
1312
+ ? {
1313
+ inline_pipeline: JSON.parse(row.pipeline_body),
1314
+ }
1315
+ : {}),
1142
1316
  };
1143
1317
  }
1144
1318
  getRunRow(runId) {
1145
1319
  const row = this.db
1146
- .prepare(`SELECT run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root
1320
+ .prepare(`SELECT run_id, pipeline_id, task_id, task_yaml, status, created_at, updated_at, checkout_root, pipeline_dag_json, git_sha, ci_pr_url, ci_job_url, pipeline_path, task_path, project_root, repository, ref, resolved_sha, run_branch, git_author_name, git_author_email, cancel_reason, finished_at, slimmed_at, disk_bytes, disk_measured_at, config_origins_json, pipeline_source, pipeline_body, caller_id, run_manifest, skip_gates
1147
1321
  FROM runs WHERE run_id = ?`)
1148
1322
  .get(runId);
1149
1323
  if (!row)