@bratsos/workflow-engine 0.6.0 → 0.8.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 (42) hide show
  1. package/README.md +93 -0
  2. package/dist/{chunk-2MWO6UVR.js → chunk-NANAXHS5.js} +2 -2
  3. package/dist/chunk-NANAXHS5.js.map +1 -0
  4. package/dist/{chunk-DIADEUGZ.js → chunk-TWYPSP7P.js} +99 -7
  5. package/dist/chunk-TWYPSP7P.js.map +1 -0
  6. package/dist/{chunk-HKGZ2WHJ.js → chunk-WWK2SPN7.js} +16 -9
  7. package/dist/chunk-WWK2SPN7.js.map +1 -0
  8. package/dist/{chunk-HOGDFLCG.js → chunk-XPWAEYOO.js} +449 -59
  9. package/dist/chunk-XPWAEYOO.js.map +1 -0
  10. package/dist/{client-llB6XpHS.d.ts → client-YFKVt4p7.d.ts} +10 -21
  11. package/dist/client.d.ts +4 -4
  12. package/dist/client.js +1 -1
  13. package/dist/conventions/index.d.ts +114 -0
  14. package/dist/conventions/index.js +95 -0
  15. package/dist/conventions/index.js.map +1 -0
  16. package/dist/{events-D_P24UaY.d.ts → events-B3XPPu0c.d.ts} +23 -1
  17. package/dist/{index-sGgV8JNu.d.ts → index-CL0KmlyW.d.ts} +10 -1
  18. package/dist/index.d.ts +10 -10
  19. package/dist/index.js +5 -5
  20. package/dist/{interface-DCdddCe0.d.ts → interface-BPz138Hf.d.ts} +110 -2
  21. package/dist/kernel/index.d.ts +6 -6
  22. package/dist/kernel/index.js +2 -2
  23. package/dist/kernel/testing/index.d.ts +3 -3
  24. package/dist/persistence/index.d.ts +2 -2
  25. package/dist/persistence/index.js +2 -2
  26. package/dist/persistence/prisma/index.d.ts +2 -2
  27. package/dist/persistence/prisma/index.js +2 -2
  28. package/dist/{plugins-Oyo_iu0l.d.ts → plugins-zT-aIcEZ.d.ts} +63 -4
  29. package/dist/{ports-ChGnJcn2.d.ts → ports-DUL4hlQr.d.ts} +11 -2
  30. package/dist/{stage-_7BKqqUG.d.ts → stage-WuK0mfrC.d.ts} +81 -1
  31. package/dist/testing/index.d.ts +8 -1
  32. package/dist/testing/index.js +88 -2
  33. package/dist/testing/index.js.map +1 -1
  34. package/package.json +6 -1
  35. package/skills/workflow-engine/SKILL.md +58 -1
  36. package/skills/workflow-engine/migrations/README.md +275 -0
  37. package/skills/workflow-engine/migrations/migrate-0.7-to-0.8.md +528 -0
  38. package/skills/workflow-engine/references/10-annotations.md +479 -0
  39. package/dist/chunk-2MWO6UVR.js.map +0 -1
  40. package/dist/chunk-DIADEUGZ.js.map +0 -1
  41. package/dist/chunk-HKGZ2WHJ.js.map +0 -1
  42. package/dist/chunk-HOGDFLCG.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { i as AnnotationActor } from './interface-BPz138Hf.js';
2
3
 
3
4
  /**
4
5
  * Core type definitions for Workflow System v2
@@ -83,6 +84,83 @@ type StageMode = "sync" | "async-batch";
83
84
  * - Can suspend workflow for long-running batch operations
84
85
  */
85
86
 
