@oisincoveney/pipeline 2.1.1 → 2.3.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 (64) hide show
  1. package/.agents/skills/orchestrate/SKILL.md +80 -0
  2. package/defaults/pipeline.yaml +111 -0
  3. package/defaults/profiles.yaml +215 -0
  4. package/defaults/runners.yaml +24 -0
  5. package/dist/argo-graph.js +59 -27
  6. package/dist/argo-submit.d.ts +0 -1
  7. package/dist/argo-submit.js +11 -6
  8. package/dist/argo-workflow.d.ts +1 -2
  9. package/dist/argo-workflow.js +0 -2
  10. package/dist/claude-settings-config.js +44 -0
  11. package/dist/cli/program.js +12 -5
  12. package/dist/cli/submit-options.js +1 -2
  13. package/dist/cluster-doctor.js +0 -12
  14. package/dist/commands/pipeline-command.js +1 -1
  15. package/dist/config/defaults.js +7 -350
  16. package/dist/config/schemas.d.ts +9 -9
  17. package/dist/install-commands/claude-code.js +160 -0
  18. package/dist/install-commands/opencode.js +56 -39
  19. package/dist/install-commands/shared.js +32 -5
  20. package/dist/install-commands.js +26 -15
  21. package/dist/json-config-merge.js +47 -0
  22. package/dist/mcp/gateway.js +9 -1
  23. package/dist/moka-global-config.d.ts +0 -1
  24. package/dist/moka-global-config.js +0 -1
  25. package/dist/moka-submit.d.ts +8 -11
  26. package/dist/moka-submit.js +1 -4
  27. package/dist/opencode-project-config.js +2 -45
  28. package/dist/pipeline-runtime.d.ts +9 -0
  29. package/dist/pipeline-runtime.js +50 -8
  30. package/dist/planned-node.js +2 -5
  31. package/dist/{workflow-planner.d.ts → planning/compile.d.ts} +2 -2
  32. package/dist/{workflow-planner.js → planning/compile.js} +6 -83
  33. package/dist/{schedule/planner.d.ts → planning/generate.d.ts} +17 -3
  34. package/dist/{schedule/planner.js → planning/generate.js} +24 -56
  35. package/dist/planning/graph.js +138 -0
  36. package/dist/runner-command/lifecycle-context.js +2 -3
  37. package/dist/runner-command/run.js +2 -3
  38. package/dist/runner-command-contract.d.ts +2 -2
  39. package/dist/runner-event-schema.d.ts +349 -0
  40. package/dist/runner-event-schema.js +185 -0
  41. package/dist/runner-output.js +2 -2
  42. package/dist/runner.d.ts +29 -0
  43. package/dist/runtime/agent-node/agent-node.js +1 -0
  44. package/dist/runtime/context/context.js +1 -1
  45. package/dist/runtime/contracts/contracts.d.ts +18 -1
  46. package/dist/runtime/node-state-store.js +7 -0
  47. package/dist/runtime/opencode-adapter.js +28 -8
  48. package/dist/runtime/opencode-agent-name.js +18 -0
  49. package/dist/runtime/opencode-runtime.js +62 -0
  50. package/dist/runtime/opencode-server.js +67 -0
  51. package/dist/runtime/opencode-session-executor.js +206 -0
  52. package/dist/schedule/passes/coverage.js +7 -51
  53. package/dist/schedule/passes/ids.js +3 -23
  54. package/dist/schedule/scheduling-roles.js +19 -0
  55. package/dist/strings.js +30 -1
  56. package/docs/adr-opencode-first-goal-loop-runtime.md +1 -1
  57. package/docs/config-architecture.md +43 -6
  58. package/docs/mcp-gateway.md +4 -4
  59. package/docs/operator-guide.md +9 -8
  60. package/docs/pipeline-console-runner-contract.md +3 -4
  61. package/docs/slash-command-adapter-contract.md +1 -0
  62. package/package.json +10 -5
  63. package/dist/schedule-planner.d.ts +0 -2
  64. package/dist/schedule-planner.js +0 -2
