stageflow 0.9.0 → 0.12.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.
Files changed (151) hide show
  1. package/README.md +1 -0
  2. package/dist/agent/activity.d.ts +9 -0
  3. package/dist/agent/agentBackend.d.ts +32 -0
  4. package/dist/agent/agentBackend.js +38 -0
  5. package/dist/agent/claudeActivity.d.ts +15 -0
  6. package/dist/agent/claudeActivity.js +58 -0
  7. package/dist/agent/claudeAdapter.d.ts +5 -0
  8. package/dist/agent/claudeAdapter.js +301 -0
  9. package/dist/agent/claudeSession.d.ts +18 -0
  10. package/dist/agent/claudeSession.js +54 -0
  11. package/dist/agent/claudeTools.d.ts +89 -0
  12. package/dist/agent/claudeTools.js +135 -0
  13. package/dist/agent/fakeAgent.js +24 -4
  14. package/dist/agent/piAdapter.d.ts +6 -3
  15. package/dist/agent/piAdapter.js +129 -21
  16. package/dist/agent/port.d.ts +50 -1
  17. package/dist/agent/resolveAgentPort.d.ts +26 -0
  18. package/dist/agent/resolveAgentPort.js +39 -0
  19. package/dist/cli/runCommand.js +2 -2
  20. package/dist/cli/runsCommand.d.ts +1 -1
  21. package/dist/cli/runsCommand.js +184 -2
  22. package/dist/cli.d.ts +1 -1
  23. package/dist/cli.js +11 -5
  24. package/dist/config/browseCatalog.js +1 -1
  25. package/dist/config/createPipeline.d.ts +2 -1
  26. package/dist/config/createPipeline.js +34 -9
  27. package/dist/config/createStage.js +14 -9
  28. package/dist/config/loadPipeline.js +10 -1
  29. package/dist/config/loadStage.js +138 -2
  30. package/dist/config/loadStageflowManifest.js +14 -1
  31. package/dist/config/mergePipelineIncludes.d.ts +1 -0
  32. package/dist/config/mergePipelineIncludes.js +14 -1
  33. package/dist/config/normalizePipelineStageEntry.d.ts +7 -2
  34. package/dist/config/normalizePipelineStageEntry.js +49 -6
  35. package/dist/config/parseCompletionContract.d.ts +8 -0
  36. package/dist/config/parseCompletionContract.js +218 -0
  37. package/dist/config/parsePreEmitChecks.d.ts +3 -0
  38. package/dist/config/parsePreEmitChecks.js +65 -0
  39. package/dist/config/pipelineNeeds.d.ts +19 -0
  40. package/dist/config/pipelineNeeds.js +151 -0
  41. package/dist/config/pipelineStageKeys.js +16 -1
  42. package/dist/config/resolveForkEmitContext.d.ts +6 -2
  43. package/dist/config/resolveForkEmitContext.js +9 -2
  44. package/dist/config/resolvePipelineDag.d.ts +2 -1
  45. package/dist/config/resolvePipelineDag.js +182 -39
  46. package/dist/config/validateCatalog.d.ts +1 -1
  47. package/dist/config/validateCompletionContract.d.ts +4 -0
  48. package/dist/config/validateCompletionContract.js +52 -0
  49. package/dist/envelope/check.d.ts +1 -1
  50. package/dist/envelope/check.js +86 -13
  51. package/dist/envelope/cloneForks.d.ts +1 -1
  52. package/dist/envelope/cloneForks.js +24 -9
  53. package/dist/envelope/feedbackLoop.d.ts +4 -0
  54. package/dist/envelope/feedbackLoop.js +31 -0
  55. package/dist/envelope/payloadSchema.d.ts +7 -1
  56. package/dist/envelope/payloadSchema.js +170 -13
  57. package/dist/envelope/preEmitChecks.d.ts +29 -0
  58. package/dist/envelope/preEmitChecks.js +57 -0
  59. package/dist/hitl/qaTrail.d.ts +25 -0
  60. package/dist/hitl/qaTrail.js +51 -0
  61. package/dist/mcp/catalogTools.js +4 -2
  62. package/dist/mcp/controlTools.js +72 -0
  63. package/dist/mcp/waitingGates.d.ts +2 -1
  64. package/dist/mcp/waitingGates.js +17 -1
  65. package/dist/package-meta.d.ts +1 -1
  66. package/dist/package-meta.js +1 -1
  67. package/dist/projection/projectRun.d.ts +4 -1
  68. package/dist/projection/projectRun.js +7 -0
  69. package/dist/prompt/feedbackLoopContext.d.ts +2 -0
  70. package/dist/prompt/feedbackLoopContext.js +17 -0
  71. package/dist/prompt/priorEnvelope.d.ts +2 -2
  72. package/dist/prompt/priorEnvelope.js +4 -1
  73. package/dist/runstore/pipelineDagSnapshot.d.ts +1 -0
  74. package/dist/runstore/pipelineDagSnapshot.js +51 -11
  75. package/dist/runstore/port.d.ts +185 -3
  76. package/dist/runstore/port.js +42 -3
  77. package/dist/runstore/runProjection.d.ts +7 -3
  78. package/dist/runstore/runProjection.js +30 -15
  79. package/dist/runstore/sqlite/SqliteRunStore.d.ts +25 -1
  80. package/dist/runstore/sqlite/SqliteRunStore.js +626 -8
  81. package/dist/runstore/sqlite/schema.d.ts +1 -1
  82. package/dist/runstore/sqlite/schema.js +99 -0
  83. package/dist/runstore/stageInstanceId.d.ts +1 -1
  84. package/dist/runstore/stageInstanceId.js +3 -2
  85. package/dist/runstore/trackProjection.js +59 -27
  86. package/dist/runstore/verificationHistory.d.ts +19 -0
  87. package/dist/runstore/verificationHistory.js +30 -0
  88. package/dist/runtime/cloneSchedule.d.ts +40 -4
  89. package/dist/runtime/cloneSchedule.js +212 -28
  90. package/dist/runtime/completionCheckRunner.d.ts +137 -0
  91. package/dist/runtime/completionCheckRunner.js +365 -0
  92. package/dist/runtime/completionCheckoutBaseline.d.ts +3 -0
  93. package/dist/runtime/completionCheckoutBaseline.js +44 -0
  94. package/dist/runtime/envelopeRouting.d.ts +10 -3
  95. package/dist/runtime/envelopeRouting.js +146 -5
  96. package/dist/runtime/feedbackLoopCoordinator.d.ts +74 -0
  97. package/dist/runtime/feedbackLoopCoordinator.js +446 -0
  98. package/dist/runtime/feedbackLoopDecision.d.ts +44 -0
  99. package/dist/runtime/feedbackLoopDecision.js +207 -0
  100. package/dist/runtime/feedbackLoopRoute.d.ts +5 -0
  101. package/dist/runtime/feedbackLoopRoute.js +13 -0
  102. package/dist/runtime/feedbackLoopSchedule.d.ts +38 -0
  103. package/dist/runtime/feedbackLoopSchedule.js +72 -0
  104. package/dist/runtime/forkGeneration.d.ts +72 -0
  105. package/dist/runtime/forkGeneration.js +295 -0
  106. package/dist/runtime/gitCheckoutCapability.d.ts +7 -0
  107. package/dist/runtime/gitCheckoutCapability.js +97 -0
  108. package/dist/runtime/manualRecoveryState.d.ts +40 -0
  109. package/dist/runtime/manualRecoveryState.js +73 -0
  110. package/dist/runtime/pipelineScheduler.d.ts +13 -1
  111. package/dist/runtime/pipelineScheduler.js +328 -45
  112. package/dist/runtime/replayLifecycle.d.ts +107 -0
  113. package/dist/runtime/replayLifecycle.js +168 -0
  114. package/dist/runtime/runManager.d.ts +54 -1
  115. package/dist/runtime/runManager.js +471 -6
  116. package/dist/runtime/runRetryCoordinator.d.ts +6 -1
  117. package/dist/runtime/runRetryCoordinator.js +43 -9
  118. package/dist/runtime/stageAttemptBootstrap.d.ts +3 -1
  119. package/dist/runtime/stageAttemptBootstrap.js +79 -1
  120. package/dist/runtime/stageProcessLauncher.d.ts +1 -1
  121. package/dist/runtime/stageRecovery.js +1 -1
  122. package/dist/runtime/stageRunner.d.ts +4 -1
  123. package/dist/runtime/stageRunner.js +29 -3
  124. package/dist/runtime/stageWorker.js +69 -2
  125. package/dist/runtime/stageWorkerProtocol.d.ts +1 -1
  126. package/dist/runtime/verifiedStageExecution.d.ts +29 -0
  127. package/dist/runtime/verifiedStageExecution.js +119 -0
  128. package/dist/server/bootstrap.js +1 -0
  129. package/dist/server/http.js +114 -0
  130. package/dist/server/operatorResults.js +2 -0
  131. package/dist/tools/askOperator.d.ts +161 -5
  132. package/dist/tools/askOperator.js +58 -25
  133. package/dist/tools/emitStageEnvelope.d.ts +12 -12
  134. package/dist/tools/emitStageEnvelope.js +112 -24
  135. package/dist/types/completion.d.ts +43 -0
  136. package/dist/types/completion.js +1 -0
  137. package/dist/types/envelope.d.ts +18 -0
  138. package/dist/types/forkChoice.d.ts +9 -4
  139. package/dist/types/forkChoice.js +1 -1
  140. package/dist/types/pipeline.d.ts +39 -2
  141. package/dist/types/preEmitCheck.d.ts +18 -0
  142. package/dist/types/preEmitCheck.js +1 -0
  143. package/dist/types/stage.d.ts +13 -0
  144. package/dist/types/stageflowManifest.d.ts +2 -0
  145. package/dist/ui/assets/index-CXGz4nL7.js +118 -0
  146. package/dist/ui/assets/{index-C3N7MXAC.css → index-uVHiae8s.css} +1 -1
  147. package/dist/ui/index.html +2 -2
  148. package/package.json +2 -1
  149. package/skills/stageflow-author/references/catalog-mapping.md +26 -2
  150. package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
  151. package/dist/ui/assets/index-CSoGDA3A.js +0 -118
