stageflow 0.16.0 → 0.19.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 +2 -4
- package/dist/agent/activity.d.ts +4 -0
- package/dist/agent/claudeAdapter.js +38 -0
- package/dist/agent/claudeTools.d.ts +1 -4
- package/dist/agent/claudeTools.js +1 -6
- package/dist/agent/fakeAgent.js +7 -6
- package/dist/agent/piAdapter.js +34 -15
- package/dist/agent/port.d.ts +1 -1
- package/dist/agent/stageTimeout.d.ts +9 -0
- package/dist/agent/stageTimeout.js +24 -0
- package/dist/cli/graphCommand.d.ts +15 -0
- package/dist/cli/graphCommand.js +79 -0
- package/dist/cli/graphRender.d.ts +2 -0
- package/dist/cli/graphRender.js +85 -0
- package/dist/cli/runsCommand.d.ts +1 -1
- package/dist/cli/runsCommand.js +37 -0
- package/dist/cli.js +12 -0
- package/dist/config/cloneChain.d.ts +12 -0
- package/dist/config/cloneChain.js +322 -0
- package/dist/config/createPipeline.js +101 -21
- package/dist/config/createStage.js +7 -0
- package/dist/config/loadOutcome.d.ts +1 -0
- package/dist/config/loadPipeline.d.ts +2 -0
- package/dist/config/loadPipeline.js +34 -22
- package/dist/config/loadStage.d.ts +2 -0
- package/dist/config/loadStage.js +135 -125
- package/dist/config/migrateYaml.js +14 -3
- package/dist/config/normalizePipelineStageEntry.d.ts +5 -9
- package/dist/config/normalizePipelineStageEntry.js +133 -60
- package/dist/config/parsePreEmitChecks.js +2 -2
- package/dist/config/pipelineNeeds.d.ts +15 -2
- package/dist/config/pipelineNeeds.js +86 -4
- package/dist/config/pipelineRoute.d.ts +46 -0
- package/dist/config/pipelineRoute.js +215 -0
- package/dist/config/pipelineStageKeys.d.ts +2 -0
- package/dist/config/pipelineStageKeys.js +15 -4
- package/dist/config/printTargetYaml.js +18 -12
- package/dist/config/resolveForkEmitContext.d.ts +1 -1
- package/dist/config/resolveForkEmitContext.js +3 -26
- package/dist/config/resolvePipelineDag.d.ts +1 -3
- package/dist/config/resolvePipelineDag.js +143 -186
- package/dist/config/routeIf.d.ts +24 -0
- package/dist/config/routeIf.js +247 -0
- package/dist/config/validateCatalog.d.ts +1 -1
- package/dist/config/validateCatalog.js +5 -3
- package/dist/config/yamlDialect.d.ts +5 -8
- package/dist/config/yamlDialect.js +37 -29
- package/dist/envelope/check.d.ts +0 -2
- package/dist/envelope/check.js +1 -57
- package/dist/envelope/feedbackLoop.js +0 -3
- package/dist/envelope/forkChoice.js +1 -1
- package/dist/envelope/payloadSchema.d.ts +14 -0
- package/dist/envelope/payloadSchema.js +87 -2
- package/dist/mcp/catalogTools.js +1 -2
- package/dist/mcp/controlTools.js +17 -0
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/projection/projectRun.d.ts +0 -2
- package/dist/projection/projectRun.js +0 -3
- package/dist/prompt/priorEnvelope.js +1 -1
- package/dist/runstore/port.js +2 -0
- package/dist/runstore/stageInstanceId.d.ts +1 -0
- package/dist/runstore/stageInstanceId.js +9 -0
- package/dist/runtime/cloneSchedule.d.ts +16 -33
- package/dist/runtime/cloneSchedule.js +155 -236
- package/dist/runtime/envelopeRouting.js +43 -94
- package/dist/runtime/forkGeneration.d.ts +6 -2
- package/dist/runtime/forkGeneration.js +45 -15
- package/dist/runtime/joinReadiness.d.ts +16 -0
- package/dist/runtime/joinReadiness.js +156 -0
- package/dist/runtime/pipelineScheduler.d.ts +0 -3
- package/dist/runtime/pipelineScheduler.js +103 -65
- package/dist/runtime/reopenSkipped.d.ts +13 -0
- package/dist/runtime/reopenSkipped.js +56 -0
- package/dist/runtime/resumeTimedOut.d.ts +33 -0
- package/dist/runtime/resumeTimedOut.js +165 -0
- package/dist/runtime/routeIfEval.d.ts +3 -0
- package/dist/runtime/routeIfEval.js +94 -0
- package/dist/runtime/runManager.d.ts +1 -0
- package/dist/runtime/runManager.js +76 -0
- package/dist/runtime/runRetryCoordinator.js +0 -4
- package/dist/runtime/stageAttemptBootstrap.js +60 -11
- package/dist/runtime/stageRecovery.js +2 -2
- package/dist/runtime/stageRunner.js +6 -2
- package/dist/runtime/taskInput.js +1 -13
- package/dist/server/http.js +18 -0
- package/dist/tools/askOperator.d.ts +1 -0
- package/dist/tools/askOperator.js +14 -11
- package/dist/tools/emitStageEnvelope.d.ts +3 -3
- package/dist/tools/emitStageEnvelope.js +4 -66
- package/dist/tools/prepareToolArguments.d.ts +4 -0
- package/dist/tools/prepareToolArguments.js +79 -0
- package/dist/types/envelope.d.ts +0 -2
- package/dist/types/forkChoice.d.ts +0 -16
- package/dist/types/pipeline.d.ts +86 -27
- package/dist/types/stage.d.ts +11 -7
- package/dist/ui/assets/{index-D2Wt8hwH.css → index-CSsDued1.css} +1 -1
- package/dist/ui/assets/index-DMVdl1qB.js +119 -0
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/skills/stageflow-author/SKILL.md +4 -4
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -2
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -4
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +6 -4
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +9 -1
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +3 -0
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +8 -0
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +5 -2
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +8 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +3 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +5 -2
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +8 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +8 -0
- package/skills/stageflow-author/references/catalog-mapping.md +159 -50
- package/skills/stageflow-author/references/catalog-write-conventions.md +3 -3
- package/skills/stageflow-author/references/stage-prompt-template.md +57 -17
- package/skills/stageflow-session-capture/SKILL.md +2 -2
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +3 -1
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +15 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +3 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +4 -2
- package/dist/envelope/cloneForks.d.ts +0 -2
- package/dist/envelope/cloneForks.js +0 -77
- package/dist/ui/assets/index-XWJovnp7.js +0 -118
|
@@ -14,12 +14,12 @@ import type { TSchema } from "typebox/type";
|
|
|
14
14
|
import { type PreEmitCheckOptions } from "../envelope/preEmitChecks.js";
|
|
15
15
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
16
16
|
import type { FeedbackLoopConfig } from "../types/pipeline.js";
|
|
17
|
-
import {
|
|
17
|
+
import type { CloneEmitContext, ForkEmitContext } from "../types/forkChoice.js";
|
|
18
18
|
export type EmitCapture = {
|
|
19
19
|
envelope?: StageEnvelope;
|
|
20
20
|
error?: string;
|
|
21
21
|
};
|
|
22
|
-
export declare function createEmitStageEnvelopeTool(capture: EmitCapture, payloadSchema?: unknown, forkEmitContext?: ForkEmitContext,
|
|
22
|
+
export declare function createEmitStageEnvelopeTool(capture: EmitCapture, payloadSchema?: unknown, forkEmitContext?: ForkEmitContext, _cloneEmitContext?: CloneEmitContext, preEmitCheckOptions?: PreEmitCheckOptions, feedbackLoopEmitContext?: FeedbackLoopConfig): {
|
|
23
23
|
name: string;
|
|
24
24
|
label: string;
|
|
25
25
|
description: string;
|
|
@@ -29,7 +29,6 @@ export declare function createEmitStageEnvelopeTool(capture: EmitCapture, payloa
|
|
|
29
29
|
artifacts: Type.TArray<Type.TString>;
|
|
30
30
|
payload: Type.TOptional<TSchema>;
|
|
31
31
|
fork_choice: Type.TArray<Type.TString>;
|
|
32
|
-
clone_forks?: Type.TArray<TSchema> | undefined;
|
|
33
32
|
feedback_loop?: Type.TOptional<TSchema> | undefined;
|
|
34
33
|
checklist_attestations: Type.TOptional<Type.TArray<Type.TObject<{
|
|
35
34
|
check_id: Type.TString;
|
|
@@ -38,6 +37,7 @@ export declare function createEmitStageEnvelopeTool(capture: EmitCapture, payloa
|
|
|
38
37
|
stage_id: Type.TOptional<Type.TString>;
|
|
39
38
|
notes: Type.TOptional<Type.TString>;
|
|
40
39
|
}>;
|
|
40
|
+
prepareArguments: (args: unknown) => never;
|
|
41
41
|
execute: (_toolCallId: string, params: unknown) => Promise<{
|
|
42
42
|
content: {
|
|
43
43
|
type: "text";
|
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
import { Type } from "typebox";
|
|
13
13
|
import { assertRequiredEnvelope, isAdvancingEnvelope, } from "../envelope/check.js";
|
|
14
14
|
import { assertFeedbackLoopAction } from "../envelope/feedbackLoop.js";
|
|
15
|
-
import { assertCloneForks } from "../envelope/cloneForks.js";
|
|
16
15
|
import { normalizeForkChoice } from "../envelope/forkChoice.js";
|
|
17
16
|
import { assertEnvelopePayload, compilePayloadSchema, } from "../envelope/payloadSchema.js";
|
|
18
17
|
import { assertPreEmitChecks, } from "../envelope/preEmitChecks.js";
|
|
19
|
-
import {
|
|
18
|
+
import { prepareEmitStageEnvelopeArguments } from "./prepareToolArguments.js";
|
|
20
19
|
function stringLiteralsSchema(values) {
|
|
21
20
|
if (values.length === 1) {
|
|
22
21
|
return Type.Literal(values[0]);
|
|
@@ -42,56 +41,6 @@ function feedbackLoopActionSchema(context) {
|
|
|
42
41
|
}, { additionalProperties: false }),
|
|
43
42
|
]);
|
|
44
43
|
}
|
|
45
|
-
function cloneForksItemSchema(cloneEmitContext) {
|
|
46
|
-
const allowedActions = cloneEmitContext.allowedActions ?? [...CLONE_ACTIONS];
|
|
47
|
-
const allowSkip = allowedActions.includes("skip");
|
|
48
|
-
const allowOnce = allowedActions.includes("once");
|
|
49
|
-
const allowFanout = allowedActions.includes("fanout");
|
|
50
|
-
const variants = [];
|
|
51
|
-
for (const successor of cloneEmitContext.clonableSuccessors) {
|
|
52
|
-
const successorId = Type.Literal(successor.successorId);
|
|
53
|
-
const nestedPayload = successor.cloneInputSchema !== undefined
|
|
54
|
-
? compilePayloadSchema(successor.cloneInputSchema)
|
|
55
|
-
: undefined;
|
|
56
|
-
const nestedEnvelope = stageEnvelopeSchema(nestedPayload);
|
|
57
|
-
if (allowSkip) {
|
|
58
|
-
variants.push(Type.Object({
|
|
59
|
-
successor_id: successorId,
|
|
60
|
-
action: Type.Literal("skip"),
|
|
61
|
-
}, { additionalProperties: false }));
|
|
62
|
-
}
|
|
63
|
-
if (allowOnce) {
|
|
64
|
-
variants.push(Type.Object({
|
|
65
|
-
successor_id: successorId,
|
|
66
|
-
action: Type.Literal("once"),
|
|
67
|
-
envelope: nestedEnvelope,
|
|
68
|
-
}));
|
|
69
|
-
}
|
|
70
|
-
if (allowFanout) {
|
|
71
|
-
variants.push(Type.Object({
|
|
72
|
-
successor_id: successorId,
|
|
73
|
-
action: Type.Literal("fanout"),
|
|
74
|
-
mode: Type.Union([
|
|
75
|
-
Type.Literal("parallel"),
|
|
76
|
-
Type.Literal("sequential"),
|
|
77
|
-
]),
|
|
78
|
-
clones: Type.Array(Type.Object({
|
|
79
|
-
envelope: nestedEnvelope,
|
|
80
|
-
}), { minItems: 2, maxItems: successor.cloneCap }),
|
|
81
|
-
}));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (variants.length === 0) {
|
|
85
|
-
return Type.Object({
|
|
86
|
-
successor_id: Type.String(),
|
|
87
|
-
action: stringLiteralsSchema(allowedActions),
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
if (variants.length === 1) {
|
|
91
|
-
return variants[0];
|
|
92
|
-
}
|
|
93
|
-
return Type.Union(variants);
|
|
94
|
-
}
|
|
95
44
|
function toolResult(text, details, options) {
|
|
96
45
|
return {
|
|
97
46
|
content: [{ type: "text", text }],
|
|
@@ -100,7 +49,7 @@ function toolResult(text, details, options) {
|
|
|
100
49
|
...(options?.terminate ? { terminate: true } : {}),
|
|
101
50
|
};
|
|
102
51
|
}
|
|
103
|
-
export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitContext,
|
|
52
|
+
export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitContext, _cloneEmitContext, preEmitCheckOptions, feedbackLoopEmitContext) {
|
|
104
53
|
const compiledPayload = payloadSchema !== undefined
|
|
105
54
|
? compilePayloadSchema(payloadSchema)
|
|
106
55
|
: undefined;
|
|
@@ -118,13 +67,6 @@ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitCont
|
|
|
118
67
|
fork_choice: forkEmitContext !== undefined && feedbackLoopEmitContext === undefined
|
|
119
68
|
? Type.Array(Type.String())
|
|
120
69
|
: Type.Optional(Type.Array(Type.String())),
|
|
121
|
-
...(cloneEmitContext !== undefined
|
|
122
|
-
? {
|
|
123
|
-
clone_forks: feedbackLoopEmitContext === undefined
|
|
124
|
-
? Type.Array(cloneForksItemSchema(cloneEmitContext))
|
|
125
|
-
: Type.Optional(Type.Array(cloneForksItemSchema(cloneEmitContext))),
|
|
126
|
-
}
|
|
127
|
-
: {}),
|
|
128
70
|
...(feedbackLoopEmitContext !== undefined
|
|
129
71
|
? {
|
|
130
72
|
feedback_loop: Type.Optional(feedbackLoopActionSchema(feedbackLoopEmitContext)),
|
|
@@ -137,12 +79,13 @@ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitCont
|
|
|
137
79
|
stage_id: Type.Optional(Type.String()),
|
|
138
80
|
notes: Type.Optional(Type.String()),
|
|
139
81
|
}),
|
|
82
|
+
prepareArguments: prepareEmitStageEnvelopeArguments,
|
|
140
83
|
execute: async (_toolCallId, params) => {
|
|
141
84
|
if (capture.envelope) {
|
|
142
85
|
return toolResult("Envelope already accepted; later emits are ignored.", { advancing: isAdvancingEnvelope(capture.envelope), error: "" }, { terminate: true });
|
|
143
86
|
}
|
|
144
87
|
try {
|
|
145
|
-
const envelope = assertRequiredEnvelope(params);
|
|
88
|
+
const envelope = assertRequiredEnvelope(prepareEmitStageEnvelopeArguments(params));
|
|
146
89
|
assertFeedbackLoopAction(envelope, feedbackLoopEmitContext);
|
|
147
90
|
const isSendBack = envelope.feedback_loop?.action === "send_back";
|
|
148
91
|
if (envelope.status !== "failure" &&
|
|
@@ -150,11 +93,6 @@ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitCont
|
|
|
150
93
|
forkEmitContext !== undefined) {
|
|
151
94
|
normalizeForkChoice(envelope.fork_choice, "emit", forkEmitContext);
|
|
152
95
|
}
|
|
153
|
-
if (envelope.status !== "failure" &&
|
|
154
|
-
!isSendBack &&
|
|
155
|
-
cloneEmitContext !== undefined) {
|
|
156
|
-
assertCloneForks(envelope, cloneEmitContext);
|
|
157
|
-
}
|
|
158
96
|
assertEnvelopePayload(envelope, payloadSchema);
|
|
159
97
|
if (envelope.status !== "failure") {
|
|
160
98
|
await assertPreEmitChecks(envelope, preEmitCheckOptions);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function coerceJsonArrayField(args: Record<string, unknown>, key: string): void;
|
|
2
|
+
export declare function coerceJsonObjectField(args: Record<string, unknown>, key: string): void;
|
|
3
|
+
export declare function prepareAskOperatorArguments(input: unknown): unknown;
|
|
4
|
+
export declare function prepareEmitStageEnvelopeArguments(input: unknown): unknown;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function parseJsonArrayString(value) {
|
|
5
|
+
if (typeof value !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
if (!trimmed.startsWith("["))
|
|
9
|
+
return undefined;
|
|
10
|
+
try {
|
|
11
|
+
const parsed = JSON.parse(trimmed);
|
|
12
|
+
return Array.isArray(parsed) ? parsed : undefined;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function parseJsonObjectString(value) {
|
|
19
|
+
if (typeof value !== "string")
|
|
20
|
+
return undefined;
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
if (!trimmed.startsWith("{"))
|
|
23
|
+
return undefined;
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(trimmed);
|
|
26
|
+
return isRecord(parsed) ? parsed : undefined;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function coerceJsonArrayField(args, key) {
|
|
33
|
+
const parsed = parseJsonArrayString(args[key]);
|
|
34
|
+
if (parsed !== undefined) {
|
|
35
|
+
args[key] = parsed;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function coerceJsonObjectField(args, key) {
|
|
39
|
+
const parsed = parseJsonObjectString(args[key]);
|
|
40
|
+
if (parsed !== undefined) {
|
|
41
|
+
args[key] = parsed;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function coerceJsonObjectArrayElements(args, key) {
|
|
45
|
+
const value = args[key];
|
|
46
|
+
if (!Array.isArray(value))
|
|
47
|
+
return;
|
|
48
|
+
args[key] = value.map((item) => parseJsonObjectString(item) ?? item);
|
|
49
|
+
}
|
|
50
|
+
export function prepareAskOperatorArguments(input) {
|
|
51
|
+
if (!isRecord(input))
|
|
52
|
+
return input;
|
|
53
|
+
const args = { ...input };
|
|
54
|
+
coerceJsonArrayField(args, "questions");
|
|
55
|
+
coerceJsonObjectArrayElements(args, "questions");
|
|
56
|
+
coerceJsonArrayField(args, "artifacts");
|
|
57
|
+
return args;
|
|
58
|
+
}
|
|
59
|
+
export function prepareEmitStageEnvelopeArguments(input) {
|
|
60
|
+
if (!isRecord(input))
|
|
61
|
+
return input;
|
|
62
|
+
const args = { ...input };
|
|
63
|
+
coerceJsonObjectField(args, "payload");
|
|
64
|
+
coerceJsonObjectField(args, "feedback_loop");
|
|
65
|
+
coerceJsonArrayField(args, "artifacts");
|
|
66
|
+
coerceJsonArrayField(args, "fork_choice");
|
|
67
|
+
coerceJsonArrayField(args, "checklist_attestations");
|
|
68
|
+
coerceJsonObjectArrayElements(args, "checklist_attestations");
|
|
69
|
+
if (Array.isArray(args.checklist_attestations)) {
|
|
70
|
+
args.checklist_attestations = args.checklist_attestations.map((item) => {
|
|
71
|
+
if (!isRecord(item))
|
|
72
|
+
return item;
|
|
73
|
+
const next = { ...item };
|
|
74
|
+
coerceJsonArrayField(next, "items");
|
|
75
|
+
return next;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return args;
|
|
79
|
+
}
|
package/dist/types/envelope.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { CloneForkItem } from "./forkChoice.js";
|
|
2
1
|
export type EnvelopeStatus = "success" | "failure";
|
|
3
2
|
export type FeedbackLoopAction = {
|
|
4
3
|
action: "continue";
|
|
@@ -12,7 +11,6 @@ export type StageEnvelope = {
|
|
|
12
11
|
artifacts: string[];
|
|
13
12
|
payload?: Record<string, unknown>;
|
|
14
13
|
fork_choice?: string[];
|
|
15
|
-
clone_forks?: CloneForkItem[];
|
|
16
14
|
feedback_loop?: FeedbackLoopAction;
|
|
17
15
|
/** Agent's explicit acknowledgement of pipeline-owned checklist items. */
|
|
18
16
|
checklist_attestations?: Array<{
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { StageEnvelope } from "./envelope.js";
|
|
2
1
|
export type ForkChoiceShape = {
|
|
3
2
|
cardinality: "one" | "subset";
|
|
4
3
|
allowNone: boolean;
|
|
@@ -9,21 +8,6 @@ export type ForkEmitContext = {
|
|
|
9
8
|
};
|
|
10
9
|
export declare const CLONE_ACTIONS: readonly ["skip", "once", "fanout"];
|
|
11
10
|
export type CloneAction = (typeof CLONE_ACTIONS)[number];
|
|
12
|
-
export type CloneForkItem = {
|
|
13
|
-
successor_id: string;
|
|
14
|
-
action: "skip";
|
|
15
|
-
} | {
|
|
16
|
-
successor_id: string;
|
|
17
|
-
action: "once";
|
|
18
|
-
envelope: StageEnvelope;
|
|
19
|
-
} | {
|
|
20
|
-
successor_id: string;
|
|
21
|
-
action: "fanout";
|
|
22
|
-
mode: "parallel" | "sequential";
|
|
23
|
-
clones: Array<{
|
|
24
|
-
envelope: StageEnvelope;
|
|
25
|
-
}>;
|
|
26
|
-
};
|
|
27
11
|
export type CloneSuccessorEmit = {
|
|
28
12
|
successorId: string;
|
|
29
13
|
cloneCap: number;
|
package/dist/types/pipeline.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { CloneAction } from "./forkChoice.js";
|
|
2
1
|
import type { LoadedStageConfig, StageGateKind, StageIoYaml } from "./stage.js";
|
|
3
2
|
import type { CompletionContract, RecoveryPolicy } from "./completion.js";
|
|
4
3
|
export type PipelineConfig = {
|
|
@@ -16,15 +15,75 @@ export type PipelineForkConfig = {
|
|
|
16
15
|
allow_none: boolean;
|
|
17
16
|
};
|
|
18
17
|
export type NeedTerminalState = "succeeded" | "failed" | "skipped";
|
|
18
|
+
export type RouteIfOp = "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "not_in";
|
|
19
|
+
export type RouteIfLeafPredicate = {
|
|
20
|
+
field: string;
|
|
21
|
+
op: RouteIfOp;
|
|
22
|
+
value: unknown;
|
|
23
|
+
};
|
|
24
|
+
export type RouteIfAllPredicate = {
|
|
25
|
+
all: RouteIfPredicate[];
|
|
26
|
+
field?: never;
|
|
27
|
+
};
|
|
28
|
+
export type RouteIfAnyPredicate = {
|
|
29
|
+
any: RouteIfPredicate[];
|
|
30
|
+
field?: never;
|
|
31
|
+
};
|
|
32
|
+
export type RouteIfNotPredicate = {
|
|
33
|
+
not: RouteIfPredicate;
|
|
34
|
+
field?: never;
|
|
35
|
+
};
|
|
36
|
+
export type RouteIfPredicate = RouteIfLeafPredicate | RouteIfAllPredicate | RouteIfAnyPredicate | RouteIfNotPredicate;
|
|
19
37
|
export type PipelineNeedEdge = {
|
|
20
38
|
id: string;
|
|
21
39
|
on: NeedTerminalState[];
|
|
40
|
+
if?: RouteIfPredicate;
|
|
22
41
|
};
|
|
23
42
|
export type PipelineNeedItem = string | {
|
|
24
43
|
id: string;
|
|
25
44
|
on?: NeedTerminalState[];
|
|
26
45
|
};
|
|
27
46
|
export type PipelineNeeds = string | PipelineNeedEdge[];
|
|
47
|
+
/**
|
|
48
|
+
* Terminal states a route entry (or its inverted predecessor edge) can gate on.
|
|
49
|
+
* Same domain as `NeedTerminalState` — kept as a distinct alias since `route`
|
|
50
|
+
* is a separate vocabulary from `needs` (see docs/yaml-catalog.md).
|
|
51
|
+
*/
|
|
52
|
+
export type RouteTerminalState = NeedTerminalState;
|
|
53
|
+
/**
|
|
54
|
+
* A forward route entry: hands off from the declaring stage to `to`, gated on
|
|
55
|
+
* the declaring stage's own terminal state (`on`, defaulting to succeeded-only).
|
|
56
|
+
*/
|
|
57
|
+
export type PipelineRouteForwardEntry = {
|
|
58
|
+
to: string;
|
|
59
|
+
on?: RouteTerminalState | RouteTerminalState[];
|
|
60
|
+
if?: RouteIfPredicate;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* A loop route entry (ticket 03, route-based-pipeline-wiring spec): sends
|
|
64
|
+
* execution back to a declared ancestor of the source stage instead of
|
|
65
|
+
* continuing forward, carrying the same replay policy `FeedbackLoopConfig`
|
|
66
|
+
* carries today — `target` renamed to `to` for naming consistency with
|
|
67
|
+
* forward entries. Contributes no forward DAG edge (`toRouteEdges` skips
|
|
68
|
+
* it), so it is excluded from cycle detection; it is a runtime-only replay
|
|
69
|
+
* schedule over the already-resolved forward graph.
|
|
70
|
+
*/
|
|
71
|
+
export type PipelineRouteLoopEntry = {
|
|
72
|
+
type: "loop";
|
|
73
|
+
to: string;
|
|
74
|
+
max_replays: number;
|
|
75
|
+
on_max_replays: "require_continue" | "wait_for_human";
|
|
76
|
+
replay_session: "resume" | "new_session";
|
|
77
|
+
};
|
|
78
|
+
export type PipelineRouteEntry = PipelineRouteForwardEntry | PipelineRouteLoopEntry;
|
|
79
|
+
/** A stage's outbound `route` field: where execution goes next. */
|
|
80
|
+
export type PipelineRoute = PipelineRouteEntry[];
|
|
81
|
+
/** Normalized forward route edge (post-parse): `on` is always populated. */
|
|
82
|
+
export type PipelineRouteEdge = {
|
|
83
|
+
to: string;
|
|
84
|
+
on: RouteTerminalState[];
|
|
85
|
+
if?: RouteIfPredicate;
|
|
86
|
+
};
|
|
28
87
|
/** Runtime feedback-loop policy declared by the stage that can send work back. */
|
|
29
88
|
export type FeedbackLoopConfig = {
|
|
30
89
|
target: string;
|
|
@@ -32,43 +91,44 @@ export type FeedbackLoopConfig = {
|
|
|
32
91
|
on_max_replays: "require_continue" | "wait_for_human";
|
|
33
92
|
replay_session: "resume" | "new_session";
|
|
34
93
|
};
|
|
94
|
+
export type CloneMode = "parallel" | "sequential";
|
|
35
95
|
export type PipelineStageRef = {
|
|
36
96
|
id: string;
|
|
37
|
-
needs?: string | PipelineNeedItem[];
|
|
38
|
-
fork?: {
|
|
39
|
-
select: "one" | "subset";
|
|
40
|
-
allow_none?: boolean;
|
|
41
|
-
};
|
|
42
|
-
clonable?: boolean;
|
|
43
|
-
clone_cap?: number;
|
|
44
97
|
/** IR: after-phase checks. YAML: `verify` items whose `when` includes `after`. */
|
|
45
98
|
completion?: CompletionContract;
|
|
46
99
|
/** IR: after-phase failure policy. YAML: `on_verify_fail`. */
|
|
47
100
|
recovery?: RecoveryPolicy;
|
|
48
|
-
feedback_loop?: FeedbackLoopConfig;
|
|
49
101
|
/** Omitted means this stage is safe to include in a feedback replay. */
|
|
50
102
|
replay_safe?: boolean;
|
|
103
|
+
/** Pipeline wiring vocabulary (see docs/yaml-catalog.md). */
|
|
104
|
+
route?: PipelineRouteEntry[];
|
|
105
|
+
/** Marks this stage as a pipeline entry point. */
|
|
106
|
+
entry?: boolean;
|
|
107
|
+
clone_cap?: number;
|
|
108
|
+
clone_mode?: CloneMode;
|
|
51
109
|
};
|
|
52
110
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* New catalog fields: add target YAML keys here and compile them in yamlDialect.ts.
|
|
111
|
+
* Catalog YAML stage entry (`io` / `verify` / `on_verify_fail`). Not IR.
|
|
112
|
+
* Dual-read of `payload_schema` / `pre_emit_checks` / `completion` / `recovery`
|
|
113
|
+
* stays in `legacyYaml.ts` on the raw record.
|
|
57
114
|
*/
|
|
58
|
-
export type PipelineStageYamlEntry =
|
|
115
|
+
export type PipelineStageYamlEntry = {
|
|
116
|
+
id?: string;
|
|
59
117
|
uses?: string;
|
|
60
118
|
system_prompt?: string;
|
|
61
119
|
model?: string;
|
|
62
|
-
payload_schema?: unknown;
|
|
63
120
|
gate_kinds?: StageGateKind[];
|
|
64
|
-
|
|
65
|
-
clone_actions?: CloneAction[];
|
|
121
|
+
timeout_ms?: number;
|
|
66
122
|
skill?: string;
|
|
67
123
|
mcp?: string[];
|
|
124
|
+
replay_safe?: boolean;
|
|
125
|
+
route?: PipelineRouteEntry[];
|
|
126
|
+
entry?: boolean;
|
|
127
|
+
clone_cap?: number;
|
|
128
|
+
clone_mode?: CloneMode;
|
|
68
129
|
io?: StageIoYaml;
|
|
69
130
|
verify?: unknown;
|
|
70
131
|
on_verify_fail?: RecoveryPolicy;
|
|
71
|
-
pre_emit_checks?: unknown;
|
|
72
132
|
};
|
|
73
133
|
export type PipelineIncludeEntry = {
|
|
74
134
|
local: string;
|
|
@@ -79,20 +139,16 @@ export type PipelineFragmentConfig = {
|
|
|
79
139
|
};
|
|
80
140
|
export type NormalizedPipelineStageEntry = {
|
|
81
141
|
id: string;
|
|
82
|
-
needs?: PipelineNeeds;
|
|
83
|
-
fork?: {
|
|
84
|
-
select: "one" | "subset";
|
|
85
|
-
allow_none?: boolean;
|
|
86
|
-
};
|
|
87
|
-
clonable?: boolean;
|
|
88
|
-
clone_cap?: number;
|
|
89
142
|
/** IR after compile. YAML `verify` after-phase / `on_verify_fail`. */
|
|
90
143
|
completion?: CompletionContract;
|
|
91
144
|
recovery?: RecoveryPolicy;
|
|
92
|
-
feedback_loop?: FeedbackLoopConfig;
|
|
93
145
|
replay_safe?: boolean;
|
|
146
|
+
route?: PipelineRouteEntry[];
|
|
147
|
+
entry?: boolean;
|
|
94
148
|
skill?: string;
|
|
95
149
|
mcp?: string[];
|
|
150
|
+
clone_cap?: number;
|
|
151
|
+
clone_mode?: CloneMode;
|
|
96
152
|
body: {
|
|
97
153
|
kind: "inline";
|
|
98
154
|
raw: Record<string, unknown>;
|
|
@@ -116,8 +172,9 @@ export type ResolvedPipelineStageNode = {
|
|
|
116
172
|
ancestors: string[];
|
|
117
173
|
stageIndex: number;
|
|
118
174
|
fork?: PipelineForkConfig;
|
|
119
|
-
clonable?: boolean;
|
|
120
175
|
clone_cap?: number;
|
|
176
|
+
clone_mode?: CloneMode;
|
|
177
|
+
clone_array_field?: string;
|
|
121
178
|
definition_id?: string;
|
|
122
179
|
/** Persisted on pipeline_dag. YAML `verify` after-phase. */
|
|
123
180
|
completion?: CompletionContract;
|
|
@@ -125,6 +182,8 @@ export type ResolvedPipelineStageNode = {
|
|
|
125
182
|
recovery?: RecoveryPolicy;
|
|
126
183
|
feedback_loop?: FeedbackLoopConfig;
|
|
127
184
|
replay_safe?: boolean;
|
|
185
|
+
/** Present (true) only when this stage was declared `entry: true`. */
|
|
186
|
+
entry?: boolean;
|
|
128
187
|
};
|
|
129
188
|
export type ResolvedPipelineDag = {
|
|
130
189
|
nodes: ResolvedPipelineStageNode[];
|
package/dist/types/stage.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { PreEmitCheck } from "./preEmitCheck.js";
|
|
2
|
-
|
|
2
|
+
/** Typed emit/schema fields from `compileTargetContract`. Not catalog YAML keys. */
|
|
3
|
+
export type CompiledStageEmitBody = {
|
|
4
|
+
payload_schema?: unknown;
|
|
5
|
+
clone_input_schema?: unknown;
|
|
6
|
+
pre_emit_checks?: PreEmitCheck[];
|
|
7
|
+
};
|
|
3
8
|
export declare const STAGE_GATE_KINDS: readonly ["free_text", "confirm", "multi_question", "artifact_backed"];
|
|
4
9
|
export type StageGateKind = (typeof STAGE_GATE_KINDS)[number];
|
|
5
10
|
/** Target YAML `io:` block. Compiles onto StageConfig.payload_schema / clone_input_schema. */
|
|
6
11
|
export type StageIoYaml = {
|
|
7
|
-
input
|
|
8
|
-
schema
|
|
12
|
+
input: {
|
|
13
|
+
schema: unknown;
|
|
9
14
|
};
|
|
10
|
-
output
|
|
11
|
-
schema
|
|
15
|
+
output: {
|
|
16
|
+
schema: unknown;
|
|
12
17
|
};
|
|
13
18
|
};
|
|
14
19
|
/**
|
|
@@ -27,9 +32,8 @@ export type StageConfig = {
|
|
|
27
32
|
gate_kinds?: StageGateKind[];
|
|
28
33
|
/** IR: emit-phase checks. YAML: `verify` items whose `when` includes `emit`. */
|
|
29
34
|
pre_emit_checks?: PreEmitCheck[];
|
|
30
|
-
/** IR:
|
|
35
|
+
/** IR: inbound assignment schema. YAML: `io.input.schema`. */
|
|
31
36
|
clone_input_schema?: unknown;
|
|
32
|
-
clone_actions?: CloneAction[];
|
|
33
37
|
/** Optional stage wall-clock timeout in milliseconds (default 60 minutes). */
|
|
34
38
|
timeout_ms?: number;
|
|
35
39
|
skill?: string;
|