@exaudeus/workrail 1.16.0 → 1.16.1

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 (46) hide show
  1. package/dist/application/services/compiler/feature-registry.js +18 -0
  2. package/dist/application/services/compiler/prompt-blocks.js +2 -1
  3. package/dist/application/services/compiler/ref-registry.js +36 -0
  4. package/dist/application/services/validation-engine.d.ts +1 -0
  5. package/dist/application/services/validation-engine.js +14 -0
  6. package/dist/application/services/workflow-validation-pipeline.d.ts +96 -0
  7. package/dist/application/services/workflow-validation-pipeline.js +94 -0
  8. package/dist/application/use-cases/raw-workflow-file-scanner.d.ts +18 -0
  9. package/dist/application/use-cases/raw-workflow-file-scanner.js +91 -0
  10. package/dist/application/use-cases/validate-workflow-file.d.ts +17 -0
  11. package/dist/application/use-cases/validate-workflow-file.js +96 -0
  12. package/dist/application/use-cases/validate-workflow-json.d.ts +2 -1
  13. package/dist/application/use-cases/validate-workflow-json.js +67 -13
  14. package/dist/application/use-cases/validate-workflow-registry.d.ts +72 -0
  15. package/dist/application/use-cases/validate-workflow-registry.js +215 -0
  16. package/dist/application/validation.d.ts +4 -0
  17. package/dist/application/validation.js +16 -0
  18. package/dist/cli/commands/validate.js +15 -0
  19. package/dist/cli.js +10 -1
  20. package/dist/infrastructure/storage/caching-workflow-storage.d.ts +1 -0
  21. package/dist/infrastructure/storage/caching-workflow-storage.js +3 -0
  22. package/dist/infrastructure/storage/enhanced-multi-source-workflow-storage.d.ts +2 -1
  23. package/dist/infrastructure/storage/enhanced-multi-source-workflow-storage.js +8 -21
  24. package/dist/infrastructure/storage/file-workflow-storage.d.ts +0 -1
  25. package/dist/infrastructure/storage/file-workflow-storage.js +15 -36
  26. package/dist/infrastructure/storage/schema-validating-workflow-storage.d.ts +1 -0
  27. package/dist/infrastructure/storage/schema-validating-workflow-storage.js +16 -6
  28. package/dist/infrastructure/storage/workflow-resolution.d.ts +62 -0
  29. package/dist/infrastructure/storage/workflow-resolution.js +150 -0
  30. package/dist/manifest.json +102 -62
  31. package/dist/mcp/handlers/v2-execution/replay.d.ts +1 -1
  32. package/dist/mcp/handlers/v2-execution/replay.js +37 -21
  33. package/dist/mcp/handlers/v2-execution/start.js +35 -13
  34. package/dist/mcp/handlers/v2-execution-helpers.d.ts +9 -11
  35. package/dist/mcp/handlers/v2-execution-helpers.js +6 -18
  36. package/dist/mcp/output-schemas.d.ts +20 -20
  37. package/dist/types/storage.d.ts +1 -0
  38. package/dist/v2/durable-core/domain/prompt-renderer.js +13 -7
  39. package/dist/v2/durable-core/domain/start-construction.d.ts +22 -0
  40. package/dist/v2/durable-core/domain/start-construction.js +31 -0
  41. package/dist/v2/durable-core/schemas/compiled-workflow/index.d.ts +8 -8
  42. package/dist/v2/read-only/v1-to-v2-shim.d.ts +5 -0
  43. package/dist/v2/read-only/v1-to-v2-shim.js +18 -0
  44. package/package.json +3 -2
  45. package/workflows/bug-investigation.agentic.v2.json +134 -0
  46. package/workflows/mr-review-workflow.agentic.v2.json +238 -0
