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.
- package/README.md +24 -5
- package/dist/a2a/configDiscovery.d.ts +9 -0
- package/dist/a2a/configDiscovery.js +18 -0
- package/dist/a2a/contracts.d.ts +94 -0
- package/dist/a2a/contracts.js +164 -0
- package/dist/a2a/limits.d.ts +14 -0
- package/dist/a2a/limits.js +29 -0
- package/dist/a2a/registry.d.ts +46 -0
- package/dist/a2a/registry.js +178 -0
- package/dist/a2a/server.d.ts +36 -0
- package/dist/a2a/server.js +344 -0
- package/dist/a2a/service.d.ts +97 -0
- package/dist/a2a/service.js +545 -0
- package/dist/a2a/store.d.ts +109 -0
- package/dist/a2a/store.js +202 -0
- 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/a2aCommand.d.ts +8 -0
- package/dist/cli/a2aCommand.js +131 -0
- 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 +34 -0
- package/dist/cli/runStageCommand.js +426 -0
- package/dist/cli/runsCommand.d.ts +1 -1
- package/dist/cli/runsCommand.js +162 -8
- package/dist/cli.js +190 -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 +591 -76
- 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 +27 -0
- package/dist/runstore/createStore.js +75 -7
- 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 +119 -8
- 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 +37 -3
- package/dist/runstore/sqlite/SqliteRunStore.js +401 -227
- 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 +283 -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/submission.d.ts +11 -0
- package/dist/runstore/submission.js +7 -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 +38 -1
- package/dist/runtime/pipelineRunner.js +179 -15
- package/dist/runtime/pipelineScheduler.d.ts +15 -0
- package/dist/runtime/pipelineScheduler.js +167 -42
- package/dist/runtime/reloadRunCatalog.js +12 -1
- package/dist/runtime/repositoryMaterialize.d.ts +47 -0
- package/dist/runtime/repositoryMaterialize.js +235 -0
- package/dist/runtime/resolveEnvelopeRef.d.ts +30 -0
- package/dist/runtime/resolveEnvelopeRef.js +79 -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 +179 -4
- package/dist/runtime/runManager.js +1644 -83
- 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 +38 -2
- package/dist/server/bootstrap.js +219 -4
- 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 +109 -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 +6 -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
|
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { buildValidationResult, loadPipelineValidated, } from "../config/validateCatalog.js";
|
|
4
4
|
import { loadTaskFromYaml } from "../config/loadTask.js";
|
|
5
|
-
import { resolveAndValidateCheckout } from "./stageRoots.js";
|
|
5
|
+
import { resolveAndValidateCheckout, resolveEffectiveGitIdentity, } from "./stageRoots.js";
|
|
6
6
|
import { buildPipelineDagSnapshotFromLoaded } from "../runstore/pipelineDagSnapshot.js";
|
|
7
7
|
import { normalizeCatalogPath } from "../runstore/normalizeCatalogPath.js";
|
|
8
8
|
import { runPipelineDag } from "./pipelineScheduler.js";
|
|
@@ -10,7 +10,55 @@ import { readMaxActiveStagesPerRun, readStageExecutionMode, } from "./stageConcu
|
|
|
10
10
|
import { StageProcessLauncher } from "./stageProcessLauncher.js";
|
|
11
11
|
import { PipelineValidationError } from "./pipelineValidationError.js";
|
|
12
12
|
import { checkTaskEntryInput } from "./taskInput.js";
|
|
13
|
+
import { pipelinePersistenceForStart } from "./startPayload.js";
|
|
14
|
+
import { materializeRunSkills, } from "./runSkills.js";
|
|
15
|
+
import { preflightFailureCode, runPipelinePreflight, } from "../preflight/pipelinePreflight.js";
|
|
16
|
+
import { networkError } from "../errors/codes.js";
|
|
17
|
+
import { newRunId } from "../runstore/paths.js";
|
|
18
|
+
import { bindingFromFields, buildInitialRunManifest, collectDeclaredSecretValues, finaliseStoredRunManifest, } from "../runstore/runManifest.js";
|
|
19
|
+
import { getRequestAuth, } from "../server/requestAuthContext.js";
|
|
20
|
+
import { registerNamedSecrets } from "../logging/namedSecrets.js";
|
|
21
|
+
import { shouldRegisterValue } from "../logging/redact.js";
|
|
13
22
|
export { PipelineValidationError } from "./pipelineValidationError.js";
|
|
23
|
+
export class PipelinePreflightError extends Error {
|
|
24
|
+
code;
|
|
25
|
+
preflight;
|
|
26
|
+
constructor(code, preflight) {
|
|
27
|
+
super(`Pipeline preflight failed: ${code}`);
|
|
28
|
+
this.name = "PipelinePreflightError";
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.preflight = preflight;
|
|
31
|
+
}
|
|
32
|
+
toNetworkBody() {
|
|
33
|
+
return networkError(this.code, this.message, {
|
|
34
|
+
checks: this.preflight.checks,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class InlinePipelineTooLargeError extends Error {
|
|
39
|
+
code = "inline_pipeline_too_large";
|
|
40
|
+
bytes;
|
|
41
|
+
maxBytes;
|
|
42
|
+
constructor(bytes, maxBytes) {
|
|
43
|
+
super(`Inline pipeline body is ${bytes} bytes; max is ${maxBytes} (inline_pipeline_too_large)`);
|
|
44
|
+
this.name = "InlinePipelineTooLargeError";
|
|
45
|
+
this.bytes = bytes;
|
|
46
|
+
this.maxBytes = maxBytes;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Thrown when queued→running CAS fails (e.g. cancel won the race). */
|
|
50
|
+
export class QueuedRunActivationAborted extends Error {
|
|
51
|
+
runId;
|
|
52
|
+
currentStatus;
|
|
53
|
+
constructor(runId, currentStatus) {
|
|
54
|
+
super(currentStatus === undefined
|
|
55
|
+
? `Queued run ${runId} could not be activated`
|
|
56
|
+
: `Queued run ${runId} could not be activated (status=${currentStatus})`);
|
|
57
|
+
this.name = "QueuedRunActivationAborted";
|
|
58
|
+
this.runId = runId;
|
|
59
|
+
this.currentStatus = currentStatus;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
14
62
|
let defaultStageProcessLauncher;
|
|
15
63
|
function resolveStageProcessLauncher(executionMode, override) {
|
|
16
64
|
if (executionMode !== "process") {
|
|
@@ -34,6 +82,14 @@ async function preparePipeline(options) {
|
|
|
34
82
|
throw new PipelineValidationError(buildValidationResult("pipeline", loadResult.findings, false));
|
|
35
83
|
}
|
|
36
84
|
const loaded = loadResult.loaded;
|
|
85
|
+
const preflight = await runPipelinePreflight(loaded, {
|
|
86
|
+
projectRoot: options.projectRoot ?? options.cwd,
|
|
87
|
+
forStart: true,
|
|
88
|
+
});
|
|
89
|
+
if (!preflight.ok) {
|
|
90
|
+
const code = preflightFailureCode(preflight, { forStart: true }) ?? "missing_tool";
|
|
91
|
+
throw new PipelinePreflightError(code, preflight);
|
|
92
|
+
}
|
|
37
93
|
const taskYaml = options.taskYaml ??
|
|
38
94
|
(options.taskPath
|
|
39
95
|
? await readFile(options.taskPath, "utf8")
|
|
@@ -56,27 +112,122 @@ async function preparePipeline(options) {
|
|
|
56
112
|
for (const finding of warningFindings) {
|
|
57
113
|
console.error(`${finding.code}: ${finding.message}`);
|
|
58
114
|
}
|
|
59
|
-
|
|
115
|
+
// Materialization is owned by RunManager (KTD1). When checkoutRoot is supplied,
|
|
116
|
+
// do not re-resolve or fetch here.
|
|
117
|
+
const checkoutRoot = options.checkoutRoot !== undefined
|
|
118
|
+
? options.checkoutRoot
|
|
119
|
+
: await resolveAndValidateCheckout(task, options.checkoutOverride, options.cwd);
|
|
60
120
|
const pipelinePath = typeof options.pipeline === "string"
|
|
61
121
|
? normalizeCatalogPath(loaded.pipelinePath)
|
|
62
122
|
: undefined;
|
|
123
|
+
const persistence = pipelinePersistenceForStart(options.pipeline);
|
|
124
|
+
if (!persistence.ok) {
|
|
125
|
+
throw new InlinePipelineTooLargeError(persistence.bytes, persistence.maxBytes);
|
|
126
|
+
}
|
|
63
127
|
const taskPath = options.taskPath
|
|
64
128
|
? normalizeCatalogPath(path.resolve(options.cwd, options.taskPath))
|
|
65
129
|
: undefined;
|
|
66
130
|
const projectRoot = normalizeCatalogPath(options.projectRoot ?? options.cwd);
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
131
|
+
const gitIdentity = resolveEffectiveGitIdentity(process.env, task.git_identity);
|
|
132
|
+
let run;
|
|
133
|
+
if (options.reuseExistingRun === true) {
|
|
134
|
+
const runId = options.runId;
|
|
135
|
+
if (runId === undefined || runId.trim() === "") {
|
|
136
|
+
throw new Error("reuseExistingRun requires a preallocated runId");
|
|
137
|
+
}
|
|
138
|
+
await options.store.patchRunWorkspaceBinding(runId, {
|
|
139
|
+
...(checkoutRoot !== undefined ? { checkoutRoot } : {}),
|
|
140
|
+
...(options.repository !== undefined
|
|
141
|
+
? { repository: options.repository }
|
|
142
|
+
: {}),
|
|
143
|
+
...(options.ref !== undefined ? { ref: options.ref } : {}),
|
|
144
|
+
...(options.resolvedSha !== undefined
|
|
145
|
+
? { resolvedSha: options.resolvedSha }
|
|
146
|
+
: {}),
|
|
147
|
+
...(options.runBranch !== undefined
|
|
148
|
+
? { runBranch: options.runBranch }
|
|
149
|
+
: {}),
|
|
150
|
+
});
|
|
151
|
+
const activated = await options.store.tryUpdateRunStatus(runId, "running", "queued");
|
|
152
|
+
if (!activated) {
|
|
153
|
+
let currentStatus;
|
|
154
|
+
try {
|
|
155
|
+
currentStatus = (await options.store.readRunMeta(runId)).status;
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
currentStatus = undefined;
|
|
159
|
+
}
|
|
160
|
+
throw new QueuedRunActivationAborted(runId, currentStatus);
|
|
161
|
+
}
|
|
162
|
+
run = { runId, workspaceDir: options.store.getWorkspaceDir(runId) };
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const runId = options.runId ?? newRunId();
|
|
166
|
+
const createdAt = new Date().toISOString();
|
|
167
|
+
const auth = getRequestAuth();
|
|
168
|
+
const surface = auth?.surface ?? "cli";
|
|
169
|
+
const callerId = options.callerId !== undefined && options.callerId !== null
|
|
170
|
+
? options.callerId
|
|
171
|
+
: null;
|
|
172
|
+
const secretNames = loaded.stages.flatMap((s) => (s.secrets ?? []).map((d) => d.name));
|
|
173
|
+
const namedSecrets = collectDeclaredSecretValues(secretNames).filter((s) => shouldRegisterValue(s.value));
|
|
174
|
+
if (namedSecrets.length > 0) {
|
|
175
|
+
registerNamedSecrets(namedSecrets);
|
|
176
|
+
}
|
|
177
|
+
const runManifest = buildInitialRunManifest({
|
|
178
|
+
runId,
|
|
179
|
+
createdAt,
|
|
180
|
+
callerId,
|
|
181
|
+
surface,
|
|
182
|
+
binding: bindingFromFields({
|
|
183
|
+
repository: options.repository,
|
|
184
|
+
ref: options.ref,
|
|
185
|
+
resolvedSha: options.resolvedSha,
|
|
186
|
+
runBranch: options.runBranch,
|
|
187
|
+
checkoutRoot,
|
|
188
|
+
}),
|
|
189
|
+
pipelineSource: persistence.fields.pipelineSource,
|
|
190
|
+
pipelinePath,
|
|
191
|
+
pipelineBody: persistence.fields.pipelineBody ?? null,
|
|
192
|
+
taskYaml,
|
|
193
|
+
taskPath,
|
|
194
|
+
skills: options.skills,
|
|
195
|
+
stages: loaded.stages,
|
|
196
|
+
toolchain: preflight.toolchain.checks,
|
|
197
|
+
namedSecrets,
|
|
198
|
+
});
|
|
199
|
+
run = await options.store.createRun({
|
|
200
|
+
submission: options.submission,
|
|
201
|
+
runId,
|
|
202
|
+
pipelineId: loaded.pipeline.id,
|
|
203
|
+
taskYaml,
|
|
204
|
+
taskId: task.id,
|
|
205
|
+
checkoutRoot,
|
|
206
|
+
gitSha: options.gitSha,
|
|
207
|
+
ciPrUrl: options.ciPrUrl,
|
|
208
|
+
ciJobUrl: options.ciJobUrl,
|
|
209
|
+
pipelineDag: buildPipelineDagSnapshotFromLoaded(loaded),
|
|
210
|
+
pipelinePath,
|
|
211
|
+
taskPath,
|
|
212
|
+
projectRoot,
|
|
213
|
+
repository: options.repository,
|
|
214
|
+
ref: options.ref,
|
|
215
|
+
resolvedSha: options.resolvedSha,
|
|
216
|
+
runBranch: options.runBranch,
|
|
217
|
+
gitAuthorName: gitIdentity.name,
|
|
218
|
+
gitAuthorEmail: gitIdentity.email,
|
|
219
|
+
pipelineSource: persistence.fields.pipelineSource,
|
|
220
|
+
...(persistence.fields.pipelineBody !== undefined
|
|
221
|
+
? { pipelineBody: persistence.fields.pipelineBody }
|
|
222
|
+
: {}),
|
|
223
|
+
...(callerId !== null ? { callerId } : {}),
|
|
224
|
+
runManifest,
|
|
225
|
+
skipGates: options.skipGates,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
if (options.skills !== undefined && Object.keys(options.skills).length > 0) {
|
|
229
|
+
await materializeRunSkills(run.workspaceDir, options.skills);
|
|
230
|
+
}
|
|
80
231
|
const executionMode = readStageExecutionMode(process.env, options.executionMode);
|
|
81
232
|
const stageProcessLauncher = resolveStageProcessLauncher(executionMode, options.stageProcessLauncher);
|
|
82
233
|
return {
|
|
@@ -110,6 +261,7 @@ export async function executeStages(prepared, options) {
|
|
|
110
261
|
startAtStageIndex: options?.startAtStageIndex,
|
|
111
262
|
executionMode,
|
|
112
263
|
stageProcessLauncher,
|
|
264
|
+
schedulingHalt: options?.schedulingHalt,
|
|
113
265
|
});
|
|
114
266
|
if (prepared.findings !== undefined && prepared.findings.length > 0) {
|
|
115
267
|
return { ...result, findings: prepared.findings };
|
|
@@ -145,6 +297,7 @@ export async function startPipeline(options) {
|
|
|
145
297
|
const cwd = options.cwd ?? process.cwd();
|
|
146
298
|
const projectRoot = options.projectRoot ?? cwd;
|
|
147
299
|
const prepared = await preparePipeline({
|
|
300
|
+
submission: options.submission,
|
|
148
301
|
agent: options.agent,
|
|
149
302
|
store: options.store,
|
|
150
303
|
taskPath: options.taskPath,
|
|
@@ -153,6 +306,13 @@ export async function startPipeline(options) {
|
|
|
153
306
|
cwd,
|
|
154
307
|
projectRoot,
|
|
155
308
|
checkoutOverride: options.checkoutOverride,
|
|
309
|
+
runId: options.runId,
|
|
310
|
+
reuseExistingRun: options.reuseExistingRun,
|
|
311
|
+
checkoutRoot: options.checkoutRoot,
|
|
312
|
+
repository: options.repository,
|
|
313
|
+
ref: options.ref,
|
|
314
|
+
resolvedSha: options.resolvedSha,
|
|
315
|
+
runBranch: options.runBranch,
|
|
156
316
|
gitSha: options.gitSha,
|
|
157
317
|
ciPrUrl: options.ciPrUrl,
|
|
158
318
|
ciJobUrl: options.ciJobUrl,
|
|
@@ -161,13 +321,17 @@ export async function startPipeline(options) {
|
|
|
161
321
|
stageProcessLauncher: options.stageProcessLauncher,
|
|
162
322
|
operatorCatalog: options.operatorCatalog,
|
|
163
323
|
skipGates: options.skipGates,
|
|
324
|
+
callerId: options.callerId,
|
|
325
|
+
...(options.skills !== undefined ? { skills: options.skills } : {}),
|
|
164
326
|
});
|
|
165
327
|
const done = executeStages(prepared, {
|
|
166
328
|
maxActiveStagesPerRun: options.maxActiveStagesPerRun,
|
|
167
329
|
executionMode: prepared.executionMode,
|
|
168
330
|
stageProcessLauncher: prepared.stageProcessLauncher,
|
|
331
|
+
schedulingHalt: options.schedulingHalt,
|
|
169
332
|
}).catch(async (err) => {
|
|
170
333
|
await prepared.store.updateRunStatus(prepared.run.runId, "failed").catch(() => undefined);
|
|
334
|
+
await finaliseStoredRunManifest(prepared.store, prepared.run.runId).catch(() => undefined);
|
|
171
335
|
return {
|
|
172
336
|
ok: false,
|
|
173
337
|
outcome: "failed",
|
|
@@ -61,7 +61,13 @@ export type ResumeRunOptions = {
|
|
|
61
61
|
initialPrior?: StageEnvelope | null;
|
|
62
62
|
executionMode?: StageExecutionMode;
|
|
63
63
|
stageProcessLauncher?: StageProcessLauncher;
|
|
64
|
+
schedulingHalt?: {
|
|
65
|
+
halted: boolean;
|
|
66
|
+
hostShutdown?: boolean;
|
|
67
|
+
};
|
|
64
68
|
};
|
|
69
|
+
/** Refuses to overwrite a cancelled run (KTD7). */
|
|
70
|
+
export declare function writeTerminalRunStatus(store: RunStore, runId: string, status: "succeeded" | "failed"): Promise<void>;
|
|
65
71
|
export declare function resumeRun(options: ResumeRunOptions): Promise<PipelineRunResult>;
|
|
66
72
|
export type RunPipelineDagOptions = {
|
|
67
73
|
prepared: SchedulerPreparedPipeline;
|
|
@@ -87,6 +93,11 @@ export type RunPipelineDagOptions = {
|
|
|
87
93
|
sourceStageId: string;
|
|
88
94
|
resolve: (decision: FeedbackLoopDecisionInput) => Promise<ResolveFeedbackLoopDecisionResult>;
|
|
89
95
|
}) => Promise<void>;
|
|
96
|
+
/** Live cancel flag — when set, launchStage/startStage stop. */
|
|
97
|
+
schedulingHalt?: {
|
|
98
|
+
halted: boolean;
|
|
99
|
+
hostShutdown?: boolean;
|
|
100
|
+
};
|
|
90
101
|
};
|
|
91
102
|
export type RetryRunOptions = {
|
|
92
103
|
prepared: SchedulerPreparedPipeline;
|
|
@@ -97,6 +108,10 @@ export type RetryRunOptions = {
|
|
|
97
108
|
mutationQueue?: RetryMutationQueue;
|
|
98
109
|
onLoopTick?: () => void | Promise<void>;
|
|
99
110
|
onRetryRootTerminal?: OnRetryRootTerminal;
|
|
111
|
+
schedulingHalt?: {
|
|
112
|
+
halted: boolean;
|
|
113
|
+
hostShutdown?: boolean;
|
|
114
|
+
};
|
|
100
115
|
};
|
|
101
116
|
export declare function retryRun(options: RetryRunOptions): Promise<PipelineRunResult>;
|
|
102
117
|
export declare function applyForkSkipsFromEnvelopes(dag: ResolvedPipelineDag, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope>): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { normalizeForkChoice } from "../envelope/forkChoice.js";
|
|
2
|
+
import { refreshRunDiskUsage } from "../runstore/diskUsage.js";
|
|
2
3
|
import { buildPipelineDagSnapshotFromLoaded } from "../runstore/pipelineDagSnapshot.js";
|
|
3
4
|
import { definitionIdForInstance } from "../runstore/stageInstanceId.js";
|
|
4
5
|
import { cloneFailureContinuesSchedule, cloneRetryDownstream, cloneFailFastSkipIds, cloneScheduleAllowsRun, failureIsAccepted, isCloneInstance, mint, protectedClonableChildIds, sequentialLaterCloneIds, skipRejectedNeedDependents, } from "./cloneSchedule.js";
|
|
@@ -8,8 +9,18 @@ import { reopenRunnableSkippedStages, persistReopenedStages } from "./reopenSkip
|
|
|
8
9
|
import { forkChoicePreservesReplaySource, forkCohortMapsFromStore, mintCohortForFanout, } from "./forkGeneration.js";
|
|
9
10
|
import { activeReplayId, activeSourceStageId, applySendBack, createReplaySchedule, hydrateFromStore, isHeld, launchAttemptFor, launchFor, noteActiveCohort, onContinued, onRouteStageFailed, onRouteStageRunning, onRouteStageSucceeded, rebindRouteAttempts, resolveDecision, } from "./replayLifecycle.js";
|
|
10
11
|
import { WAIT_WITHOUT_WORKER_DISPATCH } from "./answerResume.js";
|
|
12
|
+
import { reclaimWorkspaceOnRunSucceeded } from "./repositoryMaterialize.js";
|
|
13
|
+
import { syncRunStatusFromStages } from "./stageRecovery.js";
|
|
11
14
|
import { runStage, isRunStageWaiting } from "./stageRunner.js";
|
|
12
15
|
import { attemptContext, resumeSessionFilePath } from "./stageAttemptContext.js";
|
|
16
|
+
import { stageBindingEnvFromRun } from "./stageRoots.js";
|
|
17
|
+
import { attemptWorkspaceDir } from "../runstore/workspaceLayout.js";
|
|
18
|
+
import { cleanupCredentialsDir, loadSecretRegistry, resolveStageSecrets, SecretUnavailableError, } from "./stageSecrets.js";
|
|
19
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { logger as rootLogger, } from "../logging/logger.js";
|
|
22
|
+
import { registerNamedSecrets, REDACTION_SECRETS_FILENAME } from "../logging/namedSecrets.js";
|
|
23
|
+
import { finaliseStoredRunManifest } from "../runstore/runManifest.js";
|
|
13
24
|
function asDagSnapshot(dag) {
|
|
14
25
|
const snapshot = dag;
|
|
15
26
|
if (Array.isArray(snapshot.stage_ids))
|
|
@@ -35,6 +46,8 @@ export function snapshotToScheduleState(snap, overrides, stageId, executionMode)
|
|
|
35
46
|
return "active";
|
|
36
47
|
case "waiting_for_input":
|
|
37
48
|
return executionMode === "process" ? "waiting" : "active";
|
|
49
|
+
case "interrupted":
|
|
50
|
+
return "waiting";
|
|
38
51
|
case "skipped":
|
|
39
52
|
return "skipped";
|
|
40
53
|
default:
|
|
@@ -136,6 +149,18 @@ export async function hydrateScheduleForRetryRoots(store, runId, dag, retryStage
|
|
|
136
149
|
export async function hydrateScheduleForRetry(store, runId, dag, retryStageId) {
|
|
137
150
|
return hydrateScheduleForRetryRoots(store, runId, dag, [retryStageId]);
|
|
138
151
|
}
|
|
152
|
+
/** Refuses to overwrite a cancelled run (KTD7). */
|
|
153
|
+
export async function writeTerminalRunStatus(store, runId, status) {
|
|
154
|
+
const meta = await store.readRunMeta(runId);
|
|
155
|
+
if (meta.status === "cancelled")
|
|
156
|
+
return;
|
|
157
|
+
await store.updateRunStatus(runId, status);
|
|
158
|
+
await finaliseStoredRunManifest(store, runId).catch(() => undefined);
|
|
159
|
+
await refreshRunDiskUsage(store, runId).catch(() => undefined);
|
|
160
|
+
if (status === "succeeded") {
|
|
161
|
+
await reclaimWorkspaceOnRunSucceeded(store, runId);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
139
164
|
export async function resumeRun(options) {
|
|
140
165
|
const { prepared, resumeFromStageId, initialPrior } = options;
|
|
141
166
|
const meta = await prepared.store.readRunMeta(prepared.run.runId);
|
|
@@ -165,7 +190,7 @@ export async function resumeRun(options) {
|
|
|
165
190
|
});
|
|
166
191
|
if (allTerminal) {
|
|
167
192
|
const unhandledFailure = scheduleHasUnhandledFailure(dag, hydrated.states);
|
|
168
|
-
await prepared.store
|
|
193
|
+
await writeTerminalRunStatus(prepared.store, prepared.run.runId, unhandledFailure ? "failed" : "succeeded");
|
|
169
194
|
return {
|
|
170
195
|
ok: !unhandledFailure,
|
|
171
196
|
outcome: unhandledFailure ? "failed" : "succeeded",
|
|
@@ -191,6 +216,7 @@ export async function retryRun(options) {
|
|
|
191
216
|
mutationQueue: options.mutationQueue,
|
|
192
217
|
onLoopTick: options.onLoopTick,
|
|
193
218
|
onRetryRootTerminal: options.onRetryRootTerminal,
|
|
219
|
+
schedulingHalt: options.schedulingHalt,
|
|
194
220
|
});
|
|
195
221
|
}
|
|
196
222
|
function applyForkChoiceToSchedule(dag, forkStageId, chosen, states, options) {
|
|
@@ -220,6 +246,25 @@ export function applyForkSkipsFromEnvelopes(dag, states, completedEnvelopes) {
|
|
|
220
246
|
applyForkChoiceToSchedule(dag, node.id, chosen, states);
|
|
221
247
|
}
|
|
222
248
|
}
|
|
249
|
+
async function applyEagerRouteIfSkipsFromEnvelopes(dag, states, completedEnvelopes, persistSkip) {
|
|
250
|
+
for (const [parentId, envelope] of completedEnvelopes) {
|
|
251
|
+
if (states.get(parentId) !== "succeeded")
|
|
252
|
+
continue;
|
|
253
|
+
for (const childId of dag.childrenOf[parentId] ?? []) {
|
|
254
|
+
const child = dag.nodes.find((n) => n.id === childId);
|
|
255
|
+
if (!child)
|
|
256
|
+
continue;
|
|
257
|
+
const result = classifyInboundAfterSuccess(child, parentId, envelope.payload);
|
|
258
|
+
if (result === "missing_field") {
|
|
259
|
+
return parentId;
|
|
260
|
+
}
|
|
261
|
+
if (isEagerSingleParentIfSkip(child, parentId, envelope.payload)) {
|
|
262
|
+
await persistSkip(childId);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
223
268
|
export function applyRetryRootDelta(dag, states, completedEnvelopes, retryRoots, stageId, attempt, clearSchedulingHalt, alreadyLaunchedIds) {
|
|
224
269
|
retryRoots.set(stageId, attempt);
|
|
225
270
|
const downstream = cloneRetryDownstream(dag, [stageId]);
|
|
@@ -330,10 +375,16 @@ export async function runPipelineDag(options) {
|
|
|
330
375
|
let { states, completedEnvelopes, schedulingHalted, firstFailureReason, dag: hydratedDag, } = options.initialSchedule ??
|
|
331
376
|
(await hydrateScheduleFromStore(store, run.runId, fallbackDag, executionMode));
|
|
332
377
|
let dag = hydratedDag ?? fallbackDag;
|
|
378
|
+
const runMeta = await store.readRunMeta(run.runId);
|
|
333
379
|
if (hydratedDag === undefined) {
|
|
334
|
-
|
|
335
|
-
dag = meta.pipeline_dag ?? fallbackDag;
|
|
380
|
+
dag = runMeta.pipeline_dag ?? fallbackDag;
|
|
336
381
|
}
|
|
382
|
+
const stageBinding = stageBindingEnvFromRun({
|
|
383
|
+
meta: runMeta,
|
|
384
|
+
task,
|
|
385
|
+
runWorkspaceDir: run.workspaceDir,
|
|
386
|
+
hostEnv: process.env,
|
|
387
|
+
});
|
|
337
388
|
const stageById = buildStageConfigById(loaded);
|
|
338
389
|
const retryContext = options.retryContext;
|
|
339
390
|
const feedbackSchedule = createReplaySchedule();
|
|
@@ -472,6 +523,13 @@ export async function runPipelineDag(options) {
|
|
|
472
523
|
await persistSkipPending(id);
|
|
473
524
|
}
|
|
474
525
|
}
|
|
526
|
+
const missingRouteIfParent = await applyEagerRouteIfSkipsFromEnvelopes(dag, states, completedEnvelopes, persistSkipPending);
|
|
527
|
+
if (missingRouteIfParent !== undefined) {
|
|
528
|
+
schedulingHalted = true;
|
|
529
|
+
if (firstFailureReason === undefined) {
|
|
530
|
+
firstFailureReason = `stage "${missingRouteIfParent}": route if field missing from payload`;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
475
533
|
const markSkippedPending = () => {
|
|
476
534
|
for (const node of dag.nodes) {
|
|
477
535
|
if (states.get(node.id) === "pending") {
|
|
@@ -756,22 +814,13 @@ export async function runPipelineDag(options) {
|
|
|
756
814
|
await store.appendStageEvent(run.runId, id, { event: "skipped" });
|
|
757
815
|
}
|
|
758
816
|
}
|
|
759
|
-
const
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
if (
|
|
763
|
-
|
|
764
|
-
const result = classifyInboundAfterSuccess(child, stageId, envelope.payload);
|
|
765
|
-
if (result === "missing_field") {
|
|
766
|
-
schedulingHalted = true;
|
|
767
|
-
if (firstFailureReason === undefined) {
|
|
768
|
-
firstFailureReason = `stage "${stageId}": route if field missing from payload`;
|
|
769
|
-
}
|
|
770
|
-
return;
|
|
771
|
-
}
|
|
772
|
-
if (isEagerSingleParentIfSkip(child, stageId, envelope.payload)) {
|
|
773
|
-
await persistSkipPending(childId);
|
|
817
|
+
const missingParent = await applyEagerRouteIfSkipsFromEnvelopes(dag, states, new Map([[stageId, envelope]]), persistSkipPending);
|
|
818
|
+
if (missingParent !== undefined) {
|
|
819
|
+
schedulingHalted = true;
|
|
820
|
+
if (firstFailureReason === undefined) {
|
|
821
|
+
firstFailureReason = `stage "${missingParent}": route if field missing from payload`;
|
|
774
822
|
}
|
|
823
|
+
return;
|
|
775
824
|
}
|
|
776
825
|
await reopenRunnableSkippedStages(store, run.runId, dag, states, completedEnvelopes);
|
|
777
826
|
};
|
|
@@ -810,32 +859,83 @@ export async function runPipelineDag(options) {
|
|
|
810
859
|
stageId,
|
|
811
860
|
});
|
|
812
861
|
}
|
|
862
|
+
const attemptDir = attemptWorkspaceDir(run.workspaceDir, stageId, attempt);
|
|
863
|
+
await mkdir(attemptDir, { recursive: true });
|
|
864
|
+
const attemptHome = path.join(attemptDir, "home");
|
|
865
|
+
await mkdir(attemptHome, { recursive: true });
|
|
866
|
+
let grants;
|
|
867
|
+
try {
|
|
868
|
+
const resolved = resolveStageSecrets({
|
|
869
|
+
decls: stage.secrets,
|
|
870
|
+
registry: loadSecretRegistry(process.env),
|
|
871
|
+
hostEnv: process.env,
|
|
872
|
+
attemptDir,
|
|
873
|
+
});
|
|
874
|
+
grants = resolved.grants;
|
|
875
|
+
registerNamedSecrets(resolved.knownValues);
|
|
876
|
+
await writeFile(path.join(attemptDir, REDACTION_SECRETS_FILENAME), `${JSON.stringify(resolved.knownValues)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
877
|
+
for (const warning of resolved.warnings) {
|
|
878
|
+
rootLogger.warn("stage.secrets", warning, {
|
|
879
|
+
run_id: run.runId,
|
|
880
|
+
stage_id: stageId,
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
await writeFile(path.join(attemptDir, "declared-secrets.json"), `${JSON.stringify({ names: grants.declaredSecretNames }, null, 2)}\n`, "utf8");
|
|
884
|
+
}
|
|
885
|
+
catch (err) {
|
|
886
|
+
const reason = err instanceof SecretUnavailableError
|
|
887
|
+
? err.message
|
|
888
|
+
: err instanceof Error
|
|
889
|
+
? err.message
|
|
890
|
+
: String(err);
|
|
891
|
+
await onStageFailure(stageId, reason);
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
const cleanupAttemptCredentials = () => {
|
|
895
|
+
try {
|
|
896
|
+
cleanupCredentialsDir(attemptDir);
|
|
897
|
+
}
|
|
898
|
+
catch {
|
|
899
|
+
// best-effort Host cleanup
|
|
900
|
+
}
|
|
901
|
+
};
|
|
813
902
|
if (executionMode === "process") {
|
|
814
903
|
const launcher = options.stageProcessLauncher;
|
|
815
904
|
if (!launcher) {
|
|
905
|
+
cleanupAttemptCredentials();
|
|
816
906
|
await onStageFailure(stageId, "stage process launcher is not configured");
|
|
817
907
|
return;
|
|
818
908
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
909
|
+
let launchResult;
|
|
910
|
+
try {
|
|
911
|
+
launchResult = await launcher.launch({
|
|
912
|
+
runId: run.runId,
|
|
913
|
+
stageId,
|
|
914
|
+
rootDir: factoryCwd,
|
|
915
|
+
attempt,
|
|
916
|
+
env: stageBinding.env,
|
|
917
|
+
bindingKind: stageBinding.kind,
|
|
918
|
+
grants,
|
|
919
|
+
attemptHome,
|
|
920
|
+
...(sessionMode !== undefined
|
|
921
|
+
? {
|
|
922
|
+
mode: sessionMode === "feedback_resume"
|
|
923
|
+
? "feedback_resume"
|
|
924
|
+
: sessionMode === "new_session"
|
|
925
|
+
? "new_session"
|
|
926
|
+
: "run",
|
|
927
|
+
}
|
|
928
|
+
: {}),
|
|
929
|
+
...(resumeToken !== undefined ? { sessionFilePath: resumeToken } : {}),
|
|
930
|
+
...(prepared.operatorCatalog !== undefined
|
|
931
|
+
? { operatorCatalog: prepared.operatorCatalog }
|
|
932
|
+
: {}),
|
|
933
|
+
...(prepared.skipGates ? { skipGates: true } : {}),
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
finally {
|
|
937
|
+
cleanupAttemptCredentials();
|
|
938
|
+
}
|
|
839
939
|
if (launchResult.type === "succeeded") {
|
|
840
940
|
try {
|
|
841
941
|
const envelope = await store.readEnvelope(run.runId, stageId);
|
|
@@ -851,6 +951,10 @@ export async function runPipelineDag(options) {
|
|
|
851
951
|
states.set(stageId, "waiting");
|
|
852
952
|
return;
|
|
853
953
|
}
|
|
954
|
+
if (options.schedulingHalt?.hostShutdown) {
|
|
955
|
+
states.set(stageId, "waiting");
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
854
958
|
await onStageFailure(stageId, launchResult.reason);
|
|
855
959
|
return;
|
|
856
960
|
}
|
|
@@ -870,15 +974,25 @@ export async function runPipelineDag(options) {
|
|
|
870
974
|
operatorCatalog: prepared.operatorCatalog,
|
|
871
975
|
completedEnvelopes,
|
|
872
976
|
skipGates: prepared.skipGates,
|
|
977
|
+
stageEnv: {
|
|
978
|
+
...stageBinding.env,
|
|
979
|
+
...grants.env,
|
|
980
|
+
HOME: attemptHome,
|
|
981
|
+
},
|
|
873
982
|
...(sessionMode !== undefined ? { sessionMode } : {}),
|
|
874
983
|
...(feedbackLoopContext !== undefined ? { feedbackLoopContext } : {}),
|
|
875
984
|
...(resumeToken !== undefined ? { resumeToken } : {}),
|
|
876
985
|
});
|
|
986
|
+
cleanupAttemptCredentials();
|
|
877
987
|
if (isRunStageWaiting(result)) {
|
|
878
988
|
await onStageFailure(stageId, WAIT_WITHOUT_WORKER_DISPATCH);
|
|
879
989
|
return;
|
|
880
990
|
}
|
|
881
991
|
if (!result.ok) {
|
|
992
|
+
if (options.schedulingHalt?.hostShutdown) {
|
|
993
|
+
states.set(stageId, "waiting");
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
882
996
|
await onStageFailure(stageId, result.reason ?? "stage failed", result.envelope);
|
|
883
997
|
return;
|
|
884
998
|
}
|
|
@@ -927,11 +1041,17 @@ export async function runPipelineDag(options) {
|
|
|
927
1041
|
return true;
|
|
928
1042
|
};
|
|
929
1043
|
while (!allTerminal()) {
|
|
1044
|
+
if (options.schedulingHalt?.halted) {
|
|
1045
|
+
schedulingHalted = true;
|
|
1046
|
+
}
|
|
930
1047
|
drainRetryMutations();
|
|
931
1048
|
await applyStalledJoinSkips();
|
|
932
1049
|
if (options.onLoopTick !== undefined) {
|
|
933
1050
|
await options.onLoopTick();
|
|
934
1051
|
}
|
|
1052
|
+
if (options.schedulingHalt?.halted) {
|
|
1053
|
+
schedulingHalted = true;
|
|
1054
|
+
}
|
|
935
1055
|
if (!schedulingHalted) {
|
|
936
1056
|
const runnable = pickRunnable();
|
|
937
1057
|
for (const stageId of runnable) {
|
|
@@ -975,11 +1095,16 @@ export async function runPipelineDag(options) {
|
|
|
975
1095
|
if (schedulingHalted) {
|
|
976
1096
|
markSkippedPending();
|
|
977
1097
|
if (retryContext === undefined) {
|
|
978
|
-
|
|
1098
|
+
if (options.schedulingHalt?.hostShutdown) {
|
|
1099
|
+
await syncRunStatusFromStages(store, run.runId);
|
|
1100
|
+
}
|
|
1101
|
+
else {
|
|
1102
|
+
await writeTerminalRunStatus(store, run.runId, "failed");
|
|
1103
|
+
}
|
|
979
1104
|
}
|
|
980
1105
|
return {
|
|
981
1106
|
ok: false,
|
|
982
|
-
outcome: "failed",
|
|
1107
|
+
outcome: options.schedulingHalt?.hostShutdown ? "waiting" : "failed",
|
|
983
1108
|
runDir: run.workspaceDir,
|
|
984
1109
|
runId: run.runId,
|
|
985
1110
|
reason: firstFailureReason,
|
|
@@ -987,7 +1112,7 @@ export async function runPipelineDag(options) {
|
|
|
987
1112
|
}
|
|
988
1113
|
if (scheduleHasUnhandledFailure(dag, states) || !allTerminal()) {
|
|
989
1114
|
if (retryContext === undefined) {
|
|
990
|
-
await store
|
|
1115
|
+
await writeTerminalRunStatus(store, run.runId, "failed");
|
|
991
1116
|
}
|
|
992
1117
|
return {
|
|
993
1118
|
ok: false,
|
|
@@ -997,7 +1122,7 @@ export async function runPipelineDag(options) {
|
|
|
997
1122
|
reason: firstFailureReason ?? "pipeline incomplete",
|
|
998
1123
|
};
|
|
999
1124
|
}
|
|
1000
|
-
await store
|
|
1125
|
+
await writeTerminalRunStatus(store, run.runId, "succeeded");
|
|
1001
1126
|
return {
|
|
1002
1127
|
ok: true,
|
|
1003
1128
|
outcome: "succeeded",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { access } from "node:fs/promises";
|
|
2
|
-
import { loadPipeline } from "../config/loadPipeline.js";
|
|
2
|
+
import { loadPipeline, loadPipelineFromObject } from "../config/loadPipeline.js";
|
|
3
3
|
import { loadTask } from "../config/loadTask.js";
|
|
4
4
|
import { normalizeCatalogPath } from "../runstore/normalizeCatalogPath.js";
|
|
5
5
|
function missingLocator(field, runId) {
|
|
@@ -32,6 +32,17 @@ async function assertCatalogFileExists(filePath, label) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
export async function reloadPipelineForRun(meta) {
|
|
35
|
+
// An inline-pipeline run (no pipeline_path — nothing was ever written to a
|
|
36
|
+
// catalog file) carries its own pipeline body in meta.inline_pipeline
|
|
37
|
+
// instead, the same way a task without task_path reloads from task_yaml.
|
|
38
|
+
// Prefer this before requiring path locators; project_root is optional and
|
|
39
|
+
// falls back to cwd (same as loadPipelineFromObject).
|
|
40
|
+
if (meta.inline_pipeline) {
|
|
41
|
+
const projectRoot = meta.project_root
|
|
42
|
+
? normalizeCatalogPath(meta.project_root)
|
|
43
|
+
: process.cwd();
|
|
44
|
+
return loadPipelineFromObject(meta.inline_pipeline, { projectRoot });
|
|
45
|
+
}
|
|
35
46
|
const projectRoot = requireProjectRoot(meta);
|
|
36
47
|
const pipelinePath = requirePipelinePath(meta);
|
|
37
48
|
await assertCatalogFileExists(pipelinePath, "Pipeline");
|