@osolmaz/pi-workflows 0.9.1 → 0.11.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 (147) hide show
  1. package/README.md +64 -19
  2. package/dist/builtins/autodoc.workflow.d.ts +58 -0
  3. package/dist/builtins/autodoc.workflow.js +266 -0
  4. package/dist/builtins/autodoc.workflow.js.map +1 -0
  5. package/dist/builtins/autoimplement.workflow.d.ts +353 -0
  6. package/dist/builtins/autoimplement.workflow.js +961 -0
  7. package/dist/builtins/autoimplement.workflow.js.map +1 -0
  8. package/dist/builtins/autoplan.workflow.d.ts +58 -0
  9. package/dist/builtins/autoplan.workflow.js +190 -0
  10. package/dist/builtins/autoplan.workflow.js.map +1 -0
  11. package/dist/builtins/catalog.js +9 -1
  12. package/dist/builtins/catalog.js.map +1 -1
  13. package/dist/builtins/index.d.ts +6 -0
  14. package/dist/builtins/index.js +7 -0
  15. package/dist/builtins/index.js.map +1 -0
  16. package/dist/builtins/monitor.workflow.d.ts +29 -3
  17. package/dist/builtins/monitor.workflow.js +325 -13
  18. package/dist/builtins/monitor.workflow.js.map +1 -1
  19. package/dist/builtins/plan-approval.workflow.d.ts +83 -0
  20. package/dist/builtins/plan-approval.workflow.js +148 -0
  21. package/dist/builtins/plan-approval.workflow.js.map +1 -0
  22. package/dist/builtins/plan-presentation.d.ts +7 -0
  23. package/dist/builtins/plan-presentation.js +44 -0
  24. package/dist/builtins/plan-presentation.js.map +1 -0
  25. package/dist/extension/decision-channels.d.ts +132 -0
  26. package/dist/extension/decision-channels.js +1082 -0
  27. package/dist/extension/decision-channels.js.map +1 -0
  28. package/dist/extension/index.d.ts +1 -0
  29. package/dist/extension/index.js +426 -11
  30. package/dist/extension/index.js.map +1 -1
  31. package/dist/extension/widget.js +26 -2
  32. package/dist/extension/widget.js.map +1 -1
  33. package/dist/extension/workflow-tool.d.ts +1 -37
  34. package/dist/extension/workflow-tool.js +1 -42
  35. package/dist/extension/workflow-tool.js.map +1 -1
  36. package/dist/host/rpc-bridge.js +4 -21
  37. package/dist/host/rpc-bridge.js.map +1 -1
  38. package/dist/render/graph-render.js +46 -10
  39. package/dist/render/graph-render.js.map +1 -1
  40. package/dist/viewer/render.js +36 -2
  41. package/dist/viewer/render.js.map +1 -1
  42. package/dist/workflows/catalog.d.ts +1 -0
  43. package/dist/workflows/catalog.js +6 -0
  44. package/dist/workflows/catalog.js.map +1 -1
  45. package/dist/workflows/composition.d.ts +45 -0
  46. package/dist/workflows/composition.js +485 -0
  47. package/dist/workflows/composition.js.map +1 -0
  48. package/dist/workflows/decision-presentation.d.ts +18 -0
  49. package/dist/workflows/decision-presentation.js +417 -0
  50. package/dist/workflows/decision-presentation.js.map +1 -0
  51. package/dist/workflows/decision.d.ts +11 -5
  52. package/dist/workflows/decision.js.map +1 -1
  53. package/dist/workflows/definition.d.ts +22 -3
  54. package/dist/workflows/definition.js +46 -3
  55. package/dist/workflows/definition.js.map +1 -1
  56. package/dist/workflows/engine.d.ts +2 -1
  57. package/dist/workflows/engine.js +199 -18
  58. package/dist/workflows/engine.js.map +1 -1
  59. package/dist/workflows/graph.js +8 -6
  60. package/dist/workflows/graph.js.map +1 -1
  61. package/dist/workflows/human-decision.d.ts +87 -0
  62. package/dist/workflows/human-decision.js +583 -0
  63. package/dist/workflows/human-decision.js.map +1 -0
  64. package/dist/workflows/index.d.ts +5 -2
  65. package/dist/workflows/index.js +4 -1
  66. package/dist/workflows/index.js.map +1 -1
  67. package/dist/workflows/loader.d.ts +5 -4
  68. package/dist/workflows/loader.js +118 -18
  69. package/dist/workflows/loader.js.map +1 -1
  70. package/dist/workflows/schema.d.ts +3 -1
  71. package/dist/workflows/schema.js +64 -2
  72. package/dist/workflows/schema.js.map +1 -1
  73. package/dist/workflows/store.js +39 -2
  74. package/dist/workflows/store.js.map +1 -1
  75. package/dist/workflows/tool-input.d.ts +72 -0
  76. package/dist/workflows/tool-input.js +141 -0
  77. package/dist/workflows/tool-input.js.map +1 -0
  78. package/dist/workflows/types.d.ts +300 -2
  79. package/docs/CONTROLLERS.md +1 -1
  80. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  81. package/docs/HUMAN_DECISIONS.md +371 -0
  82. package/docs/HUMAN_DECISION_PRESENTATIONS.md +323 -0
  83. package/docs/MONITOR.md +46 -18
  84. package/docs/WORKFLOW_COMPOSITION.md +333 -0
  85. package/docs/plans/2026-08-19-human-decision-gates-plan.md +296 -0
  86. package/docs/plans/2026-08-19-human-decision-presentations-plan.md +172 -0
  87. package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +45 -0
  88. package/docs/plans/2026-08-19-workflow-composition-plan.md +308 -0
  89. package/docs/run-bundles.md +45 -10
  90. package/docs/workflows.md +106 -15
  91. package/examples/workflows/approved-plan.workflow.ts +58 -0
  92. package/examples/workflows/autoimplement.workflow.ts +1 -92
  93. package/examples/workflows/autoplan.workflow.ts +1 -0
  94. package/examples/workflows/human-decision.workflow.ts +62 -0
  95. package/herdr-plugin.toml +1 -1
  96. package/package.json +6 -1
  97. package/schemas/decision-presentation-v1.schema.json +83 -0
  98. package/schemas/human-decision-accepted-v1.schema.json +44 -0
  99. package/schemas/human-decision-accepted-v2.schema.json +50 -0
  100. package/schemas/human-decision-answer-attempt-v1.schema.json +37 -0
  101. package/schemas/human-decision-cancellation-v1.schema.json +15 -0
  102. package/schemas/human-decision-continuation-v1.schema.json +16 -0
  103. package/schemas/human-decision-delivery-v1.schema.json +28 -0
  104. package/schemas/human-decision-delivery-v2.schema.json +36 -0
  105. package/schemas/human-decision-receipt-v1.schema.json +33 -0
  106. package/schemas/human-decision-receipt-v2.schema.json +39 -0
  107. package/schemas/human-decision-request-v1.schema.json +59 -0
  108. package/schemas/human-decision-request-v2.schema.json +69 -0
  109. package/schemas/human-decision-resolution-v1.schema.json +27 -0
  110. package/schemas/human-decision-resolution-v2.schema.json +27 -0
  111. package/schemas/human-decision-settlement-v1.schema.json +28 -0
  112. package/skills/autodoc/SKILL.md +43 -0
  113. package/skills/autoimplement/SKILL.md +58 -0
  114. package/skills/autoimplement/agents/openai.yaml +4 -0
  115. package/skills/autoplan/SKILL.md +25 -0
  116. package/skills/monitor/SKILL.md +8 -1
  117. package/skills/pi-workflows/SKILL.md +5 -3
  118. package/src/builtins/autodoc.workflow.ts +325 -0
  119. package/src/builtins/autoimplement.workflow.ts +1123 -0
  120. package/src/builtins/autoplan.workflow.ts +231 -0
  121. package/src/builtins/catalog.ts +9 -1
  122. package/src/builtins/index.ts +32 -0
  123. package/src/builtins/monitor.workflow.ts +396 -15
  124. package/src/builtins/plan-approval.workflow.ts +190 -0
  125. package/src/builtins/plan-presentation.ts +57 -0
  126. package/src/extension/decision-channels.ts +1533 -0
  127. package/src/extension/index.ts +499 -9
  128. package/src/extension/widget.ts +39 -2
  129. package/src/extension/workflow-tool.ts +5 -81
  130. package/src/host/rpc-bridge.ts +7 -30
  131. package/src/render/graph-render.ts +54 -5
  132. package/src/viewer/render.ts +56 -3
  133. package/src/workflows/catalog.ts +7 -0
  134. package/src/workflows/composition.ts +642 -0
  135. package/src/workflows/decision-presentation.ts +501 -0
  136. package/src/workflows/decision.ts +12 -5
  137. package/src/workflows/definition.ts +118 -8
  138. package/src/workflows/engine.ts +257 -20
  139. package/src/workflows/graph.ts +8 -6
  140. package/src/workflows/human-decision.ts +819 -0
  141. package/src/workflows/index.ts +89 -0
  142. package/src/workflows/loader.ts +186 -18
  143. package/src/workflows/schema.ts +79 -2
  144. package/src/workflows/store.ts +45 -2
  145. package/src/workflows/tool-input.ts +202 -0
  146. package/src/workflows/types.ts +374 -2
  147. package/examples/workflows/elegant-solution.workflow.ts +0 -95