@@ -0,0 +1,349 @@
1
+ import { RunnerEventRecord } from "./runner-command-contract.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/runner-event-schema.d.ts
5
+ /**
6
+ * Zod schema for a single runner event record — one item in the events array
7
+ * that the runner POSTs to /api/pipeline/runner-events.
8
+ */
9
+ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
10
+ at: z.ZodOptional<z.ZodString>;
11
+ sequence: z.ZodNumber;
12
+ type: z.ZodEnum<{
13
+ "workflow.planned": "workflow.planned";
14
+ "workflow.start": "workflow.start";
15
+ }>;
16
+ workflowPlan: z.ZodObject<{
17
+ edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
18
+ source: z.ZodString;
19
+ target: z.ZodString;
20
+ }, z.core.$strip>>>;
21
+ nodeIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ nodes: z.ZodOptional<z.ZodArray<z.ZodObject<{
23
+ id: z.ZodString;
24
+ kind: z.ZodString;
25
+ needs: z.ZodArray<z.ZodString>;
26
+ profile: z.ZodOptional<z.ZodString>;
27
+ runnerId: z.ZodOptional<z.ZodString>;
28
+ }, z.core.$strip>>>;
29
+ workflowId: z.ZodString;
30
+ }, z.core.$strip>;
31
+ }, z.core.$strip>, z.ZodObject<{
32
+ at: z.ZodOptional<z.ZodString>;
33
+ sequence: z.ZodNumber;
34
+ edge: z.ZodObject<{
35
+ id: z.ZodString;
36
+ source: z.ZodString;
37
+ target: z.ZodString;
38
+ }, z.core.$strip>;
39
+ type: z.ZodLiteral<"workflow.edge">;
40
+ }, z.core.$strip>, z.ZodObject<{
41
+ at: z.ZodOptional<z.ZodString>;
42
+ sequence: z.ZodNumber;
43
+ node: z.ZodObject<{
44
+ attempt: z.ZodNumber;
45
+ exitCode: z.ZodOptional<z.ZodNumber>;
46
+ nodeId: z.ZodString;
47
+ profile: z.ZodOptional<z.ZodString>;
48
+ runnerId: z.ZodOptional<z.ZodString>;
49
+ status: z.ZodEnum<{
50
+ "agent-finished": "agent-finished";
51
+ "agent-running": "agent-running";
52
+ failed: "failed";
53
+ passed: "passed";
54
+ running: "running";
55
+ }>;
56
+ }, z.core.$strip>;
57
+ type: z.ZodEnum<{
58
+ "agent.finish": "agent.finish";
59
+ "agent.start": "agent.start";
60
+ "node.finish": "node.finish";
61
+ "node.start": "node.start";
62
+ }>;
63
+ }, z.core.$strip>, z.ZodObject<{
64
+ at: z.ZodOptional<z.ZodString>;
65
+ sequence: z.ZodNumber;
66
+ gate: z.ZodObject<{
67
+ event: z.ZodOptional<z.ZodString>;
68
+ evidence: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ gateId: z.ZodOptional<z.ZodString>;
70
+ hookId: z.ZodOptional<z.ZodString>;
71
+ kind: z.ZodOptional<z.ZodString>;
72
+ label: z.ZodOptional<z.ZodString>;
73
+ nodeId: z.ZodOptional<z.ZodString>;
74
+ passed: z.ZodOptional<z.ZodBoolean>;
75
+ reason: z.ZodOptional<z.ZodString>;
76
+ required: z.ZodOptional<z.ZodBoolean>;
77
+ status: z.ZodEnum<{
78
+ failed: "failed";
79
+ passed: "passed";
80
+ running: "running";
81
+ }>;
82
+ workflowId: z.ZodOptional<z.ZodString>;
83
+ }, z.core.$strip>;
84
+ type: z.ZodEnum<{
85
+ "gate.finish": "gate.finish";
86
+ "gate.start": "gate.start";
87
+ "hook.finish": "hook.finish";
88
+ "hook.start": "hook.start";
89
+ }>;
90
+ }, z.core.$strip>, z.ZodObject<{
91
+ at: z.ZodOptional<z.ZodString>;
92
+ sequence: z.ZodNumber;
93
+ hookResult: z.ZodObject<{
94
+ artifacts: z.ZodOptional<z.ZodArray<z.ZodObject<{
95
+ contentType: z.ZodOptional<z.ZodString>;
96
+ name: z.ZodString;
97
+ path: z.ZodString;
98
+ }, z.core.$strip>>>;
99
+ event: z.ZodString;
100
+ functionId: z.ZodString;
101
+ gateId: z.ZodOptional<z.ZodString>;
102
+ hookId: z.ZodString;
103
+ nodeId: z.ZodOptional<z.ZodString>;
104
+ outputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
105
+ status: z.ZodEnum<{
106
+ fail: "fail";
107
+ pass: "pass";
108
+ skip: "skip";
109
+ }>;
110
+ summary: z.ZodOptional<z.ZodString>;
111
+ workflowId: z.ZodString;
112
+ }, z.core.$strip>;
113
+ type: z.ZodLiteral<"hook.result">;
114
+ }, z.core.$strip>, z.ZodObject<{
115
+ at: z.ZodOptional<z.ZodString>;
116
+ sequence: z.ZodNumber;
117
+ artifact: z.ZodObject<{
118
+ kind: z.ZodLiteral<"artifact">;
119
+ label: z.ZodString;
120
+ nodeId: z.ZodString;
121
+ passed: z.ZodOptional<z.ZodBoolean>;
122
+ path: z.ZodString;
123
+ reason: z.ZodOptional<z.ZodString>;
124
+ required: z.ZodBoolean;
125
+ status: z.ZodEnum<{
126
+ failed: "failed";
127
+ passed: "passed";
128
+ running: "running";
129
+ }>;
130
+ uri: z.ZodString;
131
+ }, z.core.$strip>;
132
+ type: z.ZodEnum<{
133
+ "artifact.check.finish": "artifact.check.finish";
134
+ "artifact.check.start": "artifact.check.start";
135
+ }>;
136
+ }, z.core.$strip>, z.ZodObject<{
137
+ at: z.ZodOptional<z.ZodString>;
138
+ sequence: z.ZodNumber;
139
+ log: z.ZodObject<{
140
+ attempt: z.ZodOptional<z.ZodNumber>;
141
+ format: z.ZodOptional<z.ZodString>;
142
+ level: z.ZodEnum<{
143
+ info: "info";
144
+ warn: "warn";
145
+ }>;
146
+ message: z.ZodString;
147
+ nodeId: z.ZodOptional<z.ZodString>;
148
+ output: z.ZodOptional<z.ZodUnknown>;
149
+ passed: z.ZodOptional<z.ZodBoolean>;
150
+ reason: z.ZodOptional<z.ZodString>;
151
+ workflowId: z.ZodOptional<z.ZodString>;
152
+ }, z.core.$strip>;
153
+ type: z.ZodEnum<{
154
+ "node.output.recorded": "node.output.recorded";
155
+ "output.repair": "output.repair";
156
+ "run.cancelled": "run.cancelled";
157
+ "runner.command.phase": "runner.command.phase";
158
+ "runner.schema.validation": "runner.schema.validation";
159
+ "runtime.observability": "runtime.observability";
160
+ }>;
161
+ }, z.core.$strip>, z.ZodObject<{
162
+ at: z.ZodOptional<z.ZodString>;
163
+ sequence: z.ZodNumber;
164
+ finalResult: z.ZodObject<{
165
+ outcome: z.ZodEnum<{
166
+ CANCELLED: "CANCELLED";
167
+ FAIL: "FAIL";
168
+ PASS: "PASS";
169
+ }>;
170
+ workflowId: z.ZodString;
171
+ }, z.core.$strip>;
172
+ type: z.ZodLiteral<"workflow.finish">;
173
+ }, z.core.$strip>]>;
174
+ /**
175
+ * Zod schema for the POST body of /api/pipeline/runner-events.
176
+ * The runner sends { events: RunnerEventRecord[] }.
177
+ */
178
+ declare const runnerEventBatchSchema: z.ZodObject<{
179
+ events: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
180
+ at: z.ZodOptional<z.ZodString>;
181
+ sequence: z.ZodNumber;
182
+ type: z.ZodEnum<{
183
+ "workflow.planned": "workflow.planned";
184
+ "workflow.start": "workflow.start";
185
+ }>;
186
+ workflowPlan: z.ZodObject<{
187
+ edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
188
+ source: z.ZodString;
189
+ target: z.ZodString;
190
+ }, z.core.$strip>>>;
191
+ nodeIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
192
+ nodes: z.ZodOptional<z.ZodArray<z.ZodObject<{
193
+ id: z.ZodString;
194
+ kind: z.ZodString;
195
+ needs: z.ZodArray<z.ZodString>;
196
+ profile: z.ZodOptional<z.ZodString>;
197
+ runnerId: z.ZodOptional<z.ZodString>;
198
+ }, z.core.$strip>>>;
199
+ workflowId: z.ZodString;
200
+ }, z.core.$strip>;
201
+ }, z.core.$strip>, z.ZodObject<{
202
+ at: z.ZodOptional<z.ZodString>;
203
+ sequence: z.ZodNumber;
204
+ edge: z.ZodObject<{
205
+ id: z.ZodString;
206
+ source: z.ZodString;
207
+ target: z.ZodString;
208
+ }, z.core.$strip>;
209
+ type: z.ZodLiteral<"workflow.edge">;
210
+ }, z.core.$strip>, z.ZodObject<{
211
+ at: z.ZodOptional<z.ZodString>;
212
+ sequence: z.ZodNumber;
213
+ node: z.ZodObject<{
214
+ attempt: z.ZodNumber;
215
+ exitCode: z.ZodOptional<z.ZodNumber>;
216
+ nodeId: z.ZodString;
217
+ profile: z.ZodOptional<z.ZodString>;
218
+ runnerId: z.ZodOptional<z.ZodString>;
219
+ status: z.ZodEnum<{
220
+ "agent-finished": "agent-finished";
221
+ "agent-running": "agent-running";
222
+ failed: "failed";
223
+ passed: "passed";
224
+ running: "running";
225
+ }>;
226
+ }, z.core.$strip>;
227
+ type: z.ZodEnum<{
228
+ "agent.finish": "agent.finish";
229
+ "agent.start": "agent.start";
230
+ "node.finish": "node.finish";
231
+ "node.start": "node.start";
232
+ }>;
233
+ }, z.core.$strip>, z.ZodObject<{
234
+ at: z.ZodOptional<z.ZodString>;
235
+ sequence: z.ZodNumber;
236
+ gate: z.ZodObject<{
237
+ event: z.ZodOptional<z.ZodString>;
238
+ evidence: z.ZodOptional<z.ZodArray<z.ZodString>>;
239
+ gateId: z.ZodOptional<z.ZodString>;
240
+ hookId: z.ZodOptional<z.ZodString>;
241
+ kind: z.ZodOptional<z.ZodString>;
242
+ label: z.ZodOptional<z.ZodString>;
243
+ nodeId: z.ZodOptional<z.ZodString>;
244
+ passed: z.ZodOptional<z.ZodBoolean>;
245
+ reason: z.ZodOptional<z.ZodString>;
246
+ required: z.ZodOptional<z.ZodBoolean>;
247
+ status: z.ZodEnum<{
248
+ failed: "failed";
249
+ passed: "passed";
250
+ running: "running";
251
+ }>;
252
+ workflowId: z.ZodOptional<z.ZodString>;
253
+ }, z.core.$strip>;
254
+ type: z.ZodEnum<{
255
+ "gate.finish": "gate.finish";
256
+ "gate.start": "gate.start";
257
+ "hook.finish": "hook.finish";
258
+ "hook.start": "hook.start";
259
+ }>;
260
+ }, z.core.$strip>, z.ZodObject<{
261
+ at: z.ZodOptional<z.ZodString>;
262
+ sequence: z.ZodNumber;
263
+ hookResult: z.ZodObject<{
264
+ artifacts: z.ZodOptional<z.ZodArray<z.ZodObject<{
265
+ contentType: z.ZodOptional<z.ZodString>;
266
+ name: z.ZodString;
267
+ path: z.ZodString;
268
+ }, z.core.$strip>>>;
269
+ event: z.ZodString;
270
+ functionId: z.ZodString;
271
+ gateId: z.ZodOptional<z.ZodString>;
272
+ hookId: z.ZodString;
273
+ nodeId: z.ZodOptional<z.ZodString>;
274
+ outputs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
275
+ status: z.ZodEnum<{
276
+ fail: "fail";
277
+ pass: "pass";
278
+ skip: "skip";
279
+ }>;
280
+ summary: z.ZodOptional<z.ZodString>;
281
+ workflowId: z.ZodString;
282
+ }, z.core.$strip>;
283
+ type: z.ZodLiteral<"hook.result">;
284
+ }, z.core.$strip>, z.ZodObject<{
285
+ at: z.ZodOptional<z.ZodString>;
286
+ sequence: z.ZodNumber;
287
+ artifact: z.ZodObject<{
288
+ kind: z.ZodLiteral<"artifact">;
289
+ label: z.ZodString;
290
+ nodeId: z.ZodString;
291
+ passed: z.ZodOptional<z.ZodBoolean>;
292
+ path: z.ZodString;
293
+ reason: z.ZodOptional<z.ZodString>;
294
+ required: z.ZodBoolean;
295
+ status: z.ZodEnum<{
296
+ failed: "failed";
297
+ passed: "passed";
298
+ running: "running";
299
+ }>;
300
+ uri: z.ZodString;
301
+ }, z.core.$strip>;
302
+ type: z.ZodEnum<{
303
+ "artifact.check.finish": "artifact.check.finish";
304
+ "artifact.check.start": "artifact.check.start";
305
+ }>;
306
+ }, z.core.$strip>, z.ZodObject<{
307
+ at: z.ZodOptional<z.ZodString>;
308
+ sequence: z.ZodNumber;
309
+ log: z.ZodObject<{
310
+ attempt: z.ZodOptional<z.ZodNumber>;
311
+ format: z.ZodOptional<z.ZodString>;
312
+ level: z.ZodEnum<{
313
+ info: "info";
314
+ warn: "warn";
315
+ }>;
316
+ message: z.ZodString;
317
+ nodeId: z.ZodOptional<z.ZodString>;
318
+ output: z.ZodOptional<z.ZodUnknown>;
319
+ passed: z.ZodOptional<z.ZodBoolean>;
320
+ reason: z.ZodOptional<z.ZodString>;
321
+ workflowId: z.ZodOptional<z.ZodString>;
322
+ }, z.core.$strip>;
323
+ type: z.ZodEnum<{
324
+ "node.output.recorded": "node.output.recorded";
325
+ "output.repair": "output.repair";
326
+ "run.cancelled": "run.cancelled";
327
+ "runner.command.phase": "runner.command.phase";
328
+ "runner.schema.validation": "runner.schema.validation";
329
+ "runtime.observability": "runtime.observability";
330
+ }>;
331
+ }, z.core.$strip>, z.ZodObject<{
332
+ at: z.ZodOptional<z.ZodString>;
333
+ sequence: z.ZodNumber;
334
+ finalResult: z.ZodObject<{
335
+ outcome: z.ZodEnum<{
336
+ CANCELLED: "CANCELLED";
337
+ FAIL: "FAIL";
338
+ PASS: "PASS";
339
+ }>;
340
+ workflowId: z.ZodString;
341
+ }, z.core.$strip>;
342
+ type: z.ZodLiteral<"workflow.finish">;
343
+ }, z.core.$strip>]>>;
344
+ }, z.core.$strict>;
345
+ type RunnerEventRecordSchema = typeof runnerEventRecordSchema;
346
+ type RunnerEventBatchSchema = typeof runnerEventBatchSchema;
347
+ declare const _runnerEventRecordTypeCheck: z.ZodType<RunnerEventRecord>;
348
+ //#endregion
349
+ export { RunnerEventBatchSchema, type RunnerEventRecord, RunnerEventRecordSchema, _runnerEventRecordTypeCheck, runnerEventBatchSchema, runnerEventRecordSchema };
@@ -0,0 +1,185 @@
1
+ import { z } from "zod";
2
+ //#region src/runner-event-schema.ts
3
+ const runnerEventEnvelopeSchema = z.object({
4
+ at: z.string().optional(),
5
+ sequence: z.number().int().positive()
6
+ });
7
+ const runnerWorkflowNodeDetailsSchema = z.object({
8
+ id: z.string().min(1),
9
+ kind: z.string().min(1),
10
+ needs: z.array(z.string()),
11
+ profile: z.string().optional(),
12
+ runnerId: z.string().optional()
13
+ });
14
+ const runnerWorkflowEdgeDetailsSchema = z.object({
15
+ source: z.string().min(1),
16
+ target: z.string().min(1)
17
+ });
18
+ const runnerWorkflowPlanDetailsSchema = z.object({
19
+ edges: z.array(runnerWorkflowEdgeDetailsSchema).optional(),
20
+ nodeIds: z.array(z.string().min(1)).optional(),
21
+ nodes: z.array(runnerWorkflowNodeDetailsSchema).optional(),
22
+ workflowId: z.string().min(1)
23
+ });
24
+ const runnerWorkflowEdgeRecordDetailsSchema = z.object({
25
+ id: z.string().min(1),
26
+ source: z.string().min(1),
27
+ target: z.string().min(1)
28
+ });
29
+ const runnerNodeDetailsSchema = z.object({
30
+ attempt: z.number().int().nonnegative(),
31
+ exitCode: z.number().int().optional(),
32
+ nodeId: z.string().min(1),
33
+ profile: z.string().optional(),
34
+ runnerId: z.string().optional(),
35
+ status: z.enum([
36
+ "agent-finished",
37
+ "agent-running",
38
+ "failed",
39
+ "passed",
40
+ "running"
41
+ ])
42
+ });
43
+ const runnerGateDetailsSchema = z.object({
44
+ event: z.string().optional(),
45
+ evidence: z.array(z.string()).optional(),
46
+ gateId: z.string().optional(),
47
+ hookId: z.string().optional(),
48
+ kind: z.string().optional(),
49
+ label: z.string().optional(),
50
+ nodeId: z.string().optional(),
51
+ passed: z.boolean().optional(),
52
+ reason: z.string().optional(),
53
+ required: z.boolean().optional(),
54
+ status: z.enum([
55
+ "failed",
56
+ "passed",
57
+ "running"
58
+ ]),
59
+ workflowId: z.string().optional()
60
+ });
61
+ const runnerHookResultDetailsSchema = z.object({
62
+ artifacts: z.array(z.object({
63
+ contentType: z.string().optional(),
64
+ name: z.string().min(1),
65
+ path: z.string().min(1)
66
+ })).optional(),
67
+ event: z.string().min(1),
68
+ functionId: z.string().min(1),
69
+ gateId: z.string().optional(),
70
+ hookId: z.string().min(1),
71
+ nodeId: z.string().optional(),
72
+ outputs: z.record(z.string(), z.unknown()).optional(),
73
+ status: z.enum([
74
+ "fail",
75
+ "pass",
76
+ "skip"
77
+ ]),
78
+ summary: z.string().optional(),
79
+ workflowId: z.string().min(1)
80
+ });
81
+ const runnerArtifactDetailsSchema = z.object({
82
+ kind: z.literal("artifact"),
83
+ label: z.string().min(1),
84
+ nodeId: z.string().min(1),
85
+ passed: z.boolean().optional(),
86
+ path: z.string().min(1),
87
+ reason: z.string().optional(),
88
+ required: z.boolean(),
89
+ status: z.enum([
90
+ "failed",
91
+ "passed",
92
+ "running"
93
+ ]),
94
+ uri: z.string().min(1)
95
+ });
96
+ const runnerLogDetailsSchema = z.object({
97
+ attempt: z.number().int().nonnegative().optional(),
98
+ format: z.string().optional(),
99
+ level: z.enum(["info", "warn"]),
100
+ message: z.string(),
101
+ nodeId: z.string().optional(),
102
+ output: z.unknown().optional(),
103
+ passed: z.boolean().optional(),
104
+ reason: z.string().optional(),
105
+ workflowId: z.string().optional()
106
+ });
107
+ const runnerFinalResultDetailsSchema = z.object({
108
+ outcome: z.enum([
109
+ "CANCELLED",
110
+ "FAIL",
111
+ "PASS"
112
+ ]),
113
+ workflowId: z.string().min(1)
114
+ });
115
+ const workflowPlanEventSchema = runnerEventEnvelopeSchema.extend({
116
+ type: z.enum(["workflow.planned", "workflow.start"]),
117
+ workflowPlan: runnerWorkflowPlanDetailsSchema
118
+ });
119
+ const workflowEdgeEventSchema = runnerEventEnvelopeSchema.extend({
120
+ edge: runnerWorkflowEdgeRecordDetailsSchema,
121
+ type: z.literal("workflow.edge")
122
+ });
123
+ const nodeEventSchema = runnerEventEnvelopeSchema.extend({
124
+ node: runnerNodeDetailsSchema,
125
+ type: z.enum([
126
+ "agent.finish",
127
+ "agent.start",
128
+ "node.finish",
129
+ "node.start"
130
+ ])
131
+ });
132
+ const gateEventSchema = runnerEventEnvelopeSchema.extend({
133
+ gate: runnerGateDetailsSchema,
134
+ type: z.enum([
135
+ "gate.finish",
136
+ "gate.start",
137
+ "hook.finish",
138
+ "hook.start"
139
+ ])
140
+ });
141
+ const hookResultEventSchema = runnerEventEnvelopeSchema.extend({
142
+ hookResult: runnerHookResultDetailsSchema,
143
+ type: z.literal("hook.result")
144
+ });
145
+ const artifactEventSchema = runnerEventEnvelopeSchema.extend({
146
+ artifact: runnerArtifactDetailsSchema,
147
+ type: z.enum(["artifact.check.finish", "artifact.check.start"])
148
+ });
149
+ const logEventSchema = runnerEventEnvelopeSchema.extend({
150
+ log: runnerLogDetailsSchema,
151
+ type: z.enum([
152
+ "node.output.recorded",
153
+ "output.repair",
154
+ "run.cancelled",
155
+ "runner.command.phase",
156
+ "runner.schema.validation",
157
+ "runtime.observability"
158
+ ])
159
+ });
160
+ const finalResultEventSchema = runnerEventEnvelopeSchema.extend({
161
+ finalResult: runnerFinalResultDetailsSchema,
162
+ type: z.literal("workflow.finish")
163
+ });
164
+ /**
165
+ * Zod schema for a single runner event record — one item in the events array
166
+ * that the runner POSTs to /api/pipeline/runner-events.
167
+ */
168
+ const runnerEventRecordSchema = z.union([
169
+ workflowPlanEventSchema,
170
+ workflowEdgeEventSchema,
171
+ nodeEventSchema,
172
+ gateEventSchema,
173
+ hookResultEventSchema,
174
+ artifactEventSchema,
175
+ logEventSchema,
176
+ finalResultEventSchema
177
+ ]);
178
+ /**
179
+ * Zod schema for the POST body of /api/pipeline/runner-events.
180
+ * The runner sends { events: RunnerEventRecord[] }.
181
+ */
182
+ const runnerEventBatchSchema = z.object({ events: z.array(runnerEventRecordSchema).min(1) }).strict();
183
+ const _runnerEventRecordTypeCheck = runnerEventRecordSchema;
184
+ //#endregion
185
+ export { _runnerEventRecordTypeCheck, runnerEventBatchSchema, runnerEventRecordSchema };
@@ -1,4 +1,4 @@
1
- import { opencodeCliRuntimeAdapter } from "./runtime/opencode-adapter.js";
1
+ import { opencodeSdkRuntimeAdapter } from "./runtime/opencode-adapter.js";
2
2
  //#region src/runner-output.ts
