stageflow 0.2.0 → 0.8.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 +179 -14
- package/dist/agent/activity.d.ts +12 -1
- package/dist/agent/activity.js +37 -2
- package/dist/agent/activityObserver.d.ts +5 -1
- package/dist/agent/activityObserver.js +174 -11
- package/dist/agent/cursorProvider.d.ts +1 -10
- package/dist/agent/cursorProvider.js +18 -10
- package/dist/agent/fakeAgent.js +15 -7
- package/dist/agent/piAdapter.d.ts +18 -1
- package/dist/agent/piAdapter.js +115 -45
- package/dist/agent/port.d.ts +7 -0
- package/dist/agent/port.js +3 -0
- package/dist/agent/providerAuth.js +12 -7
- package/dist/catalog/displayCatalogPath.d.ts +12 -0
- package/dist/catalog/displayCatalogPath.js +28 -0
- package/dist/cli/artifactCommand.d.ts +10 -0
- package/dist/cli/artifactCommand.js +120 -0
- package/dist/cli/envelopeCommand.d.ts +32 -0
- package/dist/cli/envelopeCommand.js +285 -0
- package/dist/cli/exportRunCommand.d.ts +10 -0
- package/dist/cli/exportRunCommand.js +150 -0
- package/dist/cli/handoffFormat.d.ts +22 -0
- package/dist/cli/handoffFormat.js +61 -0
- package/dist/cli/initCommand.d.ts +9 -0
- package/dist/cli/initCommand.js +71 -0
- package/dist/cli/initTemplates.d.ts +3 -0
- package/dist/cli/initTemplates.js +19 -0
- package/dist/cli/operatorCatalog.d.ts +10 -0
- package/dist/cli/operatorCatalog.js +16 -0
- package/dist/cli/runCommand.d.ts +7 -1
- package/dist/cli/runCommand.js +83 -11
- package/dist/cli/runOutput.d.ts +4 -1
- package/dist/cli/runOutput.js +36 -8
- package/dist/cli/skillsCommand.d.ts +16 -0
- package/dist/cli/skillsCommand.js +459 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +20 -3
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +128 -22
- package/dist/config/browseCatalog.d.ts +45 -0
- package/dist/config/browseCatalog.js +170 -0
- package/dist/config/createPipeline.d.ts +12 -3
- package/dist/config/createPipeline.js +292 -100
- package/dist/config/createStage.d.ts +10 -4
- package/dist/config/createStage.js +44 -14
- package/dist/config/listConfig.d.ts +14 -19
- package/dist/config/listConfig.js +26 -191
- package/dist/config/listModelsFromManifest.d.ts +2 -0
- package/dist/config/listModelsFromManifest.js +4 -0
- package/dist/config/loadOutcome.d.ts +4 -0
- package/dist/config/loadPipeline.d.ts +1 -15
- package/dist/config/loadPipeline.js +88 -142
- package/dist/config/loadStage.d.ts +4 -0
- package/dist/config/loadStage.js +60 -32
- package/dist/config/loadStageflowManifest.d.ts +5 -0
- package/dist/config/loadStageflowManifest.js +157 -0
- package/dist/config/mergePipelineIncludes.d.ts +9 -0
- package/dist/config/mergePipelineIncludes.js +141 -0
- package/dist/config/normalizePipelineStageEntry.d.ts +18 -0
- package/dist/config/normalizePipelineStageEntry.js +210 -0
- package/dist/config/pipelineStageKeys.d.ts +4 -0
- package/dist/config/pipelineStageKeys.js +14 -0
- package/dist/config/resolveCatalogContext.d.ts +13 -0
- package/dist/config/resolveCatalogContext.js +13 -0
- package/dist/config/resolveForkEmitContext.d.ts +4 -0
- package/dist/config/resolveForkEmitContext.js +34 -0
- package/dist/config/resolvePipelineDag.d.ts +5 -1
- package/dist/config/resolvePipelineDag.js +86 -36
- package/dist/config/scanCatalogPaths.d.ts +4 -0
- package/dist/config/scanCatalogPaths.js +83 -0
- package/dist/config/validateCatalog.d.ts +22 -4
- package/dist/config/validateCatalog.js +169 -132
- package/dist/envelope/check.d.ts +2 -0
- package/dist/envelope/check.js +58 -0
- package/dist/envelope/cloneForks.d.ts +2 -0
- package/dist/envelope/cloneForks.js +62 -0
- package/dist/envelope/forkChoice.d.ts +3 -0
- package/dist/envelope/forkChoice.js +47 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/mcp/catalogTools.d.ts +3 -0
- package/dist/mcp/catalogTools.js +187 -0
- package/dist/mcp/controlTools.d.ts +3 -0
- package/dist/mcp/controlTools.js +147 -0
- package/dist/mcp/deps.d.ts +11 -0
- package/dist/mcp/deps.js +1 -0
- package/dist/mcp/projectRun.d.ts +1 -37
- package/dist/mcp/projectRun.js +1 -57
- package/dist/mcp/resources.d.ts +5 -0
- package/dist/mcp/resources.js +45 -0
- package/dist/mcp/server.d.ts +16 -3
- package/dist/mcp/server.js +159 -3
- package/dist/mcp/toolResults.d.ts +7 -0
- package/dist/mcp/toolResults.js +6 -0
- package/dist/mcp/tools.d.ts +2 -7
- package/dist/mcp/tools.js +52 -86
- package/dist/mcp/waitRun.d.ts +46 -0
- package/dist/mcp/waitRun.js +146 -0
- package/dist/mcp/waitingGates.d.ts +12 -0
- package/dist/mcp/waitingGates.js +83 -0
- package/dist/project/findProjectRoot.d.ts +2 -0
- package/dist/project/findProjectRoot.js +51 -0
- package/dist/project/globalHome.d.ts +2 -0
- package/dist/project/globalHome.js +19 -0
- package/dist/project/resolveProjectContext.d.ts +9 -0
- package/dist/project/resolveProjectContext.js +38 -0
- package/dist/project/resolveStageflowContext.d.ts +11 -0
- package/dist/project/resolveStageflowContext.js +66 -0
- package/dist/projection/projectRun.d.ts +44 -0
- package/dist/projection/projectRun.js +71 -0
- package/dist/prompt/priorEnvelope.d.ts +1 -1
- package/dist/prompt/priorEnvelope.js +4 -1
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +4 -0
- package/dist/runstore/paths.js +2 -0
- package/dist/runstore/pipelineDagSnapshot.d.ts +9 -0
- package/dist/runstore/pipelineDagSnapshot.js +90 -1
- package/dist/runstore/port.d.ts +22 -2
- package/dist/runstore/port.js +4 -1
- package/dist/runstore/runProjection.d.ts +1 -1
- package/dist/runstore/runProjection.js +25 -4
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +3 -2
- package/dist/runstore/sqlite/SqliteRunStore.js +65 -7
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +4 -1
- package/dist/runstore/stageInstanceId.d.ts +4 -0
- package/dist/runstore/stageInstanceId.js +23 -0
- package/dist/runstore/syntheticStageSnapshot.d.ts +1 -1
- package/dist/runstore/syntheticStageSnapshot.js +2 -1
- package/dist/runstore/trackProjection.js +28 -12
- package/dist/runstore/workspaceLayout.d.ts +1 -0
- package/dist/runstore/workspaceLayout.js +1 -1
- package/dist/runtime/cloneSchedule.d.ts +18 -0
- package/dist/runtime/cloneSchedule.js +233 -0
- package/dist/runtime/credentialBinding.d.ts +8 -6
- package/dist/runtime/credentialBinding.js +18 -24
- package/dist/runtime/envelopeRouting.d.ts +2 -1
- package/dist/runtime/envelopeRouting.js +80 -13
- package/dist/runtime/pipelineRunner.d.ts +3 -0
- package/dist/runtime/pipelineRunner.js +15 -1
- package/dist/runtime/pipelineScheduler.d.ts +8 -2
- package/dist/runtime/pipelineScheduler.js +215 -39
- package/dist/runtime/reloadRunCatalog.d.ts +5 -0
- package/dist/runtime/reloadRunCatalog.js +44 -0
- package/dist/runtime/resumeReconstruct.d.ts +1 -0
- package/dist/runtime/resumeReconstruct.js +31 -10
- package/dist/runtime/runChangeBus.d.ts +18 -0
- package/dist/runtime/runChangeBus.js +83 -0
- package/dist/runtime/runManager.d.ts +4 -0
- package/dist/runtime/runManager.js +36 -16
- package/dist/runtime/settingsFile.d.ts +12 -0
- package/dist/runtime/settingsFile.js +87 -6
- package/dist/runtime/stageAttemptBootstrap.d.ts +1 -0
- package/dist/runtime/stageAttemptBootstrap.js +18 -7
- package/dist/runtime/stageProcessLauncher.js +3 -0
- package/dist/runtime/stageRecovery.js +3 -1
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +17 -15
- package/dist/runtime/stageWorker.js +13 -10
- package/dist/server/bootstrap.d.ts +32 -0
- package/dist/server/bootstrap.js +56 -0
- package/dist/server/createHttpHost.d.ts +34 -0
- package/dist/server/createHttpHost.js +70 -0
- package/dist/server/http.d.ts +6 -13
- package/dist/server/http.js +297 -352
- package/dist/server/mcpHost.d.ts +22 -0
- package/dist/server/mcpHost.js +21 -0
- package/dist/server/operatorResults.d.ts +13 -0
- package/dist/server/operatorResults.js +22 -0
- package/dist/tools/emitStageEnvelope.d.ts +12 -1
- package/dist/tools/emitStageEnvelope.js +27 -1
- package/dist/types/envelope.d.ts +3 -0
- package/dist/types/forkChoice.d.ts +30 -0
- package/dist/types/forkChoice.js +1 -0
- package/dist/types/pipeline.d.ts +59 -2
- package/dist/types/stageflowManifest.d.ts +23 -0
- package/dist/types/stageflowManifest.js +1 -0
- package/dist/ui/assets/{index-DCsDopak.css → index-C3N7MXAC.css} +1 -1
- package/dist/ui/assets/index-CSoGDA3A.js +118 -0
- package/dist/ui/index.html +3 -2
- package/dist/ui/stageflow-icon.svg +12 -0
- package/package.json +8 -5
- package/skills/install-suite.sh +107 -0
- package/skills/stageflow/SKILL.md +26 -0
- package/skills/stageflow/references/control-surface.md +26 -0
- package/skills/stageflow/scripts/detect-host.mjs +54 -0
- package/skills/stageflow/scripts/detect-host.test.mjs +97 -0
- package/skills/stageflow-author/SKILL.md +58 -0
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -0
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -0
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +13 -0
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +9 -0
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +15 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -0
- package/skills/stageflow-author/references/catalog-mapping.md +131 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +29 -0
- package/skills/stageflow-author/references/stage-prompt-template.md +55 -0
- package/skills/stageflow-author/references/validate-and-report.md +38 -0
- package/skills/stageflow-delegate/SKILL.md +18 -0
- package/skills/stageflow-delegate/references/authoring-or-run.md +15 -0
- package/skills/stageflow-delegate/references/example-walkthrough.md +30 -0
- package/skills/stageflow-delegate/references/pattern-detection.md +44 -0
- package/skills/stageflow-run/SKILL.md +151 -0
- package/skills/stageflow-run/references/mcp-call.md +17 -0
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +52 -0
- package/skills/stageflow-run/scripts/mcp-call.mjs +299 -0
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +271 -0
- package/skills/stageflow-session-capture/SKILL.md +94 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +7 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +8 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +8 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +40 -0
- package/skills/stageflow-session-capture/references/transcript-sources.md +25 -0
- package/skills/stageflow-session-capture/scripts/check-provider-gate.mjs +43 -0
- package/skills/stageflow-session-capture/scripts/locate-session-transcript.mjs +141 -0
- package/skills/stageflow-session-capture/scripts/resolve-catalog-id.mjs +119 -0
- package/skills/stageflow-setup/SKILL.md +110 -0
- package/dist/ui/assets/index-Cry0Tpfx.js +0 -118
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Catalog mapping
|
|
2
|
+
|
|
3
|
+
Turn the confirmed step list into one pipeline id and one stage id per step. Ids follow `STAGE_ID_PATTERN`: start with a letter, then lowercase letters, digits, and single hyphens (`^[a-z][a-z0-9]*(-[a-z0-9]+)*$`).
|
|
4
|
+
|
|
5
|
+
Derive each id from the human's name for that step or loop:
|
|
6
|
+
|
|
7
|
+
1. Lowercase.
|
|
8
|
+
2. Replace each run of non-alphanumeric characters with `-`.
|
|
9
|
+
3. Collapse repeated hyphens; trim leading and trailing hyphens.
|
|
10
|
+
4. If the first character is a digit, prefix `x`.
|
|
11
|
+
5. If the result is empty, use `x`.
|
|
12
|
+
6. Cap at 64 characters; trim a trailing hyphen after the cut.
|
|
13
|
+
7. Keep the result only when it matches the pattern.
|
|
14
|
+
|
|
15
|
+
Collision handling lives in [`catalog-write-conventions.md`](catalog-write-conventions.md).
|
|
16
|
+
|
|
17
|
+
## Sequencing
|
|
18
|
+
|
|
19
|
+
`needs` is a single parent stage id. Fan-in (one stage needing two parents) is out of catalog shape.
|
|
20
|
+
|
|
21
|
+
| Human says | Pipeline shape |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Steps in order | Each later stage `needs` the previous id. No `fork` field. |
|
|
24
|
+
| Steps happen together | Sibling stages share one `needs` (the same parent). No `fork` field. |
|
|
25
|
+
| Exactly one branch runs | Deciding stage gets `fork: { select: one }`. Each branch `needs` the decider. |
|
|
26
|
+
| Either, both, or a subset may run | Deciding stage gets `fork: { select: subset }`. Each branch `needs` the decider. |
|
|
27
|
+
|
|
28
|
+
Default `select` is `one` unless the human says more than one branch can run.
|
|
29
|
+
|
|
30
|
+
Map linear chains, sibling fan-out, and single-level `fork`. A runtime clone count is not knowable from a static description — stay on those three shapes. Leave `clonable` and `clone_forks` unset.
|
|
31
|
+
|
|
32
|
+
A review, approval, or sign-off step is a gated stage: put `gate_kinds` on that stage file and follow [`stage-prompt-template.md`](stage-prompt-template.md).
|
|
33
|
+
|
|
34
|
+
## Worked examples
|
|
35
|
+
|
|
36
|
+
### Review loop (linear)
|
|
37
|
+
|
|
38
|
+
Three sequential steps; the middle one is a sign-off.
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
id: review-loop
|
|
42
|
+
stages:
|
|
43
|
+
- id: draft
|
|
44
|
+
uses: ./draft.yaml
|
|
45
|
+
- id: review
|
|
46
|
+
uses: ./review.yaml
|
|
47
|
+
needs: draft
|
|
48
|
+
- id: publish
|
|
49
|
+
uses: ./publish.yaml
|
|
50
|
+
needs: review
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`review` carries `gate_kinds: [artifact_backed]`. Full set: [`../assets/examples/linear-review/`](../assets/examples/linear-review/).
|
|
54
|
+
|
|
55
|
+
### Release gate (fork, select one)
|
|
56
|
+
|
|
57
|
+
One deciding step, then exactly one successor.
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
id: release-gate
|
|
61
|
+
stages:
|
|
62
|
+
- id: run-tests
|
|
63
|
+
uses: ./run-tests.yaml
|
|
64
|
+
fork:
|
|
65
|
+
select: one
|
|
66
|
+
- id: hotfix
|
|
67
|
+
uses: ./hotfix.yaml
|
|
68
|
+
needs: run-tests
|
|
69
|
+
- id: ship
|
|
70
|
+
uses: ./ship.yaml
|
|
71
|
+
needs: run-tests
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Full set: [`../assets/examples/branch-decision/`](../assets/examples/branch-decision/).
|
|
75
|
+
|
|
76
|
+
### Research digest (linear, non-software)
|
|
77
|
+
|
|
78
|
+
Weekly gather → summarize → send. Same `needs` chain as the review loop; ids and prompts stay in that domain.
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
id: research-digest
|
|
82
|
+
stages:
|
|
83
|
+
- id: gather
|
|
84
|
+
uses: ./gather.yaml
|
|
85
|
+
- id: summarize
|
|
86
|
+
uses: ./summarize.yaml
|
|
87
|
+
needs: gather
|
|
88
|
+
- id: send
|
|
89
|
+
uses: ./send.yaml
|
|
90
|
+
needs: summarize
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Full set: [`../assets/examples/non-sdlc-digest/`](../assets/examples/non-sdlc-digest/).
|
|
94
|
+
|
|
95
|
+
### Sibling fan-out
|
|
96
|
+
|
|
97
|
+
"After intake, collect quotes and collect notes at the same time":
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
stages:
|
|
101
|
+
- id: intake
|
|
102
|
+
uses: ./intake.yaml
|
|
103
|
+
- id: collect-quotes
|
|
104
|
+
uses: ./collect-quotes.yaml
|
|
105
|
+
needs: intake
|
|
106
|
+
- id: collect-notes
|
|
107
|
+
uses: ./collect-notes.yaml
|
|
108
|
+
needs: intake
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
No `fork` field. Both siblings run.
|
|
112
|
+
|
|
113
|
+
### Fork, select subset
|
|
114
|
+
|
|
115
|
+
"Email, post, or both could go out":
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
stages:
|
|
119
|
+
- id: choose-channels
|
|
120
|
+
uses: ./choose-channels.yaml
|
|
121
|
+
fork:
|
|
122
|
+
select: subset
|
|
123
|
+
- id: email
|
|
124
|
+
uses: ./email.yaml
|
|
125
|
+
needs: choose-channels
|
|
126
|
+
- id: post
|
|
127
|
+
uses: ./post.yaml
|
|
128
|
+
needs: choose-channels
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The success emit names one or more of those successor ids in `fork_choice`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Catalog write conventions
|
|
2
|
+
|
|
3
|
+
Write pipeline and stage YAML with the native Write tool. `sf ui` does not need to be running. Do not call `createPipeline` or `createStage`.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
Project root is the git top-level when `git rev-parse --show-toplevel` succeeds, otherwise the current directory.
|
|
8
|
+
|
|
9
|
+
1. **Manifest present.** Read `stageflow.yaml` at that root. Write the colocated set under a declared `catalog.pipelines` root. A new subdirectory under that root is enough — catalog scan is recursive.
|
|
10
|
+
2. **No manifest.** Write the colocated set as a flat layout at the project root (pipeline file and stage files beside each other).
|
|
11
|
+
|
|
12
|
+
Do not write a `*.task.yaml`.
|
|
13
|
+
|
|
14
|
+
## File shape
|
|
15
|
+
|
|
16
|
+
One directory (or the project root) holds:
|
|
17
|
+
|
|
18
|
+
| File | Required fields |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `<pipeline-id>.pipeline.yaml` | `id` matching the filename stem; `stages:` object entries |
|
|
21
|
+
| `<stage-id>.yaml` | `id`, `system_prompt`, `model`; `gate_kinds` when the step is gated |
|
|
22
|
+
|
|
23
|
+
Each pipeline stage entry has `id` and `uses: ./<id>.yaml` (path relative to the pipeline file). Non-root stages add `needs: <parent-id>`. A deciding stage adds `fork:`. Filename stem matches `id` on every file.
|
|
24
|
+
|
|
25
|
+
## Collisions
|
|
26
|
+
|
|
27
|
+
Before writing, list `*.pipeline.yaml` files in the target directory (and existing pipeline files under the same catalog root) plus every `*.yaml` / `*.yml` stage file beside the target pipeline. Read each file's top-level `id:` and its filename stem.
|
|
28
|
+
|
|
29
|
+
On a match for the candidate pipeline id or any stage id, ask the human for a different id. Write nothing until that id is free. Never replace an existing file silently. Proceed with a colliding name only when the human explicitly confirms overwrite.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Stage prompt template
|
|
2
|
+
|
|
3
|
+
Every external stage file has `id`, `system_prompt`, and `model`. Filename stem matches `id`. Default `model` is `anthropic/claude-sonnet-4-5`. When the human names a different model, write that string verbatim.
|
|
4
|
+
|
|
5
|
+
## Base
|
|
6
|
+
|
|
7
|
+
Use for every stage that is not a review point and does not decide a branch.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
id: <id>
|
|
11
|
+
system_prompt: |
|
|
12
|
+
<one-line goal for this step>
|
|
13
|
+
|
|
14
|
+
Write any output this step produces via write_stage_artifact.
|
|
15
|
+
|
|
16
|
+
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
17
|
+
artifacts, and a payload the next stage can use.
|
|
18
|
+
model: anthropic/claude-sonnet-4-5
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The prompt has no `ask_operator` line. It ends on the `emit_stage_envelope` instruction. Call `emit_stage_envelope` once per attempt.
|
|
22
|
+
|
|
23
|
+
## Gated
|
|
24
|
+
|
|
25
|
+
When the step is a review, approval, or sign-off, add `gate_kinds` and resolve the gate before emit. Match this sequence: `write_stage_artifact` → `ask_operator` → `emit_stage_envelope` on accept.
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
id: <id>
|
|
29
|
+
gate_kinds:
|
|
30
|
+
- artifact_backed
|
|
31
|
+
system_prompt: |
|
|
32
|
+
<one-line goal>. Get operator acceptance before completing this stage.
|
|
33
|
+
|
|
34
|
+
1. Write the reviewable output via write_stage_artifact.
|
|
35
|
+
2. Call ask_operator with kind artifact_backed referencing that artifact path.
|
|
36
|
+
3. On reject or change text: revise the artifact and call ask_operator again
|
|
37
|
+
with artifact_backed in this same stage. Do not complete yet.
|
|
38
|
+
4. Call emit_stage_envelope with an advancing success status only after the
|
|
39
|
+
operator accepts. Never emit before accept.
|
|
40
|
+
model: anthropic/claude-sonnet-4-5
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Use the `gate_kinds` value that matches the human's review: `artifact_backed` for a file to accept, `confirm` for yes/no, `free_text` for an open reply, `multi_question` for a batch. `ask_operator` does not complete the stage.
|
|
44
|
+
|
|
45
|
+
## Fork
|
|
46
|
+
|
|
47
|
+
When the pipeline entry has `fork`, the success emit names immediate successors in `fork_choice`. Add this block to the base (or gated) prompt:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
On a success emit, include fork_choice naming immediate successor id(s) that
|
|
51
|
+
should run. Name only ids listed as this stage's children. select: one →
|
|
52
|
+
exactly one id. select: subset → one or more of those ids.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`fork_choice` on a failure emit is ignored. Leave `clone_forks` unset.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Validate and report
|
|
2
|
+
|
|
3
|
+
After the pipeline and stage files exist, validate them before telling the human authoring is complete.
|
|
4
|
+
|
|
5
|
+
## Command
|
|
6
|
+
|
|
7
|
+
Default — always available:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
sf validate --pipeline <written-path> --strict
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
MCP `validate` is allowed only when [`../../stageflow/scripts/detect-host.mjs`](../../stageflow/scripts/detect-host.mjs) reports a host up. From this skill directory:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
node ../stageflow/scripts/detect-host.mjs
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| stdout | next |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `up <baseUrl>` | MCP `validate` with `{ "pipeline": "<written-path>", "strict": true }` is allowed |
|
|
22
|
+
| `down <baseUrl>` | stay on the CLI command |
|
|
23
|
+
|
|
24
|
+
Do not write a second probe. MCP-vs-CLI policy: [`../../stageflow/references/control-surface.md`](../../stageflow/references/control-surface.md). Both paths return the same `ValidationResult` shape (`ok`, `summary`, `findings[]`).
|
|
25
|
+
|
|
26
|
+
## Failure
|
|
27
|
+
|
|
28
|
+
When `ok` is false or the CLI exits non-zero, print each finding (severity, code, path, message). Fix the offending pipeline or stage file. Re-validate. Repeat until `ok` is true. Never report authoring complete on a failing validate.
|
|
29
|
+
|
|
30
|
+
## Success
|
|
31
|
+
|
|
32
|
+
When validate exits 0 / `ok: true`, print:
|
|
33
|
+
|
|
34
|
+
1. Pipeline id and pipeline path.
|
|
35
|
+
2. Every stage path written in this invocation.
|
|
36
|
+
3. Name `stageflow-run` if the human wants to execute the pipeline.
|
|
37
|
+
|
|
38
|
+
Do not write a `*.task.yaml`. Do not start a run here.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stageflow-delegate
|
|
3
|
+
description: Looks up a catalog pipeline for a repeating request, then reuses it or codifies it and runs. Use when this skill is opened for a repeating-pattern request.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Stageflow delegate
|
|
8
|
+
|
|
9
|
+
Look up the catalog once, then branch. A match runs; no match authors, then runs.
|
|
10
|
+
|
|
11
|
+
Talking jobs cite [`../stageflow/references/control-surface.md`](../stageflow/references/control-surface.md). This job names `stageflow-run` for execution and does not choose MCP vs CLI.
|
|
12
|
+
|
|
13
|
+
1. Look up the requested pattern. Follow [`references/pattern-detection.md`](references/pattern-detection.md) until you have a match, a disambiguation, or no match.
|
|
14
|
+
2. Branch on that result. Follow [`references/authoring-or-run.md`](references/authoring-or-run.md). Name `stageflow-run` and stop.
|
|
15
|
+
|
|
16
|
+
Act only when this skill is the one opened. Leave the harness's builtin subagents in place; never suggest disabling, replacing, or bypassing them.
|
|
17
|
+
|
|
18
|
+
Worked pair: [`references/example-walkthrough.md`](references/example-walkthrough.md).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Authoring or run
|
|
2
|
+
|
|
3
|
+
Take the lookup band. Open the named job and follow it. Do not start a run, write a throwaway task, or answer a gate from this skill.
|
|
4
|
+
|
|
5
|
+
| band | open | then |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| match | [`stageflow-run`](../../stageflow-run/SKILL.md) for that pipeline | stop |
|
|
8
|
+
| no match, and this session already did the matching work with readable history (this chat, or a path / paste the human supplied) | [`stageflow-session-capture`](../../stageflow-session-capture/SKILL.md) | when it reports a pipeline path, open [`stageflow-run`](../../stageflow-run/SKILL.md) for that path and stop |
|
|
9
|
+
| no match, and no readable history | [`stageflow-author`](../../stageflow-author/SKILL.md) | when it reports a pipeline path, open [`stageflow-run`](../../stageflow-run/SKILL.md) for that path and stop |
|
|
10
|
+
|
|
11
|
+
History is a coarse yes/no. Unsure → treat as no history.
|
|
12
|
+
|
|
13
|
+
If the authoring job stops on a blocker (it names [`stageflow-setup`](../../stageflow-setup/SKILL.md), or prints `blocked: <reason>`), print that blocker and stop. Do not retry, log in, or work around it.
|
|
14
|
+
|
|
15
|
+
**Done when** `stageflow-run` has been named, or an authoring blocker has been printed.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Example walkthrough
|
|
2
|
+
|
|
3
|
+
Content walkthrough. No live harness session is required.
|
|
4
|
+
|
|
5
|
+
Scratch catalog at first sight:
|
|
6
|
+
|
|
7
|
+
| path | id | task `goal` (if readable) |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `pipelines/hello.pipeline.yaml` | `hello` | Draft a one-page brief |
|
|
10
|
+
| `pipelines/plan-review.pipeline.yaml` | `plan-review` | Prove a review loop |
|
|
11
|
+
|
|
12
|
+
## First sight
|
|
13
|
+
|
|
14
|
+
Request: "Every week I gather sources, summarize them, and send a digest. Make that a reusable pipeline and run it."
|
|
15
|
+
|
|
16
|
+
[pattern-detection](pattern-detection.md) tokens include `gather`, `sources`, `summarize`, `send`, `digest`. Neither `hello` nor `plan-review` shares a distinctive topic token. Band: **no match**. This chat has not already done that work. [authoring-or-run](authoring-or-run.md) opens `stageflow-author`, then names `stageflow-run` on the written pipeline (id `research-digest`, path `pipelines/research-digest.pipeline.yaml`). One pipeline is authored. None is invented a second time.
|
|
17
|
+
|
|
18
|
+
If this session had already gathered, summarized, and sent — with that history still in chat or a pointer the human supplied — the same no-match would open `stageflow-session-capture` instead, then `stageflow-run`.
|
|
19
|
+
|
|
20
|
+
## Second sight
|
|
21
|
+
|
|
22
|
+
Same catalog, plus `pipelines/research-digest.pipeline.yaml` (`id: research-digest`).
|
|
23
|
+
|
|
24
|
+
Request: "Run the weekly research digest."
|
|
25
|
+
|
|
26
|
+
Tokens include `research`, `digest`. Exact topic overlap on one candidate's kebab `id`. Band: **match**. [authoring-or-run](authoring-or-run.md) opens `stageflow-run` only. No second pipeline is written.
|
|
27
|
+
|
|
28
|
+
## Ordinary request
|
|
29
|
+
|
|
30
|
+
Request: "Fix the typo in README." This skill is not opened. The harness's builtin subagent does the edit. Builtin subagents stay available.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Pattern detection
|
|
2
|
+
|
|
3
|
+
Decide match vs first-sight from the catalog. Listings carry `path`, `id`, and `stages` — no `description` or `title`. Do not invent a list command.
|
|
4
|
+
|
|
5
|
+
## Roots
|
|
6
|
+
|
|
7
|
+
Project root is the git top-level when `git rev-parse --show-toplevel` succeeds, otherwise the current directory. Read `stageflow.yaml` there. Walk each `catalog.pipelines` root. Use `catalog.patterns.pipeline` (default `*.pipeline.yaml`). Skip a path whose repo-relative prefix is in `catalog.exclude`.
|
|
8
|
+
|
|
9
|
+
Manifest missing or unreadable, a listed root missing, or zero pipeline files → **no match**. Not an error.
|
|
10
|
+
|
|
11
|
+
**Done when** you have a candidate list, or a no-match.
|
|
12
|
+
|
|
13
|
+
## Host
|
|
14
|
+
|
|
15
|
+
From this skill directory:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
node ../stageflow/scripts/detect-host.mjs
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Script: [`../../stageflow/scripts/detect-host.mjs`](../../stageflow/scripts/detect-host.mjs). Stdout is `up <baseUrl>` or `down <baseUrl>`.
|
|
22
|
+
|
|
23
|
+
| stdout | catalog |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `up <baseUrl>` | MCP `list_pipelines`, then `describe_pipeline` on a shortlisted path |
|
|
26
|
+
| `down <baseUrl>` | Read `*.pipeline.yaml` under the roots. When a paired `*.task.yaml` is readable, take its `goal` |
|
|
27
|
+
|
|
28
|
+
A paired task is a `*.task.yaml` in the same directory as the pipeline, or one whose `id` / directory words overlap that pipeline. Skip `goal` when no such file is readable. Host-up listings do not include `goal`.
|
|
29
|
+
|
|
30
|
+
**Done when** each candidate has `path`, `id`, and (when readable) a task `goal`.
|
|
31
|
+
|
|
32
|
+
## Score
|
|
33
|
+
|
|
34
|
+
Split the request, each kebab `id`, and each directory segment under the catalog root into lowercase tokens. Drop empty tokens and generic words (`pipeline`, `stage`, `task`, `run`, `the`, `a`, `an`). Add tokens from a readable task `goal`.
|
|
35
|
+
|
|
36
|
+
| band | test | next |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| match | The request names one candidate's kebab `id`, or exactly one candidate has a strong overlap (a distinctive topic token shared with `id`, directory words, or `goal`) | reuse that pipeline |
|
|
39
|
+
| ask once | Two or more candidates are plausible | print `id` + `path` for each; ask which; that answer is the match |
|
|
40
|
+
| no match | Zero candidates, or the catalog was empty / unreadable | first-sight |
|
|
41
|
+
|
|
42
|
+
Exact `id` beats keyword overlap. Do not guess among two-plus. Do not treat a weak shared word (`review`, `send`, `weekly`) as a match when more than one candidate could claim it.
|
|
43
|
+
|
|
44
|
+
**Done when** the band is match, a human-chosen match, or no match.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stageflow-run
|
|
3
|
+
description: >-
|
|
4
|
+
Starts a catalog pipeline from the harness, reports progress, and answers
|
|
5
|
+
every HITL gate in this chat. Triggers: run a pipeline, start <pipeline>,
|
|
6
|
+
check on my run, answer the pending question.
|
|
7
|
+
compatibility: Requires the sf CLI on PATH. An MCP host (sf ui or sf mcp) is optional.
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Stageflow run
|
|
12
|
+
|
|
13
|
+
Start a catalog pipeline, keep every HITL gate in this chat, and report the outcome. Author and session-capture own catalog YAML; this job owns the run and any throwaway `*.task.yaml`.
|
|
14
|
+
|
|
15
|
+
Talking jobs cite [`../stageflow/references/control-surface.md`](../stageflow/references/control-surface.md). Probe with [`../stageflow/scripts/detect-host.mjs`](../stageflow/scripts/detect-host.mjs) only. Do not write a second probe.
|
|
16
|
+
|
|
17
|
+
MCP tool shapes: [`docs/mcp.md`](../../docs/mcp.md). CLI flags and exit codes: [`docs/cli-reference.md`](../../docs/cli-reference.md). Direct tool calls: [`references/mcp-call.md`](references/mcp-call.md). Selection: [`references/task-and-pipeline-selection.md`](references/task-and-pipeline-selection.md).
|
|
18
|
+
|
|
19
|
+
## Preconditions
|
|
20
|
+
|
|
21
|
+
Run `sf --version`. **Done when** it prints a version. If `sf` is missing, stop and name `stageflow-setup`.
|
|
22
|
+
|
|
23
|
+
## Probe
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
node ../stageflow/scripts/detect-host.mjs
|
|
27
|
+
node ../stageflow/scripts/detect-host.mjs --base-url http://127.0.0.1:3847
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| stdout | path |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `up <baseUrl>` | [MCP path](#mcp-path) |
|
|
33
|
+
| `down <baseUrl>` | [CLI path](#cli-path) |
|
|
34
|
+
|
|
35
|
+
**Done when** you have `up` or `down` and the base URL.
|
|
36
|
+
|
|
37
|
+
## Select
|
|
38
|
+
|
|
39
|
+
Read [`references/task-and-pipeline-selection.md`](references/task-and-pipeline-selection.md). Follow it until you have a pipeline filesystem path and a task (catalog path, MCP inline object, or CLI throwaway file).
|
|
40
|
+
|
|
41
|
+
If this chat already has a `runId` and the request is check, answer, or continue: skip start. Host up → [Wait](#wait). Host down and the human wants to answer → [Bridge](#bridge).
|
|
42
|
+
|
|
43
|
+
**Done when** the target is named, or a live `runId` is in hand.
|
|
44
|
+
|
|
45
|
+
## MCP tools
|
|
46
|
+
|
|
47
|
+
Prefer this harness's native Stageflow MCP tools when their names are already in the tool list. When they are not, call [`scripts/mcp-call.mjs`](scripts/mcp-call.mjs) — see [`references/mcp-call.md`](references/mcp-call.md). Always use `mcp-call.mjs --stateless` for a bridge this skill started.
|
|
48
|
+
|
|
49
|
+
Call only `list_pipelines`, `list_tasks`, `start_run`, `get_run`, `wait_run`, `list_waiting`, `answer_gate`, `get_health`.
|
|
50
|
+
|
|
51
|
+
## MCP path
|
|
52
|
+
|
|
53
|
+
### Start
|
|
54
|
+
|
|
55
|
+
`start_run` with `pipeline` plus exactly one of `task_path` or inline `task`.
|
|
56
|
+
|
|
57
|
+
| result | next |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `{ "runId" }` | [Wait](#wait) |
|
|
60
|
+
| `busy_capacity` / `busy_checkout` | [Report](#report) the included fields. Stop. Do not retry. |
|
|
61
|
+
| other `isError` | [Report](#report) the payload. Stop. |
|
|
62
|
+
|
|
63
|
+
**Done when** you have a `runId`, or a busy/error report is printed.
|
|
64
|
+
|
|
65
|
+
### Wait
|
|
66
|
+
|
|
67
|
+
`wait_run` with `{ "runId", "until": "any" }`. A shorter `timeout_ms` is fine when the harness tool timeout is tight.
|
|
68
|
+
|
|
69
|
+
| `reason` | next |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `waiting` or `already` with a waiting snapshot | [Gate](#gate) |
|
|
72
|
+
| `terminal` | [Report](#report) |
|
|
73
|
+
| `timeout` | call `wait_run` again |
|
|
74
|
+
| `isError` with `code: "aborted"` | [Report](#report): the run continues, resumable later. Stop. |
|
|
75
|
+
| other `isError` | [Report](#report) the payload. Stop. |
|
|
76
|
+
|
|
77
|
+
**Done when** the run is waiting (hand to Gate), terminal, aborted, or a hard error is printed.
|
|
78
|
+
|
|
79
|
+
### Gate
|
|
80
|
+
|
|
81
|
+
1. `list_waiting` with `{ "runId" }`.
|
|
82
|
+
2. Print the pending prompt text **verbatim** (and artifacts / sub-questions when present).
|
|
83
|
+
3. Collect the human's reply in this chat. Map it to the prompt `kind`:
|
|
84
|
+
|
|
85
|
+
| kind | `answer` |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `free_text` | `{ "promptId", "kind": "free_text", "text" }` |
|
|
88
|
+
| `confirm` | `{ "promptId", "kind": "confirm", "decision": "accept" \| "reject" }` |
|
|
89
|
+
| `artifact_backed` | `{ "promptId", "kind": "artifact_backed", "decision": "accept" \| "reject" }` |
|
|
90
|
+
| `multi_question` | `{ "promptId", "kind": "multi_question", "answers": { "<id>": { "kind", "text" \| "decision" } } }` |
|
|
91
|
+
|
|
92
|
+
`promptId` is `pending_prompt.id` or `waiting_prompt_id`. Map yes/y/accept/approve to `accept`; no/n/reject/deny to `reject`. Ask once when the kind is `multi_question` and any sub-question is unanswered, or when confirm/artifact_backed is not a clear decision.
|
|
93
|
+
|
|
94
|
+
4. `answer_gate` with `{ "runId", "stageId", "answer" }`.
|
|
95
|
+
5. Return to [Wait](#wait).
|
|
96
|
+
|
|
97
|
+
**Done when** `answer_gate` returns `{ "ok": true }` and Wait is re-entered. On `isError` (400 / 404 / 409), print the payload and ask for a corrected reply — do not open another surface.
|
|
98
|
+
|
|
99
|
+
## CLI path
|
|
100
|
+
|
|
101
|
+
Discovery without a host: read `stageflow.yaml` catalog roots as in [`references/task-and-pipeline-selection.md`](references/task-and-pipeline-selection.md).
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
sf run --task <path> --pipeline <path> --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Add `--checkout`, `--git-sha`, `--ci-pr-url`, `--ci-job-url`, `--operator-cwd`, or `--operator-agent-dir` only when the human supplied them. Always pass `--json`. Omit `--include stages` unless the human asked for a stage projection — and then only together with `--json`.
|
|
108
|
+
|
|
109
|
+
Parse the single JSON document.
|
|
110
|
+
|
|
111
|
+
| exit | `outcome` | next |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `0` | `succeeded` | [Report](#report) |
|
|
114
|
+
| `1` | `failed` | [Report](#report) `reason` verbatim |
|
|
115
|
+
| `1` | `busy` | [Report](#report) `busy_capacity` / `busy_checkout` and the included fields. Stop. |
|
|
116
|
+
| `2` | `waiting` | [Bridge](#bridge) with this `runId` / `runDir` |
|
|
117
|
+
|
|
118
|
+
**Done when** the outcome is reported, or a waiting exit has handed `runId` and `runDir` to Bridge.
|
|
119
|
+
|
|
120
|
+
## Bridge
|
|
121
|
+
|
|
122
|
+
A CLI waiting exit has no answer command. Keep the gate in this chat by joining a host on the same project root (git top-level when `git rev-parse --show-toplevel` succeeds, otherwise the current directory).
|
|
123
|
+
|
|
124
|
+
1. Probe again with [`../stageflow/scripts/detect-host.mjs`](../stageflow/scripts/detect-host.mjs) (the host may have appeared).
|
|
125
|
+
2. **Up:** use that host — native tools if present, otherwise `mcp-call.mjs` (omit `--stateless`). Continue at [Gate](#gate).
|
|
126
|
+
3. **Down:** start `sf mcp --mcp-stateless` as a background process on that same project root. This is a disposable HITL bridge, not setup auto-start.
|
|
127
|
+
4. Probe until stdout is `up <baseUrl>`, at most 8 times. **Done when** the host is up. If it stays down, [Report](#report) the parked `runId` / `runDir` and the bind/stderr text. Stop.
|
|
128
|
+
5. Drive the rest with `mcp-call.mjs --stateless` only: [Gate](#gate) → [Wait](#wait) until terminal. A second wait on the same run reuses this process.
|
|
129
|
+
6. When the run is terminal, stop the bridge process.
|
|
130
|
+
|
|
131
|
+
If this chat ends before terminal, say the run stays in `.stageflow/` and to continue by re-invoking this skill (or starting a host and using MCP).
|
|
132
|
+
|
|
133
|
+
**Done when** the run is terminal and the bridge this skill started is stopped, or a parked-run failure is reported.
|
|
134
|
+
|
|
135
|
+
## Report
|
|
136
|
+
|
|
137
|
+
Print one shape on every path:
|
|
138
|
+
|
|
139
|
+
1. Current or last-known stage (MCP live snapshot, or "start/finish only" on a CLI-only stretch).
|
|
140
|
+
2. Waiting prompt text verbatim when the run is parked.
|
|
141
|
+
3. Outcome: `succeeded`, `failed`, `waiting`, or `busy`.
|
|
142
|
+
4. Run id.
|
|
143
|
+
5. Run folder (`runDir` / `.stageflow/`).
|
|
144
|
+
|
|
145
|
+
MCP `get_run` / `wait_run` carry live stage state. `sf run --json` reports start and finish only — say that in chat when the CLI path ran without a host. A succeeded report names id and folder and does not keep waiting language. A failure names `reason` in this same shape.
|
|
146
|
+
|
|
147
|
+
**Done when** that five-part report is printed.
|
|
148
|
+
|
|
149
|
+
## Non-goals
|
|
150
|
+
|
|
151
|
+
This job starts, watches, and answers runs. It does not require `sf ui`. The operator console is not the answer path. It does not register or invent an MCP tool.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# mcp-call
|
|
2
|
+
|
|
3
|
+
Use [`../scripts/mcp-call.mjs`](../scripts/mcp-call.mjs) when this harness has no native Stageflow MCP tools, and always for a self-started `sf mcp --mcp-stateless` bridge.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
node scripts/mcp-call.mjs --base-url <url> --tool <name> --args '<json>' [--stateless]
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Default `--base-url` is `http://127.0.0.1:3847`. `--args` defaults to `{}`.
|
|
10
|
+
|
|
11
|
+
`--stateless` sends one `tools/call` and no session header. Use it for hosts started with `sf mcp --mcp-stateless`.
|
|
12
|
+
|
|
13
|
+
Without `--stateless`: `initialize`, capture `Mcp-Session-Id`, reuse it for `tools/call`.
|
|
14
|
+
|
|
15
|
+
Stdout is the tool JSON. Exit `0` on success, including `wait_run` with `reason: "timeout"` (keep polling). Exit `1` on transport failure or `isError: true`. Exit `2` on usage or malformed `--args` — that parse error happens before any network call.
|
|
16
|
+
|
|
17
|
+
Allowed `--tool` names (see [`docs/mcp.md`](../../../docs/mcp.md)): `list_pipelines`, `list_tasks`, `start_run`, `get_run`, `wait_run`, `list_waiting`, `answer_gate`, `get_health`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Task and pipeline selection
|
|
2
|
+
|
|
3
|
+
Resolve one pipeline filesystem path and one task before `start_run` or `sf run`. Ask a disambiguating question on more than one match. Do not guess.
|
|
4
|
+
|
|
5
|
+
## Named
|
|
6
|
+
|
|
7
|
+
If the human named a pipeline or task, match that string against catalog `id` and `path`. One match → use it. Several → print id + path and ask which. Zero → say so and offer the catalog list.
|
|
8
|
+
|
|
9
|
+
## Unnamed
|
|
10
|
+
|
|
11
|
+
Print a short pick list (id + path). Ask which.
|
|
12
|
+
|
|
13
|
+
## MCP catalog
|
|
14
|
+
|
|
15
|
+
`list_pipelines` and `list_tasks` (native tools, or [`mcp-call.md`](mcp-call.md)). Listing objects carry `path` and `id`.
|
|
16
|
+
|
|
17
|
+
## CLI catalog
|
|
18
|
+
|
|
19
|
+
There is no CLI list command. Read `stageflow.yaml` at the project root (git top-level when `git rev-parse --show-toplevel` succeeds, otherwise the current directory).
|
|
20
|
+
|
|
21
|
+
Walk each `catalog.pipelines` / `catalog.tasks` root. Match `catalog.patterns.pipeline` (default `*.pipeline.yaml`) and `catalog.patterns.task` (default `*.task.yaml`). Skip paths whose repo-relative prefix is in `catalog.exclude`.
|
|
22
|
+
|
|
23
|
+
## Task input
|
|
24
|
+
|
|
25
|
+
### MCP
|
|
26
|
+
|
|
27
|
+
An existing `task_path` from `list_tasks`, or an inline `task` object built from the stated goal:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{ "id": "<slug>", "goal": "<goal>", "context": "optional", "constraints": "optional", "checkout": "optional" }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`start_run` accepts that object. Do not write a scratch file on the MCP path.
|
|
34
|
+
|
|
35
|
+
### CLI
|
|
36
|
+
|
|
37
|
+
`sf run` accepts `--task <path>` only. Reuse a catalog `*.task.yaml`, or write a throwaway file at the project root:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
.scratch/stageflow-run/<id>.task.yaml
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
id: <slug>
|
|
45
|
+
goal: <human goal>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Add `context`, `constraints`, or `checkout` only when the human gave them. Pass that path as `--task`.
|
|
49
|
+
|
|
50
|
+
## Optional run flags
|
|
51
|
+
|
|
52
|
+
`--checkout`, `--git-sha`, `--ci-pr-url`, `--ci-job-url` only when the human supplied them.
|