stageflow 0.12.0 → 0.15.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 +5 -1
- package/dist/agent/claudeAdapter.js +31 -1
- package/dist/agent/piAdapter.d.ts +6 -4
- package/dist/agent/piAdapter.js +71 -26
- package/dist/agent/piIsolatedMcp.d.ts +23 -0
- package/dist/agent/piIsolatedMcp.js +223 -0
- package/dist/agent/piIsolatedMcpProbe.d.ts +15 -0
- package/dist/agent/piIsolatedMcpProbe.js +292 -0
- package/dist/agent/port.d.ts +4 -2
- package/dist/agent/port.js +1 -1
- package/dist/cli/initTemplates.d.ts +1 -1
- package/dist/cli/initTemplates.js +1 -1
- package/dist/cli/migrateYamlCommand.d.ts +18 -0
- package/dist/cli/migrateYamlCommand.js +180 -0
- package/dist/cli/runOutput.js +26 -18
- package/dist/cli/validateCommand.d.ts +1 -0
- package/dist/cli/validateCommand.js +2 -0
- package/dist/cli.js +15 -1
- package/dist/config/browseCatalog.js +1 -1
- package/dist/config/createPipeline.d.ts +1 -1
- package/dist/config/createPipeline.js +23 -11
- package/dist/config/createStage.d.ts +1 -1
- package/dist/config/createStage.js +10 -5
- package/dist/config/legacyYaml.d.ts +28 -0
- package/dist/config/legacyYaml.js +98 -0
- package/dist/config/loadOutcome.d.ts +2 -1
- package/dist/config/loadOutcome.js +4 -1
- package/dist/config/loadPipeline.d.ts +2 -0
- package/dist/config/loadPipeline.js +151 -8
- package/dist/config/loadStage.d.ts +9 -1
- package/dist/config/loadStage.js +207 -29
- package/dist/config/loadStageflowManifest.js +10 -0
- package/dist/config/loadTask.js +14 -0
- package/dist/config/materializeStageModels.d.ts +7 -0
- package/dist/config/materializeStageModels.js +35 -0
- package/dist/config/mergePipelineIncludes.d.ts +5 -1
- package/dist/config/mergePipelineIncludes.js +82 -4
- package/dist/config/migrateYaml.d.ts +19 -0
- package/dist/config/migrateYaml.js +627 -0
- package/dist/config/modelField.d.ts +13 -0
- package/dist/config/modelField.js +16 -0
- package/dist/config/normalizePipelineStageEntry.js +48 -3
- package/dist/config/parseCompletionContract.d.ts +5 -2
- package/dist/config/parseCompletionContract.js +16 -3
- package/dist/config/parsePreEmitChecks.js +4 -0
- package/dist/config/pipelineNeeds.js +3 -3
- package/dist/config/pipelineStageKeys.d.ts +11 -0
- package/dist/config/pipelineStageKeys.js +15 -0
- package/dist/config/printTargetYaml.d.ts +28 -0
- package/dist/config/printTargetYaml.js +243 -0
- package/dist/config/resolveModel.d.ts +20 -0
- package/dist/config/resolveModel.js +35 -0
- package/dist/config/resolveStageMcpServers.d.ts +35 -0
- package/dist/config/resolveStageMcpServers.js +207 -0
- package/dist/config/validateCatalog.d.ts +5 -1
- package/dist/config/validateCatalog.js +87 -6
- package/dist/config/validateCompletionContract.js +5 -0
- package/dist/config/yamlDialect.d.ts +29 -0
- package/dist/config/yamlDialect.js +327 -0
- package/dist/envelope/payloadSchema.d.ts +37 -5
- package/dist/envelope/payloadSchema.js +272 -22
- package/dist/mcp/catalogTools.js +1 -0
- package/dist/mcp/readArtifact.d.ts +2 -0
- package/dist/mcp/readArtifact.js +25 -1
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/runstore/pipelineDagSnapshot.js +2 -0
- package/dist/runstore/port.d.ts +1 -0
- package/dist/runtime/completionCheckRunner.d.ts +3 -2
- package/dist/runtime/completionCheckRunner.js +3 -2
- package/dist/runtime/envelopeRouting.d.ts +2 -2
- package/dist/runtime/pipelineRunner.d.ts +3 -0
- package/dist/runtime/pipelineRunner.js +23 -3
- package/dist/runtime/runManager.js +3 -2
- package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
- package/dist/runtime/stageAttemptBootstrap.js +38 -2
- package/dist/runtime/stageRunner.d.ts +2 -2
- package/dist/runtime/taskInput.d.ts +7 -0
- package/dist/runtime/taskInput.js +60 -0
- package/dist/runtime/verifiedStageExecution.d.ts +2 -0
- package/dist/runtime/verifiedStageExecution.js +13 -2
- package/dist/server/http.js +23 -4
- package/dist/server/projectMcpRoutes.d.ts +6 -0
- package/dist/server/projectMcpRoutes.js +38 -0
- package/dist/types/completion.d.ts +6 -0
- package/dist/types/pipeline.d.ts +23 -2
- package/dist/types/preEmitCheck.d.ts +4 -6
- package/dist/types/stage.d.ts +24 -4
- package/dist/types/stageflowManifest.d.ts +2 -0
- package/dist/types/task.d.ts +1 -0
- package/dist/ui/assets/index-GtyiWiZg.js +118 -0
- package/dist/ui/index.html +1 -1
- package/package.json +4 -1
- package/skills/stageflow-author/SKILL.md +20 -2
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +9 -1
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +6 -2
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +9 -1
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +16 -1
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +12 -2
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +16 -1
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +11 -2
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +19 -1
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -1
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +6 -2
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +16 -1
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -1
- package/skills/stageflow-author/references/catalog-mapping.md +80 -17
- package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
- package/skills/stageflow-author/references/stage-prompt-template.md +63 -4
- package/skills/stageflow-session-capture/SKILL.md +1 -1
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +2 -1
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +13 -2
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +18 -2
- package/skills/stageflow-session-capture/references/catalog-authoring.md +6 -3
- package/dist/ui/assets/index-CXGz4nL7.js +0 -118
package/dist/ui/index.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Figtree:wght@400;500;600;700&display=swap" />
|
|
14
14
|
<link rel="icon" type="image/svg+xml" href="/stageflow-icon.svg" />
|
|
15
15
|
<title>Stageflow</title>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-GtyiWiZg.js"></script>
|
|
17
17
|
<link rel="stylesheet" crossorigin href="/assets/index-uVHiae8s.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stageflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Stageflow — CLI pipeline runtime for configurable stages on Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -63,9 +63,12 @@
|
|
|
63
63
|
"@anthropic-ai/claude-agent-sdk": "^0.3.263",
|
|
64
64
|
"@earendil-works/pi-ai": "^0.84.1",
|
|
65
65
|
"@earendil-works/pi-coding-agent": "^0.84.1",
|
|
66
|
+
"@earendil-works/pi-tui": "^0.84.4",
|
|
66
67
|
"@modelcontextprotocol/node": "^2.0.0",
|
|
67
68
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
68
69
|
"better-sqlite3": "^13.0.3",
|
|
70
|
+
"jiti": "^2.7.0",
|
|
71
|
+
"pi-mcp-adapter": "^2.32.1",
|
|
69
72
|
"typebox": "^1.3.7",
|
|
70
73
|
"yaml": "^2.9.0",
|
|
71
74
|
"zod": "^4.4.3"
|
|
@@ -35,9 +35,27 @@ Ask until you can name every step, how they sequence, any decision point, and an
|
|
|
35
35
|
|
|
36
36
|
## Map
|
|
37
37
|
|
|
38
|
-
Read [`references/catalog-mapping.md`](references/catalog-mapping.md). Apply those rules to the confirmed structure. Read [`references/stage-prompt-template.md`](references/stage-prompt-template.md) for each stage's `system_prompt`, `model`, and `gate_kinds`.
|
|
38
|
+
Read [`references/catalog-mapping.md`](references/catalog-mapping.md). Apply those rules to the confirmed structure. Read [`references/stage-prompt-template.md`](references/stage-prompt-template.md) for each stage's `system_prompt`, optional `model`, `io`, `verify`, and `gate_kinds`. Apply the Anti-patterns section below while mapping. When the human needs hard advance gates, plan body `verify` and wiring `on_verify_fail`. When a review can demand changes, include an address-feedback stage before approve/ship.
|
|
39
39
|
|
|
40
|
-
**Done when** you have a pipeline id, one stage id per step, `needs` / `fork` wiring,
|
|
40
|
+
**Done when** you have a pipeline id, one stage id per step, `needs` / `fork` wiring, a prompt plan per stage, and any `verify` / `on_verify_fail` / remediation stages the structure requires.
|
|
41
|
+
|
|
42
|
+
## Anti-patterns
|
|
43
|
+
|
|
44
|
+
Author these contracts explicitly. They come from long runs that failed after hours of real work.
|
|
45
|
+
|
|
46
|
+
| Always do | How |
|
|
47
|
+
|---|---|
|
|
48
|
+
| End every attempt on a tool call | Prompt: last call is `emit_stage_envelope`, or `ask_operator` while waiting on HITL. Each clonable instance emits on its own. |
|
|
49
|
+
| Land required files in the attempt artifact dir | Prompt `write_stage_artifact`. Body `verify` with `type: artifact` and `when` including `after`. `ask_operator` `artifact_backed` references that same path. |
|
|
50
|
+
| Make implement stages change the checkout | Body `verify` `checkout_changes` + `path_fields`; `io.output.schema` with required checkout-relative path arrays. Exploration-only is its own stage or a failure emit. |
|
|
51
|
+
| Hand successors clean envelopes | `summary` / `payload` = outcomes and artifact pointers only. Name required `io.output.schema` fields in the prompt. |
|
|
52
|
+
| Give review blockers a place to land | Wire `review → address-feedback → approve/ship`. Put `verdict` / `blocking_findings` (or equivalent) in the review `io.output.schema`. |
|
|
53
|
+
| Bind success to the full checklist | If a plan lists N commands, success requires all of them in `commands_run` with exit 0. Cheap checks first; slow suites last or in a verify stage. Size `timeout_ms` to the work. |
|
|
54
|
+
| Use configured models on every sibling | Same configured `model` family after a fork/fan-out unless the human asks otherwise. Reliable model on publish/PR stages. |
|
|
55
|
+
| Finish publish in the accept attempt | After `artifact_backed` accept: side effects (commit/push/PR) → final artifact → emit in the same attempt. Fix emit/schema errors by re-emitting. |
|
|
56
|
+
| Emit full clone assignments | When `clonable: true`, parent success uses `clone_forks` with full envelopes matching `io.input.schema`. Leave clonable unset when the clone count is unknown. |
|
|
57
|
+
|
|
58
|
+
Throwaway checkout deliverables (HTML spike, scratch file): prompt builtin `write` at a checkout-relative path, `artifacts: []` on emit, path in `payload`.
|
|
41
59
|
|
|
42
60
|
## Locate
|
|
43
61
|
|
|
@@ -7,4 +7,12 @@ system_prompt: |
|
|
|
7
7
|
|
|
8
8
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
9
9
|
artifacts, and a payload describing what you repaired.
|
|
10
|
-
|
|
10
|
+
io:
|
|
11
|
+
output:
|
|
12
|
+
schema:
|
|
13
|
+
type: object
|
|
14
|
+
required:
|
|
15
|
+
- repaired
|
|
16
|
+
properties:
|
|
17
|
+
repaired:
|
|
18
|
+
type: boolean
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
id: release-gate
|
|
2
|
+
model: anthropic/claude-sonnet-4-5
|
|
2
3
|
stages:
|
|
3
4
|
- id: run-tests
|
|
4
5
|
uses: ./run-tests.yaml
|
|
@@ -6,7 +7,10 @@ stages:
|
|
|
6
7
|
select: one
|
|
7
8
|
- id: hotfix
|
|
8
9
|
uses: ./hotfix.yaml
|
|
9
|
-
needs: run-tests
|
|
10
|
+
needs: [run-tests]
|
|
10
11
|
- id: ship
|
|
11
12
|
uses: ./ship.yaml
|
|
12
|
-
needs: run-tests
|
|
13
|
+
needs: [run-tests]
|
|
14
|
+
on_verify_fail:
|
|
15
|
+
mode: manual
|
|
16
|
+
retry_safety: side_effecting
|
|
@@ -10,4 +10,12 @@ system_prompt: |
|
|
|
10
10
|
On a success emit, include fork_choice naming immediate successor id(s) that
|
|
11
11
|
should run. Name only ids listed as this stage's children. select: one →
|
|
12
12
|
exactly one id: hotfix when the results fail, ship when they pass.
|
|
13
|
-
|
|
13
|
+
io:
|
|
14
|
+
output:
|
|
15
|
+
schema:
|
|
16
|
+
type: object
|
|
17
|
+
required:
|
|
18
|
+
- ready
|
|
19
|
+
properties:
|
|
20
|
+
ready:
|
|
21
|
+
type: boolean
|
|
@@ -7,4 +7,19 @@ system_prompt: |
|
|
|
7
7
|
|
|
8
8
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
9
9
|
artifacts, and a payload describing what you shipped.
|
|
10
|
-
|
|
10
|
+
io:
|
|
11
|
+
output:
|
|
12
|
+
schema:
|
|
13
|
+
type: object
|
|
14
|
+
required:
|
|
15
|
+
- shipped
|
|
16
|
+
properties:
|
|
17
|
+
shipped:
|
|
18
|
+
type: boolean
|
|
19
|
+
verify:
|
|
20
|
+
- id: ship-notes
|
|
21
|
+
type: artifact
|
|
22
|
+
path: ship.md
|
|
23
|
+
nonempty: true
|
|
24
|
+
when:
|
|
25
|
+
- after
|
|
@@ -5,5 +5,15 @@ system_prompt: |
|
|
|
5
5
|
Write the draft via write_stage_artifact (for example draft.md).
|
|
6
6
|
|
|
7
7
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
8
|
-
artifacts, and a payload the next stage can use.
|
|
9
|
-
|
|
8
|
+
artifacts, and a payload the next stage can use. Your last tool call in this
|
|
9
|
+
attempt must be emit_stage_envelope (or ask_operator if waiting on HITL).
|
|
10
|
+
An empty final message is a stage failure.
|
|
11
|
+
io:
|
|
12
|
+
output:
|
|
13
|
+
schema:
|
|
14
|
+
type: object
|
|
15
|
+
required:
|
|
16
|
+
- title
|
|
17
|
+
properties:
|
|
18
|
+
title:
|
|
19
|
+
type: string
|
|
@@ -7,4 +7,19 @@ system_prompt: |
|
|
|
7
7
|
|
|
8
8
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
9
9
|
artifacts, and a payload describing what you produced.
|
|
10
|
-
|
|
10
|
+
io:
|
|
11
|
+
output:
|
|
12
|
+
schema:
|
|
13
|
+
type: object
|
|
14
|
+
required:
|
|
15
|
+
- published
|
|
16
|
+
properties:
|
|
17
|
+
published:
|
|
18
|
+
type: boolean
|
|
19
|
+
verify:
|
|
20
|
+
- id: published-artifact
|
|
21
|
+
type: artifact
|
|
22
|
+
path: published.md
|
|
23
|
+
nonempty: true
|
|
24
|
+
when:
|
|
25
|
+
- after
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
id: review-loop
|
|
2
|
+
model: anthropic/claude-sonnet-4-5
|
|
2
3
|
stages:
|
|
3
4
|
- id: draft
|
|
4
5
|
uses: ./draft.yaml
|
|
5
6
|
- id: review
|
|
6
7
|
uses: ./review.yaml
|
|
7
|
-
needs: draft
|
|
8
|
+
needs: [draft]
|
|
9
|
+
on_verify_fail:
|
|
10
|
+
mode: repair
|
|
11
|
+
max_attempts: 3
|
|
12
|
+
retry_safety: idempotent
|
|
13
|
+
include_failed_checks: true
|
|
8
14
|
- id: publish
|
|
9
15
|
uses: ./publish.yaml
|
|
10
|
-
needs: review
|
|
16
|
+
needs: [review]
|
|
17
|
+
on_verify_fail:
|
|
18
|
+
mode: manual
|
|
19
|
+
retry_safety: side_effecting
|
|
@@ -12,4 +12,22 @@ system_prompt: |
|
|
|
12
12
|
again with artifact_backed in this same stage. Do not complete yet.
|
|
13
13
|
4. Call emit_stage_envelope with an advancing success status only after the
|
|
14
14
|
operator accepts. Never emit before accept.
|
|
15
|
-
|
|
15
|
+
io:
|
|
16
|
+
output:
|
|
17
|
+
schema:
|
|
18
|
+
type: object
|
|
19
|
+
required:
|
|
20
|
+
- verdict
|
|
21
|
+
properties:
|
|
22
|
+
verdict:
|
|
23
|
+
type: string
|
|
24
|
+
verify:
|
|
25
|
+
- id: review-accepted
|
|
26
|
+
type: gate
|
|
27
|
+
kind: artifact_backed
|
|
28
|
+
- id: review-artifact
|
|
29
|
+
type: artifact
|
|
30
|
+
path: review.md
|
|
31
|
+
nonempty: true
|
|
32
|
+
when:
|
|
33
|
+
- after
|
|
@@ -6,4 +6,12 @@ system_prompt: |
|
|
|
6
6
|
|
|
7
7
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
8
8
|
artifacts, and a payload the next stage can use.
|
|
9
|
-
|
|
9
|
+
io:
|
|
10
|
+
output:
|
|
11
|
+
schema:
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- source_count
|
|
15
|
+
properties:
|
|
16
|
+
source_count:
|
|
17
|
+
type: integer
|
package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
id: research-digest
|
|
2
|
+
model: anthropic/claude-sonnet-4-5
|
|
2
3
|
stages:
|
|
3
4
|
- id: gather
|
|
4
5
|
uses: ./gather.yaml
|
|
5
6
|
- id: summarize
|
|
6
7
|
uses: ./summarize.yaml
|
|
7
|
-
needs: gather
|
|
8
|
+
needs: [gather]
|
|
8
9
|
- id: send
|
|
9
10
|
uses: ./send.yaml
|
|
10
|
-
needs: summarize
|
|
11
|
+
needs: [summarize]
|
|
12
|
+
on_verify_fail:
|
|
13
|
+
mode: manual
|
|
14
|
+
retry_safety: side_effecting
|
|
@@ -7,4 +7,19 @@ system_prompt: |
|
|
|
7
7
|
|
|
8
8
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
9
9
|
artifacts, and a payload describing who received the digest.
|
|
10
|
-
|
|
10
|
+
io:
|
|
11
|
+
output:
|
|
12
|
+
schema:
|
|
13
|
+
type: object
|
|
14
|
+
required:
|
|
15
|
+
- sent
|
|
16
|
+
properties:
|
|
17
|
+
sent:
|
|
18
|
+
type: boolean
|
|
19
|
+
verify:
|
|
20
|
+
- id: sent-record
|
|
21
|
+
type: artifact
|
|
22
|
+
path: sent.md
|
|
23
|
+
nonempty: true
|
|
24
|
+
when:
|
|
25
|
+
- after
|
|
@@ -6,4 +6,12 @@ system_prompt: |
|
|
|
6
6
|
|
|
7
7
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
8
8
|
artifacts, and a payload the next stage can use.
|
|
9
|
-
|
|
9
|
+
io:
|
|
10
|
+
output:
|
|
11
|
+
schema:
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- headline
|
|
15
|
+
properties:
|
|
16
|
+
headline:
|
|
17
|
+
type: string
|
|
@@ -16,7 +16,7 @@ Collision handling lives in [`catalog-write-conventions.md`](catalog-write-conve
|
|
|
16
16
|
|
|
17
17
|
## Sequencing
|
|
18
18
|
|
|
19
|
-
`needs` is a
|
|
19
|
+
`needs` is a parent stage id, or a non-empty array (length ≥ 1). Strings default to `on: [succeeded]`. `{ id, on }` accepts a non-empty unique subset of `succeeded` | `failed` | `skipped`.
|
|
20
20
|
|
|
21
21
|
| Human says | Pipeline shape |
|
|
22
22
|
|---|---|
|
|
@@ -28,30 +28,93 @@ Collision handling lives in [`catalog-write-conventions.md`](catalog-write-conve
|
|
|
28
28
|
|
|
29
29
|
Default `select` is `one` unless the human says more than one branch can run.
|
|
30
30
|
|
|
31
|
-
Map linear chains, sibling fan-out, generic fan-in (`needs` array), and single-level `fork`.
|
|
31
|
+
Map linear chains, sibling fan-out, generic fan-in (`needs` array), and single-level `fork`.
|
|
32
32
|
|
|
33
33
|
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).
|
|
34
34
|
|
|
35
|
+
## Review then fix then approve
|
|
36
|
+
|
|
37
|
+
When the human wants a review that can demand changes, then a later approve/ship:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
… → review → address-feedback → approve
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Do not wire approve/ship as the immediate child of review. Pipelines are forward-only; without an address-feedback stage, blocking findings have nowhere to land. The address-feedback stage is the only post-review editor; the approve stage is the backstop.
|
|
44
|
+
|
|
45
|
+
## Verify and on_verify_fail
|
|
46
|
+
|
|
47
|
+
Put `verify` on the **stage body** (the `uses:` file or inline entry). Put `on_verify_fail` on the **pipeline** stage entry (the `uses:` wrapper). Use when the human needs a hard gate before advance:
|
|
48
|
+
|
|
49
|
+
| Need | Catalog |
|
|
50
|
+
|---|---|
|
|
51
|
+
| Required file under the attempt artifact dir | `verify` with `type: artifact`, `path`, usually `nonempty: true`, `when: [after]` |
|
|
52
|
+
| HITL must complete this attempt | `type: gate` with `kind` that appears in the stage's `gate_kinds` (default `when: [emit]`) |
|
|
53
|
+
| Implement must change the checkout | `type: checkout_changes` with `path_fields` naming required arrays in `io.output.schema` |
|
|
54
|
+
| Auto-retry when after-phase verify fails | `on_verify_fail: { mode: repair, max_attempts: N, retry_safety: idempotent, include_failed_checks: true }` |
|
|
55
|
+
| Side-effecting publish / ship | `on_verify_fail: { mode: manual, retry_safety: side_effecting }` |
|
|
56
|
+
|
|
57
|
+
`on_verify_fail` requires at least one after-phase `verify` item. Check `id` values must be unique within the stage. Check discriminator is `type:` (gate widgets still use `kind:`). Wire these for writer stages and final gates; prompts alone do not enforce them.
|
|
58
|
+
|
|
59
|
+
## Clonable successors
|
|
60
|
+
|
|
61
|
+
A runtime clone count is not knowable from a vague description — leave `clonable` and `clone_forks` unset and prefer sibling stages or a single review.
|
|
62
|
+
|
|
63
|
+
When the human explicitly wants N parallel instances of **one** successor catalog id (e.g. several review lenses, several prototype variants):
|
|
64
|
+
|
|
65
|
+
- On that successor pipeline entry: `clonable: true` and `clone_cap` (integer ≥ 2).
|
|
66
|
+
- That successor must have at least one child (a join / address-feedback / collect stage). It cannot be a DAG leaf.
|
|
67
|
+
- Parent success emit uses `clone_forks` for that successor (not `fork_choice`). Each clone assignment is a full envelope; validate assignments with `io.input.schema` on the clonable stage body.
|
|
68
|
+
- Join stages that wait on the clonable parent read clone-list `priorEnvelopes`, not `priorEnvelopesByStage`.
|
|
69
|
+
|
|
70
|
+
`fork` + `fork_choice` picks which **branch stage ids** run. `clone_forks` spawns **N instances** of one successor id.
|
|
71
|
+
|
|
72
|
+
## Models
|
|
73
|
+
|
|
74
|
+
Confirm providers before writing. After a fork, give every sibling the same configured `model` unless the human asks for different ones. Prefer a reliable configured model on side-effecting final stages.
|
|
75
|
+
|
|
35
76
|
## Worked examples
|
|
36
77
|
|
|
37
78
|
### Review loop (linear)
|
|
38
79
|
|
|
39
|
-
Three sequential steps; the middle one is a sign-off.
|
|
80
|
+
Three sequential steps; the middle one is a sign-off. Reject/revise stays inside the gated `review` stage.
|
|
40
81
|
|
|
41
82
|
```yaml
|
|
42
83
|
id: review-loop
|
|
84
|
+
model: anthropic/claude-sonnet-4-5
|
|
43
85
|
stages:
|
|
44
86
|
- id: draft
|
|
45
87
|
uses: ./draft.yaml
|
|
46
88
|
- id: review
|
|
47
89
|
uses: ./review.yaml
|
|
48
|
-
needs: draft
|
|
90
|
+
needs: [draft]
|
|
49
91
|
- id: publish
|
|
50
92
|
uses: ./publish.yaml
|
|
51
|
-
needs: review
|
|
93
|
+
needs: [review]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`review` carries `gate_kinds: [artifact_backed]` and emit-phase `verify` `type: gate`. Full set: [`../assets/examples/linear-review/`](../assets/examples/linear-review/).
|
|
97
|
+
|
|
98
|
+
### Review with separate fix stage
|
|
99
|
+
|
|
100
|
+
When review can emit blockers and a later stage approves or ships, insert address-feedback between them:
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
stages:
|
|
104
|
+
- id: implement
|
|
105
|
+
uses: ./implement.yaml
|
|
106
|
+
- id: review
|
|
107
|
+
uses: ./review.yaml
|
|
108
|
+
needs: [implement]
|
|
109
|
+
- id: address-feedback
|
|
110
|
+
uses: ./address-feedback.yaml
|
|
111
|
+
needs: [review]
|
|
112
|
+
- id: approve
|
|
113
|
+
uses: ./approve.yaml
|
|
114
|
+
needs: [address-feedback]
|
|
52
115
|
```
|
|
53
116
|
|
|
54
|
-
`
|
|
117
|
+
Do not make `approve` / `ship` `needs: review` when blockers are expected.
|
|
55
118
|
|
|
56
119
|
### Release gate (fork, select one)
|
|
57
120
|
|
|
@@ -66,10 +129,10 @@ stages:
|
|
|
66
129
|
select: one
|
|
67
130
|
- id: hotfix
|
|
68
131
|
uses: ./hotfix.yaml
|
|
69
|
-
needs: run-tests
|
|
132
|
+
needs: [run-tests]
|
|
70
133
|
- id: ship
|
|
71
134
|
uses: ./ship.yaml
|
|
72
|
-
needs: run-tests
|
|
135
|
+
needs: [run-tests]
|
|
73
136
|
```
|
|
74
137
|
|
|
75
138
|
Full set: [`../assets/examples/branch-decision/`](../assets/examples/branch-decision/).
|
|
@@ -85,10 +148,10 @@ stages:
|
|
|
85
148
|
uses: ./gather.yaml
|
|
86
149
|
- id: summarize
|
|
87
150
|
uses: ./summarize.yaml
|
|
88
|
-
needs: gather
|
|
151
|
+
needs: [gather]
|
|
89
152
|
- id: send
|
|
90
153
|
uses: ./send.yaml
|
|
91
|
-
needs: summarize
|
|
154
|
+
needs: [summarize]
|
|
92
155
|
```
|
|
93
156
|
|
|
94
157
|
Full set: [`../assets/examples/non-sdlc-digest/`](../assets/examples/non-sdlc-digest/).
|
|
@@ -103,10 +166,10 @@ stages:
|
|
|
103
166
|
uses: ./intake.yaml
|
|
104
167
|
- id: collect-quotes
|
|
105
168
|
uses: ./collect-quotes.yaml
|
|
106
|
-
needs: intake
|
|
169
|
+
needs: [intake]
|
|
107
170
|
- id: collect-notes
|
|
108
171
|
uses: ./collect-notes.yaml
|
|
109
|
-
needs: intake
|
|
172
|
+
needs: [intake]
|
|
110
173
|
```
|
|
111
174
|
|
|
112
175
|
No `fork` field. Both siblings run.
|
|
@@ -121,10 +184,10 @@ stages:
|
|
|
121
184
|
uses: ./clarify.yaml
|
|
122
185
|
- id: research
|
|
123
186
|
uses: ./research.yaml
|
|
124
|
-
needs: clarify
|
|
187
|
+
needs: [clarify]
|
|
125
188
|
- id: validation
|
|
126
189
|
uses: ./validation.yaml
|
|
127
|
-
needs: clarify
|
|
190
|
+
needs: [clarify]
|
|
128
191
|
- id: synthesize
|
|
129
192
|
uses: ./synthesize.yaml
|
|
130
193
|
needs:
|
|
@@ -132,7 +195,7 @@ stages:
|
|
|
132
195
|
- validation
|
|
133
196
|
```
|
|
134
197
|
|
|
135
|
-
`needs` array length is
|
|
198
|
+
`needs` array length ≥ 2 is keyed fan-in. The join reads `priorEnvelopesByStage`, not clone-list `priorEnvelopes`.
|
|
136
199
|
|
|
137
200
|
### Fork, select subset
|
|
138
201
|
|
|
@@ -146,10 +209,10 @@ stages:
|
|
|
146
209
|
select: subset
|
|
147
210
|
- id: email
|
|
148
211
|
uses: ./email.yaml
|
|
149
|
-
needs: choose-channels
|
|
212
|
+
needs: [choose-channels]
|
|
150
213
|
- id: post
|
|
151
214
|
uses: ./post.yaml
|
|
152
|
-
needs: choose-channels
|
|
215
|
+
needs: [choose-channels]
|
|
153
216
|
```
|
|
154
217
|
|
|
155
218
|
The success emit names one or more of those successor ids in `fork_choice`.
|
|
@@ -18,9 +18,9 @@ One directory (or the project root) holds:
|
|
|
18
18
|
| File | Required fields |
|
|
19
19
|
|---|---|
|
|
20
20
|
| `<pipeline-id>.pipeline.yaml` | `id` matching the filename stem; `stages:` object entries |
|
|
21
|
-
| `<stage-id>.yaml` | `id`, `system_prompt
|
|
21
|
+
| `<stage-id>.yaml` | `id`, `system_prompt`; `model` when not inherited; `io` / `verify` / `gate_kinds` when the step needs them |
|
|
22
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
|
|
23
|
+
Each pipeline stage entry has `id` and `uses: ./<id>.yaml` (path relative to the pipeline file). Non-root stages add `needs: <parent-id>` or `needs: [<parent-id>, …]` (length ≥ 1; strings or `{ id, on }`). A deciding stage adds `fork:`. Put `on_verify_fail` on the pipeline entry when after-phase `verify` should repair or wait for an operator. Filename stem matches `id` on every file. Optional pipeline-root `model` fills stages that omit `model`.
|
|
24
24
|
|
|
25
25
|
## Collisions
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Stage prompt template
|
|
2
2
|
|
|
3
|
-
Every external stage file has `id
|
|
3
|
+
Every external stage file has `id` and `system_prompt`. Filename stem matches `id`. `model` is optional when the pipeline or `stageflow.yaml` supplies it — otherwise set it on the stage. Default when writing a concrete string is `anthropic/claude-sonnet-4-5`. When the human names a different model, write that string verbatim. Before writing models, confirm at least one provider is `configured` (see the skill Provider gate). Sibling stages after a fork should use the same configured model family unless the human asks otherwise.
|
|
4
4
|
|
|
5
5
|
## Base
|
|
6
6
|
|
|
@@ -14,12 +14,48 @@ system_prompt: |
|
|
|
14
14
|
Write any output this step produces via write_stage_artifact.
|
|
15
15
|
|
|
16
16
|
When finished, call emit_stage_envelope exactly once with status, summary,
|
|
17
|
-
artifacts, and a payload the next stage can use.
|
|
17
|
+
artifacts, and a payload the next stage can use. Your last tool call in this
|
|
18
|
+
attempt must be emit_stage_envelope (or ask_operator if waiting on HITL).
|
|
19
|
+
An empty final message is a stage failure.
|
|
18
20
|
model: anthropic/claude-sonnet-4-5
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
The prompt has no `ask_operator` line. It ends on the `emit_stage_envelope` instruction. Call `emit_stage_envelope` once per attempt.
|
|
22
24
|
|
|
25
|
+
When the pipeline entry will carry after-phase `verify` with `type: artifact`, add this line after the goal:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Required files must be created with write_stage_artifact. Checkout write/edit
|
|
29
|
+
does not satisfy after-phase verify.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
When the stage must change the project checkout (implement, patch, edit source), add:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Success requires real checkout edits. Put checkout-relative paths in
|
|
36
|
+
payload.changed_files. Do not put stages/.../artifacts paths there. A report
|
|
37
|
+
or map alone is a failure emit, not success.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
When the deliverable is throwaway checkout content instead of a stage artifact:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Write the deliverable with builtin write at <checkout-relative path>.
|
|
44
|
+
Set artifacts: [] on emit. Put that path in payload.<field>.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Summary and payload
|
|
48
|
+
|
|
49
|
+
Add to every stage (base, gated, or fork):
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
summary and payload are handed to the next stage verbatim. State outcomes and
|
|
53
|
+
artifact pointers only. Do not repeat this stage's prohibitions in summary —
|
|
54
|
+
downstream will obey them literally.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
When `io.output.schema` is on the stage file, name the required fields in the prompt so the emit matches.
|
|
58
|
+
|
|
23
59
|
## Gated
|
|
24
60
|
|
|
25
61
|
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.
|
|
@@ -32,7 +68,8 @@ system_prompt: |
|
|
|
32
68
|
<one-line goal>. Get operator acceptance before completing this stage.
|
|
33
69
|
|
|
34
70
|
1. Write the reviewable output via write_stage_artifact.
|
|
35
|
-
2. Call ask_operator with kind artifact_backed referencing that artifact path
|
|
71
|
+
2. Call ask_operator with kind artifact_backed referencing that artifact path
|
|
72
|
+
(stage artifact path, not a checkout path).
|
|
36
73
|
3. On reject or change text: revise the artifact and call ask_operator again
|
|
37
74
|
with artifact_backed in this same stage. Do not complete yet.
|
|
38
75
|
4. Call emit_stage_envelope with an advancing success status only after the
|
|
@@ -42,6 +79,14 @@ model: anthropic/claude-sonnet-4-5
|
|
|
42
79
|
|
|
43
80
|
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
81
|
|
|
82
|
+
When the gated stage also publishes or opens a PR after accept, append:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
After the operator accepts, immediately finish publish side effects in this
|
|
86
|
+
same attempt (commit, push, open PR as required), write any final artifact,
|
|
87
|
+
then emit. Do not pause after accept. Do not ask_operator for emit/schema errors.
|
|
88
|
+
```
|
|
89
|
+
|
|
45
90
|
## Fork
|
|
46
91
|
|
|
47
92
|
When the pipeline entry has `fork`, the success emit names immediate successors in `fork_choice`. Add this block to the base (or gated) prompt:
|
|
@@ -50,6 +95,20 @@ When the pipeline entry has `fork`, the success emit names immediate successors
|
|
|
50
95
|
On a success emit, include fork_choice naming immediate successor id(s) that
|
|
51
96
|
should run. Name only ids listed as this stage's children. select: one →
|
|
52
97
|
exactly one id. select: subset → one or more of those ids.
|
|
98
|
+
Normalize free_text answers before mapping (trim, lowercase, collapse spaces
|
|
99
|
+
and hyphens). If unmapped, ask_operator again; do not emit.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`fork_choice` on a failure emit is ignored. Leave `clone_forks` unset unless the human explicitly asked for clonable fan-out (see [`catalog-mapping.md`](catalog-mapping.md)).
|
|
103
|
+
|
|
104
|
+
## Clonable parent
|
|
105
|
+
|
|
106
|
+
When a successor is `clonable: true`, the parent success emit uses `clone_forks` (not `fork_choice`) for that successor. Add:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
On success, include clone_forks covering every clonable successor exactly once.
|
|
110
|
+
Each clone entry is a full envelope with status, summary, artifacts, and payload
|
|
111
|
+
matching that successor's io.input.schema — not a stub object.
|
|
53
112
|
```
|
|
54
113
|
|
|
55
|
-
|
|
114
|
+
Clonable child stages use the base (or gated) prompt. Remind them they are one clone among others and must emit independently.
|
|
@@ -74,7 +74,7 @@ Read [`references/catalog-authoring.md`](references/catalog-authoring.md) before
|
|
|
74
74
|
`node scripts/resolve-catalog-id.mjs --text "<phrase>" --dir <write-dir> --kind pipeline|stage`
|
|
75
75
|
|
|
76
76
|
Use the printed `{"id":"..."}`.
|
|
77
|
-
3. Write one external stage YAML per phase (`id`, `system_prompt`, `model`). End every `system_prompt` with an `emit_stage_envelope` footer. Omit `gate_kinds`. Filename stem must match `id`.
|
|
77
|
+
3. Write one external stage YAML per phase (`id`, `system_prompt`, optional `model`). End every `system_prompt` with an `emit_stage_envelope` footer. Omit `gate_kinds`. Filename stem must match `id`.
|
|
78
78
|
4. Write one pipeline YAML that wires the stages with `uses:` and `needs:` in dependency order.
|
|
79
79
|
|
|
80
80
|
Do not write a `*.task.yaml`.
|
|
@@ -4,5 +4,16 @@ system_prompt: |
|
|
|
4
4
|
there. Prefer what already worked in the source session.
|
|
5
5
|
|
|
6
6
|
When finished, call emit_stage_envelope once with status, summary, artifacts,
|
|
7
|
-
and a payload describing what you produced.
|
|
8
|
-
|
|
7
|
+
and a payload describing what you produced. Your last tool call in this
|
|
8
|
+
attempt must be emit_stage_envelope. An empty final message is a stage failure.
|
|
9
|
+
io:
|
|
10
|
+
output:
|
|
11
|
+
schema:
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- changed_files
|
|
15
|
+
properties:
|
|
16
|
+
changed_files:
|
|
17
|
+
type: array
|
|
18
|
+
items:
|
|
19
|
+
type: string
|
|
@@ -4,5 +4,21 @@ system_prompt: |
|
|
|
4
4
|
unknown, and the next useful work.
|
|
5
5
|
|
|
6
6
|
When finished, call emit_stage_envelope once with status, summary, artifacts,
|
|
7
|
-
and a payload the next stage can use.
|
|
8
|
-
|
|
7
|
+
and a payload the next stage can use. Your last tool call in this attempt must
|
|
8
|
+
be emit_stage_envelope. An empty final message is a stage failure.
|
|
9
|
+
io:
|
|
10
|
+
output:
|
|
11
|
+
schema:
|
|
12
|
+
type: object
|
|
13
|
+
required:
|
|
14
|
+
- known
|
|
15
|
+
- unknown
|
|
16
|
+
properties:
|
|
17
|
+
known:
|
|
18
|
+
type: array
|
|
19
|
+
items:
|
|
20
|
+
type: string
|
|
21
|
+
unknown:
|
|
22
|
+
type: array
|
|
23
|
+
items:
|
|
24
|
+
type: string
|