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.
- package/README.md +10 -3
- package/dist/a2a/contracts.d.ts +1 -0
- package/dist/a2a/contracts.js +1 -0
- package/dist/a2a/registry.d.ts +2 -0
- package/dist/a2a/registry.js +20 -1
- package/dist/a2a/server.d.ts +7 -0
- package/dist/a2a/server.js +5 -2
- package/dist/a2a/service.d.ts +1 -1
- package/dist/a2a/service.js +57 -8
- package/dist/a2a/store.d.ts +8 -5
- package/dist/a2a/store.js +24 -67
- package/dist/agent/activity.d.ts +3 -0
- package/dist/agent/bootProviderConfig.d.ts +21 -0
- package/dist/agent/bootProviderConfig.js +74 -0
- package/dist/agent/piAdapter.d.ts +9 -1
- package/dist/agent/piAdapter.js +58 -3
- package/dist/agent/piIsolatedMcp.d.ts +2 -0
- package/dist/agent/piIsolatedMcp.js +10 -2
- package/dist/agent/port.d.ts +6 -0
- package/dist/agent/streamLogRedact.d.ts +1 -1
- package/dist/agent/streamLogRedact.js +4 -11
- package/dist/cli/artifactCommand.js +9 -16
- package/dist/cli/backupCommand.d.ts +9 -0
- package/dist/cli/backupCommand.js +111 -0
- package/dist/cli/debugRunCommand.d.ts +10 -0
- package/dist/cli/debugRunCommand.js +109 -0
- package/dist/cli/doctorCommand.d.ts +32 -0
- package/dist/cli/doctorCommand.js +453 -0
- package/dist/cli/envelopeCommand.js +9 -2
- package/dist/cli/exportAllCommand.d.ts +55 -0
- package/dist/cli/exportAllCommand.js +218 -0
- package/dist/cli/exportRunCommand.js +23 -21
- package/dist/cli/hostClient.d.ts +21 -3
- package/dist/cli/hostClient.js +93 -12
- package/dist/cli/initTemplates.d.ts +1 -1
- package/dist/cli/initTemplates.js +8 -1
- package/dist/cli/resolveSafeOutPath.d.ts +2 -0
- package/dist/cli/resolveSafeOutPath.js +40 -0
- package/dist/cli/restoreCommand.d.ts +10 -0
- package/dist/cli/restoreCommand.js +90 -0
- package/dist/cli/runCommand.d.ts +3 -2
- package/dist/cli/runCommand.js +93 -11
- package/dist/cli/runOutput.d.ts +4 -0
- package/dist/cli/runOutput.js +33 -7
- package/dist/cli/runStageCommand.d.ts +1 -0
- package/dist/cli/runStageCommand.js +44 -25
- package/dist/cli/runsCommand.d.ts +1 -1
- package/dist/cli/runsCommand.js +162 -8
- package/dist/cli.js +171 -30
- package/dist/config/catalogRelativePath.d.ts +62 -0
- package/dist/config/catalogRelativePath.js +118 -0
- package/dist/config/configOrigin.d.ts +27 -0
- package/dist/config/configOrigin.js +59 -0
- package/dist/config/hostConfig.d.ts +55 -0
- package/dist/config/hostConfig.js +333 -0
- package/dist/config/listSkills.d.ts +26 -0
- package/dist/config/listSkills.js +190 -3
- package/dist/config/loadOutcome.d.ts +1 -1
- package/dist/config/loadPipeline.js +23 -2
- package/dist/config/loadStage.js +18 -0
- package/dist/config/loadTask.d.ts +2 -0
- package/dist/config/loadTask.js +57 -18
- package/dist/config/materializeStageModels.js +5 -1
- package/dist/config/mergePipelineIncludes.d.ts +3 -0
- package/dist/config/mergePipelineIncludes.js +19 -0
- package/dist/config/migrateYaml.js +6 -11
- package/dist/config/multiProjectCatalog.d.ts +30 -0
- package/dist/config/multiProjectCatalog.js +142 -0
- package/dist/config/normalizePipelineStageEntry.js +20 -1
- package/dist/config/pipelineStageKeys.js +2 -0
- package/dist/config/resolveCatalogRoots.d.ts +27 -0
- package/dist/config/resolveCatalogRoots.js +76 -0
- package/dist/config/resolveModel.d.ts +7 -1
- package/dist/config/resolveModel.js +11 -1
- package/dist/config/resolveStageMcpServers.d.ts +9 -1
- package/dist/config/resolveStageMcpServers.js +36 -9
- package/dist/config/secretFromEnvOrFile.d.ts +9 -0
- package/dist/config/secretFromEnvOrFile.js +34 -0
- package/dist/config/seededCatalog.d.ts +11 -0
- package/dist/config/seededCatalog.js +29 -0
- package/dist/config/toolRequires.d.ts +24 -0
- package/dist/config/toolRequires.js +115 -0
- package/dist/config/validateCatalog.d.ts +5 -1
- package/dist/config/validateCatalog.js +140 -1
- package/dist/diagnostics/checks.d.ts +39 -0
- package/dist/diagnostics/checks.js +135 -0
- package/dist/errors/codes.d.ts +14 -0
- package/dist/errors/codes.js +59 -0
- package/dist/git/cache.d.ts +14 -0
- package/dist/git/cache.js +150 -0
- package/dist/git/credentials.d.ts +9 -0
- package/dist/git/credentials.js +88 -0
- package/dist/git/errors.d.ts +20 -0
- package/dist/git/errors.js +94 -0
- package/dist/git/exec.d.ts +16 -0
- package/dist/git/exec.js +135 -0
- package/dist/git/operations.d.ts +29 -0
- package/dist/git/operations.js +153 -0
- package/dist/git/version.d.ts +1 -0
- package/dist/git/version.js +10 -0
- package/dist/logging/audit.d.ts +16 -0
- package/dist/logging/audit.js +19 -0
- package/dist/logging/commonWords.d.ts +2 -0
- package/dist/logging/commonWords.js +13 -0
- package/dist/logging/logger.d.ts +49 -0
- package/dist/logging/logger.js +193 -0
- package/dist/logging/namedSecrets.d.ts +6 -0
- package/dist/logging/namedSecrets.js +58 -0
- package/dist/logging/redact.d.ts +13 -0
- package/dist/logging/redact.js +88 -0
- package/dist/mcp/catalogTools.js +456 -80
- package/dist/mcp/checkoutTools.d.ts +52 -0
- package/dist/mcp/checkoutTools.js +332 -0
- package/dist/mcp/controlTools.js +179 -5
- package/dist/mcp/deps.d.ts +1 -0
- package/dist/mcp/getStartedTool.d.ts +3 -0
- package/dist/mcp/getStartedTool.js +62 -0
- package/dist/mcp/readArtifact.d.ts +11 -0
- package/dist/mcp/readArtifact.js +46 -30
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/net/proxy.d.ts +14 -0
- package/dist/net/proxy.js +78 -0
- package/dist/package-meta.d.ts +2 -1
- package/dist/package-meta.js +2 -1
- package/dist/preflight/bash.d.ts +8 -0
- package/dist/preflight/bash.js +34 -0
- package/dist/preflight/claudeRoot.d.ts +11 -0
- package/dist/preflight/claudeRoot.js +23 -0
- package/dist/preflight/mcpCommands.d.ts +8 -0
- package/dist/preflight/mcpCommands.js +36 -0
- package/dist/preflight/pipelinePreflight.d.ts +40 -0
- package/dist/preflight/pipelinePreflight.js +192 -0
- package/dist/preflight/tls.d.ts +6 -0
- package/dist/preflight/tls.js +18 -0
- package/dist/preflight/toolchain.d.ts +45 -0
- package/dist/preflight/toolchain.js +219 -0
- package/dist/project/findProjectRoot.js +3 -4
- package/dist/project/globalHome.d.ts +7 -0
- package/dist/project/globalHome.js +63 -2
- package/dist/project/resolveProjectContext.js +2 -2
- package/dist/project/resolveStageflowContext.js +2 -2
- package/dist/projection/projectRun.d.ts +2 -1
- package/dist/projection/projectRun.js +1 -0
- package/dist/runstore/assertTmpdir.d.ts +1 -0
- package/dist/runstore/assertTmpdir.js +21 -0
- package/dist/runstore/backup.d.ts +52 -0
- package/dist/runstore/backup.js +292 -0
- package/dist/runstore/createStore.d.ts +18 -1
- package/dist/runstore/createStore.js +64 -5
- package/dist/runstore/debugBundle.d.ts +60 -0
- package/dist/runstore/debugBundle.js +143 -0
- package/dist/runstore/diskUsage.d.ts +50 -0
- package/dist/runstore/diskUsage.js +214 -0
- package/dist/runstore/exportRunPayload.d.ts +8 -0
- package/dist/runstore/exportRunPayload.js +23 -0
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +10 -0
- package/dist/runstore/paths.d.ts +5 -0
- package/dist/runstore/paths.js +145 -1
- package/dist/runstore/port.d.ts +111 -13
- package/dist/runstore/port.js +8 -1
- package/dist/runstore/restore.d.ts +81 -0
- package/dist/runstore/restore.js +355 -0
- package/dist/runstore/retention.d.ts +27 -0
- package/dist/runstore/retention.js +74 -0
- package/dist/runstore/runManifest.d.ts +146 -0
- package/dist/runstore/runManifest.js +288 -0
- package/dist/runstore/runProjection.d.ts +3 -1
- package/dist/runstore/runProjection.js +63 -1
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +28 -3
- package/dist/runstore/sqlite/SqliteRunStore.js +352 -219
- package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
- package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
- package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
- package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
- package/dist/runstore/sqlite/migrations/index.js +72 -0
- package/dist/runstore/sqlite/schema.d.ts +20 -1
- package/dist/runstore/sqlite/schema.js +277 -1
- package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
- package/dist/runstore/sqlite/storeOpenError.js +11 -0
- package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
- package/dist/runstore/sqlite/storeSchemaError.js +8 -0
- package/dist/runstore/stageExecution.js +3 -0
- package/dist/runstore/storeFilesystem.d.ts +32 -0
- package/dist/runstore/storeFilesystem.js +148 -0
- package/dist/runstore/trackProjection.js +2 -0
- package/dist/runstore/workspaceLayout.d.ts +13 -0
- package/dist/runstore/workspaceLayout.js +76 -0
- package/dist/runtime/completionCheckRunner.d.ts +3 -0
- package/dist/runtime/completionCheckRunner.js +45 -7
- package/dist/runtime/containerLimits.d.ts +16 -0
- package/dist/runtime/containerLimits.js +84 -0
- package/dist/runtime/credentialMaterialisation.d.ts +28 -0
- package/dist/runtime/credentialMaterialisation.js +128 -0
- package/dist/runtime/gitCheckoutCapability.js +7 -13
- package/dist/runtime/pipelineRunner.d.ts +36 -1
- package/dist/runtime/pipelineRunner.js +178 -17
- package/dist/runtime/pipelineScheduler.d.ts +15 -0
- package/dist/runtime/pipelineScheduler.js +135 -27
- package/dist/runtime/reloadRunCatalog.js +6 -1
- package/dist/runtime/repositoryMaterialize.d.ts +47 -0
- package/dist/runtime/repositoryMaterialize.js +235 -0
- package/dist/runtime/resumeTimedOut.d.ts +1 -1
- package/dist/runtime/resumeTimedOut.js +5 -2
- package/dist/runtime/runChangeBus.js +9 -0
- package/dist/runtime/runDeletion.d.ts +7 -0
- package/dist/runtime/runDeletion.js +37 -0
- package/dist/runtime/runManager.d.ts +158 -4
- package/dist/runtime/runManager.js +1596 -79
- package/dist/runtime/runRetentionSweep.d.ts +31 -0
- package/dist/runtime/runRetentionSweep.js +328 -0
- package/dist/runtime/runRetryCoordinator.d.ts +2 -0
- package/dist/runtime/runRetryCoordinator.js +19 -2
- package/dist/runtime/runSkills.d.ts +40 -0
- package/dist/runtime/runSkills.js +173 -0
- package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
- package/dist/runtime/stageAttemptBootstrap.js +195 -24
- package/dist/runtime/stageCacheEnv.d.ts +6 -0
- package/dist/runtime/stageCacheEnv.js +34 -0
- package/dist/runtime/stageConcurrency.d.ts +2 -1
- package/dist/runtime/stageConcurrency.js +4 -2
- package/dist/runtime/stageEnvironment.d.ts +38 -0
- package/dist/runtime/stageEnvironment.js +193 -0
- package/dist/runtime/stageProcessLauncher.d.ts +18 -0
- package/dist/runtime/stageProcessLauncher.js +194 -38
- package/dist/runtime/stageRecovery.d.ts +3 -1
- package/dist/runtime/stageRecovery.js +19 -4
- package/dist/runtime/stageRoots.d.ts +38 -1
- package/dist/runtime/stageRoots.js +118 -0
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +3 -1
- package/dist/runtime/stageSecretDecl.d.ts +9 -0
- package/dist/runtime/stageSecretDecl.js +102 -0
- package/dist/runtime/stageSecrets.d.ts +40 -0
- package/dist/runtime/stageSecrets.js +181 -0
- package/dist/runtime/stageWorker.d.ts +3 -2
- package/dist/runtime/stageWorker.js +58 -10
- package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
- package/dist/runtime/stageWorkerProtocol.js +8 -0
- package/dist/runtime/startPayload.d.ts +32 -0
- package/dist/runtime/startPayload.js +59 -0
- package/dist/runtime/taskInput.js +14 -5
- package/dist/runtime/verifiedStageExecution.d.ts +1 -0
- package/dist/runtime/verifiedStageExecution.js +2 -1
- package/dist/runtime/workspaceBinding.d.ts +20 -0
- package/dist/runtime/workspaceBinding.js +60 -0
- package/dist/server/allowedHosts.d.ts +19 -0
- package/dist/server/allowedHosts.js +179 -0
- package/dist/server/bootstrap.d.ts +36 -2
- package/dist/server/bootstrap.js +209 -5
- package/dist/server/controlToken.d.ts +47 -0
- package/dist/server/controlToken.js +241 -0
- package/dist/server/createHttpHost.d.ts +11 -2
- package/dist/server/createHttpHost.js +103 -10
- package/dist/server/ensureGlobalService.d.ts +5 -1
- package/dist/server/ensureGlobalService.js +35 -1
- package/dist/server/healthSurfaces.d.ts +6 -0
- package/dist/server/healthSurfaces.js +98 -0
- package/dist/server/http.d.ts +12 -1
- package/dist/server/http.js +1085 -485
- package/dist/server/listenHost.d.ts +5 -0
- package/dist/server/listenHost.js +56 -0
- package/dist/server/mcpHost.d.ts +10 -1
- package/dist/server/mcpHost.js +36 -6
- package/dist/server/operatorResults.d.ts +2 -2
- package/dist/server/operatorResults.js +40 -29
- package/dist/server/requestAuthContext.d.ts +12 -0
- package/dist/server/requestAuthContext.js +21 -0
- package/dist/server/shutdown.d.ts +69 -0
- package/dist/server/shutdown.js +219 -0
- package/dist/types/pipeline.d.ts +7 -0
- package/dist/types/stage.d.ts +8 -0
- package/dist/types/task.d.ts +8 -0
- package/dist/ui/assets/index-B6hlSXXn.js +120 -0
- package/dist/ui/index.html +1 -1
- package/examples/README.md +98 -0
- package/examples/archify-on-pr/README.md +213 -0
- package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
- package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
- package/examples/archify-on-pr/author-diagrams.yaml +106 -0
- package/examples/archify-on-pr/detect-changes.yaml +89 -0
- package/examples/ci-validate/README.md +35 -0
- package/examples/ci-validate/check.yaml +13 -0
- package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
- package/examples/ci-validate/validate.sh +5 -0
- package/examples/compliance-review-demo/README.md +125 -0
- package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
- package/examples/compliance-review-demo/connect-account.yaml +47 -0
- package/examples/compliance-review-demo/map-to-control.yaml +123 -0
- package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
- package/examples/compliance-review-demo/publish-report.yaml +79 -0
- package/examples/compliance-review-demo/review-verdict.yaml +122 -0
- package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
- package/examples/compliance-review-demo/store-evidence.yaml +143 -0
- package/examples/conditional-fork/README.md +89 -0
- package/examples/conditional-fork/branch-a.yaml +13 -0
- package/examples/conditional-fork/branch-b.yaml +13 -0
- package/examples/conditional-fork/decide.yaml +35 -0
- package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
- package/examples/conditional-fork/fork-demo.task.yaml +8 -0
- package/examples/context7-mcp/README.md +42 -0
- package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
- package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
- package/examples/context7-mcp/fetch-docs.yaml +52 -0
- package/examples/context7-mcp/resolve-library.yaml +31 -0
- package/examples/context7-mcp/write-brief.yaml +52 -0
- package/examples/feature-loop/README.md +104 -0
- package/examples/feature-loop/address-feedback.yaml +148 -0
- package/examples/feature-loop/align.yaml +116 -0
- package/examples/feature-loop/decompose.yaml +86 -0
- package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
- package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
- package/examples/feature-loop/feature-loop.task.yaml +25 -0
- package/examples/feature-loop/implement.yaml +128 -0
- package/examples/feature-loop/plan.yaml +111 -0
- package/examples/feature-loop/publish.yaml +167 -0
- package/examples/feature-loop/review.yaml +146 -0
- package/examples/feature-loop/verify.yaml +106 -0
- package/examples/feedback-loop/README.md +72 -0
- package/examples/feedback-loop/VERIFY.md +208 -0
- package/examples/feedback-loop/continue-only.task.yaml +4 -0
- package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
- package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
- package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
- package/examples/feedback-loop/implement.yaml +14 -0
- package/examples/feedback-loop/plan.yaml +14 -0
- package/examples/feedback-loop/review.yaml +15 -0
- package/examples/feedback-loop/send-back-once.task.yaml +6 -0
- package/examples/feedback-loop/submit.yaml +12 -0
- package/examples/generic-fan-in/README.md +151 -0
- package/examples/generic-fan-in/clarify.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
- package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
- package/examples/generic-fan-in/research.yaml +45 -0
- package/examples/generic-fan-in/synthesize.yaml +66 -0
- package/examples/generic-fan-in/validation.yaml +45 -0
- package/examples/github-release/README.md +78 -0
- package/examples/github-release/draft-release-notes.yaml +64 -0
- package/examples/github-release/github-release.pipeline.yaml +11 -0
- package/examples/github-release/github-release.task.yaml +13 -0
- package/examples/github-release/publish-github-release.yaml +64 -0
- package/examples/hello-world/README.md +28 -0
- package/examples/hello-world/hello.pipeline.yaml +4 -0
- package/examples/hello-world/my-task.task.yaml +6 -0
- package/examples/hello-world/research.yaml +18 -0
- package/examples/mcp-hitl-tour/README.md +113 -0
- package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
- package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
- package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
- package/examples/mcp-hitl-tour/gather.yaml +31 -0
- package/examples/mcp-hitl-tour/intake.yaml +62 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
- package/examples/mcp-hitl-tour/polish.yaml +33 -0
- package/examples/mcp-hitl-tour/review.yaml +17 -0
- package/examples/mcp-hitl-tour/ship.yaml +25 -0
- package/examples/oss-issue-contribution/README.md +218 -0
- package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
- package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
- package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
- package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
- package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
- package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
- package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
- package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
- package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
- package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
- package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
- package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
- package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
- package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
- package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
- package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
- package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
- package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
- package/examples/oss-quick-fix/README.md +65 -0
- package/examples/oss-quick-fix/implement-fix.yaml +84 -0
- package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
- package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
- package/examples/oss-quick-fix/ship-fix.yaml +81 -0
- package/examples/oss-quick-fix/understand-issue.yaml +67 -0
- package/examples/oss-quick-fix/verify-fix.yaml +73 -0
- package/examples/plan-review/README.md +37 -0
- package/examples/plan-review/plan-review-followup.yaml +13 -0
- package/examples/plan-review/plan-review.pipeline.yaml +9 -0
- package/examples/plan-review/plan-review.task.yaml +9 -0
- package/examples/plan-review/plan-review.yaml +25 -0
- package/examples/playwright-mcp/README.md +39 -0
- package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
- package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
- package/examples/playwright-mcp/screenshot.yaml +40 -0
- package/examples/retry-tour/README.md +75 -0
- package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
- package/examples/retry-tour/retry-tour.task.yaml +9 -0
- package/examples/route-if-tour/README.md +202 -0
- package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
- package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
- package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
- package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
- package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
- package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
- package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
- package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
- package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
- package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
- package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
- package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
- package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
- package/examples/route-wiring-smoke-test/README.md +377 -0
- package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
- package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
- package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
- package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
- package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
- package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
- package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
- package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
- package/examples/ship-feature/README.md +190 -0
- package/examples/ship-feature/feat-address-feedback.yaml +119 -0
- package/examples/ship-feature/feat-implement.yaml +180 -0
- package/examples/ship-feature/feat-plan.yaml +120 -0
- package/examples/ship-feature/feat-review.yaml +109 -0
- package/examples/ship-feature/feat-ship.yaml +203 -0
- package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
- package/examples/ship-feature/ship-feature.task.yaml +78 -0
- package/examples/stage-mcp/README.md +144 -0
- package/examples/stage-mcp/echo-mcp.mjs +20 -0
- package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
- package/examples/stage-mcp/use-echo.yaml +20 -0
- package/examples/verify-tour/README.md +80 -0
- package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
- package/examples/verify-tour/verify-tour.task.yaml +11 -0
- package/package.json +5 -1
- package/skills/stageflow/SKILL.md +6 -6
- package/skills/stageflow/references/control-surface.md +11 -5
- package/skills/stageflow/scripts/detect-host.mjs +14 -1
- package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
- package/skills/stageflow-author/SKILL.md +4 -3
- package/skills/stageflow-author/references/catalog-mapping.md +16 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
- package/skills/stageflow-run/SKILL.md +20 -12
- package/skills/stageflow-run/references/mcp-call.md +9 -1
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +16 -5
- package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
- package/skills/stageflow-setup/SKILL.md +40 -8
- package/dist/ui/assets/index-Da5EHU6M.js +0 -119
|
@@ -1,196 +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 {
|
|
12
|
+
import { applyPendingMigrations, assertSchemaVersion, } from "./migrations/index.js";
|
|
13
|
+
import { StoreSchemaError } from "./storeSchemaError.js";
|
|
14
|
+
import { applyStorePragmas } from "./applyStorePragmas.js";
|
|
12
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`;
|
|
13
17
|
const ensuredStageDirs = new Set();
|
|
14
|
-
const DEFAULT_SQLITE_BUSY_TIMEOUT_MS = 5000;
|
|
15
|
-
function readSqliteBusyTimeoutMs() {
|
|
16
|
-
const raw = process.env.STAGEFLOW_SQLITE_BUSY_TIMEOUT_MS;
|
|
17
|
-
if (raw === undefined || raw.trim() === "") {
|
|
18
|
-
return DEFAULT_SQLITE_BUSY_TIMEOUT_MS;
|
|
19
|
-
}
|
|
20
|
-
const parsed = Number.parseInt(raw, 10);
|
|
21
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
22
|
-
return DEFAULT_SQLITE_BUSY_TIMEOUT_MS;
|
|
23
|
-
}
|
|
24
|
-
return parsed;
|
|
25
|
-
}
|
|
26
|
-
function ensureCheckoutRootColumn(db) {
|
|
27
|
-
const cols = db.prepare(`PRAGMA table_info(runs)`).all();
|
|
28
|
-
if (!cols.some((c) => c.name === "checkout_root")) {
|
|
29
|
-
db.exec(`ALTER TABLE runs ADD COLUMN checkout_root TEXT`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function ensureCiIdentityColumns(db) {
|
|
33
|
-
const cols = db.prepare(`PRAGMA table_info(runs)`).all();
|
|
34
|
-
const names = new Set(cols.map((c) => c.name));
|
|
35
|
-
for (const name of ["git_sha", "ci_pr_url", "ci_job_url"]) {
|
|
36
|
-
if (!names.has(name)) {
|
|
37
|
-
db.exec(`ALTER TABLE runs ADD COLUMN ${name} TEXT`);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
function ensurePipelineDagColumn(db) {
|
|
42
|
-
const cols = db.prepare(`PRAGMA table_info(runs)`).all();
|
|
43
|
-
if (!cols.some((c) => c.name === "pipeline_dag_json")) {
|
|
44
|
-
db.exec(`ALTER TABLE runs ADD COLUMN pipeline_dag_json TEXT`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function ensureRunLocatorColumns(db) {
|
|
48
|
-
const cols = db.prepare(`PRAGMA table_info(runs)`).all();
|
|
49
|
-
const names = new Set(cols.map((c) => c.name));
|
|
50
|
-
for (const name of ["pipeline_path", "task_path", "project_root"]) {
|
|
51
|
-
if (!names.has(name)) {
|
|
52
|
-
db.exec(`ALTER TABLE runs ADD COLUMN ${name} TEXT`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function ensureInlinePipelineColumn(db) {
|
|
57
|
-
const cols = db.prepare(`PRAGMA table_info(runs)`).all();
|
|
58
|
-
if (!cols.some((c) => c.name === "inline_pipeline_json")) {
|
|
59
|
-
db.exec(`ALTER TABLE runs ADD COLUMN inline_pipeline_json TEXT`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function ensureStageExecutionsTable(db) {
|
|
63
|
-
db.exec(`
|
|
64
|
-
CREATE TABLE IF NOT EXISTS stage_executions (
|
|
65
|
-
run_id TEXT NOT NULL,
|
|
66
|
-
stage_id TEXT NOT NULL,
|
|
67
|
-
attempt INTEGER NOT NULL,
|
|
68
|
-
status TEXT NOT NULL,
|
|
69
|
-
verification_outcome TEXT NOT NULL DEFAULT 'not_run',
|
|
70
|
-
started_at TEXT,
|
|
71
|
-
finished_at TEXT,
|
|
72
|
-
envelope_json TEXT,
|
|
73
|
-
PRIMARY KEY (run_id, stage_id, attempt),
|
|
74
|
-
FOREIGN KEY (run_id) REFERENCES runs(run_id)
|
|
75
|
-
);
|
|
76
|
-
CREATE INDEX IF NOT EXISTS idx_stage_executions_run_stage
|
|
77
|
-
ON stage_executions (run_id, stage_id, attempt);
|
|
78
|
-
`);
|
|
79
|
-
}
|
|
80
|
-
function ensureStageExecutionVerificationOutcomeColumn(db) {
|
|
81
|
-
const cols = db
|
|
82
|
-
.prepare(`PRAGMA table_info(stage_executions)`)
|
|
83
|
-
.all();
|
|
84
|
-
if (!cols.some((c) => c.name === "verification_outcome")) {
|
|
85
|
-
db.exec(`ALTER TABLE stage_executions ADD COLUMN verification_outcome TEXT NOT NULL DEFAULT 'not_run'`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function ensureStageExecutionCostColumns(db) {
|
|
89
|
-
const cols = db
|
|
90
|
-
.prepare(`PRAGMA table_info(stage_executions)`)
|
|
91
|
-
.all();
|
|
92
|
-
const names = new Set(cols.map((c) => c.name));
|
|
93
|
-
if (!names.has("cost_usd")) {
|
|
94
|
-
db.exec(`ALTER TABLE stage_executions ADD COLUMN cost_usd REAL`);
|
|
95
|
-
}
|
|
96
|
-
if (!names.has("usage_json")) {
|
|
97
|
-
db.exec(`ALTER TABLE stage_executions ADD COLUMN usage_json TEXT`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
function backfillVerificationOutcomes(db) {
|
|
101
|
-
db.exec(`
|
|
102
|
-
UPDATE stage_executions
|
|
103
|
-
SET verification_outcome = CASE
|
|
104
|
-
WHEN status = 'succeeded'
|
|
105
|
-
AND EXISTS (
|
|
106
|
-
SELECT 1 FROM verification_check_results AS check_result
|
|
107
|
-
WHERE check_result.run_id = stage_executions.run_id
|
|
108
|
-
AND check_result.stage_id = stage_executions.stage_id
|
|
109
|
-
AND check_result.attempt = stage_executions.attempt
|
|
110
|
-
)
|
|
111
|
-
AND NOT EXISTS (
|
|
112
|
-
SELECT 1 FROM verification_check_results AS check_result
|
|
113
|
-
WHERE check_result.run_id = stage_executions.run_id
|
|
114
|
-
AND check_result.stage_id = stage_executions.stage_id
|
|
115
|
-
AND check_result.attempt = stage_executions.attempt
|
|
116
|
-
AND check_result.status != 'passed'
|
|
117
|
-
)
|
|
118
|
-
THEN 'passed'
|
|
119
|
-
WHEN status = 'failed'
|
|
120
|
-
AND EXISTS (
|
|
121
|
-
SELECT 1 FROM verification_check_results AS check_result
|
|
122
|
-
WHERE check_result.run_id = stage_executions.run_id
|
|
123
|
-
AND check_result.stage_id = stage_executions.stage_id
|
|
124
|
-
AND check_result.attempt = stage_executions.attempt
|
|
125
|
-
)
|
|
126
|
-
THEN 'failed'
|
|
127
|
-
ELSE verification_outcome
|
|
128
|
-
END
|
|
129
|
-
WHERE verification_outcome = 'not_run';
|
|
130
|
-
`);
|
|
131
|
-
}
|
|
132
|
-
function ensureStageEventsAttemptColumn(db) {
|
|
133
|
-
const cols = db
|
|
134
|
-
.prepare(`PRAGMA table_info(stage_events)`)
|
|
135
|
-
.all();
|
|
136
|
-
if (!cols.some((c) => c.name === "attempt")) {
|
|
137
|
-
db.exec(`ALTER TABLE stage_events ADD COLUMN attempt INTEGER NOT NULL DEFAULT 1`);
|
|
138
|
-
db.exec(`
|
|
139
|
-
CREATE INDEX IF NOT EXISTS idx_stage_events_run_stage_attempt_at
|
|
140
|
-
ON stage_events (run_id, stage_id, attempt, at);
|
|
141
|
-
`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function ensureVerificationCheckResultsTable(db) {
|
|
145
|
-
db.exec(`
|
|
146
|
-
CREATE TABLE IF NOT EXISTS verification_check_results (
|
|
147
|
-
run_id TEXT NOT NULL,
|
|
148
|
-
stage_id TEXT NOT NULL,
|
|
149
|
-
attempt INTEGER NOT NULL,
|
|
150
|
-
check_id TEXT NOT NULL,
|
|
151
|
-
check_type TEXT NOT NULL,
|
|
152
|
-
status TEXT NOT NULL,
|
|
153
|
-
started_at TEXT,
|
|
154
|
-
finished_at TEXT,
|
|
155
|
-
evidence_json TEXT,
|
|
156
|
-
PRIMARY KEY (run_id, stage_id, attempt, check_id),
|
|
157
|
-
FOREIGN KEY (run_id, stage_id, attempt)
|
|
158
|
-
REFERENCES stage_executions(run_id, stage_id, attempt)
|
|
159
|
-
);
|
|
160
|
-
CREATE INDEX IF NOT EXISTS idx_verification_check_results_execution
|
|
161
|
-
ON verification_check_results (run_id, stage_id, attempt, check_id);
|
|
162
|
-
`);
|
|
163
|
-
}
|
|
164
|
-
function ensureFeedbackReplayStagePassEnvelopeColumn(db) {
|
|
165
|
-
const cols = db
|
|
166
|
-
.prepare(`PRAGMA table_info(feedback_replay_stage_passes)`)
|
|
167
|
-
.all();
|
|
168
|
-
if (cols.length === 0)
|
|
169
|
-
return;
|
|
170
|
-
if (!cols.some((c) => c.name === "emitted_envelope_json")) {
|
|
171
|
-
db.exec(`ALTER TABLE feedback_replay_stage_passes ADD COLUMN emitted_envelope_json TEXT`);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function ensureFeedbackReplayStagePassSessionOriginColumn(db) {
|
|
175
|
-
const cols = db
|
|
176
|
-
.prepare(`PRAGMA table_info(feedback_replay_stage_passes)`)
|
|
177
|
-
.all();
|
|
178
|
-
if (cols.length === 0)
|
|
179
|
-
return;
|
|
180
|
-
if (!cols.some((c) => c.name === "session_origin_attempt")) {
|
|
181
|
-
db.exec(`ALTER TABLE feedback_replay_stage_passes ADD COLUMN session_origin_attempt INTEGER`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function ensureFeedbackLoopDeferredSendBackColumn(db) {
|
|
185
|
-
const cols = db
|
|
186
|
-
.prepare(`PRAGMA table_info(feedback_loops)`)
|
|
187
|
-
.all();
|
|
188
|
-
if (cols.length === 0)
|
|
189
|
-
return;
|
|
190
|
-
if (!cols.some((c) => c.name === "deferred_send_back_json")) {
|
|
191
|
-
db.exec(`ALTER TABLE feedback_loops ADD COLUMN deferred_send_back_json TEXT`);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
18
|
function executionFromRow(row) {
|
|
195
19
|
return {
|
|
196
20
|
run_id: row.run_id,
|
|
@@ -204,7 +28,10 @@ function executionFromRow(row) {
|
|
|
204
28
|
? JSON.parse(row.envelope_json)
|
|
205
29
|
: null,
|
|
206
30
|
...(row.cost_usd != null ? { cost_usd: row.cost_usd } : {}),
|
|
207
|
-
...(row.usage_json != null
|
|
31
|
+
...(row.usage_json != null
|
|
32
|
+
? { usage: JSON.parse(row.usage_json) }
|
|
33
|
+
: {}),
|
|
34
|
+
auto_resume_count: row.auto_resume_count ?? 0,
|
|
208
35
|
};
|
|
209
36
|
}
|
|
210
37
|
function verificationCheckResultFromRow(row) {
|
|
@@ -300,33 +127,44 @@ export class SqliteRunStore {
|
|
|
300
127
|
storeRoot;
|
|
301
128
|
db;
|
|
302
129
|
migratePromise;
|
|
303
|
-
constructor(storeRoot) {
|
|
130
|
+
constructor(storeRoot, options) {
|
|
304
131
|
this.storeRoot = storeRoot;
|
|
132
|
+
const openerMode = options?.openerMode ??
|
|
133
|
+
(process.env.VITEST === "true" ? "migrate" : "assert");
|
|
305
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
|
+
}
|
|
306
145
|
this.db = new Database(dbPath);
|
|
307
|
-
this.db
|
|
308
|
-
this.db
|
|
309
|
-
this.db.exec(SCHEMA_SQL);
|
|
310
|
-
ensureCheckoutRootColumn(this.db);
|
|
311
|
-
ensureCiIdentityColumns(this.db);
|
|
312
|
-
ensurePipelineDagColumn(this.db);
|
|
313
|
-
ensureRunLocatorColumns(this.db);
|
|
314
|
-
ensureInlinePipelineColumn(this.db);
|
|
315
|
-
ensureStageExecutionsTable(this.db);
|
|
316
|
-
ensureStageExecutionVerificationOutcomeColumn(this.db);
|
|
317
|
-
ensureStageExecutionCostColumns(this.db);
|
|
318
|
-
ensureStageEventsAttemptColumn(this.db);
|
|
319
|
-
ensureVerificationCheckResultsTable(this.db);
|
|
320
|
-
ensureFeedbackReplayStagePassEnvelopeColumn(this.db);
|
|
321
|
-
ensureFeedbackReplayStagePassSessionOriginColumn(this.db);
|
|
322
|
-
ensureFeedbackLoopDeferredSendBackColumn(this.db);
|
|
323
|
-
backfillVerificationOutcomes(this.db);
|
|
146
|
+
applyStorePragmas(this.db);
|
|
147
|
+
applyPendingMigrations(this.db);
|
|
324
148
|
this.migratePromise = importDiskRunsIfEmpty(this.db, storeRoot).then(() => undefined);
|
|
325
149
|
}
|
|
326
150
|
/** Await one-shot disk import before catalog reads (create paths also wait). */
|
|
327
151
|
async ready() {
|
|
328
152
|
await this.migratePromise;
|
|
329
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
|
+
}
|
|
330
168
|
/**
|
|
331
169
|
* The connection this store owns, for the one caller allowed to share it: the composition root
|
|
332
170
|
* wiring the A2A tables into the same `state.db` file. Not part of the `RunStore` interface.
|
|
@@ -339,7 +177,7 @@ export class SqliteRunStore {
|
|
|
339
177
|
}
|
|
340
178
|
async createRun(input) {
|
|
341
179
|
await this.ready();
|
|
342
|
-
const runId = newRunId();
|
|
180
|
+
const runId = input.runId ?? newRunId();
|
|
343
181
|
const workspaceDir = this.getWorkspaceDir(runId);
|
|
344
182
|
await mkdir(path.join(workspaceDir, "stages"), { recursive: true });
|
|
345
183
|
const now = new Date().toISOString();
|
|
@@ -352,6 +190,12 @@ export class SqliteRunStore {
|
|
|
352
190
|
const projectRoot = input.projectRoot
|
|
353
191
|
? normalizeCatalogPath(input.projectRoot)
|
|
354
192
|
: null;
|
|
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);
|
|
355
199
|
this.db.transaction(() => {
|
|
356
200
|
if (input.submission) {
|
|
357
201
|
const existing = this.readSubmission(input.submission.key);
|
|
@@ -360,15 +204,15 @@ export class SqliteRunStore {
|
|
|
360
204
|
}
|
|
361
205
|
this.db
|
|
362
206
|
.prepare(`INSERT INTO runs
|
|
363
|
-
(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,
|
|
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)
|
|
364
208
|
VALUES
|
|
365
|
-
(@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)`)
|
|
366
210
|
.run({
|
|
367
211
|
run_id: runId,
|
|
368
212
|
pipeline_id: input.pipelineId,
|
|
369
213
|
task_id: input.taskId ?? null,
|
|
370
214
|
task_yaml: input.taskYaml,
|
|
371
|
-
status: "running",
|
|
215
|
+
status: input.status ?? "running",
|
|
372
216
|
created_at: now,
|
|
373
217
|
updated_at: now,
|
|
374
218
|
checkout_root: input.checkoutRoot ?? null,
|
|
@@ -381,9 +225,19 @@ export class SqliteRunStore {
|
|
|
381
225
|
pipeline_path: pipelinePath,
|
|
382
226
|
task_path: taskPath,
|
|
383
227
|
project_root: projectRoot,
|
|
384
|
-
|
|
385
|
-
|
|
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)
|
|
386
239
|
: null,
|
|
240
|
+
skip_gates: input.skipGates === undefined ? null : input.skipGates ? 1 : 0,
|
|
387
241
|
});
|
|
388
242
|
if (input.submission) {
|
|
389
243
|
this.db.prepare("INSERT INTO run_submissions (submission_key, request_hash, run_id) VALUES (?, ?, ?)")
|
|
@@ -403,17 +257,198 @@ export class SqliteRunStore {
|
|
|
403
257
|
}
|
|
404
258
|
async updateRunStatus(runId, status) {
|
|
405
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
|
+
}
|
|
406
349
|
const result = this.db
|
|
407
|
-
.prepare(`UPDATE runs SET
|
|
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`)
|
|
408
378
|
.run({
|
|
409
379
|
run_id: runId,
|
|
410
|
-
|
|
380
|
+
config_origins_json: JSON.stringify(merged),
|
|
411
381
|
updated_at: new Date().toISOString(),
|
|
412
382
|
});
|
|
413
383
|
if (result.changes === 0) {
|
|
414
384
|
throw new Error(`Run not found: ${runId}`);
|
|
415
385
|
}
|
|
416
386
|
}
|
|
387
|
+
async setCancelReason(runId, reason) {
|
|
388
|
+
await this.ready();
|
|
389
|
+
const result = this.db
|
|
390
|
+
.prepare(`UPDATE runs SET cancel_reason = @cancel_reason, updated_at = @updated_at WHERE run_id = @run_id`)
|
|
391
|
+
.run({
|
|
392
|
+
run_id: runId,
|
|
393
|
+
cancel_reason: reason,
|
|
394
|
+
updated_at: new Date().toISOString(),
|
|
395
|
+
});
|
|
396
|
+
if (result.changes === 0) {
|
|
397
|
+
throw new Error(`Run not found: ${runId}`);
|
|
398
|
+
}
|
|
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
|
+
}
|
|
417
452
|
async updatePipelineDag(runId, dag) {
|
|
418
453
|
await this.ready();
|
|
419
454
|
const result = this.db
|
|
@@ -435,6 +470,25 @@ export class SqliteRunStore {
|
|
|
435
470
|
await this.ready();
|
|
436
471
|
return this.getRunRow(runId).task_yaml;
|
|
437
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
|
+
}
|
|
438
492
|
async ensureStageWorkspace(runId, stageId) {
|
|
439
493
|
await this.ready();
|
|
440
494
|
this.getRunRow(runId);
|
|
@@ -485,7 +539,7 @@ export class SqliteRunStore {
|
|
|
485
539
|
verification_outcome: "not_run",
|
|
486
540
|
});
|
|
487
541
|
const row = this.db
|
|
488
|
-
.prepare(`SELECT
|
|
542
|
+
.prepare(`SELECT ${EXECUTION_SELECT_COLS}
|
|
489
543
|
FROM stage_executions
|
|
490
544
|
WHERE run_id = ? AND stage_id = ? AND attempt = ?`)
|
|
491
545
|
.get(runId, stageId, attempt);
|
|
@@ -495,7 +549,7 @@ export class SqliteRunStore {
|
|
|
495
549
|
async listStageExecutions(runId, stageId) {
|
|
496
550
|
await this.ready();
|
|
497
551
|
const rows = this.db
|
|
498
|
-
.prepare(`SELECT
|
|
552
|
+
.prepare(`SELECT ${EXECUTION_SELECT_COLS}
|
|
499
553
|
FROM stage_executions
|
|
500
554
|
WHERE run_id = ? AND stage_id = ?
|
|
501
555
|
ORDER BY attempt ASC`)
|
|
@@ -505,7 +559,7 @@ export class SqliteRunStore {
|
|
|
505
559
|
async getLatestStageExecution(runId, stageId) {
|
|
506
560
|
await this.ready();
|
|
507
561
|
const row = this.db
|
|
508
|
-
.prepare(`SELECT
|
|
562
|
+
.prepare(`SELECT ${EXECUTION_SELECT_COLS}
|
|
509
563
|
FROM stage_executions
|
|
510
564
|
WHERE run_id = ? AND stage_id = ?
|
|
511
565
|
ORDER BY attempt DESC
|
|
@@ -524,7 +578,7 @@ export class SqliteRunStore {
|
|
|
524
578
|
async getStageExecution(runId, stageId, attempt) {
|
|
525
579
|
await this.ready();
|
|
526
580
|
const row = this.db
|
|
527
|
-
.prepare(`SELECT
|
|
581
|
+
.prepare(`SELECT ${EXECUTION_SELECT_COLS}
|
|
528
582
|
FROM stage_executions
|
|
529
583
|
WHERE run_id = ? AND stage_id = ? AND attempt = ?`)
|
|
530
584
|
.get(runId, stageId, attempt);
|
|
@@ -533,6 +587,21 @@ export class SqliteRunStore {
|
|
|
533
587
|
}
|
|
534
588
|
return executionFromRow(row);
|
|
535
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
|
+
}
|
|
536
605
|
async updateStageExecution(runId, stageId, attempt, patch) {
|
|
537
606
|
await this.ready();
|
|
538
607
|
const sets = [];
|
|
@@ -570,6 +639,10 @@ export class SqliteRunStore {
|
|
|
570
639
|
sets.push("usage_json = @usage_json");
|
|
571
640
|
params.usage_json = JSON.stringify(patch.usage);
|
|
572
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
|
+
}
|
|
573
646
|
if (sets.length === 0)
|
|
574
647
|
return;
|
|
575
648
|
const result = this.db
|
|
@@ -746,9 +819,13 @@ export class SqliteRunStore {
|
|
|
746
819
|
clauses.push("(pipeline_id = ? OR pipeline_path = ? OR pipeline_path = ?)");
|
|
747
820
|
params.push(pipeline, pipeline, normalized);
|
|
748
821
|
}
|
|
822
|
+
if (filter?.caller_id !== undefined) {
|
|
823
|
+
clauses.push("caller_id = ?");
|
|
824
|
+
params.push(filter.caller_id);
|
|
825
|
+
}
|
|
749
826
|
const where = clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "";
|
|
750
827
|
const rows = this.db
|
|
751
|
-
.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
|
|
752
829
|
FROM runs ${where} ORDER BY created_at DESC`)
|
|
753
830
|
.all(...params);
|
|
754
831
|
const summaries = [];
|
|
@@ -762,10 +839,34 @@ export class SqliteRunStore {
|
|
|
762
839
|
}
|
|
763
840
|
return summaries;
|
|
764
841
|
}
|
|
765
|
-
async
|
|
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() {
|
|
766
867
|
await this.ready();
|
|
767
868
|
const rows = this.db
|
|
768
|
-
.prepare(`SELECT
|
|
869
|
+
.prepare(`SELECT project_root FROM projects ORDER BY project_root`)
|
|
769
870
|
.all();
|
|
770
871
|
return rows.map((row) => row.project_root);
|
|
771
872
|
}
|
|
@@ -1176,15 +1277,47 @@ export class SqliteRunStore {
|
|
|
1176
1277
|
...(row.pipeline_path != null ? { pipeline_path: row.pipeline_path } : {}),
|
|
1177
1278
|
...(row.task_path != null ? { task_path: row.task_path } : {}),
|
|
1178
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 } : {}),
|
|
1179
1310
|
...(pipeline_dag ? { pipeline_dag } : {}),
|
|
1180
|
-
...(row.
|
|
1181
|
-
? {
|
|
1311
|
+
...(row.pipeline_body
|
|
1312
|
+
? {
|
|
1313
|
+
inline_pipeline: JSON.parse(row.pipeline_body),
|
|
1314
|
+
}
|
|
1182
1315
|
: {}),
|
|
1183
1316
|
};
|
|
1184
1317
|
}
|
|
1185
1318
|
getRunRow(runId) {
|
|
1186
1319
|
const row = this.db
|
|
1187
|
-
.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
|
|
1188
1321
|
FROM runs WHERE run_id = ?`)
|
|
1189
1322
|
.get(runId);
|
|
1190
1323
|
if (!row)
|