3
3
  function normalizeRunnerOutput(plan, stdout) {
4
4
  const latest = runnerTextCandidates(plan, stdout).at(-1);
@@ -12,7 +12,7 @@ function normalizeRunnerOutput(plan, stdout) {
12
12
  };
13
13
  }
14
14
  function runnerTextCandidates(plan, stdout) {
15
- if (plan.type === "opencode") return opencodeCliRuntimeAdapter.outputCandidates(stdout);
15
+ if (plan.type === "opencode") return opencodeSdkRuntimeAdapter.outputCandidates(stdout);
16
16
  return [];
17
17
  }
18
18
  //#endregion
package/dist/runner.d.ts CHANGED
@@ -2,18 +2,47 @@ import { PipelineConfig, RunnerType } from "./config/schemas.js";
2
2
  //#region src/runner.d.ts
3
3
  type Harness = "opencode";
4
4
  type AgentRole = "researcher" | "test-writer" | "code-writer" | "verifier";
5
+ /**
6
+ * Agent-output boundary, layer 1 of 4 (PIPE-74 B3). `AgentResult` is the RAW
7
+ * terminal result of one runner subprocess/session: exit code, accumulated
8
+ * stdout/stderr, and execution metadata. It carries no parsing or semantic
9
+ * interpretation — downstream layers refine it:
10
+ * 1. {@link AgentResult} — raw subprocess result (this type)
11
+ * 2. {@link RunnerOutputEvent} — a live stream chunk during execution
12
+ * 3. RuntimeNormalizedOutput — adapter-extracted text + evidence
13
+ * (src/runtime/opencode-adapter.ts)
14
+ * 4. RuntimeStructuredOutput — parsed + schema-validated output
15
+ * (src/runtime/contracts/contracts.ts)
16
+ */
5
17
  interface AgentResult {
6
18
  argv?: string[];
7
19
  exitCode: number;
20
+ /** opencode session id when driven through the SDK executor (PIPE-73). */
21
+ sessionId?: string;
8
22
  stderr?: string;
9
23
  stdout: string;
10
24
  timedOut?: boolean;
11
25
  }