@@ -11,6 +11,7 @@ const workflow_hash_ref_js_1 = require("../../../v2/durable-core/ids/workflow-ha
11
11
  const neverthrow_1 = require("neverthrow");
12
12
  const validation_loader_js_1 = require("../../../v2/durable-core/domain/validation-loader.js");
13
13
  const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
14
+ const prompt_renderer_js_1 = require("../../../v2/durable-core/domain/prompt-renderer.js");
14
15
  const v2_token_ops_js_1 = require("../v2-token-ops.js");
15
16
  const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
16
17
  const constants_js_1 = require("../../../v2/durable-core/constants.js");
@@ -19,8 +20,9 @@ function buildBlockedReplayResponse(args) {
19
20
  const { sessionId, runId, nodeId, attemptId, blockers, snapshot, truth, workflow, inputStateToken, inputAckToken, ports } = args;
20
21
  const pendingNow = snapshot ? (0, snapshot_state_js_1.derivePendingStep)(snapshot.enginePayload.engineState) : null;
21
22
  const isCompleteNow = snapshot ? (0, snapshot_state_js_1.deriveIsComplete)(snapshot.enginePayload.engineState) : false;
22
- const meta = pendingNow
23
- ? (0, v2_execution_helpers_js_1.renderPendingPromptOrDefault)({
23
+ let metaOrNull = null;
24
+ if (pendingNow) {
25
+ const result = (0, prompt_renderer_js_1.renderPendingPrompt)({
24
26
  workflow,
25
27
  stepId: String(pendingNow.stepId),
26
28
  loopPath: pendingNow.loopPath,
@@ -28,10 +30,14 @@ function buildBlockedReplayResponse(args) {
28
30
  runId: (0, index_js_2.asRunId)(String(runId)),
29
31
  nodeId: (0, index_js_2.asNodeId)(String(nodeId)),
30
32
  rehydrateOnly: false,
31
- })
32
- : null;
33
+ });
34
+ if (result.isErr()) {
35
+ return (0, neverthrow_1.errAsync)({ kind: 'prompt_render_failed', message: result.error.message });
36
+ }
37
+ metaOrNull = result.value;
38
+ }
33
39
  const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId });
34
- const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete: isCompleteNow, pending: meta });
40
+ const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete: isCompleteNow, pending: metaOrNull });
35
41
  const replayCheckpointTokenRes = pendingNow
36
42
  ? (0, v2_token_ops_js_1.signTokenOrErr)({
37
43
  payload: { tokenVersion: 1, tokenKind: 'checkpoint', sessionId, runId, nodeId, attemptId },
@@ -44,10 +50,10 @@ function buildBlockedReplayResponse(args) {
44
50
  ackToken: inputAckToken,
45
51
  checkpointToken: replayCheckpointTokenRes.isOk() ? replayCheckpointTokenRes.value : undefined,
46
52
  isComplete: isCompleteNow,
47
- pending: meta ? { stepId: meta.stepId, title: meta.title, prompt: meta.prompt } : null,
53
+ pending: metaOrNull ? { stepId: metaOrNull.stepId, title: metaOrNull.title, prompt: metaOrNull.prompt } : null,
48
54
  preferences,
49
55
  nextIntent,
50
- nextCall: (0, index_js_3.buildNextCall)({ stateToken: inputStateToken, ackToken: inputAckToken, isComplete: isCompleteNow, pending: meta }),
56
+ nextCall: (0, index_js_3.buildNextCall)({ stateToken: inputStateToken, ackToken: inputAckToken, isComplete: isCompleteNow, pending: metaOrNull }),
51
57
  blockers,
52
58
  retryable: undefined,
53
59
  retryAckToken: undefined,
@@ -114,8 +120,9 @@ function buildAdvancedReplayResponse(args) {
114
120
  return (0, neverthrow_1.errAsync)({ kind: 'token_signing_failed', cause: retryAckTokenRes.error });
115
121
  }
116
122
  const validation = (0, validation_loader_js_1.loadValidationResultV1)(truth.events, String(blocked.validationRef)).unwrapOr(null) ?? undefined;
117
- const meta = pending
118
- ? (0, v2_execution_helpers_js_1.renderPendingPromptOrDefault)({
123
+ let blockedMeta = null;
124
+ if (pending) {
125
+ const result = (0, prompt_renderer_js_1.renderPendingPrompt)({
119
126
  workflow,
120
127
  stepId: String(pending.stepId),
121
128
  loopPath: pending.loopPath,
@@ -123,28 +130,33 @@ function buildAdvancedReplayResponse(args) {
123
130
  runId: (0, index_js_2.asRunId)(String(runId)),
124
131
  nodeId: (0, index_js_2.asNodeId)(String(toNodeIdBranded)),
125
132
  rehydrateOnly: false,
126
- })
127
- : null;
133
+ });
134
+ if (result.isErr()) {
135
+ return (0, neverthrow_1.errAsync)({ kind: 'prompt_render_failed', message: result.error.message });
136
+ }
137
+ blockedMeta = result.value;
138
+ }
128
139
  const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded });
129
- const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: meta });
140
+ const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: blockedMeta });
130
141
  return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
131
142
  kind: 'blocked',
132
143
  stateToken: nextStateTokenRes.value,
133
144
  ackToken: pending ? nextAckTokenRes.value : undefined,
134
145
  checkpointToken: pending ? nextCheckpointTokenRes.value : undefined,
135
146
  isComplete,
136
- pending: meta ? { stepId: meta.stepId, title: meta.title, prompt: meta.prompt } : null,
147
+ pending: blockedMeta ? { stepId: blockedMeta.stepId, title: blockedMeta.title, prompt: blockedMeta.prompt } : null,
137
148
  preferences,
138
149
  nextIntent,