87
+ /**
88
+ * Single-attribute form options.
89
+ *
90
+ * The `actor` field accepts an `AnnotationActor` ({ kind?, id?, version? }).
91
+ * `payload` is a separate blob slot for non-queryable rich data.
92
+ * `idempotencyKey` opts the annotation into the unique constraint on
93
+ * `(workflowRunId, key, idempotencyKey)` so retries are deduped.
94
+ */
95
+ interface AnnotateOpts {
96
+ actor?: AnnotationActor;
97
+ payload?: Record<string, unknown>;
98
+ idempotencyKey?: string;
99
+ /**
100
+ * If true, the engine writes an `annotation:created` outbox event in
101
+ * the same transaction as the annotation row. Useful for plugins or
102
+ * external systems (audit pipelines, SIEM, live dashboards) that
103
+ * want push notifications on provenance writes. Off by default.
104
+ */
105
+ emitEvent?: boolean;
106
+ }
107
+ /**
108
+ * Batch form — multiple attributes share one envelope (actor / payload /
109
+ * idempotencyKey / emitEvent). Each attribute becomes one row in
110
+ * WorkflowAnnotation; if `emitEvent` is set, each row also emits its
111
+ * own `annotation:created` outbox event.
112
+ */
113
+ interface AnnotateBatch {
114
+ attributes: Record<string, unknown>;
115
+ actor?: AnnotationActor;
116
+ payload?: Record<string, unknown>;
117
+ idempotencyKey?: string;
118
+ emitEvent?: boolean;
119
+ }
120
+ /**
121
+ * Stability level for a well-known annotation key, attached at definition
122
+ * time and surfaced to IDEs through the conventions module.
123
+ *
124
+ * Policy: once a key is `stable`, it is immutable. Renames and value-type
125
+ * changes must ship as new keys; the old key gets a `@deprecated` JSDoc
126
+ * tag. No env-var stability opt-in (we deliberately do not copy
127
+ * OpenTelemetry's `OTEL_SEMCONV_STABILITY_OPT_IN`).
128
+ */
129
+ type Stability = "stable" | "experimental" | "deprecated";
130
+ /**
131
+ * Typed annotation key. The phantom `_valueType` parameter lets
132
+ * `ctx.annotate(key, value)` enforce that `value` matches `T` at compile
133
+ * time when the key was defined with `typedKey<T>(...)`. The marker is
134
+ * never set at runtime — only the `key` string is.
135
+ */
136
+ interface TypedKey<T = unknown> {
137
+ readonly key: string;
138
+ readonly stability: Stability;
139
+ readonly description?: string;
140
+ /** Phantom — never populated. Used only for `T` inference. */
141
+ readonly _valueType?: T;
142
+ }
143
+ /**
144
+ * Overloaded callable supporting three forms:
145
+ *
146
+ * - **Typed key**: `ctx.annotate(Decision.outcome, "low")` — value type
147
+ * is inferred from the TypedKey, giving compile-time linkage between
148
+ * well-known keys and their expected value shapes.
149
+ * - **String key**: `ctx.annotate("custom.namespace.key", value)` —
150
+ * escape hatch for org-defined conventions.
151
+ * - **Batch**: `ctx.annotate({ attributes: {...}, actor?, ... })` —
152
+ * emit several related attributes sharing one envelope.
153
+ *
154
+ * All three return `void` from the caller's perspective; writes are
155
+ * buffered on the context and flushed inside the stage-completion
156
+ * transaction. `undefined` values are dropped (OTel pattern: callers can
157
+ * write `ctx.annotate("x.id", maybeId)` without guarding).
158
+ */
159
+ interface AnnotateFn {
160
+ <T>(key: TypedKey<T>, value: T, opts?: AnnotateOpts): void;
161
+ (key: string, value: unknown, opts?: AnnotateOpts): void;
162
+ (args: AnnotateBatch): void;
163
+ }
86
164
  interface StageContext<TInput, TConfig, TWorkflowContext = Record<string, unknown>> {
87
165
  workflowRunId: string;
88
166
  stageId: string;
@@ -96,6 +174,7 @@ interface StageContext<TInput, TConfig, TWorkflowContext = Record<string, unknow
96
174
  onProgress: (update: ProgressUpdate) => void;
97
175
  onLog: (level: LogLevel, message: string, meta?: Record<string, unknown>) => void;
98
176
  log: (level: LogLevel, message: string, meta?: Record<string, unknown>) => void;
177
+ annotate: AnnotateFn;
99
178
  storage: StageStorage;
100
179
  workflowContext: Partial<TWorkflowContext>;
101
180
  }