26
+ /**
27
+ * Agent-output boundary, layer 2 of 4 (PIPE-74 B3). A single incremental chunk
28
+ * of a runner's live output stream, surfaced via
29
+ * {@link RunnerExecutionOptions.onOutput} while the subprocess is still
30
+ * running — distinct from {@link AgentResult}, which is the final accumulated
31
+ * result.
32
+ */
12
33
  interface RunnerOutputEvent {
13
34
  chunk: string;
14
35
  nodeId: string;
15
36
  stream: "stderr" | "stdout";
16
37
  }
38
+ /**
39
+ * Lowest layer of the runtime-options stack (PIPE-74 B3): the per-invocation
40
+ * controls a runner executor needs — cancellation and live-output streaming.
41
+ * Widened by the runtime layers above it:
42
+ * RunnerExecutionOptions (this type)
43
+ * < PipelineRuntimeOptions (src/runtime/contracts/contracts.ts)
44
+ * < ScheduledWorkflowTaskRuntimeOptions (src/pipeline-runtime.ts)
45
+ */
17
46
  interface RunnerExecutionOptions {
18
47
  onOutput?: (event: RunnerOutputEvent) => void;
19
48
  signal?: AbortSignal;
@@ -43,6 +43,7 @@ async function executeAgentNode(node, context, attempt) {
43
43
  signal: context.signal
44
44
  });
