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
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { projectRun } from "../projection/projectRun.js";
|
|
4
|
+
import { PACKAGE_VERSION } from "../package-meta.js";
|
|
5
|
+
import { globalStageflowHome } from "../project/globalHome.js";
|
|
6
|
+
import { createRunStoreAfterHostEnsure, } from "../runstore/createStore.js";
|
|
7
|
+
import { isInsideDir } from "../runstore/workspaceLayout.js";
|
|
8
|
+
import { ensureGlobalService } from "../server/ensureGlobalService.js";
|
|
9
|
+
export const EXPORT_ALL_USAGE = `Usage:
|
|
10
|
+
sf export --all [--status <status>] [--since <iso>] [--pipeline <id-or-path>] [--out <file>]
|
|
11
|
+
|
|
12
|
+
Streams whole-instance NDJSON (header + one projectRun line per run, including
|
|
13
|
+
non-terminal). Not a backup — restore does not accept export streams.`;
|
|
14
|
+
const defaultIo = {
|
|
15
|
+
log: (line) => console.log(line),
|
|
16
|
+
error: (line) => console.error(line),
|
|
17
|
+
};
|
|
18
|
+
export function buildExportHeader(filter, now = new Date()) {
|
|
19
|
+
return {
|
|
20
|
+
type: "stageflow_export",
|
|
21
|
+
version: 1,
|
|
22
|
+
stageflow_version: PACKAGE_VERSION,
|
|
23
|
+
created_at: now.toISOString(),
|
|
24
|
+
...(filter !== undefined ? { filter } : {}),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function resolveExportPipelineSource(options) {
|
|
28
|
+
if (options.pipelineSource === "inline") {
|
|
29
|
+
if (options.pipelineBody != null && options.pipelineBody !== "") {
|
|
30
|
+
try {
|
|
31
|
+
return {
|
|
32
|
+
kind: "inline",
|
|
33
|
+
pipeline: JSON.parse(options.pipelineBody),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {
|
|
38
|
+
kind: "unavailable",
|
|
39
|
+
pipeline: null,
|
|
40
|
+
note: "pipeline_body is not valid JSON",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
kind: "unavailable",
|
|
46
|
+
pipeline: null,
|
|
47
|
+
note: "inline pipeline body missing",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (options.pipelineSource === "path" || options.pipelinePath) {
|
|
51
|
+
return {
|
|
52
|
+
kind: "path",
|
|
53
|
+
path: options.pipelinePath ?? "",
|
|
54
|
+
pipeline: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
kind: "unavailable",
|
|
59
|
+
pipeline: null,
|
|
60
|
+
note: "pipeline source not recorded",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export function projectRunForExport(detail, pipelineBody) {
|
|
64
|
+
return {
|
|
65
|
+
...projectRun(detail),
|
|
66
|
+
pipeline_source: resolveExportPipelineSource({
|
|
67
|
+
pipelineSource: detail.pipeline_source,
|
|
68
|
+
pipelinePath: detail.pipeline_path,
|
|
69
|
+
pipelineBody,
|
|
70
|
+
}),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export function assertExportOutPathAllowed(outPath, homeDir = globalStageflowHome(), cwd = process.cwd()) {
|
|
74
|
+
const segments = outPath.split(/[/\\]/);
|
|
75
|
+
if (segments.some((segment) => segment === "..")) {
|
|
76
|
+
throw new Error("path must not contain .. segments");
|
|
77
|
+
}
|
|
78
|
+
const resolved = path.isAbsolute(outPath)
|
|
79
|
+
? path.resolve(outPath)
|
|
80
|
+
: path.resolve(cwd, outPath);
|
|
81
|
+
const worktrees = path.resolve(homeDir, "worktrees");
|
|
82
|
+
const runs = path.resolve(homeDir, "runs");
|
|
83
|
+
if (isInsideDir(resolved, worktrees) || isInsideDir(resolved, runs)) {
|
|
84
|
+
throw new Error("output path must not be under worktrees/ or runs/");
|
|
85
|
+
}
|
|
86
|
+
return resolved;
|
|
87
|
+
}
|
|
88
|
+
function parseExportArgs(args) {
|
|
89
|
+
let help = false;
|
|
90
|
+
let all = false;
|
|
91
|
+
let status;
|
|
92
|
+
let since;
|
|
93
|
+
let pipeline;
|
|
94
|
+
let outPath;
|
|
95
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
96
|
+
const arg = args[i];
|
|
97
|
+
if (arg === "--help" || arg === "-h") {
|
|
98
|
+
help = true;
|
|
99
|
+
}
|
|
100
|
+
else if (arg === "--all") {
|
|
101
|
+
all = true;
|
|
102
|
+
}
|
|
103
|
+
else if (arg === "--status") {
|
|
104
|
+
const value = args[++i];
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
throw new Error("Missing value for --status");
|
|
107
|
+
status = value;
|
|
108
|
+
}
|
|
109
|
+
else if (arg === "--since") {
|
|
110
|
+
const value = args[++i];
|
|
111
|
+
if (value === undefined)
|
|
112
|
+
throw new Error("Missing value for --since");
|
|
113
|
+
since = value;
|
|
114
|
+
}
|
|
115
|
+
else if (arg === "--pipeline") {
|
|
116
|
+
const value = args[++i];
|
|
117
|
+
if (value === undefined)
|
|
118
|
+
throw new Error("Missing value for --pipeline");
|
|
119
|
+
pipeline = value;
|
|
120
|
+
}
|
|
121
|
+
else if (arg === "--out") {
|
|
122
|
+
const value = args[++i];
|
|
123
|
+
if (value === undefined)
|
|
124
|
+
throw new Error("Missing value for --out");
|
|
125
|
+
outPath = value;
|
|
126
|
+
}
|
|
127
|
+
else if (arg?.startsWith("-")) {
|
|
128
|
+
throw new Error(`Unknown flag: ${arg}`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return { help, all, status, since, pipeline, outPath };
|
|
135
|
+
}
|
|
136
|
+
export async function* iterateExportNdjson(options) {
|
|
137
|
+
yield `${JSON.stringify(buildExportHeader(options.filter, options.now ?? new Date()))}\n`;
|
|
138
|
+
const runs = await options.store.listRuns(options.filter);
|
|
139
|
+
for (const summary of runs) {
|
|
140
|
+
const detail = await options.store.readRun(summary.run_id);
|
|
141
|
+
const pipelineBody = await options.store.readPipelineBody(summary.run_id);
|
|
142
|
+
const line = {
|
|
143
|
+
type: "projectRun",
|
|
144
|
+
run: projectRunForExport(detail, pipelineBody),
|
|
145
|
+
};
|
|
146
|
+
yield `${JSON.stringify(line)}\n`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export async function runExportAllCommand(args, options = {}) {
|
|
150
|
+
const cwd = options.cwd ?? process.cwd();
|
|
151
|
+
const out = { ...defaultIo, ...options.io };
|
|
152
|
+
let parsed;
|
|
153
|
+
try {
|
|
154
|
+
parsed = parseExportArgs(args);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
158
|
+
out.error(message);
|
|
159
|
+
out.error(EXPORT_ALL_USAGE);
|
|
160
|
+
return 1;
|
|
161
|
+
}
|
|
162
|
+
if (parsed.help) {
|
|
163
|
+
out.error(EXPORT_ALL_USAGE);
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
if (!parsed.all) {
|
|
167
|
+
out.error("sf export requires --all (whole-instance NDJSON)");
|
|
168
|
+
out.error(EXPORT_ALL_USAGE);
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
171
|
+
const filter = {};
|
|
172
|
+
if (parsed.status !== undefined)
|
|
173
|
+
filter.status = parsed.status;
|
|
174
|
+
if (parsed.since !== undefined)
|
|
175
|
+
filter.since = parsed.since;
|
|
176
|
+
if (parsed.pipeline !== undefined)
|
|
177
|
+
filter.pipeline = parsed.pipeline;
|
|
178
|
+
const opened = await createRunStoreAfterHostEnsure({ rootDir: globalStageflowHome() }, () => ensureGlobalService());
|
|
179
|
+
if (!opened.ok) {
|
|
180
|
+
out.error(opened.message);
|
|
181
|
+
return 1;
|
|
182
|
+
}
|
|
183
|
+
const store = opened.store;
|
|
184
|
+
try {
|
|
185
|
+
let sink = (line) => out.log(line.replace(/\n$/, ""));
|
|
186
|
+
let close;
|
|
187
|
+
if (parsed.outPath !== undefined) {
|
|
188
|
+
const target = assertExportOutPathAllowed(parsed.outPath, globalStageflowHome(), cwd);
|
|
189
|
+
const stream = createWriteStream(target);
|
|
190
|
+
sink = (line) => {
|
|
191
|
+
stream.write(line);
|
|
192
|
+
};
|
|
193
|
+
close = () => new Promise((resolve, reject) => {
|
|
194
|
+
stream.end(() => resolve());
|
|
195
|
+
stream.on("error", reject);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
for await (const line of iterateExportNdjson({
|
|
199
|
+
store,
|
|
200
|
+
filter: Object.keys(filter).length > 0 ? filter : undefined,
|
|
201
|
+
})) {
|
|
202
|
+
sink(line);
|
|
203
|
+
}
|
|
204
|
+
await close?.();
|
|
205
|
+
if (parsed.outPath !== undefined) {
|
|
206
|
+
out.error(`Wrote ${assertExportOutPathAllowed(parsed.outPath, globalStageflowHome(), cwd)}`);
|
|
207
|
+
}
|
|
208
|
+
return 0;
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
212
|
+
out.error(message);
|
|
213
|
+
return 1;
|
|
214
|
+
}
|
|
215
|
+
finally {
|
|
216
|
+
await store.close();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { projectRun } from "../projection/projectRun.js";
|
|
4
3
|
import { globalStageflowHome } from "../project/globalHome.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { createRunStoreAfterHostEnsure, } from "../runstore/createStore.js";
|
|
5
|
+
import { ensureGlobalService, } from "../server/ensureGlobalService.js";
|
|
6
|
+
import { buildRunExportPayload } from "../runstore/exportRunPayload.js";
|
|
7
|
+
import { resolveSafeOutPath } from "./resolveSafeOutPath.js";
|
|
7
8
|
export const EXPORT_RUN_USAGE = `Usage:
|
|
8
9
|
sf export-run --run <runId> [--from <sf-run.json>] [--out <file>]`;
|
|
9
10
|
const defaultIo = {
|
|
@@ -75,23 +76,19 @@ function resolveRunIdFromFile(fromPath, cwd) {
|
|
|
75
76
|
}
|
|
76
77
|
return runId;
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return resolved;
|
|
89
|
-
}
|
|
90
|
-
function assertRunComplete(status, runId) {
|
|
91
|
-
if (status === "succeeded" || status === "failed") {
|
|
79
|
+
const EXPORTABLE_STATUSES = new Set([
|
|
80
|
+
"running",
|
|
81
|
+
"succeeded",
|
|
82
|
+
"failed",
|
|
83
|
+
"cancelled",
|
|
84
|
+
"queued",
|
|
85
|
+
"created",
|
|
86
|
+
]);
|
|
87
|
+
function assertRunExportable(status, runId) {
|
|
88
|
+
if (EXPORTABLE_STATUSES.has(status)) {
|
|
92
89
|
return;
|
|
93
90
|
}
|
|
94
|
-
throw new Error(`run
|
|
91
|
+
throw new Error(`run cannot be exported: ${runId} (status: ${status})`);
|
|
95
92
|
}
|
|
96
93
|
export async function runExportRunCommand(args, options = {}) {
|
|
97
94
|
const cwd = options.cwd ?? process.cwd();
|
|
@@ -126,11 +123,16 @@ export async function runExportRunCommand(args, options = {}) {
|
|
|
126
123
|
out.error(EXPORT_RUN_USAGE);
|
|
127
124
|
return 1;
|
|
128
125
|
}
|
|
129
|
-
const
|
|
126
|
+
const opened = await createRunStoreAfterHostEnsure({ rootDir: globalStageflowHome() }, () => ensureGlobalService());
|
|
127
|
+
if (!opened.ok) {
|
|
128
|
+
out.error(opened.message);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
const store = opened.store;
|
|
130
132
|
try {
|
|
131
133
|
const detail = await store.readRun(runId);
|
|
132
|
-
|
|
133
|
-
const projection =
|
|
134
|
+
assertRunExportable(detail.status, runId);
|
|
135
|
+
const projection = buildRunExportPayload(detail);
|
|
134
136
|
const json = JSON.stringify(projection, null, 2);
|
|
135
137
|
if (parsed.outPath !== undefined) {
|
|
136
138
|
const target = resolveSafeOutPath(parsed.outPath, cwd);
|
package/dist/cli/hostClient.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { PipelineRunResult } from "../runtime/pipelineRunner.js";
|
|
2
|
-
import type { AbandonStageResult, DecideFeedbackLoopResult, StartRunResult, StopManualRecoveryResult } from "../runtime/runManager.js";
|
|
2
|
+
import type { AbandonStageResult, CancelRunResult, DecideFeedbackLoopResult, DeleteRunResult, GcRunsResult, StartRunResult, StopManualRecoveryResult } from "../runtime/runManager.js";
|
|
3
3
|
import type { DeliverAnswerResult } from "../runtime/stageHitl.js";
|
|
4
4
|
import type { RetryStageResult } from "../runtime/runRetryCoordinator.js";
|
|
5
5
|
import type { RunDetail, RunStore } from "../runstore/port.js";
|
|
6
|
+
import type { TaskFile } from "../types/task.js";
|
|
6
7
|
export declare function computeRunDir(runId: string): string;
|
|
7
8
|
export declare function httpReadRun(base: string, runId: string): Promise<RunDetail>;
|
|
8
9
|
/** Thin RunStore-shaped reader backed by the global service, for the CLI output helpers that only need `readRun`. */
|
|
@@ -13,7 +14,8 @@ export declare function pollRunUntilTerminal(base: string, runId: string, option
|
|
|
13
14
|
export declare function runDetailToPipelineRunResult(detail: RunDetail): PipelineRunResult;
|
|
14
15
|
export type HttpStartRunInput = {
|
|
15
16
|
pipeline: string;
|
|
16
|
-
task: string;
|
|
17
|
+
task: string | TaskFile;
|
|
18
|
+
project_root?: string;
|
|
17
19
|
checkoutOverride?: string;
|
|
18
20
|
skipGates?: boolean;
|
|
19
21
|
gitSha?: string;
|
|
@@ -21,7 +23,16 @@ export type HttpStartRunInput = {
|
|
|
21
23
|
ciJobUrl?: string;
|
|
22
24
|
};
|
|
23
25
|
export declare function httpStartRun(base: string, input: HttpStartRunInput): Promise<StartRunResult>;
|
|
24
|
-
export
|
|
26
|
+
export type HttpEnsureProjectResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
project_root: string;
|
|
29
|
+
} | Extract<StartRunResult, {
|
|
30
|
+
ok: false;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function httpEnsureProject(base: string, projectRoot: string): Promise<HttpEnsureProjectResult>;
|
|
33
|
+
export declare function httpRerun(base: string, runId: string, options?: {
|
|
34
|
+
pinned?: boolean;
|
|
35
|
+
}): Promise<StartRunResult>;
|
|
25
36
|
export declare function httpDeliverAnswer(base: string, runId: string, stageId: string, answer: unknown): Promise<DeliverAnswerResult>;
|
|
26
37
|
export declare function httpDecideFeedbackLoop(base: string, runId: string, stageId: string, input: {
|
|
27
38
|
decision: "extend" | "continue" | "abandon";
|
|
@@ -39,5 +50,12 @@ export declare function httpResumeTimedOutStage(base: string, runId: string, sta
|
|
|
39
50
|
export declare function httpRecoverManualStageUntilStop(base: string, runId: string, stageId: string, guidance?: string): Promise<RetryOrchestrationResult>;
|
|
40
51
|
export declare function httpStopManualRecovery(base: string, runId: string, stageId: string): Promise<StopManualRecoveryResult>;
|
|
41
52
|
export declare function httpAbandonStage(base: string, runId: string, stageId: string): Promise<AbandonStageResult>;
|
|
53
|
+
export declare function httpCancelRun(base: string, runId: string, reason: string): Promise<CancelRunResult>;
|
|
54
|
+
export declare function httpDeleteRun(base: string, runId: string, options?: {
|
|
55
|
+
force?: boolean;
|
|
56
|
+
}): Promise<DeleteRunResult>;
|
|
57
|
+
export declare function httpGcRuns(base: string, options?: {
|
|
58
|
+
execute?: boolean;
|
|
59
|
+
}): Promise<GcRunsResult>;
|
|
42
60
|
export declare function resolveAbsolute(cwd: string, maybeRelative: string): string;
|
|
43
61
|
export {};
|
package/dist/cli/hostClient.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { globalStageflowHome } from "../project/globalHome.js";
|
|
3
3
|
import { PipelineValidationError } from "../runtime/pipelineValidationError.js";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveStoreRoot, runWorkspaceDir } from "../runstore/paths.js";
|
|
5
|
+
import { clientAuthorizationHeaders } from "../server/controlToken.js";
|
|
5
6
|
async function postJson(base, urlPath, body) {
|
|
6
7
|
const res = await fetch(`${base}${urlPath}`, {
|
|
7
8
|
method: "POST",
|
|
8
|
-
headers: {
|
|
9
|
+
headers: {
|
|
10
|
+
"Content-Type": "application/json",
|
|
11
|
+
...clientAuthorizationHeaders("POST"),
|
|
12
|
+
},
|
|
9
13
|
body: JSON.stringify(body ?? {}),
|
|
10
14
|
});
|
|
11
15
|
return { status: res.status, body: await parseJsonBody(res) };
|
|
12
16
|
}
|
|
13
17
|
async function getJson(base, urlPath) {
|
|
14
|
-
const res = await fetch(`${base}${urlPath}
|
|
18
|
+
const res = await fetch(`${base}${urlPath}`, {
|
|
19
|
+
headers: { ...clientAuthorizationHeaders("GET") },
|
|
20
|
+
});
|
|
15
21
|
return { status: res.status, body: await parseJsonBody(res) };
|
|
16
22
|
}
|
|
17
23
|
async function parseJsonBody(res) {
|
|
@@ -35,7 +41,7 @@ function enc(value) {
|
|
|
35
41
|
return encodeURIComponent(value);
|
|
36
42
|
}
|
|
37
43
|
export function computeRunDir(runId) {
|
|
38
|
-
return runWorkspaceDir(
|
|
44
|
+
return runWorkspaceDir(resolveStoreRoot(globalStageflowHome()), runId);
|
|
39
45
|
}
|
|
40
46
|
export async function httpReadRun(base, runId) {
|
|
41
47
|
const { status, body } = await getJson(base, `/api/runs/${enc(runId)}`);
|
|
@@ -51,6 +57,7 @@ export function httpStoreReader(base) {
|
|
|
51
57
|
function isRunTerminal(detail) {
|
|
52
58
|
return (detail.status === "succeeded" ||
|
|
53
59
|
detail.status === "failed" ||
|
|
60
|
+
detail.status === "cancelled" ||
|
|
54
61
|
(detail.status === "running" && detail.waiting_stage_id !== undefined));
|
|
55
62
|
}
|
|
56
63
|
function sleep(ms) {
|
|
@@ -70,15 +77,20 @@ export function runDetailToPipelineRunResult(detail) {
|
|
|
70
77
|
? "succeeded"
|
|
71
78
|
: detail.status === "failed"
|
|
72
79
|
? "failed"
|
|
73
|
-
: "
|
|
80
|
+
: detail.status === "cancelled"
|
|
81
|
+
? "cancelled"
|
|
82
|
+
: "waiting";
|
|
83
|
+
const reason = outcome === "cancelled"
|
|
84
|
+
? (detail.cancel_reason ?? detail.failed_reason)
|
|
85
|
+
: outcome === "failed"
|
|
86
|
+
? detail.failed_reason
|
|
87
|
+
: undefined;
|
|
74
88
|
return {
|
|
75
89
|
ok: outcome === "succeeded",
|
|
76
90
|
outcome,
|
|
77
91
|
runId: detail.run_id,
|
|
78
92
|
runDir: computeRunDir(detail.run_id),
|
|
79
|
-
...(
|
|
80
|
-
? { reason: detail.failed_reason }
|
|
81
|
-
: {}),
|
|
93
|
+
...(reason !== undefined ? { reason } : {}),
|
|
82
94
|
};
|
|
83
95
|
}
|
|
84
96
|
function toStartFailure(status, body) {
|
|
@@ -107,15 +119,36 @@ export async function httpStartRun(base, input) {
|
|
|
107
119
|
}
|
|
108
120
|
if (status !== 202)
|
|
109
121
|
return toStartFailure(status, body);
|
|
110
|
-
const
|
|
122
|
+
const parsed = body;
|
|
123
|
+
const runId = parsed.runId;
|
|
111
124
|
return {
|
|
112
125
|
ok: true,
|
|
113
126
|
runId,
|
|
127
|
+
...(parsed.queued === true
|
|
128
|
+
? { queued: true, queuePosition: parsed.queuePosition }
|
|
129
|
+
: {}),
|
|
114
130
|
done: pollRunUntilTerminal(base, runId).then(runDetailToPipelineRunResult),
|
|
115
131
|
};
|
|
116
132
|
}
|
|
117
|
-
export async function
|
|
118
|
-
const { status, body } = await postJson(base,
|
|
133
|
+
export async function httpEnsureProject(base, projectRoot) {
|
|
134
|
+
const { status, body } = await postJson(base, "/api/projects", {
|
|
135
|
+
project_root: projectRoot,
|
|
136
|
+
});
|
|
137
|
+
if (status === 200) {
|
|
138
|
+
const parsed = body;
|
|
139
|
+
if (typeof parsed.project_root === "string" && parsed.project_root.length > 0) {
|
|
140
|
+
return { ok: true, project_root: parsed.project_root };
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
ok: false,
|
|
144
|
+
reason: "ensure_project response missing project_root",
|
|
145
|
+
status,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return toStartFailure(status, body);
|
|
149
|
+
}
|
|
150
|
+
export async function httpRerun(base, runId, options) {
|
|
151
|
+
const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/rerun`, options?.pinned !== undefined ? { pinned: options.pinned } : {});
|
|
119
152
|
if (status !== 202)
|
|
120
153
|
return toStartFailure(status, body);
|
|
121
154
|
const newRunId = body.runId;
|
|
@@ -142,7 +175,15 @@ export async function httpDecideFeedbackLoop(base, runId, stageId, input) {
|
|
|
142
175
|
export async function httpRetryStageUntilStop(base, runId, stageId) {
|
|
143
176
|
const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/stages/${enc(stageId)}/retry`, {});
|
|
144
177
|
if (status !== 202) {
|
|
145
|
-
|
|
178
|
+
const code = body && typeof body === "object" && typeof body.code === "string"
|
|
179
|
+
? body.code
|
|
180
|
+
: undefined;
|
|
181
|
+
return {
|
|
182
|
+
ok: false,
|
|
183
|
+
reason: extractError(body, status),
|
|
184
|
+
status,
|
|
185
|
+
...(code !== undefined ? { code } : {}),
|
|
186
|
+
};
|
|
146
187
|
}
|
|
147
188
|
const detail = await pollRunUntilTerminal(base, runId);
|
|
148
189
|
return { ok: true, pipeline: runDetailToPipelineRunResult(detail) };
|
|
@@ -177,6 +218,46 @@ export async function httpAbandonStage(base, runId, stageId) {
|
|
|
177
218
|
}
|
|
178
219
|
return { ok: false, reason: extractError(body, status), status };
|
|
179
220
|
}
|
|
221
|
+
export async function httpCancelRun(base, runId, reason) {
|
|
222
|
+
const { status, body } = await postJson(base, `/api/runs/${enc(runId)}/cancel`, { reason });
|
|
223
|
+
if (status === 202) {
|
|
224
|
+
const parsed = body;
|
|
225
|
+
return { ok: true, runId: parsed.runId };
|
|
226
|
+
}
|
|
227
|
+
return { ok: false, reason: extractError(body, status), status };
|
|
228
|
+
}
|
|
229
|
+
export async function httpDeleteRun(base, runId, options) {
|
|
230
|
+
const forceQs = options?.force ? "?force=true" : "";
|
|
231
|
+
const res = await fetch(`${base}/api/runs/${enc(runId)}${forceQs}`, {
|
|
232
|
+
method: "DELETE",
|
|
233
|
+
headers: { ...clientAuthorizationHeaders("DELETE") },
|
|
234
|
+
});
|
|
235
|
+
const body = await parseJsonBody(res);
|
|
236
|
+
if (res.status === 200) {
|
|
237
|
+
const parsed = body;
|
|
238
|
+
return { ok: true, runId: parsed.runId };
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
ok: false,
|
|
242
|
+
reason: extractError(body, res.status),
|
|
243
|
+
status: res.status,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
export async function httpGcRuns(base, options) {
|
|
247
|
+
const { status, body } = await postJson(base, "/api/runs/gc", {
|
|
248
|
+
execute: options?.execute === true,
|
|
249
|
+
});
|
|
250
|
+
if (status === 200) {
|
|
251
|
+
const parsed = body;
|
|
252
|
+
return {
|
|
253
|
+
ok: true,
|
|
254
|
+
slimmed: parsed.slimmed ?? [],
|
|
255
|
+
purged: parsed.purged ?? [],
|
|
256
|
+
bareCachesEvicted: parsed.bareCachesEvicted ?? [],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { ok: false, reason: extractError(body, status), status };
|
|
260
|
+
}
|
|
180
261
|
export function resolveAbsolute(cwd, maybeRelative) {
|
|
181
262
|
return path.resolve(cwd, maybeRelative);
|
|
182
263
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export declare const STAGEFLOW_YAML = "version: 1\ncatalog:\n pipelines:\n - pipelines\n tasks:\n - tasks\n patterns:\n pipeline: \"*.pipeline.yaml\"\n task: \"*.task.yaml\"\n";
|
|
2
|
-
export declare const HELLO_PIPELINE_YAML = "id: hello\
|
|
2
|
+
export declare const HELLO_PIPELINE_YAML = "id: hello\nstages:\n - id: hello\n model: anthropic/claude-sonnet-4-5\n system_prompt: Say hello and emit a success envelope.\n io:\n input:\n schema:\n type: object\n output:\n schema:\n type: object\n";
|
|
3
3
|
export declare const HELLO_TASK_YAML = "id: hello\ngoal: Run the hello pipeline scaffold.\n";
|
|
@@ -9,10 +9,17 @@ catalog:
|
|
|
9
9
|
task: "*.task.yaml"
|
|
10
10
|
`;
|
|
11
11
|
export const HELLO_PIPELINE_YAML = `id: hello
|
|
12
|
-
model: anthropic/claude-sonnet-4-5
|
|
13
12
|
stages:
|
|
14
13
|
- id: hello
|
|
14
|
+
model: anthropic/claude-sonnet-4-5
|
|
15
15
|
system_prompt: Say hello and emit a success envelope.
|
|
16
|
+
io:
|
|
17
|
+
input:
|
|
18
|
+
schema:
|
|
19
|
+
type: object
|
|
20
|
+
output:
|
|
21
|
+
schema:
|
|
22
|
+
type: object
|
|
16
23
|
`;
|
|
17
24
|
export const HELLO_TASK_YAML = `id: hello
|
|
18
25
|
goal: Run the hello pipeline scaffold.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isInsideDir } from "../runstore/workspaceLayout.js";
|
|
4
|
+
function resolveEffectiveRealPathSync(candidatePath) {
|
|
5
|
+
try {
|
|
6
|
+
return realpathSync(candidatePath);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
const missing = [];
|
|
10
|
+
let current = candidatePath;
|
|
11
|
+
while (true) {
|
|
12
|
+
missing.unshift(path.basename(current));
|
|
13
|
+
const parent = path.dirname(current);
|
|
14
|
+
if (parent === current) {
|
|
15
|
+
return path.resolve(candidatePath);
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const realParent = realpathSync(parent);
|
|
19
|
+
return path.join(realParent, ...missing);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
current = parent;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Resolve `--out` under cwd, realpath-normalizing both sides before containment. */
|
|
28
|
+
export function resolveSafeOutPath(outPath, cwd) {
|
|
29
|
+
const segments = outPath.split(/[/\\]/);
|
|
30
|
+
if (segments.some((segment) => segment === "..")) {
|
|
31
|
+
throw new Error("path must not contain .. segments");
|
|
32
|
+
}
|
|
33
|
+
const resolved = path.resolve(cwd, outPath);
|
|
34
|
+
const cwdResolved = resolveEffectiveRealPathSync(path.resolve(cwd));
|
|
35
|
+
const outResolved = resolveEffectiveRealPathSync(resolved);
|
|
36
|
+
if (!isInsideDir(outResolved, cwdResolved)) {
|
|
37
|
+
throw new Error("output path must resolve under the current working directory");
|
|
38
|
+
}
|
|
39
|
+
return resolved;
|
|
40
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { probeGlobalServiceDetailed } from "../server/ensureGlobalService.js";
|
|
2
|
+
export declare const RESTORE_USAGE = "Usage:\n sf restore <file> [--force] [--json]\n\nRestores a Stageflow backup. The Host must be down (probed via /livez).\nNever autostarts a Host. Previous state.db is moved aside, not deleted.";
|
|
3
|
+
export type RestoreCommandIo = {
|
|
4
|
+
log: (line: string) => void;
|
|
5
|
+
error: (line: string) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare function runRestoreCommand(args: string[], options?: {
|
|
8
|
+
io?: Partial<RestoreCommandIo>;
|
|
9
|
+
probe?: typeof probeGlobalServiceDetailed;
|
|
10
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { applyRestoreArchive, RestoreError, } from "../runstore/restore.js";
|
|
3
|
+
import { StoreSchemaError } from "../runstore/sqlite/storeSchemaError.js";
|
|
4
|
+
import { globalStageflowHome } from "../project/globalHome.js";
|
|
5
|
+
export const RESTORE_USAGE = `Usage:
|
|
6
|
+
sf restore <file> [--force] [--json]
|
|
7
|
+
|
|
8
|
+
Restores a Stageflow backup. The Host must be down (probed via /livez).
|
|
9
|
+
Never autostarts a Host. Previous state.db is moved aside, not deleted.`;
|
|
10
|
+
const defaultIo = {
|
|
11
|
+
log: (line) => console.log(line),
|
|
12
|
+
error: (line) => console.error(line),
|
|
13
|
+
};
|
|
14
|
+
function parseRestoreArgs(args) {
|
|
15
|
+
let help = false;
|
|
16
|
+
let file;
|
|
17
|
+
let force = false;
|
|
18
|
+
let json = false;
|
|
19
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
20
|
+
const arg = args[i];
|
|
21
|
+
if (arg === "--help" || arg === "-h") {
|
|
22
|
+
help = true;
|
|
23
|
+
}
|
|
24
|
+
else if (arg === "--force") {
|
|
25
|
+
force = true;
|
|
26
|
+
}
|
|
27
|
+
else if (arg === "--json") {
|
|
28
|
+
json = true;
|
|
29
|
+
}
|
|
30
|
+
else if (arg?.startsWith("-")) {
|
|
31
|
+
throw new Error(`Unknown flag: ${arg}`);
|
|
32
|
+
}
|
|
33
|
+
else if (file === undefined) {
|
|
34
|
+
file = arg;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { help, file, force, json };
|
|
41
|
+
}
|
|
42
|
+
export async function runRestoreCommand(args, options = {}) {
|
|
43
|
+
const out = { ...defaultIo, ...options.io };
|
|
44
|
+
let parsed;
|
|
45
|
+
try {
|
|
46
|
+
parsed = parseRestoreArgs(args);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
50
|
+
out.error(message);
|
|
51
|
+
out.error(RESTORE_USAGE);
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
if (parsed.help) {
|
|
55
|
+
out.error(RESTORE_USAGE);
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
if (!parsed.file) {
|
|
59
|
+
out.error("Missing <file>");
|
|
60
|
+
out.error(RESTORE_USAGE);
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const result = await applyRestoreArchive({
|
|
65
|
+
archivePath: path.resolve(parsed.file),
|
|
66
|
+
homeDir: globalStageflowHome(),
|
|
67
|
+
force: parsed.force,
|
|
68
|
+
probe: options.probe,
|
|
69
|
+
});
|
|
70
|
+
if (parsed.json) {
|
|
71
|
+
out.log(JSON.stringify({ ok: true, ...result }));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
out.log(`Restored schema_version=${result.schema_version}` +
|
|
75
|
+
(result.missing_a2a_artifact_rows > 0
|
|
76
|
+
? ` (missing A2A artifact bytes: ${result.missing_a2a_artifact_rows})`
|
|
77
|
+
: ""));
|
|
78
|
+
}
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
if (err instanceof RestoreError || err instanceof StoreSchemaError) {
|
|
83
|
+
out.error(`${err.code}: ${err.message}`);
|
|
84
|
+
return 1;
|
|
85
|
+
}
|
|
86
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
87
|
+
out.error(message);
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
}
|