@@ -118,6 +197,7 @@ interface CheckCompletionContext<TConfig> {
118
197
  config: TConfig;
119
198
  onLog: (level: LogLevel, message: string, meta?: Record<string, unknown>) => void;
120
199
  log: (level: LogLevel, message: string, meta?: Record<string, unknown>) => void;
200
+ annotate: AnnotateFn;
121
201
  storage: StageStorage;
122
202
  }
123
203
  interface Stage<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TConfig extends z.ZodTypeAny, TWorkflowContext = Record<string, unknown>, TId extends string = string> {
@@ -141,4 +221,4 @@ interface Stage<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny, TConf
141
221
  estimateCost?: (input: z.infer<TInput>, config: z.infer<TConfig>) => number;
142
222
  }
143
223
 
144
- export { type CheckCompletionContext as C, type LogLevel as L, type Stage as S, type StageResult as a, type StageContext as b, SuspendedStateSchema as c, type CompletionCheckResult as d };
224
+ export { type CheckCompletionContext as C, type LogLevel as L, type Stability as S, type TypedKey as T, type Stage as a, type StageResult as b, type StageContext as c, SuspendedStateSchema as d, type CompletionCheckResult as e };
@@ -1,4 +1,4 @@
1
- import { A as AICallLogger, g as CreateAICallInput, h as AIHelperStats, i as AICallRecord, J as JobQueue, E as EnqueueJobInput, D as DequeueResult, j as JobRecord, k as JobStatus, l as WorkflowPersistence, C as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, m as WorkflowStatus, a as CreateStageInput, b as WorkflowStageRecord, c as UpsertStageInput, d as UpdateStageInput, n as WorkflowStageStatus, e as CreateLogInput, f as CreateOutboxEventInput, O as OutboxRecord, o as SaveArtifactInput, p as WorkflowArtifactRecord, q as WorkflowLogRecord } from '../interface-DCdddCe0.js';
1
+ import { k as AICallLogger, l as CreateAICallInput, m as AIHelperStats, n as AICallRecord, J as JobQueue, E as EnqueueJobInput, D as DequeueResult, o as JobRecord, p as JobStatus, q as WorkflowPersistence, C as CreateRunInput, W as WorkflowRunRecord, U as UpdateRunInput, r as WorkflowStatus, a as CreateStageInput, b as WorkflowStageRecord, c as UpsertStageInput, d as UpdateStageInput, s as WorkflowStageStatus, e as CreateLogInput, h as CreateOutboxEventInput, O as OutboxRecord, t as SaveArtifactInput, u as WorkflowArtifactRecord, f as CreateAnnotationInput, A as AnnotationFilters, g as WorkflowAnnotationRecord, v as WorkflowLogRecord } from '../interface-BPz138Hf.js';
2
2
 
3
3
  /**
4
4
  * In-Memory AI Call Logger
@@ -185,6 +185,7 @@ declare class InMemoryWorkflowPersistence implements WorkflowPersistence {
185
185
  private stages;
186
186
  private logs;
187
187
  private artifacts;
188
+ private annotations;
188
189
  private outbox;
189
190
  private idempotencyKeys;
190
191
  private idempotencyInProgress;
@@ -240,6 +241,8 @@ declare class InMemoryWorkflowPersistence implements WorkflowPersistence {
240
241
  deleteArtifact(runId: string, key: string): Promise<void>;
241
242
  listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]>;
242
243
  getStageIdForArtifact(runId: string, stageId: string): Promise<string | null>;
244
+ appendAnnotations(inputs: CreateAnnotationInput[]): Promise<void>;
245
+ listAnnotations(workflowRunId: string, filters?: AnnotationFilters): Promise<WorkflowAnnotationRecord[]>;
243
246
  saveStageOutput(runId: string, workflowType: string, stageId: string, output: unknown): Promise<string>;
244
247
  /**
245
248
  * Clear all data - useful between tests
@@ -261,6 +264,10 @@ declare class InMemoryWorkflowPersistence implements WorkflowPersistence {
261
264
  * Get all artifacts for inspection
262
265
  */