@@ -141,6 +141,219 @@ export type ShellActionNodeDefinition = WorkflowNodeCommon & {
141
141
  updates?: ShellActionUpdates;
142
142
  };
143
143
  export type ActionNodeDefinition = FunctionActionNodeDefinition | ShellActionNodeDefinition;
144
+ export type HumanDecisionTextInput = {
145
+ kind: "text";
146
+ name: string;
147
+ prompt: string;
148
+ minLength: number;
149
+ maxLength: number;
150
+ };
151
+ export type HumanDecisionChoice = {
152
+ label: string;
153
+ input?: HumanDecisionTextInput;
154
+ };
155
+ export type HumanDecisionChoiceMap = Record<string, HumanDecisionChoice>;
156
+ export type DecisionPresentationParagraph = {
157
+ kind: "paragraph";
158
+ text: string;
159
+ };
160
+ export type DecisionPresentationSection = {
161
+ kind: "section";
162
+ title: string;
163
+ };
164
+ export type DecisionPresentationBullets = {
165
+ kind: "bullets";
166
+ items: string[];
167
+ };
168
+ export type DecisionPresentationFields = {
169
+ kind: "fields";
170
+ items: Array<{
171
+ label: string;
172
+ value: string;
173
+ }>;
174
+ };
175
+ export type DecisionPresentationPreformatted = {
176
+ kind: "preformatted";
177
+ text: string;
178
+ };
179
+ export type DecisionPresentationBlock = DecisionPresentationParagraph | DecisionPresentationSection | DecisionPresentationBullets | DecisionPresentationFields | DecisionPresentationPreformatted;
180
+ export type DecisionPresentation = {
181
+ schema: "pi-workflows.decision-presentation.v1";
182
+ summary: string;
183
+ blocks: DecisionPresentationBlock[];
184
+ };
185
+ export type LegacyHumanDecisionPrompt = {
186
+ title: string;
187
+ body: unknown;
188
+ subject?: never;
189
+ presentation?: never;
190
+ revision?: never;
191
+ /** Optional absolute expiry. An expired request cannot accept an answer. */
192
+ expiresAt?: string;
193
+ };
194
+ export type PresentedHumanDecisionPrompt<TSubject = unknown> = {
195
+ title: string;
196
+ subject: TSubject;
197
+ presentation: DecisionPresentation;
198
+ body?: never;
199
+ /** Positive revision of the decision subject and presentation. Defaults to 1. */
200
+ revision?: number;
201
+ /** Optional absolute expiry. An expired request cannot accept an answer. */
202
+ expiresAt?: string;
203
+ };
204
+ export type HumanDecisionPrompt = LegacyHumanDecisionPrompt | PresentedHumanDecisionPrompt;
205
+ export type HumanDecisionAudience = string | ((context: WorkflowNodeContext) => MaybePromise<string>);
206
+ export type HumanDecisionNodeContract = {
207
+ audience: HumanDecisionAudience;
208
+ choices: HumanDecisionChoiceMap;
209
+ request: (context: WorkflowNodeContext) => MaybePromise<HumanDecisionPrompt>;
210
+ };
211
+ type HumanDecisionRequestCommon = {
212
+ decisionId: string;
213
+ requestDigest: string;
214
+ runId: string;
215
+ workflowName: string;
216
+ nodeId: string;
217
+ attemptId: string;
218
+ audience: string;
219
+ title: string;
220
+ choices: HumanDecisionChoiceMap;
221
+ createdAt: string;
222
+ expiresAt?: string;
223
+ };
224
+ export type HumanDecisionRequestV1 = HumanDecisionRequestCommon & {
225
+ schema: "pi-workflows.human-decision-request.v1";
226
+ body: unknown;
227
+ };
228
+ export type HumanDecisionRequestV2 = HumanDecisionRequestCommon & {
229
+ schema: "pi-workflows.human-decision-request.v2";
230
+ subject: unknown;
231
+ presentation: DecisionPresentation;
232
+ revision: number;
233
+ subjectDigest: string;
234
+ presentationDigest: string;
235
+ };
236
+ export type HumanDecisionRequest = HumanDecisionRequestV1 | HumanDecisionRequestV2;
237
+ /**
238
+ * Complete operator-facing request passed to a decision channel. It excludes
239
+ * the canonical subject and legacy body by design.
240
+ */
241
+ export type HumanDecisionChannelRequest = HumanDecisionRequestCommon & {
242
+ schema: "pi-workflows.human-decision-channel-request.v1";
243
+ sourceSchema: HumanDecisionRequest["schema"];
244
+ presentation: DecisionPresentation;
245
+ presentationDigest: string;
246
+ revision: number;
247
+ };
248
+ export type HumanDecisionResponse = {
249
+ choice: string;
250
+ input?: Record<string, string>;
251
+ };
252
+ export type HumanDecisionAnswerSource = {
253
+ channel: string;
254
+ actorId: string;
255
+ eventId: string;
256
+ };
257
+ export type HumanDecisionSubmission = HumanDecisionResponse & {
258
+ decisionId: string;
259
+ requestDigest: string;
260
+ source: HumanDecisionAnswerSource;
261
+ idempotencyKey: string;
262
+ };
263
+ type AcceptedHumanDecisionCommon = {
264
+ decisionId: string;
265
+ requestDigest: string;
266
+ response: HumanDecisionResponse;
267
+ source: HumanDecisionAnswerSource;
268
+ idempotencyKey: string;
269
+ acceptedAt: string;
270
+ answerDigest: string;
271
+ };
272
+ export type AcceptedHumanDecisionV1 = AcceptedHumanDecisionCommon & {
273
+ schema: "pi-workflows.human-decision-accepted.v1";
274
+ };
275
+ export type AcceptedHumanDecisionV2 = AcceptedHumanDecisionCommon & {
276
+ schema: "pi-workflows.human-decision-accepted.v2";
277
+ subjectDigest: string;
278
+ presentationDigest: string;
279
+ revision: number;
280
+ };
281
+ export type AcceptedHumanDecision = AcceptedHumanDecisionV1 | AcceptedHumanDecisionV2;
282
+ type HumanDecisionReceiptCommon = {
283
+ decisionId: string;
284
+ requestDigest: string;
285
+ nodeId: string;
286
+ response: HumanDecisionResponse;
287
+ acceptedAt: string;
288
+ answerDigest: string;
289
+ };
290
+ export type HumanDecisionReceiptV1 = HumanDecisionReceiptCommon & {
291
+ schema: "pi-workflows.human-decision-receipt.v1";
292
+ };
293
+ export type HumanDecisionReceiptV2 = HumanDecisionReceiptCommon & {
294
+ schema: "pi-workflows.human-decision-receipt.v2";
295
+ subjectDigest: string;
296
+ presentationDigest: string;
297
+ revision: number;
298
+ };
299
+ export type HumanDecisionReceipt = HumanDecisionReceiptV1 | HumanDecisionReceiptV2;
300
+ export type HumanDecisionDeliveryRecordV1 = {
301
+ schema: "pi-workflows.human-decision-delivery.v1";
302
+ attemptId: string;
303
+ decisionId: string;
304
+ requestDigest: string;
305
+ channel: string;
306
+ state: "intent" | "confirmed" | "failed" | "unknown";
307
+ createdAt: string;
308
+ finishedAt?: string;
309
+ messageCount?: number;
310
+ errorCode?: string;
311
+ };
312
+ export type HumanDecisionDeliveryRecordV2 = {
313
+ schema: "pi-workflows.human-decision-delivery.v2";
314
+ attemptId: string;
315
+ decisionId: string;
316
+ requestDigest: string;
317
+ presentationDigest: string;
318
+ channel: string;
319
+ phase: "intent" | "part" | "complete";
320
+ state: "intent" | "confirmed" | "failed" | "unknown";
321
+ createdAt: string;
322
+ finishedAt?: string;
323
+ recipientIndex?: number;
324
+ partIndex?: number;
325
+ partCount?: number;
326
+ contentDigest?: string;
327
+ messageCount?: number;
328
+ errorCode?: string;
329
+ };
330
+ export type HumanDecisionDeliveryRecord = HumanDecisionDeliveryRecordV1 | HumanDecisionDeliveryRecordV2;
331
+ export type HumanDecisionSettlementRecord = {
332
+ schema: "pi-workflows.human-decision-settlement.v1";
333
+ attemptId: string;
334
+ decisionId: string;
335
+ requestDigest: string;
336
+ channel: string;
337
+ state: "confirmed" | "failed";
338
+ createdAt: string;
339
+ finishedAt: string;
340
+ errorCode?: string;
341
+ };
342
+ export type HumanDecisionCancellationRecord = {
343
+ schema: "pi-workflows.human-decision-cancellation.v1";
344
+ decisionId: string;
345
+ requestDigest: string;
346
+ cancelledAt: string;
347
+ reason: "cancelled" | "expired";
348
+ };
349
+ export type HumanDecisionContinuationRecord = {
350
+ schema: "pi-workflows.human-decision-continuation.v1";
351
+ decisionId: string;
352
+ requestDigest: string;
353
+ parentRunId: string;
354
+ runId: string;
355
+ createdAt: string;
356
+ };
144
357
  /**
145
358
  * A pause point. The run terminates with status `waiting` so a human (or an
146
359
  * external trigger) can decide how to continue. The optional `run` callback
@@ -150,6 +363,8 @@ export type CheckpointNodeDefinition = WorkflowNodeCommon & {
150
363
  nodeType: "checkpoint";
151
364
  summary?: string;
152
365
  run?: (context: WorkflowNodeContext) => MaybePromise<unknown>;
366
+ /** Typed verified-human request. Still executes as a checkpoint node. */
367
+ humanDecision?: HumanDecisionNodeContract;
153
368
  };