45
45
  emitAgentFinish(context, plan, attempt, result);
46
+ if (result.sessionId) context.nodeStateStore.recordSessionId(node.id, result.sessionId);
46
47
  const finalized = await finalizeAgentOutput({
47
48
  context,
48
49
  node,
@@ -1,7 +1,7 @@
1
1
  import { loadPipelineConfig } from "../../config/load.js";
2
2
  import "../../config.js";
3
3
  import { runLaunchPlan } from "../../runner.js";
4
- import { compileWorkflowPlan } from "../../workflow-planner.js";
4
+ import { compileWorkflowPlan } from "../../planning/compile.js";
5
5
  import { createPublicRuntimeObservabilityEmitter } from "../events/events.js";
6
6
  import "../events/index.js";
7
7
  import { initialNodeStateStore } from "../node-state-store.js";
@@ -1,5 +1,5 @@
1
1
  import { HookEvent, PipelineConfig } from "../../config/schemas.js";
2
- import { PlannedWorkflowNode, WorkflowExecutionPlan } from "../../workflow-planner.js";
2
+ import { PlannedWorkflowNode, WorkflowExecutionPlan } from "../../planning/compile.js";
3
3
  import { HookResult } from "../../hooks.js";
4
4
  import { AgentResult, RunnerExecutionOptions, RunnerLaunchPlan } from "../../runner.js";
5
5
  import { RuntimeActorDescriptor, RuntimeObservabilityEvent } from "../actor-ids.js";
@@ -44,6 +44,13 @@ interface RuntimeNodeResult {
44
44
  output: string;
45
45
  status: "failed" | "passed";
46
46
  }
47
+ /**
48
+ * Agent-output boundary, layer 4 of 4 (PIPE-74 B3). The terminal, structured
49
+ * form of agent output: the layer-3 RuntimeNormalizedOutput text
50
+ * (src/runtime/opencode-adapter.ts) parsed into a typed `output` value and
51
+ * validated against the node's declared schema. This is what downstream nodes
52
+ * and gates consume.
53
+ */
47
54
  interface RuntimeStructuredOutput {
48
55
  attempt: number;
49
56
  format: "json" | "json_schema" | "jsonl";
@@ -79,6 +86,8 @@ interface NodeExecutionState {
79
86
  retryReason: string;
80
87
  scheduled: boolean;
81
88
  };
89
+ /** opencode session id when the node ran through the SDK executor (PIPE-73). */
90
+ sessionId?: string;
82
91
  startedAt?: string;
83
92
  status: NodeStatus;
84
93
  }
@@ -226,6 +235,14 @@ type PipelineRuntimeEvent = {
226
235
  type: "workflow.finish";
227
236
  workflowId: string;
228
237
  });
238
+ /**
239
+ * Middle layer of the runtime-options stack (PIPE-74 B3): everything needed to
240
+ * run one pipeline workflow from config — the config/entrypoint to run, the
241
+ * task, reporting, and the executor (whose per-call controls come from the
242
+ * layer below, {@link RunnerExecutionOptions} in src/runner.ts). Extended by
243
+ * ScheduledWorkflowTaskRuntimeOptions (src/pipeline-runtime.ts) for the
244
+ * single-node, schedule-driven execution path.
245
+ */
229
246
  interface PipelineRuntimeOptions {
230
247
  config?: PipelineConfig;
231
248
  entrypoint?: string;
@@ -50,6 +50,13 @@ var NodeStateStore = class NodeStateStore {
50
50
  recordOutput(nodeId, output) {
51
51
  this.lastOutputByNode.set(nodeId, output);
52
52
  }
53
+ recordSessionId(nodeId, sessionId) {
54
+ const existing = this.nodeStates.get(nodeId);
55
+ if (existing) this.nodeStates.set(nodeId, {
56
+ ...existing,
57
+ sessionId
58
+ });
59
+ }
53
60
  recordStructuredOutput(output) {
54
61
  this.structuredOutputs.push(output);
55
62
  }