@@ -11,9 +11,87 @@
11
11
  */
12
12
  import { Type } from "typebox";
13
13
  import { assertRequiredEnvelope, isAdvancingEnvelope, } from "../envelope/check.js";
14
+ import { assertFeedbackLoopAction } from "../envelope/feedbackLoop.js";
14
15
  import { assertCloneForks } from "../envelope/cloneForks.js";
15
16
  import { normalizeForkChoice } from "../envelope/forkChoice.js";
16
17
  import { assertEnvelopePayload, compilePayloadSchema, } from "../envelope/payloadSchema.js";
18
+ import { assertPreEmitChecks, } from "../envelope/preEmitChecks.js";
19
+ import { CLONE_ACTIONS, } from "../types/forkChoice.js";
20
+ function stringLiteralsSchema(values) {
21
+ if (values.length === 1) {
22
+ return Type.Literal(values[0]);
23
+ }
24
+ return Type.Union(values.map((value) => Type.Literal(value)));
25
+ }
26
+ function stageEnvelopeSchema(payloadSchema) {
27
+ return Type.Object({
28
+ status: Type.Union([Type.Literal("success"), Type.Literal("failure")]),
29
+ summary: Type.String({ minLength: 1 }),
30
+ artifacts: Type.Array(Type.String()),
31
+ payload: Type.Optional(payloadSchema !== undefined
32
+ ? payloadSchema
33
+ : Type.Record(Type.String(), Type.Unknown())),
34
+ });
35
+ }
36
+ function feedbackLoopActionSchema(context) {
37
+ return Type.Union([
38
+ Type.Object({ action: Type.Literal("continue") }, { additionalProperties: false }),
39
+ Type.Object({
40
+ action: Type.Literal("send_back"),
41
+ target: stringLiteralsSchema([context.target]),
42
+ }, { additionalProperties: false }),
43
+ ]);
44
+ }
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
+ }
17
95
  function toolResult(text, details, options) {
18
96
  return {
19
97
  content: [{ type: "text", text }],
@@ -22,23 +100,10 @@ function toolResult(text, details, options) {
22
100
  ...(options?.terminate ? { terminate: true } : {}),
23
101
  };
24
102
  }
25
- export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitContext, cloneEmitContext) {
103
+ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitContext, cloneEmitContext, preEmitCheckOptions, feedbackLoopEmitContext) {
26
104
  const compiledPayload = payloadSchema !== undefined
27
105
  ? compilePayloadSchema(payloadSchema)
28
106
  : undefined;
29
- const cloneForksSchema = Type.Array(Type.Object({
30
- successor_id: Type.String(),
31
- action: Type.Union([
32
- Type.Literal("skip"),
33
- Type.Literal("once"),
34
- Type.Literal("fanout"),
35
- ]),
36
- envelope: Type.Optional(Type.Unknown()),
37
- mode: Type.Optional(Type.Union([Type.Literal("parallel"), Type.Literal("sequential")])),
38
- clones: Type.Optional(Type.Array(Type.Object({
39
- envelope: Type.Unknown(),
40
- }))),
41
- }));
42
107
  return {
43
108
  name: "emit_stage_envelope",
44
109
  label: "Emit stage envelope",
@@ -47,13 +112,28 @@ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitCont
47
112
  status: Type.Union([Type.Literal("success"), Type.Literal("failure")]),
48
113
  summary: Type.String({ minLength: 1 }),
49
114
  artifacts: Type.Array(Type.String()),
50
- payload: compiledPayload !== undefined
115
+ payload: Type.Optional(compiledPayload !== undefined
51
116
  ? compiledPayload
52
- : Type.Optional(Type.Record(Type.String(), Type.Unknown())),
53
- fork_choice: forkEmitContext !== undefined
117
+ : Type.Record(Type.String(), Type.Unknown())),
118
+ fork_choice: forkEmitContext !== undefined && feedbackLoopEmitContext === undefined
54
119
  ? Type.Array(Type.String())
55
120
  : Type.Optional(Type.Array(Type.String())),
56
- ...(cloneEmitContext !== undefined ? { clone_forks: cloneForksSchema } : {}),
121
+ ...(cloneEmitContext !== undefined
122
+ ? {
123
+ clone_forks: feedbackLoopEmitContext === undefined
124
+ ? Type.Array(cloneForksItemSchema(cloneEmitContext))
125
+ : Type.Optional(Type.Array(cloneForksItemSchema(cloneEmitContext))),
126
+ }
127
+ : {}),
128
+ ...(feedbackLoopEmitContext !== undefined
129
+ ? {
130
+ feedback_loop: Type.Optional(feedbackLoopActionSchema(feedbackLoopEmitContext)),
131
+ }
132
+ : {}),
133
+ checklist_attestations: Type.Optional(Type.Array(Type.Object({
134
+ check_id: Type.String({ minLength: 1 }),
135
+ items: Type.Array(Type.String()),
136
+ }))),
57
137
  stage_id: Type.Optional(Type.String()),
58
138
  notes: Type.Optional(Type.String()),
59
139
  }),