139
- nextCall: (0, index_js_3.buildNextCall)({ stateToken: nextStateTokenRes.value, ackToken: pending ? nextAckTokenRes.value : undefined, isComplete, pending: meta, retryable, retryAckToken: retryAckTokenRes.value }),
150
+ nextCall: (0, index_js_3.buildNextCall)({ stateToken: nextStateTokenRes.value, ackToken: pending ? nextAckTokenRes.value : undefined, isComplete, pending: blockedMeta, retryable, retryAckToken: retryAckTokenRes.value }),
140
151
  blockers,
141
152
  retryable,
142
153
  retryAckToken: retryAckTokenRes.value,
143
154
  validation,
144
155
  }));
145
156
  }
146
- const meta = pending
147
- ? (0, v2_execution_helpers_js_1.renderPendingPromptOrDefault)({
157
+ let okMeta = null;
158
+ if (pending) {
159
+ const result = (0, prompt_renderer_js_1.renderPendingPrompt)({
148
160
  workflow,
149
161
  stepId: String(pending.stepId),
150
162
  loopPath: pending.loopPath,
@@ -152,20 +164,24 @@ function buildAdvancedReplayResponse(args) {
152
164
  runId: (0, index_js_2.asRunId)(String(runId)),
153
165
  nodeId: (0, index_js_2.asNodeId)(String(toNodeIdBranded)),
154
166
  rehydrateOnly: false,
155
- })
156
- : { stepId: '', title: '', prompt: '', requireConfirmation: false };
167
+ });
168
+ if (result.isErr()) {
169
+ return (0, neverthrow_1.errAsync)({ kind: 'prompt_render_failed', message: result.error.message });
170
+ }
171
+ okMeta = result.value;
172
+ }
157
173
  const preferences = (0, v2_execution_helpers_js_1.derivePreferencesOrDefault)({ truth, runId, nodeId: toNodeIdBranded });
158
- const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: pending ? meta : null });
174
+ const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete, pending: okMeta });
159
175
  return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2ContinueWorkflowOutputSchema.parse({
160
176
  kind: 'ok',
161
177
  stateToken: nextStateTokenRes.value,
162
178
  ackToken: pending ? nextAckTokenRes.value : undefined,
163
179
  checkpointToken: pending ? nextCheckpointTokenRes.value : undefined,
164
180
  isComplete,
165
- pending: pending ? { stepId: meta.stepId, title: meta.title, prompt: meta.prompt } : null,
181
+ pending: okMeta ? { stepId: okMeta.stepId, title: okMeta.title, prompt: okMeta.prompt } : null,
166
182
  preferences,
167
183
  nextIntent,
168
- nextCall: (0, index_js_3.buildNextCall)({ stateToken: nextStateTokenRes.value, ackToken: pending ? nextAckTokenRes.value : undefined, isComplete, pending: pending ? meta : null }),
184
+ nextCall: (0, index_js_3.buildNextCall)({ stateToken: nextStateTokenRes.value, ackToken: pending ? nextAckTokenRes.value : undefined, isComplete, pending: okMeta }),
169
185
  }));
170
186
  }