154
369
  export type WorkflowNodeDefinition = AgentNodeDefinition | ComputeNodeDefinition | NotifyNodeDefinition | ActionNodeDefinition | CheckpointNodeDefinition;
155
370
  export type WorkflowPresentationContext = {
@@ -160,11 +375,58 @@ export type WorkflowPresentationContext = {
160
375
  /** Aborted if a new run starts, the session closes, or prompt generation times out. */
161
376
  signal: AbortSignal;
162
377
  };
163
- export type WorkflowDefinition = {
378
+ /** Runtime parser that also carries its normalized TypeScript result type. */
379
+ export type WorkflowValueParser<T> = (value: unknown) => MaybePromise<T>;
380
+ export type WorkflowExitDefinition<TOutput = unknown> = {
381
+ /** Successful terminal node whose output leaves through this exit. */
382
+ from: string;
383
+ /** Optional runtime output normalizer and validator. */
384
+ validate?: WorkflowValueParser<TOutput>;
385
+ };
386
+ export type WorkflowExitMap = Record<string, WorkflowExitDefinition>;
387
+ export type WorkflowInputOf<TWorkflow> = TWorkflow extends WorkflowDefinition<infer TInput, any, any> ? TInput : unknown;
388
+ export type WorkflowExitOutputs<TWorkflow> = TWorkflow extends WorkflowDefinition<any, infer TExits, any> ? {
389
+ [K in keyof TExits]: TExits[K] extends WorkflowExitDefinition<infer TOutput> ? TOutput : unknown;
390
+ } : Record<string, unknown>;
391
+ export type WorkflowIncludedResult<TWorkflow> = {
392
+ [K in keyof WorkflowExitOutputs<TWorkflow>]: {
393
+ exit: K;
394
+ output: WorkflowExitOutputs<TWorkflow>[K];
395
+ };
396
+ }[keyof WorkflowExitOutputs<TWorkflow>];
397
+ export type WorkflowIncludeDefinition<TWorkflow extends WorkflowDefinition<any, any, any> = WorkflowDefinition<any, any, any>> = {
398
+ /** Imported child definition or dynamic discovered name/path. */
399
+ workflow: TWorkflow | string;
400
+ /** Pure parent-to-child input mapping, evaluated on every mount entry. */
401
+ input?: (context: WorkflowNodeContext) => MaybePromise<WorkflowInputOf<TWorkflow>>;
402
+ /** Optional direct definition that supplies the contract for a dynamic reference. */
403
+ contract?: TWorkflow;
404
+ };
405
+ export type WorkflowIncludeMap = Record<string, WorkflowIncludeDefinition>;
406
+ export type WorkflowIncludeExitReference<TIncludes extends WorkflowIncludeMap> = {
407
+ [K in keyof TIncludes & string]: TIncludes[K] extends WorkflowIncludeDefinition<infer TWorkflow> ? `${K}.${Extract<keyof WorkflowExitOutputs<TWorkflow>, string>}` : never;
408
+ }[keyof TIncludes & string];
409
+ export type WorkflowTypedEdge<TNodes extends Record<string, WorkflowNodeDefinition>, TIncludes extends WorkflowIncludeMap> = {
410
+ from: (keyof TNodes & string) | WorkflowIncludeExitReference<TIncludes>;
411
+ to: (keyof TNodes & string) | (keyof TIncludes & string);
412
+ } | {
413
+ from: keyof TNodes & string;
414
+ switch: {
415
+ on: string;
416
+ cases: Record<string, (keyof TNodes & string) | (keyof TIncludes & string)>;
417
+ };
418
+ };
419
+ export type WorkflowDefinition<TInput = any, TExits extends WorkflowExitMap = WorkflowExitMap, TIncludes extends WorkflowIncludeMap = WorkflowIncludeMap> = {
164
420
  name: string;
421
+ /** Module URL used to attest directly imported child workflow files. */
422
+ source?: string;
423
+ /** Stable public input-and-exit contract identity for compatible overrides. */
424
+ contractId?: string;
425
+ /** Optional runtime input normalizer and validator. */
426
+ input?: WorkflowValueParser<TInput>;
165
427
  /** Optional human-readable run title (static or derived from input). */
166
428
  title?: string | ((context: {
167
- input: unknown;
429
+ input: TInput;
168
430
  workflowName: string;
169
431
  }) => MaybePromise<string | undefined>);
170
432
  /**
@@ -175,6 +437,8 @@ export type WorkflowDefinition = {
175
437
  presentationPrompt?: string | ((context: WorkflowPresentationContext) => MaybePromise<string | undefined>);
176
438
  startAt: string;
177
439
  nodes: Record<string, WorkflowNodeDefinition>;
440
+ includes?: TIncludes;
441
+ exits?: TExits;
178
442
  edges: WorkflowEdge[];
179
443
  /** Guard against unbounded loops. Defaults to the engine's maxSteps. */
180
444
  maxSteps?: number;
@@ -255,6 +519,21 @@ export type WorkflowSource = {
255
519
  path: string;
256
520
  hash: string;
257
521
  };
522
+ export type WorkflowMountedSource = {
523
+ mountPath: string[];
524
+ workflowName: string;
525
+ source: WorkflowSource;
526
+ };
527
+ export type WorkflowMountSnapshot = {
528
+ mountPath: string[];
529
+ workflowName: string;
530
+ entryNode: string;
531
+ exits: Record<string, string>;
532
+ maxSteps?: number;
533
+ };
534
+ export type WorkflowCompositionSnapshot = {
535
+ mounts: WorkflowMountSnapshot[];
536
+ };
258
537
  export type WorkflowRunState = {
259
538
  schema: "pi-workflows.run-state.v1";
260
539
  /**
@@ -276,6 +555,10 @@ export type WorkflowRunState = {
276
555
  runTitle?: string;
277
556
  /** Stable built-in identity or immutable file source used by this run. */
278
557
  workflowSource?: WorkflowSource;
558
+ /** Sorted immutable sources used by included workflow mounts. */
559
+ workflowSources?: WorkflowMountedSource[];
560
+ /** SHA-256 of the fully resolved definition snapshot. */
561
+ definitionDigest?: string;
279
562
  /** Legacy fields accepted only by the bounded built-in migration. */
280
563
  workflowPath?: string;
281
564
  workflowHash?: string;
@@ -293,6 +576,8 @@ export type WorkflowRunState = {
293
576
  currentAttemptId?: string;
294
577
  currentNodeStartedAt?: string;
295
578
  statusDetail?: string;
579
+ /** Redacted verified-human receipt carried by a continuation run. */
580
+ humanDecision?: HumanDecisionReceipt;
296
581
  /** True while the run is held at a step boundary by a pause request. */
297
582
  paused?: boolean;
298
583
  waitingOn?: string;
@@ -306,13 +591,23 @@ export type WorkflowNodeSnapshot = {
306
591
  summary?: string;
307
592
  expectedOutput?: string;
308
593
  actionExecution?: "function" | "shell";
594
+ mountPath?: string[];
595
+ localNodeId?: string;
596
+ includeTransition?: "entry" | "exit";
597
+ humanDecision?: {
598
+ audience: string;
599
+ dynamicAudience?: boolean;
600
+ choices: HumanDecisionChoiceMap;
601
+ };
309
602
  };
310
603
  export type WorkflowDefinitionSnapshot = {
311
604
  schema: "pi-workflows.definition-snapshot.v1";
312
605
  name: string;
606
+ contractId?: string;
313
607
  startAt: string;
314
608
  nodes: Record<string, WorkflowNodeSnapshot>;
315
609
  edges: WorkflowEdge[];
610
+ composition?: WorkflowCompositionSnapshot;
316
611
  };
317
612
  export type WorkflowTraceEvent = {
318
613
  seq: number;
@@ -388,6 +683,8 @@ export type WorkflowRunManifest = {
388
683
  workflowName: string;
389
684
  runTitle?: string;
390
685
  workflowSource?: WorkflowSource;
686
+ workflowSources?: WorkflowMountedSource[];
687
+ definitionDigest?: string;
391
688
  startedAt: string;
392
689
  finishedAt?: string;
393
690
  status: WorkflowRunStatus;
@@ -501,3 +798,4 @@ export type WorkflowEngineOptions = {
501
798
  /** Observer invoked after every persisted trace event. */
502
799
  onEvent?: (event: WorkflowTraceEvent, state: WorkflowRunState) => void;
503
800
  };
801
+ export {};
@@ -25,7 +25,7 @@ The first production use case is pull request automation. A controller can obser
25
25
 
26
26
  ## Boundaries
27
27
 
28
- The graph engine remains the execution layer for finite work. It does not import the controller runtime. The controller runtime may start workflows through a narrow scheduler interface.
28
+ The graph engine remains the execution layer for finite work. A finite workflow can include another finite workflow in the same run through `includeWorkflow()`. Use a controller child run when work needs an independent retry history, stable request key, parallel lifecycle, or indefinite reconciliation. The graph engine does not import the controller runtime. The controller runtime may start workflows through a narrow scheduler interface.
29
29
 
30
30
  The Pi extension is a host. It discovers definitions, displays status, and supplies the conversation-backed agent executor while Pi is running. A headless host can use the same controller runtime with another `AgentStepExecutor`.
31
31
 
@@ -10,7 +10,7 @@ A new primitive belongs in the engine only when it solves a general problem that
10
10
 
11
11
  ## Composition
12
12
 
13
- Workflows combine `agent`, `compute`, `action`, `notify`, and `checkpoint` nodes through explicit edges. `shell` is the command form of an action. Built-in workflows should use the same public parts available to workflow authors.
13
+ Workflows combine `agent`, `compute`, `action`, `notify`, and `checkpoint` nodes through explicit edges. `shell` is the command form of an action. A finite workflow can include another finite workflow through typed input and named exits. This keeps shared prompts and routing in one source. Built-in workflows should use the same public parts available to workflow authors.
14
14
 
15
15
  Shared behavior should usually start as a data format or pure helper used by a workflow composition. For example, progress can be structured data carried through a general update channel instead of a special progress node.
16
16