263
266
  getAllArtifacts(): WorkflowArtifactRecord[];
267
+ /**
268
+ * Get all annotations for inspection
269
+ */
270
+ getAllAnnotations(): WorkflowAnnotationRecord[];
264
271
  }
265
272
 
266
273
  export { InMemoryAICallLogger, InMemoryJobQueue, InMemoryWorkflowPersistence };
@@ -1,4 +1,4 @@
1
- import { StaleVersionError } from '../chunk-2MWO6UVR.js';
1
+ import { StaleVersionError } from '../chunk-NANAXHS5.js';
2
2
  import { randomUUID } from 'crypto';
3
3
 
4
4
  var InMemoryAICallLogger = class {
@@ -447,6 +447,7 @@ var InMemoryWorkflowPersistence = class {
447
447
  stages = /* @__PURE__ */ new Map();
448
448
  logs = /* @__PURE__ */ new Map();
449
449
  artifacts = /* @__PURE__ */ new Map();
450
+ annotations = [];
450
451
  outbox = [];
451
452
  idempotencyKeys = /* @__PURE__ */ new Map();
452
453
  idempotencyInProgress = /* @__PURE__ */ new Set();
@@ -487,7 +488,8 @@ var InMemoryWorkflowPersistence = class {
487
488
  config: data.config ?? {},
488
489
  totalCost: 0,
489
490
  totalTokens: 0,
490
- priority: data.priority ?? 5
491
+ priority: data.priority ?? 5,
492
+ metadata: data.metadata ?? null
491
493
  };
492
494
  this.runs.set(record.id, record);
493
495
  return { ...record };
@@ -599,6 +601,7 @@ var InMemoryWorkflowPersistence = class {
599
601
  stageName: data.stageName,
600
602
  stageNumber: data.stageNumber,
601
603
  executionGroup: data.executionGroup,
604
+ attempt: data.attempt ?? 0,
602
605
  status: data.status ?? "PENDING",
603
606
  startedAt: data.startedAt ?? null,
604
607
  completedAt: null,
@@ -747,6 +750,11 @@ var InMemoryWorkflowPersistence = class {
747
750
  if (stage) {
748
751
  this.stages.delete(id);
749
752
  this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));
753
+ for (const annotation of this.annotations) {
754
+ if (annotation.workflowStageRecordId === id) {
755
+ annotation.workflowStageRecordId = null;
756
+ }
757
+ }
750
758
  }
751
759
  }
752
760
  // ============================================================================
@@ -894,6 +902,77 @@ var InMemoryWorkflowPersistence = class {
894
902
  return stage?.id ?? null;
895
903
  }
896
904
  // ============================================================================
905
+ // WorkflowAnnotation Operations
906
+ // ============================================================================
907
+ async appendAnnotations(inputs) {
908
+ for (const input of inputs) {
909
+ if (input.idempotencyKey !== null && input.idempotencyKey !== void 0) {
910
+ const exists = this.annotations.some(
911
+ (a) => a.workflowRunId === input.workflowRunId && a.key === input.key && a.idempotencyKey === input.idempotencyKey
912
+ );
913
+ if (exists) continue;
914
+ }
915
+ const record = {
916
+ id: randomUUID(),
917
+ createdAt: /* @__PURE__ */ new Date(),
918
+ workflowRunId: input.workflowRunId,
919
+ workflowStageRecordId: input.workflowStageRecordId ?? null,
920
+ attempt: input.attempt ?? 0,
921
+ scope: input.scope,
922
+ scopeId: input.scopeId ?? null,
923
+ actorKind: input.actor?.kind ?? null,
924
+ actorId: input.actor?.id ?? null,
925
+ actorVersion: input.actor?.version ?? null,
926
+ key: input.key,
927
+ value: input.value,
928
+ payload: input.payload ?? null,
929
+ idempotencyKey: input.idempotencyKey ?? null
930
+ };
931
+ this.annotations.push(record);
932
+ }
933
+ }
934
+ async listAnnotations(workflowRunId, filters = {}) {
935
+ let rows = this.annotations.filter(
936
+ (a) => a.workflowRunId === workflowRunId
937
+ );
938
+ if (filters.key !== void 0) {
939
+ rows = rows.filter((a) => a.key === filters.key);
940
+ } else if (filters.keyPrefix !== void 0) {
941
+ const prefix = filters.keyPrefix;
942
+ rows = rows.filter((a) => a.key.startsWith(prefix));
943
+ }
944
+ if (filters.scope !== void 0) {
945
+ rows = rows.filter((a) => a.scope === filters.scope);
946
+ }
947
+ if (filters.scopeId !== void 0) {
948
+ rows = rows.filter((a) => a.scopeId === filters.scopeId);
949
+ }
950
+ if (filters.actorId !== void 0) {
951
+ rows = rows.filter((a) => a.actorId === filters.actorId);
952
+ }
953
+ if (filters.actorKind !== void 0) {
954
+ rows = rows.filter((a) => a.actorKind === filters.actorKind);
955
+ }
956
+ if (filters.attempt !== void 0) {
957
+ rows = rows.filter((a) => a.attempt === filters.attempt);
958
+ }
959
+ if (filters.since !== void 0) {
960
+ const since = filters.since;
961
+ rows = rows.filter((a) => a.createdAt >= since);
962
+ }
963
+ if (filters.until !== void 0) {
964
+ const until = filters.until;
965
+ rows = rows.filter((a) => a.createdAt <= until);
966
+ }
967
+ rows.sort((a, b) => {
968
+ const cmp = a.createdAt.getTime() - b.createdAt.getTime();
969
+ if (cmp !== 0) return cmp;
970
+ return a.id.localeCompare(b.id);
971
+ });
972
+ const limit = filters.limit ?? 1e3;
973
+ return rows.slice(0, limit).map((a) => ({ ...a }));
974
+ }
975
+ // ============================================================================
897
976
  // Stage Output Convenience Method
898
977
  // ============================================================================
899
978
  async saveStageOutput(runId, workflowType, stageId, output) {
@@ -920,6 +999,7 @@ var InMemoryWorkflowPersistence = class {
920
999
  this.stages.clear();
921
1000
  this.logs.clear();
922
1001
  this.artifacts.clear();
1002
+ this.annotations = [];
923
1003
  this.outbox = [];
924
1004
  this.idempotencyKeys.clear();
925
1005
  this.idempotencyInProgress.clear();
@@ -949,6 +1029,12 @@ var InMemoryWorkflowPersistence = class {
949
1029
  getAllArtifacts() {
950
1030
  return Array.from(this.artifacts.values()).map((a) => ({ ...a }));
951
1031
  }
1032
+ /**
1033
+ * Get all annotations for inspection
1034
+ */
1035
+ getAllAnnotations() {
1036
+ return this.annotations.map((a) => ({ ...a }));
1037
+ }
952
1038
  };
953
1039
 
954
1040
  export { InMemoryAICallLogger, InMemoryJobQueue, InMemoryWorkflowPersistence };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 0,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job and increment attempt (matches Prisma dequeue semantics)\n const newAttempt = job.attempt + 1;\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n attempt: newAttempt,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: newAttempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING (attempt was already incremented during dequeue)\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n async cancelByRun(workflowRunId: string): Promise<number> {\n const now = new Date();\n let count = 0;\n for (const job of this.jobs.values()) {\n if (\n job.workflowRunId === workflowRunId &&\n (job.status === \"PENDING\" || job.status === \"SUSPENDED\")\n ) {\n const updated: JobRecord = {\n ...job,\n status: \"CANCELLED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n count++;\n }\n }\n return count;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 0,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job and increment attempt (matches Prisma dequeue semantics)\n const newAttempt = job.attempt + 1;\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n attempt: newAttempt,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: newAttempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING (attempt was already incremented during dequeue)\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n async cancelByRun(workflowRunId: string): Promise<number> {\n const now = new Date();\n let count = 0;\n for (const job of this.jobs.values()) {\n if (\n job.workflowRunId === workflowRunId &&\n (job.status === \"PENDING\" || job.status === \"SUSPENDED\")\n ) {\n const updated: JobRecord = {\n ...job,\n status: \"CANCELLED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n count++;\n }\n }\n return count;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type AnnotationFilters,\n type CreateAnnotationInput,\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowAnnotationRecord,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private annotations: WorkflowAnnotationRecord[] = [];\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n metadata: data.metadata ?? null,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n attempt: data.attempt ?? 0,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n // Mirror Prisma `onDelete: SetNull` on WorkflowAnnotation.workflowStage:\n // surviving annotations keep their data but lose the FK to the\n // deleted stage record. Their `attempt` value already captured at\n // write time still disambiguates them from new attempts.\n for (const annotation of this.annotations) {\n if (annotation.workflowStageRecordId === id) {\n annotation.workflowStageRecordId = null;\n }\n }\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // WorkflowAnnotation Operations\n // ============================================================================\n\n async appendAnnotations(inputs: CreateAnnotationInput[]): Promise<void> {\n for (const input of inputs) {\n // Honor the (workflowRunId, key, idempotencyKey) unique constraint.\n if (input.idempotencyKey !== null && input.idempotencyKey !== undefined) {\n const exists = this.annotations.some(\n (a) =>\n a.workflowRunId === input.workflowRunId &&\n a.key === input.key &&\n a.idempotencyKey === input.idempotencyKey,\n );\n if (exists) continue;\n }\n\n const record: WorkflowAnnotationRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: input.workflowRunId,\n workflowStageRecordId: input.workflowStageRecordId ?? null,\n attempt: input.attempt ?? 0,\n scope: input.scope,\n scopeId: input.scopeId ?? null,\n actorKind: input.actor?.kind ?? null,\n actorId: input.actor?.id ?? null,\n actorVersion: input.actor?.version ?? null,\n key: input.key,\n value: input.value,\n payload: input.payload ?? null,\n idempotencyKey: input.idempotencyKey ?? null,\n };\n this.annotations.push(record);\n }\n }\n\n async listAnnotations(\n workflowRunId: string,\n filters: AnnotationFilters = {},\n ): Promise<WorkflowAnnotationRecord[]> {\n let rows = this.annotations.filter(\n (a) => a.workflowRunId === workflowRunId,\n );\n\n if (filters.key !== undefined) {\n rows = rows.filter((a) => a.key === filters.key);\n } else if (filters.keyPrefix !== undefined) {\n const prefix = filters.keyPrefix;\n rows = rows.filter((a) => a.key.startsWith(prefix));\n }\n\n if (filters.scope !== undefined) {\n rows = rows.filter((a) => a.scope === filters.scope);\n }\n if (filters.scopeId !== undefined) {\n rows = rows.filter((a) => a.scopeId === filters.scopeId);\n }\n if (filters.actorId !== undefined) {\n rows = rows.filter((a) => a.actorId === filters.actorId);\n }\n if (filters.actorKind !== undefined) {\n rows = rows.filter((a) => a.actorKind === filters.actorKind);\n }\n if (filters.attempt !== undefined) {\n rows = rows.filter((a) => a.attempt === filters.attempt);\n }\n if (filters.since !== undefined) {\n const since = filters.since;\n rows = rows.filter((a) => a.createdAt >= since);\n }\n if (filters.until !== undefined) {\n const until = filters.until;\n rows = rows.filter((a) => a.createdAt <= until);\n }\n\n // Sort by createdAt with id as tiebreaker (matches Prisma adapter,\n // keeps batched-insert ordering deterministic).\n rows.sort((a, b) => {\n const cmp = a.createdAt.getTime() - b.createdAt.getTime();\n if (cmp !== 0) return cmp;\n return a.id.localeCompare(b.id);\n });\n\n const limit = filters.limit ?? 1000;\n return rows.slice(0, limit).map((a) => ({ ...a }));\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.annotations = [];\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n\n /**\n * Get all annotations for inspection\n */\n getAllAnnotations(): WorkflowAnnotationRecord[] {\n return this.annotations.map((a) => ({ ...a }));\n }\n}\n"]}