171
187
  function replayFromRecordedAdvance(args) {
@@ -15,13 +15,14 @@ const hashing_js_1 = require("../../../v2/durable-core/canonical/hashing.js");
15
15
  const observation_builder_js_1 = require("../../../v2/durable-core/domain/observation-builder.js");
16
16
  const workflow_source_js_1 = require("../../../types/workflow-source.js");
17
17
  const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
18
- const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
18
+ const prompt_renderer_js_1 = require("../../../v2/durable-core/domain/prompt-renderer.js");
19
19
  const v2_workspace_resolution_js_1 = require("../v2-workspace-resolution.js");
20
20
  const v2_token_ops_js_1 = require("../v2-token-ops.js");
21
21
  const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
22
- const v2_execution_helpers_js_2 = require("../v2-execution-helpers.js");
22
+ const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
23
23
  const constants_js_1 = require("../../../v2/durable-core/constants.js");
24
24
  const index_js_2 = require("./index.js");
25
+ const start_construction_js_1 = require("../../../v2/durable-core/domain/start-construction.js");
25
26
  function loadAndPinWorkflow(args) {
26
27
  const { workflowId, workflowService, crypto, pinnedStore } = args;
27
28
  return neverthrow_1.ResultAsync.fromPromise(workflowService.getWorkflowById(workflowId), (e) => ({
@@ -32,14 +33,20 @@ function loadAndPinWorkflow(args) {
32
33
  if (!workflow) {
33
34
  return (0, neverthrow_1.errAsync)({ kind: 'workflow_not_found', workflowId: (0, index_js_1.asWorkflowId)(workflowId) });
34
35
  }
35
- const firstStep = workflow.definition.steps[0];
36
- if (!firstStep) {
36
+ if (workflow.definition.steps.length === 0) {
37
37
  return (0, neverthrow_1.errAsync)({ kind: 'workflow_has_no_steps', workflowId: (0, index_js_1.asWorkflowId)(workflowId) });
38
38
  }
39
- return (0, neverthrow_1.okAsync)({ workflow, firstStep });
39
+ return (0, neverthrow_1.okAsync)({ workflow });
40
40
  })
41
- .andThen(({ workflow, firstStep }) => {
42
- const compiled = (0, v1_to_v2_shim_js_1.compileV1WorkflowToPinnedSnapshot)(workflow);
41
+ .andThen(({ workflow }) => {
42
+ const normalizeResult = (0, v1_to_v2_shim_js_1.normalizeV1WorkflowToPinnedSnapshot)(workflow);
43
+ if (normalizeResult.isErr()) {
44
+ return (0, neverthrow_1.errAsync)({
45
+ kind: 'workflow_compile_failed',
46
+ message: normalizeResult.error.message,
47
+ });
48
+ }
49
+ const compiled = normalizeResult.value;
43
50
  const workflowHashRes = (0, hashing_js_1.workflowHashForCompiledSnapshot)(compiled, crypto);
44
51
  if (workflowHashRes.isErr()) {
45
52
  return (0, neverthrow_1.errAsync)({ kind: 'hash_computation_failed', message: workflowHashRes.error.message });
@@ -63,6 +70,14 @@ function loadAndPinWorkflow(args) {
63
70
  });
64
71
  }
65
72
  const pinnedWorkflow = (0, workflow_js_1.createWorkflow)(pinned.definition, (0, workflow_source_js_1.createBundledSource)());
73
+ const resolution = (0, start_construction_js_1.resolveFirstStep)(workflow, pinned);
74
+ if (resolution.isErr()) {
75
+ const error = resolution.error.reason === 'no_steps'
76
+ ? { kind: 'workflow_has_no_steps', workflowId: (0, index_js_1.asWorkflowId)(resolution.error.detail) }
77
+ : { kind: 'invariant_violation', message: resolution.error.detail };
78
+ return (0, neverthrow_1.errAsync)(error);
79
+ }
80
+ const firstStep = resolution.value;
66
81
  return (0, neverthrow_1.okAsync)({ workflow, firstStep, workflowHash, pinnedWorkflow });
67
82
  });
68
83
  });
@@ -126,12 +141,12 @@ function buildInitialEvents(args) {
126
141
  changeId,
127
142
  source: 'system',
128
143
  delta: [
129
- { key: 'autonomy', value: v2_execution_helpers_js_2.defaultPreferences.autonomy },
130
- { key: 'riskPolicy', value: v2_execution_helpers_js_2.defaultPreferences.riskPolicy },
144
+ { key: 'autonomy', value: v2_execution_helpers_js_1.defaultPreferences.autonomy },
145
+ { key: 'riskPolicy', value: v2_execution_helpers_js_1.defaultPreferences.riskPolicy },
131
146
  ],
132
147
  effective: {
133
- autonomy: v2_execution_helpers_js_2.defaultPreferences.autonomy,
134
- riskPolicy: v2_execution_helpers_js_2.defaultPreferences.riskPolicy,
148
+ autonomy: v2_execution_helpers_js_1.defaultPreferences.autonomy,
149
+ riskPolicy: v2_execution_helpers_js_1.defaultPreferences.riskPolicy,
135
150
  },
136
151
  },
137
152
  },
@@ -278,7 +293,7 @@ function executeStartWorkflow(input, ctx) {
278
293
  workflowHashRef: wfRefRes.value,
279
294
  ports: tokenCodecPorts,
280
295
  }).andThen((tokens) => {
281
- const meta = (0, v2_execution_helpers_js_1.renderPendingPromptOrDefault)({
296
+ const metaResult = (0, prompt_renderer_js_1.renderPendingPrompt)({
282
297
  workflow: pinnedWorkflow,
283
298
  stepId: firstStep.id,
284
299
  loopPath: [],
@@ -287,8 +302,15 @@ function executeStartWorkflow(input, ctx) {
287
302
  nodeId: (0, index_js_1.asNodeId)(String(nodeId)),
288
303
  rehydrateOnly: false,
289
304
  });
305
+ if (metaResult.isErr()) {
306
+ return (0, neverthrow_1.errAsync)({
307
+ kind: 'prompt_render_failed',
308
+ message: metaResult.error.message,
309
+ });
310
+ }
311
+ const meta = metaResult.value;
290
312
  const pending = { stepId: meta.stepId, title: meta.title, prompt: meta.prompt };
291
- const preferences = v2_execution_helpers_js_2.defaultPreferences;
313
+ const preferences = v2_execution_helpers_js_1.defaultPreferences;
292
314
  const nextIntent = (0, v2_state_conversion_js_1.deriveNextIntent)({ rehydrateOnly: false, isComplete: false, pending: meta });
293
315
  return (0, neverthrow_1.okAsync)(output_schemas_js_1.V2StartWorkflowOutputSchema.parse({
294
316
  stateToken: tokens.stateToken,
@@ -25,6 +25,9 @@ export type StartWorkflowError = {
25
25
  } | {
26
26
  readonly kind: 'workflow_has_no_steps';
27
27
  readonly workflowId: WorkflowId;
28
+ } | {
29
+ readonly kind: 'workflow_compile_failed';
30
+ readonly message: string;
28
31
  } | {
29
32
  readonly kind: 'keyring_load_failed';
30
33
  readonly cause: KeyringError;
@@ -43,6 +46,9 @@ export type StartWorkflowError = {
43
46
  } | {
44
47
  readonly kind: 'token_signing_failed';
45
48
  readonly cause: TokenDecodeErrorV2 | TokenVerifyErrorV2 | TokenSignErrorV2;
49
+ } | {
50
+ readonly kind: 'prompt_render_failed';
51
+ readonly message: string;
46
52
  };
47
53
  export type ContinueWorkflowError = {
48
54
  readonly kind: 'precondition_failed';
@@ -86,6 +92,9 @@ export type ContinueWorkflowError = {
86
92
  } | {
87
93
  readonly kind: 'advance_execution_failed';
88
94
  readonly cause: ExecutionSessionGateErrorV2 | SessionEventLogStoreError;
95
+ } | {
96
+ readonly kind: 'prompt_render_failed';
97
+ readonly message: string;
89
98
  };
90
99
  export declare function mapStartWorkflowErrorToToolError(e: StartWorkflowError): ToolFailure;
91
100
  export declare function mapContinueWorkflowErrorToToolError(e: ContinueWorkflowError): ToolFailure;
@@ -98,19 +107,8 @@ export declare function mapExecutionSessionGateErrorToToolError(e: ExecutionSess
98
107
  export declare function mapSnapshotStoreErrorToToolError(e: SnapshotStoreError, _suggestion?: string): ToolFailure;
99
108
  export declare function mapPinnedWorkflowStoreErrorToToolError(e: PinnedWorkflowStoreError, _suggestion?: string): ToolFailure;
100
109
  export declare function mapSessionOrGateErrorToToolError(e: SessionEventLogStoreError | ExecutionSessionGateErrorV2): ToolFailure;
101
- import type { LoopPathFrameV1 } from '../../v2/durable-core/schemas/execution-snapshot/index.js';
102
110
  import type { RunId, NodeId } from '../../v2/durable-core/ids/index.js';
103
111
  import type { LoadedSessionTruthV2 } from '../../v2/ports/session-event-log-store.port.js';
104
- import { type StepMetadata } from '../../v2/durable-core/domain/prompt-renderer.js';
105
- export declare function renderPendingPromptOrDefault(args: {
106
- readonly workflow: ReturnType<typeof import('../../types/workflow.js').createWorkflow>;
107
- readonly stepId: string;
108
- readonly loopPath: readonly LoopPathFrameV1[];
109
- readonly truth: LoadedSessionTruthV2;
110
- readonly runId: RunId;
111
- readonly nodeId: NodeId;
112
- readonly rehydrateOnly: boolean;
113
- }): StepMetadata;
114
112
  export type PreferencesV2 = {
115
113
  readonly autonomy: 'guided' | 'full_auto_stop_on_user_deps' | 'full_auto_never_stop';
116
114
  readonly riskPolicy: 'conservative' | 'balanced' | 'aggressive';
@@ -13,7 +13,6 @@ exports.mapExecutionSessionGateErrorToToolError = mapExecutionSessionGateErrorTo
13
13
  exports.mapSnapshotStoreErrorToToolError = mapSnapshotStoreErrorToToolError;
14
14
  exports.mapPinnedWorkflowStoreErrorToToolError = mapPinnedWorkflowStoreErrorToToolError;
15
15
  exports.mapSessionOrGateErrorToToolError = mapSessionOrGateErrorToToolError;
16
- exports.renderPendingPromptOrDefault = renderPendingPromptOrDefault;
17
16
  exports.derivePreferencesOrDefault = derivePreferencesOrDefault;
18
17
  const types_js_1 = require("../types.js");
19
18
  const types_js_2 = require("../types.js");
@@ -37,6 +36,8 @@ function mapStartWorkflowErrorToToolError(e) {
37
36
  return (0, types_js_1.errNotRetryable)('PRECONDITION_FAILED', `Workflow "${e.workflowId}" has no steps and cannot be started.`, {
38
37
  suggestion: 'Tell the user: "This workflow definition is empty (no steps). The workflow JSON file needs to be fixed."',
39
38
  });
39
+ case 'workflow_compile_failed':
40
+ return (0, types_js_1.errNotRetryable)('PRECONDITION_FAILED', `Workflow definition is invalid and cannot be started: ${e.message}`, { suggestion: 'Tell the user: "The workflow definition has an authoring error that prevents execution. Fix the workflow JSON file and try again."' });
40
41
  case 'keyring_load_failed':
41
42
  return mapKeyringErrorToToolError(e.cause);
42
43
  case 'hash_computation_failed':
@@ -49,6 +50,8 @@ function mapStartWorkflowErrorToToolError(e) {
49
50
  return mapSessionOrGateErrorToToolError(e.cause);
50
51
  case 'token_signing_failed':
51
52
  return mapTokenSigningErrorToToolError(e.cause);
53
+ case 'prompt_render_failed':
54
+ return (0, types_js_1.errNotRetryable)('INTERNAL_ERROR', `WorkRail could not render the pending step prompt: ${e.message}`, { suggestion: internalSuggestion('Retry start_workflow.', 'A step referenced by the workflow was not found in the executable definition.') });
52
55
  default:
53
56
  const _exhaustive = e;
54
57
  return _exhaustive;
@@ -82,6 +85,8 @@ function mapContinueWorkflowErrorToToolError(e) {
82
85
  return mapTokenSigningErrorToToolError(e.cause);
83
86
  case 'advance_execution_failed':
84
87
  return mapSessionOrGateErrorToToolError(e.cause);
88
+ case 'prompt_render_failed':
89
+ return (0, types_js_1.errNotRetryable)('INTERNAL_ERROR', `WorkRail could not render the pending step prompt: ${e.message}`, { suggestion: internalSuggestion('Retry continue_workflow.', 'A step referenced by the workflow was not found in the executable definition.') });
85
90
  default:
86
91
  const _exhaustive = e;
87
92
  return _exhaustive;
@@ -257,23 +262,6 @@ function mapSessionOrGateErrorToToolError(e) {
257
262
  const _exhaustive = e;
258
263
  return _exhaustive;
259
264
  }
260
- const prompt_renderer_js_1 = require("../../v2/durable-core/domain/prompt-renderer.js");
261
- function renderPendingPromptOrDefault(args) {
262
- return (0, prompt_renderer_js_1.renderPendingPrompt)({
263
- workflow: args.workflow,
264
- stepId: args.stepId,
265
- loopPath: args.loopPath,
266
- truth: args.truth,
267
- runId: args.runId,
268
- nodeId: args.nodeId,
269
- rehydrateOnly: args.rehydrateOnly,
270
- }).unwrapOr({
271
- stepId: args.stepId,
272
- title: args.stepId,
273
- prompt: `Pending step: ${args.stepId}`,
274
- requireConfirmation: false,
275
- });
276
- }
277
265
  const constants_js_1 = require("../../v2/durable-core/constants.js");
278
266
  const preferences_js_1 = require("../../v2/projections/preferences.js");
279
267
  exports.defaultPreferences = {
@@ -238,12 +238,12 @@ export declare const V2PendingStepSchema: z.ZodObject<{
238
238
  prompt: z.ZodString;
239
239
  }, "strip", z.ZodTypeAny, {
240
240
  stepId: string;
241
- prompt: string;
242
241
  title: string;
242
+ prompt: string;
243
243
  }, {
244
244
  stepId: string;
245
- prompt: string;
246
245
  title: string;
246
+ prompt: string;
247
247
  }>;
248
248
  export declare const V2PreferencesSchema: z.ZodObject<{
249
249
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -485,12 +485,12 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
485
485
  prompt: z.ZodString;
486
486
  }, "strip", z.ZodTypeAny, {
487
487
  stepId: string;
488
- prompt: string;
489
488
  title: string;
489
+ prompt: string;
490
490
  }, {
491
491
  stepId: string;
492
- prompt: string;
493
492
  title: string;
493
+ prompt: string;
494
494
  }>>;
495
495
  preferences: z.ZodObject<{
496
496
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -552,8 +552,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
552
552
  kind: "ok";
553
553
  pending: {
554
554
  stepId: string;
555
- prompt: string;
556
555
  title: string;
556
+ prompt: string;
557
557
  } | null;
558
558
  isComplete: boolean;
559
559
  stateToken: string;
@@ -579,8 +579,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
579
579
  kind: "ok";
580
580
  pending: {
581
581
  stepId: string;
582
- prompt: string;
583
582
  title: string;
583
+ prompt: string;
584
584
  } | null;
585
585
  isComplete: boolean;
586
586
  stateToken: string;
@@ -614,12 +614,12 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
614
614
  prompt: z.ZodString;
615
615
  }, "strip", z.ZodTypeAny, {
616
616
  stepId: string;
617
- prompt: string;
618
617
  title: string;
618
+ prompt: string;
619
619
  }, {
620
620
  stepId: string;
621
- prompt: string;
622
621
  title: string;
622
+ prompt: string;
623
623
  }>>;
624
624
  preferences: z.ZodObject<{
625
625
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -887,8 +887,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
887
887
  };
888
888
  pending: {
889
889
  stepId: string;
890
- prompt: string;
891
890
  title: string;
891
+ prompt: string;
892
892
  } | null;
893
893
  isComplete: boolean;
894
894
  stateToken: string;
@@ -942,8 +942,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
942
942
  };
943
943
  pending: {
944
944
  stepId: string;
945
- prompt: string;
946
945
  title: string;
946
+ prompt: string;
947
947
  } | null;
948
948
  isComplete: boolean;
949
949
  stateToken: string;
@@ -975,8 +975,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
975
975
  kind: "ok";
976
976
  pending: {
977
977
  stepId: string;
978
- prompt: string;
979
978
  title: string;
979
+ prompt: string;
980
980
  } | null;
981
981
  isComplete: boolean;
982
982
  stateToken: string;
@@ -1024,8 +1024,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1024
1024
  };
1025
1025
  pending: {
1026
1026
  stepId: string;
1027
- prompt: string;
1028
1027
  title: string;
1028
+ prompt: string;
1029
1029
  } | null;
1030
1030
  isComplete: boolean;
1031
1031
  stateToken: string;
@@ -1057,8 +1057,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1057
1057
  kind: "ok";
1058
1058
  pending: {
1059
1059
  stepId: string;
1060
- prompt: string;
1061
1060
  title: string;
1061
+ prompt: string;
1062
1062
  } | null;
1063
1063
  isComplete: boolean;
1064
1064
  stateToken: string;
@@ -1106,8 +1106,8 @@ export declare const V2ContinueWorkflowOutputSchema: z.ZodEffects<z.ZodDiscrimin
1106
1106
  };
1107
1107
  pending: {
1108
1108
  stepId: string;
1109
- prompt: string;
1110
1109
  title: string;
1110
+ prompt: string;
1111
1111
  } | null;
1112
1112
  isComplete: boolean;
1113
1113
  stateToken: string;
@@ -1264,12 +1264,12 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1264
1264
  prompt: z.ZodString;
1265
1265
  }, "strip", z.ZodTypeAny, {
1266
1266
  stepId: string;
1267
- prompt: string;
1268
1267
  title: string;
1268
+ prompt: string;
1269
1269
  }, {
1270
1270
  stepId: string;
1271
- prompt: string;
1272
1271
  title: string;
1272
+ prompt: string;
1273
1273
  }>>;
1274
1274
  preferences: z.ZodObject<{
1275
1275
  autonomy: z.ZodEnum<["guided", "full_auto_stop_on_user_deps", "full_auto_never_stop"]>;
@@ -1330,8 +1330,8 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1330
1330
  }, "strip", z.ZodTypeAny, {
1331
1331
  pending: {
1332
1332
  stepId: string;
1333
- prompt: string;
1334
1333
  title: string;
1334
+ prompt: string;
1335
1335
  } | null;
1336
1336
  isComplete: boolean;
1337
1337
  stateToken: string;
@@ -1356,8 +1356,8 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1356
1356
  }, {
1357
1357
  pending: {
1358
1358
  stepId: string;
1359
- prompt: string;
1360
1359
  title: string;
1360
+ prompt: string;
1361
1361
  } | null;
1362
1362
  isComplete: boolean;
1363
1363
  stateToken: string;
@@ -1382,8 +1382,8 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1382
1382
  }>, {
1383
1383
  pending: {
1384
1384
  stepId: string;
1385
- prompt: string;
1386
1385
  title: string;
1386
+ prompt: string;
1387
1387
  } | null;
1388
1388
  isComplete: boolean;
1389
1389
  stateToken: string;
@@ -1408,8 +1408,8 @@ export declare const V2StartWorkflowOutputSchema: z.ZodEffects<z.ZodObject<{
1408
1408
  }, {
1409
1409
  pending: {
1410
1410
  stepId: string;
1411
- prompt: string;
1412
1411
  title: string;
1412
+ prompt: string;
1413
1413
  } | null;
1414
1414
  isComplete: boolean;
1415
1415
  stateToken: string;
@@ -12,6 +12,7 @@ export interface IWorkflowStorage extends IWorkflowReader {
12
12
  export interface ICompositeWorkflowStorage extends IWorkflowReader {
13
13
  readonly kind: 'composite';
14
14
  getSources(): readonly WorkflowSource[];
15
+ getStorageInstances(): readonly IWorkflowStorage[];
15
16
  }
16
17
  export type AnyWorkflowStorage = IWorkflowStorage | ICompositeWorkflowStorage;
17
18
  export declare function isSingleSourceStorage(storage: AnyWorkflowStorage): storage is IWorkflowStorage;
@@ -170,16 +170,22 @@ function loadRecoveryProjections(args) {
170
170
  }
171
171
  function renderPendingPrompt(args) {
172
172
  const step = (0, workflow_js_1.getStepById)(args.workflow, args.stepId);
173
- const baseTitle = step?.title ?? args.stepId;
174
- const basePrompt = step?.prompt ?? `Pending step: ${args.stepId}`;
175
- const requireConfirmation = Boolean(step?.requireConfirmation);
176
- const functionReferences = step?.functionReferences ?? [];
177
- const outputContract = step && typeof step === 'object' && 'outputContract' in step
173
+ if (!step) {
174
+ return (0, neverthrow_1.err)({
175
+ code: 'RENDER_FAILED',
176
+ message: `Step '${args.stepId}' not found in workflow '${args.workflow.definition.id}'`,
177
+ });
178
+ }
179
+ const baseTitle = step.title;
180
+ const basePrompt = step.prompt;
181
+ const requireConfirmation = Boolean(step.requireConfirmation);
182
+ const functionReferences = step.functionReferences ?? [];
183
+ const outputContract = 'outputContract' in step
178
184
  ? step.outputContract
179
185
  : undefined;
180
186
  const isExitStep = outputContract?.contractRef === index_js_2.LOOP_CONTROL_CONTRACT_REF;
181
187
  const loopBanner = buildLoopContextBanner({ loopPath: args.loopPath, isExitStep });
182
- const validationCriteria = step?.validationCriteria;
188
+ const validationCriteria = step.validationCriteria;
183
189
  const requirements = (0, validation_requirements_extractor_js_1.extractValidationRequirements)(validationCriteria);
184
190
  const requirementsSection = requirements.length > 0
185
191
  ? `\n\n**OUTPUT REQUIREMENTS:**\n${requirements.map(r => `- ${r}`).join('\n')}`
@@ -189,7 +195,7 @@ function renderPendingPrompt(args) {
189
195
  ? `\n\n**OUTPUT REQUIREMENTS (System):**\n${contractRequirements.map(r => `- ${r}`).join('\n')}`
190
196
  : '';
191
197
  const isNotesOptional = outputContract !== undefined ||
192
- (step !== null && step !== undefined && 'notesOptional' in step && step.notesOptional === true);
198
+ ('notesOptional' in step && step.notesOptional === true);
193
199
  const notesSection = isNotesOptional
194
200
  ? ''
195
201
  : '\n\n**NOTES REQUIRED (System):** You must include `output.notesMarkdown` when advancing. ' +
@@ -0,0 +1,22 @@
1
+ import type { Workflow } from '../../../types/workflow.js';
2
+ import type { CompiledWorkflowSnapshotV1 } from '../schemas/compiled-workflow/index.js';
3
+ import { type Result } from 'neverthrow';
4
+ export type StartabilityFailure = {
5
+ readonly reason: 'no_steps';
6
+ readonly detail: 'Workflow has no steps in authored form';
7
+ } | {
8
+ readonly reason: 'first_step_not_in_executable';
9
+ readonly authoredStepId: string;
10
+ readonly detail: string;
11
+ } | {
12
+ readonly reason: 'no_reachable_step';
13
+ readonly detail: 'Interpreter returned isComplete=true with zero completed steps';
14
+ } | {
15
+ readonly reason: 'interpreter_error';
16
+ readonly detail: string;
17
+ };
18
+ export declare function resolveFirstStep(authoredWorkflow: Workflow, pinnedSnapshot: Extract<CompiledWorkflowSnapshotV1, {
19
+ sourceKind: 'v1_pinned';
20
+ }>): Result<{
21
+ readonly id: string;
22
+ }, StartabilityFailure>;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveFirstStep = resolveFirstStep;
4
+ const neverthrow_1 = require("neverthrow");
5
+ function resolveFirstStep(authoredWorkflow, pinnedSnapshot) {
6
+ const firstStep = authoredWorkflow.definition.steps[0];
7
+ if (!firstStep) {
8
+ return (0, neverthrow_1.err)({
9
+ reason: 'no_steps',
10
+ detail: 'Workflow has no steps in authored form',
11
+ });
12
+ }
13
+ const firstStepId = firstStep.id;
14
+ const definition = pinnedSnapshot.definition;
15
+ const steps = typeof definition === 'object' &&
16
+ definition !== null &&
17
+ !Array.isArray(definition) &&
18
+ 'steps' in definition &&
19
+ Array.isArray(definition.steps)
20
+ ? definition.steps
21
+ : [];
22
+ const executableStep = steps.find((s) => typeof s === 'object' && s !== null && 'id' in s && s.id === firstStepId);
23
+ if (!executableStep) {
24
+ return (0, neverthrow_1.err)({
25
+ reason: 'first_step_not_in_executable',
26
+ authoredStepId: firstStepId,
27
+ detail: `Step '${firstStepId}' from authored workflow steps[0] not found in executable workflow`,
28
+ });
29
+ }
30
+ return (0, neverthrow_1.ok)({ id: firstStepId });
31
+ }