@@ -62,15 +142,23 @@ export function createEmitStageEnvelopeTool(capture, payloadSchema, forkEmitCont
62
142
  return toolResult("Envelope already accepted; later emits are ignored.", { advancing: isAdvancingEnvelope(capture.envelope), error: "" }, { terminate: true });
63
143
  }
64
144
  try {
65
- const record = params;
66
- if (record.status !== "failure" && forkEmitContext !== undefined) {
67
- normalizeForkChoice(record.fork_choice, "emit", forkEmitContext);
145
+ const envelope = assertRequiredEnvelope(params);
146
+ assertFeedbackLoopAction(envelope, feedbackLoopEmitContext);
147
+ const isSendBack = envelope.feedback_loop?.action === "send_back";
148
+ if (envelope.status !== "failure" &&
149
+ !isSendBack &&
150
+ forkEmitContext !== undefined) {
151
+ normalizeForkChoice(envelope.fork_choice, "emit", forkEmitContext);
68
152
  }
69
- if (record.status !== "failure" && cloneEmitContext !== undefined) {
70
- assertCloneForks(params, cloneEmitContext);
153
+ if (envelope.status !== "failure" &&
154
+ !isSendBack &&
155
+ cloneEmitContext !== undefined) {
156
+ assertCloneForks(envelope, cloneEmitContext);
71
157
  }
72
- const envelope = assertRequiredEnvelope(params);
73
158
  assertEnvelopePayload(envelope, payloadSchema);
159
+ if (envelope.status !== "failure") {
160
+ await assertPreEmitChecks(envelope, preEmitCheckOptions);
161
+ }
74
162
  capture.envelope = envelope;
75
163
  const advancing = isAdvancingEnvelope(envelope);
76
164
  return toolResult(advancing
@@ -0,0 +1,43 @@
1
+ import type { StageGateKind } from "./stage.js";
2
+ export declare const COMPLETION_VERIFICATION_FAILURE_PREFIX = "Completion verification failed:";
3
+ export type CompletionCheck = {
4
+ id: string;
5
+ type: "command";
6
+ run: string;
7
+ cwd?: string;
8
+ timeout_ms?: number;
9
+ } | {
10
+ id: string;
11
+ type: "artifact";
12
+ path: string;
13
+ nonempty?: boolean;
14
+ } | {
15
+ id: string;
16
+ type: "checklist";
17
+ items: string[];
18
+ } | {
19
+ id: string;
20
+ type: "payload_schema";
21
+ } | {
22
+ id: string;
23
+ type: "gate";
24
+ kind: StageGateKind;
25
+ } | {
26
+ id: string;
27
+ type: "checkout_changes";
28
+ path_fields?: string[];
29
+ };
30
+ export type CompletionContract = {
31
+ mode: "all";
32
+ checks: CompletionCheck[];
33
+ };
34
+ export type RecoveryPolicy = {
35
+ mode: "repair";
36
+ max_attempts: number;
37
+ retry_safety: "idempotent";
38
+ include_failed_checks: boolean;
39
+ } | {
40
+ mode: "manual";
41
+ retry_safety: "idempotent" | "side_effecting";
42
+ include_failed_checks?: boolean;
43
+ };
@@ -0,0 +1 @@
1
+ export const COMPLETION_VERIFICATION_FAILURE_PREFIX = "Completion verification failed:";
@@ -1,5 +1,11 @@
1
1
  import type { CloneForkItem } from "./forkChoice.js";
2
2
  export type EnvelopeStatus = "success" | "failure";
3
+ export type FeedbackLoopAction = {
4
+ action: "continue";
5
+ } | {
6
+ action: "send_back";
7
+ target: string;
8
+ };
3
9
  export type StageEnvelope = {
4
10
  status: EnvelopeStatus;
5
11
  summary: string;
@@ -7,9 +13,21 @@ export type StageEnvelope = {
7
13
  payload?: Record<string, unknown>;
8
14
  fork_choice?: string[];
9
15
  clone_forks?: CloneForkItem[];
16
+ feedback_loop?: FeedbackLoopAction;
17
+ /** Agent's explicit acknowledgement of pipeline-owned checklist items. */
18
+ checklist_attestations?: Array<{
19
+ check_id: string;
20
+ items: string[];
21
+ }>;
10
22
  stage_id?: string;
11
23
  notes?: string;
12
24
  };
25
+ export type SyntheticSkippedEnvelope = {
26
+ status: "skipped";
27
+ summary: string;
28
+ artifacts: string[];
29
+ };
30
+ export type TerminalEnvelope = StageEnvelope | SyntheticSkippedEnvelope;
13
31
  export declare class EnvelopeError extends Error {
14
32
  constructor(message: string);
15
33
  }
@@ -7,6 +7,8 @@ export type ForkEmitContext = {
7
7
  immediateSuccessorIds: string[];
8
8
  forkShape: ForkChoiceShape | null;
9
9
  };
10
+ export declare const CLONE_ACTIONS: readonly ["skip", "once", "fanout"];
11
+ export type CloneAction = (typeof CLONE_ACTIONS)[number];
10
12
  export type CloneForkItem = {
11
13
  successor_id: string;
12
14
  action: "skip";
@@ -22,9 +24,12 @@ export type CloneForkItem = {
22
24
  envelope: StageEnvelope;
23
25
  }>;
24
26
  };
27
+ export type CloneSuccessorEmit = {
28
+ successorId: string;
29
+ cloneCap: number;
30
+ cloneInputSchema?: unknown;
31
+ };
25
32
  export type CloneEmitContext = {
26
- clonableSuccessors: Array<{
27
- successorId: string;
28
- cloneCap: number;
29
- }>;
33
+ clonableSuccessors: CloneSuccessorEmit[];
34
+ allowedActions?: CloneAction[];
30
35
  };
@@ -1 +1 @@
1
- export {};
1
+ export const CLONE_ACTIONS = ["skip", "once", "fanout"];
@@ -1,21 +1,47 @@
1
+ import type { CloneAction } from "./forkChoice.js";
1
2
  import type { StageConfig, StageGateKind } from "./stage.js";
3
+ import type { CompletionContract, RecoveryPolicy } from "./completion.js";
2
4
  export type PipelineConfig = {
3
5
  id: string;
4
6
  stages: string[];
7
+ /** Selects the AgentPort backend for every stage in this pipeline; overrides the global default. */
8
+ agent?: string;
5
9
  };
6
10
  export type PipelineForkConfig = {
7
11
  select: "one" | "subset";
8
12
  allow_none: boolean;
9
13
  };
14
+ export type NeedTerminalState = "succeeded" | "failed" | "skipped";
15
+ export type PipelineNeedEdge = {
16
+ id: string;
17
+ on: NeedTerminalState[];
18
+ };
19
+ export type PipelineNeedItem = string | {
20
+ id: string;
21
+ on?: NeedTerminalState[];
22
+ };
23
+ export type PipelineNeeds = string | PipelineNeedEdge[];
24
+ /** Runtime feedback-loop policy declared by the stage that can send work back. */
25
+ export type FeedbackLoopConfig = {
26
+ target: string;
27
+ max_replays: number;
28
+ on_max_replays: "require_continue" | "wait_for_human";
29
+ replay_session: "resume" | "new_session";
30
+ };
10
31
  export type PipelineStageRef = {
11
32
  id: string;
12
- needs?: string;
33
+ needs?: string | PipelineNeedItem[];
13
34
  fork?: {
14
35
  select: "one" | "subset";
15
36
  allow_none?: boolean;
16
37
  };
17
38
  clonable?: boolean;
18
39
  clone_cap?: number;
40
+ completion?: CompletionContract;
41
+ recovery?: RecoveryPolicy;
42
+ feedback_loop?: FeedbackLoopConfig;
43
+ /** Omitted means this stage is safe to include in a feedback replay. */
44
+ replay_safe?: boolean;
19
45
  };
20
46
  export type PipelineStageYamlEntry = PipelineStageRef & {
21
47
  uses?: string;
@@ -23,6 +49,8 @@ export type PipelineStageYamlEntry = PipelineStageRef & {
23
49
  model?: string;
24
50
  payload_schema?: unknown;
25
51
  gate_kinds?: StageGateKind[];
52
+ clone_input_schema?: unknown;
53
+ clone_actions?: CloneAction[];
26
54
  skill?: string;
27
55
  };
28
56
  export type PipelineIncludeEntry = {
@@ -34,13 +62,17 @@ export type PipelineFragmentConfig = {
34
62
  };
35
63
  export type NormalizedPipelineStageEntry = {
36
64
  id: string;
37
- needs?: string;
65
+ needs?: PipelineNeeds;
38
66
  fork?: {
39
67
  select: "one" | "subset";
40
68
  allow_none?: boolean;
41
69
  };
42
70
  clonable?: boolean;
43
71
  clone_cap?: number;
72
+ completion?: CompletionContract;
73
+ recovery?: RecoveryPolicy;
74
+ feedback_loop?: FeedbackLoopConfig;
75
+ replay_safe?: boolean;
44
76
  skill?: string;
45
77
  body: {
46
78
  kind: "inline";
@@ -61,12 +93,17 @@ export type PipelineStageSource = {
61
93
  export type ResolvedPipelineStageNode = {
62
94
  id: string;
63
95
  needs: string | null;
96
+ needsEdges: PipelineNeedEdge[];
64
97
  ancestors: string[];
65
98
  stageIndex: number;
66
99
  fork?: PipelineForkConfig;
67
100
  clonable?: boolean;
68
101
  clone_cap?: number;
69
102
  definition_id?: string;
103
+ completion?: CompletionContract;
104
+ recovery?: RecoveryPolicy;
105
+ feedback_loop?: FeedbackLoopConfig;
106
+ replay_safe?: boolean;
70
107
  };
71
108
  export type ResolvedPipelineDag = {
72
109
  nodes: ResolvedPipelineStageNode[];
@@ -0,0 +1,18 @@
1
+ import type { StageGateKind } from "./stage.js";
2
+ /**
3
+ * In-session checks `emit_stage_envelope` must satisfy this attempt before a
4
+ * success emit is accepted. Distinct from `CompletionCheck`/`CompletionContract`
5
+ * (`src/types/completion.ts`): those run post-hoc, after a candidate envelope
6
+ * has already been captured, driven by the pipeline-wiring `completion` field.
7
+ * `PreEmitCheck` runs synchronously inside the agent's own `emit_stage_envelope`
8
+ * tool call, driven by the stage-body `pre_emit_checks` field.
9
+ */
10
+ export type PreEmitCheck = {
11
+ id: string;
12
+ type: "gate";
13
+ kind: StageGateKind;
14
+ } | {
15
+ id: string;
16
+ type: "artifact_declared";
17
+ basename: string;
18
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,5 @@
1
+ import type { PreEmitCheck } from "./preEmitCheck.js";
2
+ import type { CloneAction } from "./forkChoice.js";
1
3
  export declare const STAGE_GATE_KINDS: readonly ["free_text", "confirm", "multi_question", "artifact_backed"];
2
4
  export type StageGateKind = (typeof STAGE_GATE_KINDS)[number];
3
5
  export type StageConfig = {
@@ -8,5 +10,16 @@ export type StageConfig = {
8
10
  payload_schema?: unknown;
9
11
  /** Declared ask_operator kinds this stage is expected to stop on. */
10
12
  gate_kinds?: StageGateKind[];
13
+ /** In-session checks emit must satisfy this attempt before success is accepted. */
14
+ pre_emit_checks?: PreEmitCheck[];
15
+ clone_input_schema?: unknown;
16
+ clone_actions?: CloneAction[];
17
+ /** Optional stage wall-clock timeout in milliseconds (default 15 minutes). */
18
+ timeout_ms?: number;
11
19
  skill?: string;
20
+ /**
21
+ * Selects the AgentPort backend for this stage, overriding pipeline/global.
22
+ * Parsed but not yet consulted — see STAGE_LEVEL_AGENT_OVERRIDE_ENABLED.
23
+ */
24
+ agent?: string;
12
25
  };
@@ -11,6 +11,8 @@ export type StageflowManifestCatalog = {
11
11
  export type StageflowManifest = {
12
12
  version: StageflowManifestVersion;
13
13
  catalog: StageflowManifestCatalog;
14
+ /** Default AgentPort backend for every pipeline/stage that doesn't override it. */
15
+ agent?: string;
14
16
  };
15
17
  export type LoadedManifest = {
16
18
  path: string;