@dudousxd/nestjs-durable-core 0.74.0 → 0.75.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.
- package/dist/index.cjs +61 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +61 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/queue.ts","../src/admission.ts","../src/ambient-ctx.ts","../src/ambient-step.ts","../src/control-flow-signal.ts","../src/errors.ts","../src/workflow-ref.ts","../src/durable-workflow.ts","../src/duration.ts","../src/backoff.ts","../src/execution-hooks.ts","../src/step-logger.ts","../src/protocol.ts","../src/checkpoints.ts","../src/completion.ts","../src/concurrency.ts","../src/entities.ts","../src/event-accumulators.ts","../src/events.ts","../src/fan-join.ts","../src/handshake/descriptor.ts","../src/handshake/announced.ts","../src/handshake/directory.ts","../src/handshake/negotiate.ts","../src/handshake/routing.ts","../src/handshake/dispatch-routing.ts","../src/interfaces.ts","../src/tenant-group.ts","../src/remote-workflow-executor.ts","../src/run-waiting.ts","../src/scheduler.ts","../src/cron-compat.ts","../src/schedules.ts","../src/singleton-admission.ts","../src/singleton-gate.ts","../src/transport-pool.ts","../src/step-name-symbol.ts","../src/workflow-ctx.ts","../src/engine.ts","../src/run-facets.ts","../src/run-value-facets.ts","../src/run-gateway.ts","../src/codec-state-store.ts","../src/metrics.ts","../src/search-attributes.ts","../src/search-attributes-schema.ts","../src/tokens.ts","../src/testing/in-memory-state-store.ts","../src/testing/in-memory-transport.ts"],"sourcesContent":["/**\n * Flow control for dispatched steps. A queue caps how much work `ctx.step(step, input, { queue })`\n * admits at once — a concurrency limit and/or a fixed-window rate limit. When a call can't be\n * admitted it doesn't dispatch: the run re-suspends with a near-future wake time, and the timer\n * poller re-tries admission later — so flow control is durable (survives crashes) without holding\n * the run in memory.\n *\n * Accounting is per engine instance (the DBOS `workerConcurrency` tier): correct for the common\n * single-orchestrator deployment. Global, cross-instance limits would need a durable counter in the\n * store — a deliberate follow-up, not built here.\n *\n * Beyond raw caps, the controller can admit contended slots by PRIORITY and by per-KEY FAIRNESS\n * (round-robin), so a single noisy key/tenant can't monopolize the concurrency budget. This is the\n * DISPATCH/admission layer — it never touches workflow replay (engine positional logic). Default\n * behaviour is unchanged FIFO when neither priority nor fairness is configured/passed.\n *\n * Design (vs Temporal/Inngest/DBOS): Temporal task queues are FIFO with separate priority levels;\n * Inngest concurrency keys + throttle give per-key fairness; DBOS queues are FIFO with a\n * `workerConcurrency` cap. We fold both knobs into the same in-process admission gate: an optional\n * per-call `priority` (higher first) and an optional queue-level `fairness: 'key'` (round-robin by\n * the per-call `key`). Because blocked calls re-suspend durably and retry independently (there is no\n * resident FIFO list to reorder), the controller remembers the set of WAITERS that asked-and-were-\n * blocked, and on a later retry only admits the one that is rightful-next under the policy.\n */\nexport interface QueueConfig {\n /** Queue name, referenced by `ctx.step(step, input, { queue: name })`. */\n name: string;\n /** Max steps in flight at once for this queue (this instance). Omit for unlimited. */\n concurrency?: number;\n /** Fixed-window rate limit: at most `limit` admissions per `periodMs`. Omit for unlimited. */\n rateLimit?: { limit: number; periodMs: number };\n /** Delay (ms) before a concurrency-blocked call re-checks for a free slot. Default 1000. */\n retryMs?: number;\n /**\n * Fairness policy for a contended concurrency slot. `'key'` round-robins across distinct per-call\n * keys (the least-recently-served key wins the next slot), so one key can't monopolize the budget.\n * Omit (or `'fifo'`) for plain first-come ordering. Priority always wins over fairness; fairness\n * only breaks ties within the same priority.\n */\n fairness?: 'fifo' | 'key';\n /**\n * Arrival-order tiebreak among otherwise-equal waiters (same priority, same fairness rank).\n * `'fifo'` (default) admits the earliest arrival; `'lifo'` admits the most recent (a stack). Orthogonal\n * to `priority` and `fairness` — those still win first; this only breaks their ties.\n */\n order?: 'fifo' | 'lifo';\n}\n\n/**\n * Per-call admission hints. All optional — omitting them keeps the legacy FIFO behaviour.\n * - `priority`: higher is admitted first (default 0).\n * - `key`: the fairness bucket (e.g. a tenant id) for `fairness: 'key'`.\n * - `waiterId`: a stable id for THIS call across its retries (the engine passes the stepId), so the\n * controller can track it as one waiter instead of counting each retry as a new contender.\n */\nexport interface AdmissionItem {\n priority?: number | undefined;\n key?: string | undefined;\n waiterId?: string | undefined;\n}\n\n/** Admission decision: either admitted, or blocked until `retryAt` (epoch ms). */\nexport type Admission = { ok: true } | { ok: false; retryAt: number };\n\n/** A call that asked for a slot and was blocked — remembered so the controller can order admission. */\ninterface Waiter {\n priority: number;\n key?: string | undefined;\n /** Monotonic registration order — FIFO tiebreak within equal priority/fairness. */\n seq: number;\n}\n\n/** In-process admission controller for one {@link QueueConfig}. */\nexport class QueueController {\n private inFlight = 0;\n private windowStart = 0;\n private windowCount = 0;\n /** Registered waiters by id (only used when priority/fairness ordering is in play). */\n private readonly waiters = new Map<string, Waiter>();\n /** Monotonic counter stamping each newly-seen waiter for a stable FIFO tiebreak. */\n private waiterSeq = 0;\n /** Per-key \"last served\" order for round-robin fairness — higher = more recently served. */\n private readonly keyServed = new Map<string, number>();\n private servedTick = 0;\n\n constructor(\n readonly config: QueueConfig,\n private readonly clock: () => number,\n ) {}\n\n /** Whether this controller does any priority/fairness ordering (else it's a plain FIFO gate). */\n private get ordered(): boolean {\n return this.config.fairness === 'key' || this.config.order === 'lifo';\n }\n\n /**\n * Try to admit one unit of work. On `ok`, the caller has taken a concurrency slot and must call\n * {@link release} when the step settles. On block, `retryAt` is when admission may next succeed.\n *\n * `item` carries optional priority/fairness hints; omitting it is the legacy FIFO path. When\n * ordering is configured (or a priority is given), a blocked call REGISTERS as a waiter and is only\n * admitted on a later retry once it is the rightful next under (priority desc, fairness, FIFO).\n */\n tryAdmit(item?: AdmissionItem): Admission {\n const now = this.clock();\n const rl = this.config.rateLimit;\n // Rate limit is a hard global window — checked first and unaffected by priority/fairness.\n if (rl) {\n if (now - this.windowStart >= rl.periodMs) {\n this.windowStart = now;\n this.windowCount = 0;\n }\n if (this.windowCount >= rl.limit)\n return { ok: false, retryAt: this.windowStart + rl.periodMs };\n }\n\n const usingOrder = this.ordered || item?.priority != null || item?.waiterId != null;\n const waiterId = item?.waiterId;\n\n // Concurrency gate.\n const full = this.config.concurrency != null && this.inFlight >= this.config.concurrency;\n if (full) {\n // No slot at all → block (and register as a waiter so a later retry can be ordered).\n if (usingOrder && waiterId != null) this.register(waiterId, item);\n return { ok: false, retryAt: now + (this.config.retryMs ?? 1000) };\n }\n\n // A slot is free. Without ordering, admit immediately (legacy FIFO). With ordering, only admit if\n // THIS call is the rightful next among all registered waiters — otherwise keep it waiting so the\n // freed slot can go to a higher-priority / under-served key on its retry.\n if (usingOrder && this.waiters.size > 0) {\n if (waiterId != null) this.register(waiterId, item);\n if (!this.isNext(waiterId, item)) {\n return { ok: false, retryAt: now + (this.config.retryMs ?? 1000) };\n }\n }\n\n // Admit: consume the slot, the rate-window tick, and clear this waiter.\n if (rl) this.windowCount += 1;\n this.inFlight += 1;\n if (waiterId != null) this.waiters.delete(waiterId);\n if (item?.key != null) this.keyServed.set(item.key, ++this.servedTick);\n return { ok: true };\n }\n\n /** Release a concurrency slot taken by a successful {@link tryAdmit}. */\n release(): void {\n if (this.inFlight > 0) this.inFlight -= 1;\n }\n\n /** Track (or refresh) a blocked call as a waiter; its FIFO seq is stamped only on first sight. */\n private register(waiterId: string, item?: AdmissionItem): void {\n const existing = this.waiters.get(waiterId);\n if (existing) {\n existing.priority = item?.priority ?? 0;\n existing.key = item?.key;\n return;\n }\n this.waiters.set(waiterId, {\n priority: item?.priority ?? 0,\n key: item?.key,\n seq: this.waiterSeq++,\n });\n }\n\n /**\n * Is the calling item the best candidate among all registered waiters? Ordering, best first:\n * 1. higher `priority`;\n * 2. fairness: with `fairness: 'key'`, the least-recently-served key wins (round-robin);\n * 3. earliest registration (FIFO) — stable tiebreak.\n * A bare item (no waiterId) is compared on its hints directly.\n */\n private isNext(waiterId: string | undefined, item?: AdmissionItem): boolean {\n const self: Waiter =\n (waiterId != null ? this.waiters.get(waiterId) : undefined) ??\n ({ priority: item?.priority ?? 0, key: item?.key, seq: Number.POSITIVE_INFINITY } as Waiter);\n let best = self;\n for (const w of this.waiters.values()) {\n if (this.better(w, best)) best = w;\n }\n return best === self;\n }\n\n /** Strict \"a should be admitted before b\" comparison under the active policy. */\n private better(a: Waiter, b: Waiter): boolean {\n if (a.priority !== b.priority) return a.priority > b.priority;\n if (this.config.fairness === 'key') {\n const sa = this.servedOf(a.key);\n const sb = this.servedOf(b.key);\n if (sa !== sb) return sa < sb; // least-recently-served key first\n }\n return this.config.order === 'lifo' ? a.seq > b.seq : a.seq < b.seq; // arrival tiebreak\n }\n\n /** Last-served tick for a key (0 = never served, so an unseen key is admitted before a busy one). */\n private servedOf(key?: string): number {\n if (key == null) return 0;\n return this.keyServed.get(key) ?? 0;\n }\n}\n","import { type Admission, type AdmissionItem, type QueueConfig, QueueController } from './queue';\n\n/**\n * Pluggable backend for the step flow-control gate (`ctx.step(step, input, { queue })`). The\n * engine asks it whether a queued call may be admitted now (concurrency / rate / ordering) and tells\n * it when an admitted slot is released.\n *\n * The default {@link InMemoryAdmissionBackend} keeps per-instance counts — correct for a single\n * orchestrator. Swap in a store/Redis-backed backend to make the caps and ordering GLOBAL across\n * engine replicas (so `concurrency: 5` means 5 in-flight across the whole fleet, not 5 per pod).\n *\n * `tryAdmit`/`release` are async so a global backend can do its atomic round-trip; the in-memory one\n * resolves synchronously. An UNREGISTERED queue name is treated as ungated (admits immediately) — the\n * engine only tracks/releases a slot for a registered queue.\n */\nexport interface AdmissionBackend {\n /** Register (or replace) a queue's config. Called from `engine.registerQueue`. */\n register(config: QueueConfig): void;\n /** Whether `queue` is registered (gated). The engine only tracks/releases a slot for a gated queue. */\n handles(queue: string): boolean;\n /** May a call on `queue` take a slot now? On `ok`, the caller holds a slot until {@link release}. */\n tryAdmit(queue: string, item: AdmissionItem): Promise<Admission>;\n /**\n * Release the slot granted by {@link tryAdmit} for `queue`. `slotId` is the admitted item's\n * `waiterId` (the engine's stepId), so a lease-based backend can drop the exact slot; an in-process\n * counter ignores it.\n */\n release(queue: string, slotId: string): Promise<void>;\n /**\n * Optional: subscribe to \"a slot just freed on `queue`\" events (e.g. a fleet-wide pub/sub). The\n * engine uses it to wake its admission-blocked runs early instead of waiting for their retry tick.\n * A backend without it falls back to retry-tick polling. Fired best-effort across the fleet.\n */\n onFreed?(handler: (queue: string) => void): void;\n}\n\n/**\n * Default admission backend: one in-process {@link QueueController} per registered queue. Caps and\n * waiter ordering are per engine instance (see {@link QueueConfig}). Preserves the exact pre-backend\n * behaviour — the engine used to hold these controllers directly.\n */\nexport class InMemoryAdmissionBackend implements AdmissionBackend {\n private readonly controllers = new Map<string, QueueController>();\n\n constructor(private readonly clock: () => number) {}\n\n register(config: QueueConfig): void {\n this.controllers.set(config.name, new QueueController(config, this.clock));\n }\n\n handles(queue: string): boolean {\n return this.controllers.has(queue);\n }\n\n async tryAdmit(queue: string, item: AdmissionItem): Promise<Admission> {\n const controller = this.controllers.get(queue);\n // Unregistered queue → ungated (mirrors the old `this.queues.get(queue)` truthiness check).\n if (!controller) return { ok: true };\n return controller.tryAdmit(item);\n }\n\n async release(queue: string, _slotId: string): Promise<void> {\n this.controllers.get(queue)?.release();\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { WorkflowCtx } from './interfaces';\n\n/**\n * The ambient workflow context: an `AsyncLocalStorage` the engine (and the thin worker runtime)\n * installs around every execution of a workflow body, so code running ON the body's async path can\n * discover the live {@link WorkflowCtx} without threading it through — the mechanism behind the\n * class-first `MyWorkflow.start()` / `MyWorkflow.execute()` statics (see `durable-workflow.ts`).\n *\n * One storage per PROCESS, not per copy of this package: stashed on `globalThis` under a\n * `Symbol.for` key, so a dependency tree carrying duplicate copies of core still shares the same\n * ambient context (the same duplicate-copy trap the DI tokens guard against — see `tokens.ts`).\n */\nconst STORAGE_KEY = Symbol.for('nestjs-durable:ambient-workflow-ctx');\n\ntype GlobalWithStorage = typeof globalThis & {\n [STORAGE_KEY]?: AsyncLocalStorage<WorkflowCtx>;\n};\n\nconst globalRef = globalThis as GlobalWithStorage;\nif (!globalRef[STORAGE_KEY]) {\n globalRef[STORAGE_KEY] = new AsyncLocalStorage<WorkflowCtx>();\n}\nconst storage: AsyncLocalStorage<WorkflowCtx> = globalRef[STORAGE_KEY];\n\n/**\n * Run `fn` with `ctx` as the ambient workflow context. Engine-internal: wraps every execution of a\n * workflow body (first run and every replay), so ambient reads inside the body see the SAME ctx the\n * body received.\n */\nexport function runInWorkflowCtx<T>(ctx: WorkflowCtx, fn: () => T): T {\n return storage.run(ctx, fn);\n}\n\n/**\n * The {@link WorkflowCtx} of the workflow body currently executing on this async path — or\n * `undefined` outside one. Note a `@Step` HANDLER runs on a worker, off the body's path: it has no\n * ambient workflow context (by design — a handler is not the workflow body).\n */\nexport function currentWorkflowCtx(): WorkflowCtx | undefined {\n return storage.getStore();\n}\n\n/**\n * The ambient STEP scope: which workflow ctx's checkpointed step body (if any) is executing on this\n * async path. The engine installs it around every in-body step execution (`ctx.localStep`,\n * `ctx.transaction`, and everything built on them) so the ctx primitives can refuse to run from\n * inside a step body — see {@link NestedWorkflowCallError}. `owner` is the identity of the ctx whose\n * step is running, so a DIFFERENT run's body executed inline from a step (e.g. a step that signals a\n * run which resumes on this async path) is never mistaken for a nested call.\n *\n * Shared per process under a `Symbol.for` key, for the same duplicate-copy reason as the ctx storage.\n */\nexport interface StepScope {\n readonly owner: object;\n readonly step: string;\n}\n\nconst STEP_SCOPE_KEY = Symbol.for('nestjs-durable:ambient-step-scope');\ntype GlobalWithStepScope = typeof globalThis & {\n [STEP_SCOPE_KEY]?: AsyncLocalStorage<StepScope>;\n};\nconst stepScopeRef = globalThis as GlobalWithStepScope;\nif (!stepScopeRef[STEP_SCOPE_KEY]) {\n stepScopeRef[STEP_SCOPE_KEY] = new AsyncLocalStorage<StepScope>();\n}\nconst stepScopeStorage: AsyncLocalStorage<StepScope> = stepScopeRef[STEP_SCOPE_KEY];\n\n/** Run `fn` as the body of step `step` of the ctx identified by `owner`. Engine-internal. */\nexport function runInStepScope<T>(owner: object, step: string, fn: () => T): T {\n return stepScopeStorage.run({ owner, step }, fn);\n}\n\n/** The step body currently executing on this async path, or `undefined` outside one. */\nexport function currentStepScope(): StepScope | undefined {\n return stepScopeStorage.getStore();\n}\n\n/**\n * Run `fn` with NO ambient workflow ctx and no step scope — for a dispatched `@Step` handler. A\n * handler is not the workflow body (on a remote worker it never sees one), but an in-process\n * transport invokes it on the body's async path, where the parent's ctx would otherwise leak in and\n * turn a handler's `MyWorkflow.start()` into a journal-corrupting `ctx.startChild` of a parent that\n * is already suspended. Clearing it makes in-process and remote handlers behave identically.\n */\nexport function runOutsideWorkflowCtx<T>(fn: () => T): T {\n return storage.exit(() => stepScopeStorage.exit(fn));\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { StepLogger, SubProcessHandle } from './interfaces';\n\n/**\n * The ambient step logger: an `AsyncLocalStorage` the engine installs around every execution of a\n * step body — local (`ctx.step`) and remote (`runStepHandler`) alike — so code running DEEP inside\n * a step can record events without the {@link StepLogger} being threaded through every signature\n * on the way down. The TypeScript twin of the Python SDK's context-local `current_step()`.\n *\n * This is what makes observability symmetric across the two SDKs: in Python a nested helper emits\n * without receiving anything, whereas in TypeScript the logger only ever arrived as the step body's\n * second argument. A generic utility a few layers below the handler (a batch inserter, an HTTP\n * client) can now emit progress without its callers being edited.\n *\n * One storage per PROCESS, not per copy of this package: stashed on `globalThis` under a\n * `Symbol.for` key, so a dependency tree carrying duplicate copies of core still shares the same\n * ambient logger (the same duplicate-copy trap `ambient-ctx.ts` and the DI tokens guard against).\n */\nconst STORAGE_KEY = Symbol.for('nestjs-durable:ambient-step-logger');\n\ntype GlobalWithStorage = typeof globalThis & {\n [STORAGE_KEY]?: AsyncLocalStorage<StepLogger>;\n};\n\nconst globalRef = globalThis as GlobalWithStorage;\nif (!globalRef[STORAGE_KEY]) {\n globalRef[STORAGE_KEY] = new AsyncLocalStorage<StepLogger>();\n}\nconst storage: AsyncLocalStorage<StepLogger> = globalRef[STORAGE_KEY];\n\n/**\n * Run `fn` with `logger` as the ambient step logger. Engine-internal: wraps every execution of a\n * step body, binding the SAME logger instance the body receives as its second argument — never a\n * second one, so an event emitted ambiently and one emitted through the argument land in the same\n * `StepEvent[]` and are checkpointed together.\n *\n * Because it is an `AsyncLocalStorage`, concurrent step invocations (the worker runs steps under\n * adaptive concurrency) each see their own logger — they never leak into one another.\n */\nexport function runInStepLogger<T>(logger: StepLogger, fn: () => T): T {\n return storage.run(logger, fn);\n}\n\n/**\n * The {@link StepLogger} of the step body currently executing on this async path — or `undefined`\n * outside one. Reading it is the escape hatch for code that cannot take a logger parameter:\n *\n * ```ts\n * currentStep()?.subEvent({ id, name: 'insert', phase: `${rows} rows` });\n * ```\n */\nexport function currentStep(): StepLogger | undefined {\n return storage.getStore();\n}\n\n/**\n * Record a log line on the current step, taking the level as a value. No-op outside a step. The\n * literal twin of the Python SDK's module-level `log(level, message, data)` — keep reaching for it\n * when the level is computed (mapping a foreign log level, re-emitting a captured record); for a\n * level known at the call site the per-level shortcuts below read better.\n *\n * The no-op contract is what lets a generic utility be instrumented without an `if` at the call\n * site, and keeps it usable in a unit test with no durable run around it.\n */\nexport function log(\n level: 'debug' | 'info' | 'warn' | 'error',\n message: string,\n data?: unknown,\n): void {\n currentStep()?.[level](message, data);\n}\n\n// The per-level shortcuts, mirroring the same four methods on a `StepLogger` instance so ambient\n// code reads exactly like code that was handed the logger — `info('...')` vs `log.info('...')`.\n// They are the idiomatic TypeScript form; `log(level, ...)` above is the Python-symmetric one.\n// Both are kept: neither subsumes the other (one takes the level as data, the other as a name).\n\n/** Record a `debug` line on the current step. No-op outside a step. */\nexport function debug(message: string, data?: unknown): void {\n currentStep()?.debug(message, data);\n}\n\n/** Record an `info` line on the current step. No-op outside a step. */\nexport function info(message: string, data?: unknown): void {\n currentStep()?.info(message, data);\n}\n\n/** Record a `warn` line on the current step. No-op outside a step. */\nexport function warn(message: string, data?: unknown): void {\n currentStep()?.warn(message, data);\n}\n\n/** Record an `error` line on the current step. No-op outside a step — note this only RECORDS a line;\n * it never fails the step (that is what throwing from the body does). */\nexport function error(message: string, data?: unknown): void {\n currentStep()?.error(message, data);\n}\n\n/** Record a sub-step / sub-process outcome on the current step. No-op outside a step. */\nexport function sub(\n name: string,\n status: 'ok' | 'failed' | 'skipped',\n message?: string,\n data?: unknown,\n): void {\n currentStep()?.sub(name, status, message, data);\n}\n\n/** Record a sub-process event (phase or terminal outcome) on the current step. No-op outside a step. */\nexport function subEvent(e: {\n id: string;\n name: string;\n group?: string | undefined;\n phase?: string | undefined;\n status?: 'ok' | 'failed' | 'skipped' | undefined;\n message?: string | undefined;\n data?: unknown;\n}): void {\n currentStep()?.subEvent(e);\n}\n\n// Outside a step there is nothing to emit to, but `subProcess`'s body still has to run and still\n// receives a handle — so the same business code takes the same path whether or not it is durable.\nconst noopSubProcessHandle: SubProcessHandle = {\n phase: () => noopSubProcessHandle,\n skip: () => {},\n fail: () => {},\n};\n\n/**\n * Run `body` as a timed sub-process of the current step (see {@link StepLogger.subProcess}).\n * Outside a step the body still RUNS — and still gets a handle — but nothing is emitted; only the\n * observability disappears, never the work. Mirrors the Python SDK's `sub_process`.\n */\nexport function subProcess<T>(\n name: string,\n body: (sp: SubProcessHandle) => Promise<T> | T,\n opts?: { group?: string; id?: string },\n): Promise<T> {\n const logger = currentStep();\n if (!logger) return Promise.resolve(body(noopSubProcessHandle));\n return logger.subProcess(name, body, opts);\n}\n","/**\n * Cross-package, cross-runtime marker for engine CONTROL-FLOW signals — {@link WorkflowSuspended}\n * and {@link ContinueAsNew} (this package), plus the thin worker's {@link\n * import('@dudousxd/durable-worker').Suspend} (`@dudousxd/durable-worker`, the BullMQ\n * route-by-handler runtime). These are thrown by `WorkflowCtx`/`WorkflowContext` ops to unwind the\n * current turn — never real failures — so a workflow's `catch` block MUST rethrow them untouched.\n * Running a failure/cleanup path on a control-flow signal corrupts the run: it emits extra\n * `recordStep` commands into history that a subsequent replay didn't produce the first time,\n * surfacing as a `NonDeterminismError`/`NondeterminismError` on resume.\n *\n * `Symbol.for` (the GLOBAL registry), NOT a plain `Symbol()` — so a duplicate copy of this module\n * (pnpm peer-dependency multiplexing, a dual ESM/CJS load, or the SEPARATE `@dudousxd/durable-worker`\n * package declaring the same `Symbol.for` key locally) still collapses onto the SAME symbol. Same\n * rationale as `DURABLE_STEP_NAME` in `./step-name-symbol.ts`.\n *\n * Deliberately checked as a stamped property, NOT `instanceof` — `instanceof` only recognizes a\n * signal thrown by the SAME class the checking code imported, which fails across the in-process\n * engine (`@dudousxd/nestjs-durable-core`'s `WorkflowSuspended`/`ContinueAsNew`) and the thin worker\n * (`@dudousxd/durable-worker`'s `Suspend`) — two different classes for what is, from a workflow\n * author's catch block, the same \"this isn't a real error, let it through\" event.\n *\n * NOT designed to survive a serialization boundary (e.g. JSON over the wire) — these signals are\n * always thrown and caught in-process within a single replay turn, never (de)serialized, so a\n * stamped-but-not-cloneable property is sufficient.\n */\nexport const CONTROL_FLOW_SIGNAL = Symbol.for('aviary:durable:control-flow');\n\n/**\n * True for any engine control-flow signal (currently: {@link WorkflowSuspended}, {@link\n * ContinueAsNew}, and the thin worker's `Suspend`) — regardless of which runtime or module instance\n * threw it. Workflow `catch` blocks MUST rethrow these untouched; running a failure/cleanup path on\n * one corrupts the run's history (extra commands recorded during what replay will later see as a\n * suspend, not a failure) and the resumed replay dies with a non-determinism error.\n *\n * Deliberately NOT control-flow (do not add to this predicate):\n * - `Cancelled` (worker) / a cancelled run — a TERMINAL outcome the consumer may legitimately want\n * to observe and react to (e.g. release a lock), not a mid-turn unwind to rethrow untouched.\n * - `StepFailed` (worker) / an awaited step rejection reaching the engine — a REAL failure a\n * workflow's `catch` is meant to compensate for; misclassifying it as control-flow would swallow\n * genuine errors instead of protecting them.\n *\n * @example\n * ```ts\n * try {\n * await ctx.step('chargeCard', input);\n * } catch (error) {\n * if (isWorkflowControlFlowSignal(error)) throw error; // suspend/continue-as-new: rethrow as-is\n * await ctx.step('refund', input); // a REAL failure — safe to run cleanup here\n * throw error;\n * }\n * ```\n */\nexport function isWorkflowControlFlowSignal(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as { [CONTROL_FLOW_SIGNAL]?: unknown })[CONTROL_FLOW_SIGNAL] === true\n );\n}\n","import { CONTROL_FLOW_SIGNAL, type isWorkflowControlFlowSignal } from './control-flow-signal';\n\n/**\n * Thrown inside a step to signal an unrecoverable failure: the engine will NOT retry it,\n * regardless of the step's `retries` setting, and fails the run immediately. Use it for\n * business errors that retrying cannot fix (e.g. a declined card, invalid input).\n */\nexport class FatalError extends Error {\n readonly code?: string | undefined;\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'FatalError';\n this.code = code;\n }\n}\n\n/**\n * Thrown by `start` when a run would exceed its concurrency quota: `active` runs sharing the quota\n * `key` are already in flight (in the quota's counted statuses) and the `limit` is `limit`. Nothing\n * was created — the start is rejected up front, so the caller can shed load or answer \"try again in a\n * moment\" (e.g. map it to HTTP 429). See `StartOptions.concurrency` / `ConcurrencyConfig`.\n */\nexport class ConcurrencyLimitError extends Error {\n readonly workflow: string;\n readonly key: string;\n readonly limit: number;\n readonly active: number;\n constructor(workflow: string, key: string, limit: number, active: number) {\n super(\n `concurrency limit reached for key \"${key}\" (${active}/${limit} in flight); ${workflow} was not started — retry later`,\n );\n this.name = 'ConcurrencyLimitError';\n this.workflow = workflow;\n this.key = key;\n this.limit = limit;\n this.active = active;\n }\n}\n\n/**\n * Thrown by `start` when a singleton workflow's wait queue is full: the count of in-flight + gated\n * runs sharing the key already equals `limit + maxQueueDepth`, so admitting another would let the\n * same-key backlog grow unbounded. Back-pressure — the caller should retry later or shed load. Only\n * raised when {@link SingletonConfig.maxQueueDepth} is set (omit it for the old unbounded behavior).\n */\nexport class SingletonQueueFullError extends Error {\n readonly workflow: string;\n readonly key: string;\n readonly maxQueueDepth: number;\n constructor(workflow: string, key: string, maxQueueDepth: number) {\n super(\n `singleton queue for ${workflow} key \"${key}\" is full (maxQueueDepth=${maxQueueDepth}); retry later`,\n );\n this.name = 'SingletonQueueFullError';\n this.workflow = workflow;\n this.key = key;\n this.maxQueueDepth = maxQueueDepth;\n }\n}\n\n/**\n * Internal control signal thrown to suspend a run (e.g. on a durable sleep). Not an error the\n * user should throw or catch; the engine uses it to stop execution and persist `wakeAt`.\n */\nexport class SignalTimeoutError extends Error {\n readonly token: string;\n readonly timeoutMs: number;\n constructor(token: string, timeoutMs: number) {\n super(`timed out after ${timeoutMs}ms waiting for signal \"${token}\"`);\n this.name = 'SignalTimeoutError';\n this.token = token;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown when a remote step produces no result and no heartbeat within its `timeoutMs` window —\n * i.e. the worker is presumed dead. Subject to the step's `retries` (it's retryable), so the engine\n * re-dispatches before giving up.\n */\nexport class RemoteStepTimeout extends Error {\n readonly stepId: string;\n readonly timeoutMs: number;\n constructor(stepId: string, timeoutMs: number) {\n super(`remote step ${stepId} produced no result/heartbeat within ${timeoutMs}ms`);\n this.name = 'RemoteStepTimeout';\n this.stepId = stepId;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown by a remote {@link WorkflowExecutor} (e.g. {@link RemoteWorkflowExecutor}) when an `advance`\n * does not produce its decision within the configured `timeoutMs` — i.e. the worker is presumed gone\n * (the decision was dropped by a stall/redelivery or an instance restart spanning the in-memory waiter\n * map). Crucially this is NOT a run failure: the work may have actually completed and only the decision\n * was lost. The engine treats it as RECOVERABLE — it releases the run lease and leaves the run\n * `running` so `recoverIncomplete` re-drives it deterministically (replaying completed steps from\n * history). Distinct from a real executor error, which still fails the run.\n *\n * OPT-IN: only thrown when the executor was constructed with a `timeoutMs`. Absent a timeout, the\n * engine awaits the decision with its prior (unbounded) behavior — so existing users see no change.\n *\n * Known hazard: a timeout that fires while a worker is LEGITIMATELY still executing a not-yet-\n * checkpointed step will re-drive and re-run that in-flight step → DUPLICATE side effects. Therefore\n * the timeout is only safe when set GENEROUSLY (longer than the longest legitimate single turn). The\n * robust fix — a liveness/heartbeat-rearmed deadline so only a genuinely-dead worker re-drives — is the\n * documented follow-up (see the Track A diagnosis doc, \"Part B\").\n */\nexport class RemoteWorkflowTimeout extends Error {\n readonly taskId: string;\n readonly timeoutMs: number;\n constructor(taskId: string, timeoutMs: number) {\n super(\n `remote workflow task ${taskId} produced no decision within ${timeoutMs}ms — presumed dropped; re-driving via recovery`,\n );\n this.name = 'RemoteWorkflowTimeout';\n this.taskId = taskId;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown on resume when the workflow code no longer matches the recorded history: the step at a\n * logical position has a different name/kind than the checkpoint saved there. This means the\n * workflow definition changed (a step was added/removed/reordered) under an in-flight run without a\n * new `@Workflow` version — continuing would replay the wrong checkpoint into the wrong step and\n * silently corrupt the run, so the engine fails loudly instead. Register a new workflow version for\n * breaking changes (old runs finish on the version they started on).\n */\nexport class NonDeterminismError extends Error {\n readonly runId: string;\n readonly seq: number;\n constructor(runId: string, seq: number, expected: string, recorded: string) {\n super(\n `non-determinism at ${runId}#${seq}: code expects \"${expected}\" but history recorded ` +\n `\"${recorded}\". The workflow changed under an in-flight run — register a new @Workflow version.`,\n );\n this.name = 'NonDeterminismError';\n this.runId = runId;\n this.seq = seq;\n }\n}\n\n/**\n * Thrown AT THE CALL SITE when a workflow-ctx primitive (`ctx.startChild`, `ctx.child`, `ctx.step`,\n * `ctx.sleep`, `ctx.sideEffect`, … — or a `MyWorkflow.start()`/`.execute()` static, which route to\n * them through the ambient ctx) is called from INSIDE the body of a checkpointed step\n * (`ctx.localStep`, `ctx.transaction`, `ctx.sideEffect`, `ctx.now`, `ctx.task`'s dispatch).\n *\n * A step body runs once and is replayed from its checkpoint WITHOUT re-running, so a primitive it\n * called claims a journal position on the first run that no replay ever claims again: every later\n * position shifts and the run dies on its next replay with a `NonDeterminismError` far from the\n * cause. Failing here instead names the real mistake. Move the call out of the step body (into the\n * workflow body), or — from a dispatched `@Step` handler — start a top-level run.\n *\n * A `FatalError` (code `nested_workflow_call`): the step is not retried, the run fails.\n */\nexport class NestedWorkflowCallError extends FatalError {\n readonly runId: string;\n readonly primitive: string;\n readonly step: string;\n constructor(runId: string, primitive: string, step: string) {\n super(\n `ctx.${primitive}() was called inside the body of step \"${step}\" (run ${runId}). Workflow primitives (child/startChild/step/sleep/signals/sideEffect/…, and MyWorkflow.start()/.execute() via the ambient ctx) must be called from the workflow body, never from inside a step body: the step's checkpoint replays without re-running it, so the nested call would shift every later journal position and corrupt the run on replay. Move the call out of the step.`,\n 'nested_workflow_call',\n );\n this.name = 'NestedWorkflowCallError';\n this.runId = runId;\n this.primitive = primitive;\n this.step = step;\n }\n}\n\n/**\n * Thrown by `ctx.all` when one or more parallel child workflows fail. Carries the per-item failures\n * (input index, child run id, error message) and presents an aggregate message summarizing the count\n * and the failing ids — the wait-all/fail-fast counterpart to a single child's FatalError. Mirrors\n * the Python SDK's `GatherFailed`.\n */\nexport class GatherError extends Error {\n readonly failures: { index: number; id: string; error: string }[];\n constructor(failures: { index: number; id: string; error: string }[], total?: number) {\n const ids = failures.map((f) => f.id).join(', ');\n const denom = total ?? failures.length;\n super(`ctx.all: ${failures.length} of ${denom} child(ren) failed: ${ids}`);\n this.name = 'GatherError';\n this.failures = failures;\n }\n}\n\nexport class WorkflowSuspended extends Error {\n /** Epoch ms to auto-resume (durable sleep), or undefined when waiting on an external signal. */\n readonly wakeAt?: number | undefined;\n /** Set when awaited children are what the run is waiting on — see {@link FanJoin}. */\n readonly fan?: FanJoin | undefined;\n /** Marks this as a control-flow signal — see {@link isWorkflowControlFlowSignal}. */\n readonly [CONTROL_FLOW_SIGNAL] = true;\n constructor(wakeAt?: number, fan?: FanJoin) {\n super('workflow suspended');\n this.name = 'WorkflowSuspended';\n this.wakeAt = wakeAt;\n this.fan = fan;\n }\n}\n\n/**\n * What a run suspended on when it awaits children (`ctx.all`, `ctx.child`). For each group of\n * children, every waiter token starts with `waiterPrefix` and every `signal:child:` checkpoint name\n * with `checkpointPrefix`, so the engine can tell whether the group has settled without knowing the\n * children's ids.\n */\nexport interface FanJoin {\n waits: FanWait[];\n}\n\nexport interface FanWait {\n waiterPrefix: string;\n checkpointPrefix: string;\n}\n\n/**\n * Thrown by `ctx.continueAsNew(input)` to end the current run and hand off to a fresh execution of\n * the same workflow with a clean history — for long-running / looping workflows that would otherwise\n * accumulate unbounded checkpoints. The engine completes this run and starts the next one.\n */\nexport class ContinueAsNew extends Error {\n /** Marks this as a control-flow signal — see {@link isWorkflowControlFlowSignal}. */\n readonly [CONTROL_FLOW_SIGNAL] = true;\n constructor(readonly input: unknown) {\n super('workflow continued as new');\n this.name = 'ContinueAsNew';\n }\n}\n","/**\n * A **workflow reference** is how one workflow names another to call it: either a registered workflow\n * **name** (a string — the only option across runtimes, e.g. a Python workflow) or, for a same-runtime\n * TypeScript workflow, its **class**. The class carries the input/output types through the call, so\n * `ctx.child(ShippingWorkflow, input)` type-checks the input and returns a typed result — while a\n * string stays available for the cross-runtime case.\n */\n\n/**\n * The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can\n * be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate\n * copies of this package in a dependency tree.\n */\nexport const WORKFLOW_NAME_KEY: unique symbol = Symbol.for('nestjs-durable:workflow-name');\n\n/** Structural shape of a `@Workflow` class — its `run(ctx, input)` carries the input/output types. */\nexport type WorkflowClass<TInput = unknown, TOutput = unknown> = abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: TInput): Promise<TOutput> | TOutput;\n};\n\n/** A workflow reference: a registered name (cross-runtime) or a workflow class (typed, same-runtime). */\nexport type WorkflowRef<TInput = unknown, TOutput = unknown> =\n | string\n | WorkflowClass<TInput, TOutput>;\n\n/** The input type a workflow class's `run` accepts. */\nexport type WorkflowInputOf<C> = C extends abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: infer I): unknown;\n}\n ? I\n : unknown;\n\n/** The output type a workflow class's `run` resolves to (Promise unwrapped). */\nexport type WorkflowOutputOf<C> = C extends abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: never): infer R;\n}\n ? Awaited<R>\n : unknown;\n\n/**\n * Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a\n * `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was\n * never decorated (so it carries no registered name).\n */\nexport function workflowName(ref: WorkflowRef): string {\n if (typeof ref === 'string') return ref;\n const name = (ref as { [WORKFLOW_NAME_KEY]?: string })[WORKFLOW_NAME_KEY];\n if (!name) {\n throw new Error(\n `workflow class ${ref.name} has no registered name — is it decorated with @Workflow({ name })?`,\n );\n }\n return name;\n}\n","import { currentWorkflowCtx } from './ambient-ctx';\nimport type { StartOptions } from './engine';\nimport { FatalError } from './errors';\nimport type { RunResult } from './interfaces';\nimport {\n type WorkflowClass,\n type WorkflowInputOf,\n type WorkflowOutputOf,\n workflowName,\n} from './workflow-ref';\n\n/**\n * What the class-first statics need from whoever registered the workflow class: the engine, or a\n * store-less start facade (a tenant's `DurableStartClient`). `waitForRun` is optional — a facade\n * without a store cannot wait, so `execute` outside a workflow throws a clear error there.\n */\nexport interface WorkflowStartClient {\n start(workflow: string, input: unknown, runId: string, opts?: StartOptions): Promise<RunResult>;\n waitForRun?(\n runId: string,\n opts?: { timeoutMs?: number; until?: 'settled' | 'terminal' },\n ): Promise<RunResult>;\n}\n\n/**\n * Per-process class → start-client bindings, written by the registrar at boot. On `globalThis`\n * under a `Symbol.for` key for the same duplicate-copy reason as the ambient context: every copy of\n * core in the tree must read the same map. A WeakMap so a torn-down module doesn't pin its classes.\n */\nconst BINDINGS_KEY = Symbol.for('nestjs-durable:workflow-class-bindings');\n\ntype GlobalWithBindings = typeof globalThis & {\n // biome-ignore lint/complexity/noBannedTypes: keyed by class constructors\n [BINDINGS_KEY]?: WeakMap<Function, WorkflowStartClient>;\n};\n\nconst globalRef = globalThis as GlobalWithBindings;\nif (!globalRef[BINDINGS_KEY]) {\n globalRef[BINDINGS_KEY] = new WeakMap();\n}\nconst bindings = globalRef[BINDINGS_KEY];\n\n/**\n * Bind a `@Workflow` class to the client that can start it — called by the registrar for every\n * discovered workflow at boot. This is what lets `MyWorkflow.start()` resolve THE engine that\n * registered it, with no global engine singleton (two engines in one process each bind their own\n * classes).\n */\n// biome-ignore lint/complexity/noBannedTypes: keyed by class constructors\nexport function bindWorkflowClass(ctor: Function, client: WorkflowStartClient): void {\n bindings.set(ctor, client);\n}\n\nfunction clientOf(ctor: WorkflowClass): WorkflowStartClient {\n const client = bindings.get(ctor);\n if (!client) {\n throw new Error(\n `${workflowName(ctor)} is not bound to a durable engine — the class-first statics only work after the module that registers this workflow has booted (or, in a store-less tenant worker, use the injected WorkflowService/engine facade instead).`,\n );\n }\n return client;\n}\n\n/**\n * Optional base class giving a `@Workflow` a **class-first API** — start it from anywhere without\n * injecting the engine or `WorkflowService`:\n *\n * ```ts\n * @Workflow({ name: 'checkout', version: '1' })\n * export class CheckoutWorkflow extends DurableWorkflow {\n * async run(ctx: WorkflowCtx, order: Order) { ... }\n * }\n *\n * const { runId } = await CheckoutWorkflow.start(order); // fire-and-forget, typed input\n * const result = await CheckoutWorkflow.execute(order); // run-and-await, typed output\n * ```\n *\n * Each method means the same thing everywhere; only the mechanism adapts to where you call it:\n *\n * - {@link DurableWorkflow.start | `start`} — **fire-and-forget**. Outside a workflow it is exactly\n * `engine.start` (enqueue, return `{ runId, status }` immediately). Inside a workflow body it\n * becomes `ctx.startChild` — checkpointed, replay-safe, parent-linked — same contract.\n * - {@link DurableWorkflow.execute | `execute`} — **run-and-await the typed output**. Inside a\n * workflow it is `ctx.child` (the parent suspends with zero compute and resumes with the result).\n * Outside it starts the run and waits until it settles terminally, resolving the output or\n * throwing `FatalError` when the run failed/cancelled/dead.\n *\n * Inside-ness is detected via the ambient workflow context the engine installs around every body\n * execution (see `ambient-ctx.ts`). A `@Step` handler runs on a worker, off the body's path — the\n * statics there start a TOP-LEVEL run, which is correct: a handler is not the workflow body.\n */\nexport class DurableWorkflow {\n /**\n * Fire-and-forget start — `engine.start` outside a workflow, `ctx.startChild` (parent-linked)\n * inside one. `opts.id` pins the run id (outside) / child id (inside) for idempotent starts.\n */\n static async start<C extends WorkflowClass>(\n this: C,\n input: WorkflowInputOf<C>,\n opts?: { id?: string } & StartOptions,\n ): Promise<RunResult> {\n // biome-ignore lint/complexity/noThisInStatic: the polymorphic `this` IS the subclass being started — the class name would break every subclass\n // biome-ignore lint/complexity/noUselessThisAlias: aliased ONCE on purpose so the noThisInStatic suppression lives in one place, not on every `this` use below\n const cls = this;\n const ctx = currentWorkflowCtx();\n if (ctx) {\n const runId = await ctx.startChild(cls, input, opts?.id);\n return { runId, status: 'pending' };\n }\n const runId = opts?.id ?? globalThis.crypto.randomUUID();\n return clientOf(cls).start(workflowName(cls), input, runId, opts);\n }\n\n /**\n * Run-and-await the typed output — `ctx.child` inside a workflow (suspends the parent, zero\n * compute); outside, starts the run and waits until it settles terminally. Throws `FatalError`\n * when the run does not complete. `opts.timeoutMs` bounds the OUTSIDE wait only (inside, a\n * suspended parent costs nothing — bound the child itself with `executionTimeout` instead).\n */\n static async execute<C extends WorkflowClass>(\n this: C,\n input: WorkflowInputOf<C>,\n opts?: { id?: string; timeoutMs?: number } & StartOptions,\n ): Promise<WorkflowOutputOf<C>> {\n // biome-ignore lint/complexity/noThisInStatic: the polymorphic `this` IS the subclass being run — the class name would break every subclass\n // biome-ignore lint/complexity/noUselessThisAlias: aliased ONCE on purpose so the noThisInStatic suppression lives in one place, not on every `this` use below\n const cls = this;\n const ctx = currentWorkflowCtx();\n if (ctx) return ctx.child(cls, input, opts?.id);\n const client = clientOf(cls);\n if (!client.waitForRun) {\n throw new FatalError(\n `${workflowName(cls)}.execute() outside a workflow needs a store-backed engine to await the result — this class is bound to a store-less start facade (tenant worker). Use ${workflowName(cls)}.start() and observe the run instead.`,\n 'execute_unsupported',\n );\n }\n const runId = opts?.id ?? globalThis.crypto.randomUUID();\n await client.start(workflowName(cls), input, runId, opts);\n const settled = await client.waitForRun(runId, {\n ...(opts?.timeoutMs != null ? { timeoutMs: opts.timeoutMs } : {}),\n until: 'terminal',\n });\n if (settled.status === 'completed') return settled.output as WorkflowOutputOf<C>;\n const detail = settled.error ? `: ${settled.error.message}` : '';\n throw new FatalError(\n `${workflowName(cls)} run ${runId} settled ${settled.status}${detail}`,\n settled.error?.code ?? 'execute_failed',\n );\n }\n}\n","const UNIT_MS: Record<string, number> = {\n ms: 1,\n s: 1_000,\n sec: 1_000,\n second: 1_000,\n seconds: 1_000,\n m: 60_000,\n min: 60_000,\n minute: 60_000,\n minutes: 60_000,\n h: 3_600_000,\n hr: 3_600_000,\n hour: 3_600_000,\n hours: 3_600_000,\n d: 86_400_000,\n day: 86_400_000,\n days: 86_400_000,\n w: 604_800_000,\n week: 604_800_000,\n weeks: 604_800_000,\n};\n\n/**\n * Parse a human duration to milliseconds. Accepts a number (already ms) or a string like\n * `'500ms'`, `'30s'`, `'15m'`, `'2h'`, `'7d'`, `'7 days'`.\n */\nexport function parseDuration(duration: string | number): number {\n if (typeof duration === 'number') return duration;\n const match = duration.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*([a-z]+)$/i);\n if (!match) throw new Error(`invalid duration: ${duration}`);\n const value = Number(match[1]);\n const unit = (match[2] ?? '').toLowerCase();\n const factor = UNIT_MS[unit];\n if (factor === undefined) throw new Error(`unknown duration unit: ${unit}`);\n return value * factor;\n}\n","import type { StepOptions } from './interfaces';\n\n/** Delay in ms before the next retry attempt, per a step's `StepOptions` backoff config. Shared by\n * the local-step retry loop and the durable remote-step retry, so they stay consistent. */\nexport function backoffDelay(attempt: number, options?: StepOptions): number {\n const base = options?.backoffMs ?? 0;\n if (base <= 0) return 0;\n const raw = options?.backoff === 'exp' ? base * 2 ** (attempt - 1) : base;\n const capped = options?.backoffMaxMs ? Math.min(raw, options.backoffMaxMs) : raw;\n return options?.jitter ? Math.round(capped * (0.5 + Math.random() * 0.5)) : capped;\n}\n","/**\n * Wrappers around the **real execution** of a unit of durable work — a workflow turn, or a step\n * handler body. Distinct from {@link StepInterceptor} (`engine.use`), which only sees the in-process\n * `localStep` primitives (`ctx.now`, `ctx.sideEffect`, `ctx.task`'s dispatch step, saga\n * compensations): a user's `ctx.step` is ALWAYS dispatched, so its handler runs inside a transport\n * callback or a worker process where no engine is in scope at all.\n *\n * That is exactly why this registry is process-level rather than per-engine. `runStepHandler` is a\n * free function every transport shares, and a thin worker (`DurableModule` with a `connection` and\n * no `store`) holds no `WorkflowEngine` to hang a hook off. A per-engine registry could not reach\n * either, so the seam that covers every deployment shape has to sit above the engine.\n *\n * The intended consumer is an observability bridge (Telescope, OTel, a logger) that needs to\n * establish an ambient scope — an AsyncLocalStorage batch, a span — that the executing code records\n * into. It is deliberately NOT a transform point: see {@link runDurableExecution}.\n */\n\n/** The unit of durable work a wrapper is being invoked around. */\nexport interface DurableExecution {\n /** `'workflow'` = one turn of a run's body; `'step'` = one step handler body. */\n readonly unit: 'workflow' | 'step';\n readonly runId: string;\n /** The workflow name. Present on a turn; a dispatched step task does not carry it on the wire. */\n readonly workflow: string | undefined;\n /** The step name, for `unit: 'step'`. Undefined for a turn. */\n readonly name: string | undefined;\n /** The step's logical position within the run, for `unit: 'step'`. */\n readonly seq: number | undefined;\n /** 1-based dispatch attempt, when the task carries one. */\n readonly attempt: number | undefined;\n}\n\n/**\n * Wraps one unit of durable work. Call `next()` to run the body (or the next wrapper). Whatever the\n * wrapper returns or throws is discarded — see {@link runDurableExecution} for why.\n */\nexport type DurableExecutionWrapper = (\n execution: DurableExecution,\n next: () => Promise<unknown>,\n) => Promise<unknown>;\n\n/** First registered is outermost, matching `engine.use`'s onion order. */\nconst wrappers: DurableExecutionWrapper[] = [];\n\n/**\n * Register a {@link DurableExecutionWrapper}. Returns an unregister function.\n *\n * Registering is the ONLY cost an unused hook imposes: with an empty registry\n * {@link runDurableExecution} returns the body's own promise without allocating a chain, so a host\n * that wires no observability pays nothing at all on the execution path.\n */\nexport function useDurableExecution(wrapper: DurableExecutionWrapper): () => void {\n wrappers.push(wrapper);\n return () => {\n const i = wrappers.indexOf(wrapper);\n if (i >= 0) wrappers.splice(i, 1);\n };\n}\n\n/** Drop every registered wrapper. For tests that must not leak a wrapper into the next file. */\nexport function clearDurableExecutionWrappers(): void {\n wrappers.length = 0;\n}\n\n/** Whether any wrapper is registered — lets a hot path skip building an execution descriptor. */\nexport function hasDurableExecutionWrappers(): boolean {\n return wrappers.length > 0;\n}\n\n/**\n * Run `body` inside every registered wrapper and settle with **the body's own outcome**.\n *\n * The wrappers' return values and throws are deliberately ignored. An observer that misbehaves —\n * returns early without calling `next()` is the one case we cannot paper over, but one that throws\n * *after* the body settled, or swallows the body's error and returns normally, is common enough in\n * telemetry code — must not be able to change what the workflow saw. A wrapper that turned a failed\n * step into a completed one would corrupt the run's history and its checkpoints, which is a far\n * worse failure than a missing trace. This is the same reasoning the bullmq/schedule Telescope\n * watchers apply when they re-throw the host's error rather than swallowing it, pushed down into\n * the seam so every wrapper gets it for free instead of having to remember.\n *\n * The one unrecoverable case is a wrapper that never calls `next()`: the body did not run, so there\n * is no outcome to return and we throw rather than invent one.\n */\nexport async function runDurableExecution<T>(\n execution: DurableExecution,\n body: () => Promise<T>,\n): Promise<T> {\n if (wrappers.length === 0) return body();\n\n let outcome: { ok: true; value: T } | { ok: false; error: unknown } | undefined;\n const inner = async (): Promise<unknown> => {\n try {\n const value = await body();\n outcome = { ok: true, value };\n return value;\n } catch (error) {\n outcome = { ok: false, error };\n throw error;\n }\n };\n const chain = wrappers.reduceRight<() => Promise<unknown>>(\n (next, wrapper) => () => wrapper(execution, next),\n inner,\n );\n\n try {\n await chain();\n } catch (error) {\n // Only a throw from BEFORE the body ran can surface here — anything else is a wrapper's own\n // failure layered on top of a body that already settled, and the body wins below.\n if (outcome === undefined) throw error;\n }\n if (outcome === undefined) {\n throw new Error(\n 'a durable execution wrapper returned without calling next() — the unit of work never ran',\n );\n }\n if (outcome.ok) return outcome.value;\n throw outcome.error;\n}\n","import type { StepEvent, StepLogger, SubProcessHandle } from './interfaces';\n\n/** Attach the elapsed `durationMs` (from `start`) to `data`, unless the caller already set one. */\nfunction withDuration(start: number, now: () => number, data?: unknown): Record<string, unknown> {\n if (data && typeof data === 'object' && 'durationMs' in data) {\n return data as Record<string, unknown>;\n }\n const base = data && typeof data === 'object' ? (data as Record<string, unknown>) : {};\n return { ...base, durationMs: now() - start };\n}\n\n/**\n * A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the\n * local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records\n * the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's\n * `StepContext`.\n */\nexport function createStepLogger(events: StepEvent[], now: () => number): StepLogger {\n // The sub-process a `subProcess(...)` body is currently inside; debug/info/warn/error emitted while\n // inside get tagged with its id, so the dashboard groups that log trail under the sub-process.\n let currentSub: { id: string } | undefined;\n const push = (level: StepEvent['level'], message: string, data?: unknown) =>\n events.push({\n at: now(),\n level,\n message,\n ...(currentSub ? { subId: currentSub.id } : {}),\n ...(data === undefined ? {} : { data }),\n });\n const subEvent: StepLogger['subEvent'] = (e) =>\n events.push({\n at: now(),\n level: e.status === 'failed' ? 'error' : e.status === 'skipped' ? 'warn' : 'info',\n message: e.message ?? e.phase ?? e.name,\n subId: e.id,\n name: e.name,\n ...(e.group === undefined ? {} : { group: e.group }),\n ...(e.phase === undefined ? {} : { phase: e.phase }),\n ...(e.status === undefined ? {} : { status: e.status }),\n ...(e.data === undefined ? {} : { data: e.data }),\n });\n const subProcess: StepLogger['subProcess'] = async (name, body, opts) => {\n const id = opts?.id ?? globalThis.crypto.randomUUID();\n const group = opts?.group;\n const start = now();\n const prevSub = currentSub;\n currentSub = { id };\n let terminal = false;\n const emit = (status: 'ok' | 'failed' | 'skipped', message?: string, data?: unknown) => {\n if (terminal) return;\n terminal = true;\n subEvent({ id, name, group, status, message, data: withDuration(start, now, data) });\n };\n const handle: SubProcessHandle = {\n phase: (phase, data) => {\n if (!terminal) subEvent({ id, name, group, phase, data });\n return handle;\n },\n skip: (reason, data) => emit('skipped', reason, data),\n fail: (reason, data) => emit('failed', reason, data),\n };\n try {\n const result = await body(handle);\n emit('ok'); // no-op if the body already called skip()/fail()\n return result;\n } catch (err) {\n emit('failed', err instanceof Error ? err.message : String(err));\n throw err;\n } finally {\n currentSub = prevSub;\n }\n };\n return {\n debug: (m, d) => push('debug', m, d),\n info: (m, d) => push('info', m, d),\n warn: (m, d) => push('warn', m, d),\n error: (m, d) => push('error', m, d),\n sub: (name, status, message, data) =>\n events.push({\n at: now(),\n level: status === 'failed' ? 'error' : status === 'skipped' ? 'warn' : 'info',\n message: message ?? name,\n name,\n status,\n ...(data === undefined ? {} : { data }),\n }),\n subEvent,\n subProcess,\n };\n}\n","import { runOutsideWorkflowCtx } from './ambient-ctx';\nimport { runInStepLogger } from './ambient-step';\nimport { runDurableExecution } from './execution-hooks';\nimport type { RemoteTask, StepEvent, StepLogger, StepResult } from './interfaces';\nimport { createStepLogger } from './step-logger';\n\n/** Canonical step id — the stable identity of a step within a run, used for dedupe and\n * correlation. The format is part of the cross-language wire contract (Python builds the same). */\nexport function stepId(runId: string, seq: number): string {\n return `${runId}:${seq}`;\n}\n\n/** Deterministic signal token a breakpoint suspends on — derived from its logical position. Shared\n * so `ctx.breakpoint` (which records it) and `engine.continue` (which signals it) agree. */\nexport const breakpointToken = (runId: string, seq: number): string => `bp:${runId}:${seq}`;\n\n/** A remote-worker step body. The optional `log` records sub-process outcomes and debug/error\n * lines that ride back on the result — the TypeScript twin of the Python SDK's `StepContext`. */\nexport type StepHandler = (input: unknown, log: StepLogger) => Promise<unknown> | unknown;\n\n/**\n * Run `handler` for `task` and produce the wire-format {@link StepResult}. Pure (no transport,\n * no I/O beyond the handler), so every transport — and any language port — can share the exact\n * same completed / failed / no-handler contract instead of re-deriving it.\n */\nexport async function runStepHandler(\n task: RemoteTask,\n handler: StepHandler | undefined,\n): Promise<StepResult> {\n // Stamp the worker's pickup time so the engine can report queue-wait (startedAt − enqueuedAt).\n // This is the one place every transport funnels through, so timing comes for free everywhere.\n const base = { runId: task.runId, seq: task.seq, stepId: task.stepId, startedAt: Date.now() };\n if (!handler) {\n return {\n ...base,\n status: 'failed',\n error: { message: `no handler for ${task.name}`, retryable: false },\n };\n }\n const events: StepEvent[] = [];\n const withEvents = (result: StepResult): StepResult =>\n events.length > 0 ? { ...result, events } : result;\n try {\n // The SAME logger goes to the handler's second argument and into the ambient storage, so a\n // helper buried under the handler emits into this step's `events` without being handed one.\n const logger = createStepLogger(events, Date.now);\n // The registered execution wrappers go OUTSIDE the handler and INSIDE this try/catch, so an\n // observability scope opened here (a Telescope batch, an OTel span) is ambient while the handler\n // body runs — a query it issues or an exception it throws is recorded inside the scope, which is\n // the whole point. Wrapping the `runStepHandler` call from a transport instead would put the\n // scope around the result-building too, and wrapping after the fact would put it around nothing.\n const output = await runDurableExecution(\n {\n unit: 'step',\n runId: task.runId,\n workflow: undefined, // a dispatched step task does not carry its workflow name on the wire\n name: task.name,\n seq: task.seq,\n attempt: task.attempt,\n },\n // Outside any ambient workflow ctx: an in-process transport runs the handler on the parent\n // body's async path, but a handler is not the body (see `runOutsideWorkflowCtx`).\n async () =>\n runOutsideWorkflowCtx(() => runInStepLogger(logger, () => handler(task.input, logger))),\n );\n return withEvents({ ...base, status: 'completed', output });\n } catch (err) {\n // Carry `code`/`retryable` off the thrown error if present, so the engine's durable retry can\n // honour a worker's \"don't retry this\" verdict (e.g. a declined card).\n const e = err as { message?: string; code?: string; retryable?: boolean };\n return withEvents({\n ...base,\n status: 'failed',\n error: {\n message: err instanceof Error ? err.message : String(err),\n ...(typeof e?.code === 'string' ? { code: e.code } : {}),\n ...(typeof e?.retryable === 'boolean' ? { retryable: e.retryable } : {}),\n },\n });\n }\n}\n","import type { StepCheckpoint, StepError, StepEvent, StepKind } from './interfaces';\nimport { stepId } from './protocol';\n\n/**\n * The step-event names the lost-dispatch self-heal stamps on a checkpoint's trail, so an operator (and\n * the dashboard, which renders a step's events under it) can tell a re-drive apart from an ordinary\n * failure retry WITHOUT a schema change: `step.redispatched` = the dispatched job was presumed lost\n * (its lease lapsed with no result and no heartbeat) and the step was re-enqueued; `step.lost` = the\n * re-drive bound (`remoteRedispatchMax`) ran out and the step was failed `remote_step_lost`.\n */\nexport const REDISPATCHED_STEP_EVENT = 'step.redispatched';\nexport const LOST_STEP_EVENT = 'step.lost';\n\n/**\n * A `warn` step event recording a lost-dispatch re-drive (or the give-up at its bound). `attempts` is\n * the dispatch count AFTER the transition, so the trail reads as the attempt an operator sees on the\n * checkpoint.\n */\nexport function lostStepEvent(\n at: number,\n attempts: number,\n outcome: 'redispatched' | 'lost',\n): StepEvent {\n return {\n at,\n level: 'warn',\n name: outcome === 'lost' ? LOST_STEP_EVENT : REDISPATCHED_STEP_EVENT,\n message:\n outcome === 'lost'\n ? `dispatch lost and the re-drive bound is spent after ${attempts} dispatch(es) — failing the step`\n : `re-dispatched after a lost dispatch (attempt ${attempts}): the step's lease lapsed with no result and no heartbeat`,\n };\n}\n\n/** Drop an empty events array to `undefined` (the repeated `events?.length ? events : undefined`). */\nfunction nonEmptyEvents(events: StepEvent[] | undefined): StepEvent[] | undefined {\n return events && events.length > 0 ? events : undefined;\n}\n\n/**\n * Build a *phased* step checkpoint — one with distinct enqueue/run/finish timestamps (a local step\n * that is running/completed/failed, or a pending remote/sleep step). Computes the deterministic\n * `stepId` and normalizes empty event arrays, so the engine's running/completed/failed/pending\n * checkpoint literals are constructed in exactly one place instead of ~8.\n *\n * For instantaneous checkpoints (sleep timers, markers, delivered signals) use {@link instantCheckpoint}.\n */\nexport function stepCheckpoint(p: {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n status: StepCheckpoint['status'];\n attempts: number;\n enqueuedAt: Date;\n startedAt: Date;\n finishedAt: Date;\n input?: unknown;\n output?: unknown;\n error?: StepError | undefined;\n events?: StepEvent[] | undefined;\n workerGroup?: string | undefined;\n wakeAt?: number | undefined;\n parallelGroup?: string | undefined;\n}): StepCheckpoint {\n return {\n runId: p.runId,\n seq: p.seq,\n name: p.name,\n kind: p.kind,\n stepId: stepId(p.runId, p.seq),\n status: p.status,\n input: p.input,\n output: p.output,\n error: p.error,\n events: nonEmptyEvents(p.events),\n attempts: p.attempts,\n workerGroup: p.workerGroup,\n wakeAt: p.wakeAt,\n parallelGroup: p.parallelGroup,\n enqueuedAt: p.enqueuedAt,\n startedAt: p.startedAt,\n finishedAt: p.finishedAt,\n };\n}\n\n/**\n * Build an *instantaneous* checkpoint — one with no distinct enqueue/run/finish phases (a durable\n * sleep timer, a breakpoint marker, a delivered signal, a published `setEvent` value, a `patched`\n * marker). All three timestamps collapse to now and `attempts` is 1. Collapses what was five\n * near-identical 10-field `saveCheckpoint({...})` literals into one builder.\n */\nexport function instantCheckpoint(p: {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n status?: StepCheckpoint['status'];\n output?: unknown;\n wakeAt?: number;\n parallelGroup?: string | undefined;\n}): StepCheckpoint {\n const at = new Date();\n return {\n runId: p.runId,\n seq: p.seq,\n name: p.name,\n kind: p.kind,\n stepId: stepId(p.runId, p.seq),\n status: p.status ?? 'completed',\n output: p.output,\n wakeAt: p.wakeAt,\n parallelGroup: p.parallelGroup,\n attempts: 1,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n };\n}\n","import { FatalError } from './errors';\n\n/**\n * The payload an external `ctx.task` / child run delivers back on its completion signal: either a\n * value or a failure. One typed envelope so `task` and `child` share the same unwrap (instead of\n * sniffing ad-hoc `__error` keys).\n */\nexport type Completion<T> = { ok: true; value: T } | { ok: false; error: string };\n\n/** Whether a signal payload is a failed `Completion`. */\nexport function isFailedCompletion(payload: unknown): boolean {\n const c = payload as Completion<unknown> | null;\n return !!c && typeof c === 'object' && 'ok' in c && c.ok === false;\n}\n\n/** Read a `Completion` from a signal payload: return the value, or throw a FatalError if it failed. */\nexport function unwrapCompletion<T>(payload: unknown, label: string): T {\n const c = payload as Completion<T> | null;\n if (c && typeof c === 'object' && 'ok' in c && c.ok === false) {\n throw new FatalError(`${label} failed: ${c.error}`);\n }\n return (c as { value: T } | null)?.value as T;\n}\n","import { ConcurrencyLimitError } from './errors';\nimport type { RunQuery, RunStatus, StateStore } from './interfaces';\n\n/**\n * A start-time concurrency quota for ONE start: at most `limit` runs sharing `key` may be in flight\n * (in `countStatuses`) at once; a start that would exceed it is rejected with\n * {@link ConcurrencyLimitError} before any run is created.\n *\n * The key is global — not per workflow — so different workflows started with the same key share the\n * quota (e.g. `tenant:acme` capping every kind of run a tenant can have executing). Passed per start\n * as `StartOptions.concurrency`, or derived from the input by a workflow's {@link ConcurrencyConfig}.\n */\nexport interface ConcurrencyQuota {\n /** The quota bucket, e.g. `tenant:acme`. Stamped on the run as the tag `concurrency:<key>`. */\n key: string;\n /** Max runs of this key in flight at once. `limit <= 0` rejects every start. */\n limit: number;\n /**\n * Which statuses occupy a slot. Default: every non-terminal status\n * ({@link DEFAULT_CONCURRENCY_STATUSES}). Narrow it to e.g. `['pending', 'running']` so runs parked\n * on a human (`suspended`) stop counting against the quota.\n */\n countStatuses?: RunStatus[] | undefined;\n}\n\n/**\n * A workflow's standing concurrency quota, declared at registration (`register(..., { concurrency })`\n * / `@Workflow({ concurrency })`): the key is derived from each start's input, and the limit may be a\n * function of the key (per-tenant plans). A `StartOptions.concurrency` on one start overrides it.\n */\nexport interface ConcurrencyConfig {\n /** Derive the quota key from the input. Return `undefined` to leave this start unlimited. */\n key: (input: unknown) => string | undefined;\n /** Max in-flight runs per key — a number, or resolved per key (e.g. from the tenant's plan). */\n limit: number | ((key: string) => number | Promise<number>);\n /** Which statuses occupy a slot. See {@link ConcurrencyQuota.countStatuses}. */\n countStatuses?: RunStatus[] | undefined;\n}\n\n/** Every non-terminal status: what \"in flight\" means when a quota doesn't narrow it. */\nexport const DEFAULT_CONCURRENCY_STATUSES: readonly RunStatus[] = [\n 'pending',\n 'running',\n 'suspended',\n 'cancelling',\n 'blocked',\n];\n\n/** The tag a quota-bearing run carries, so its siblings can be counted by one tag+status query. */\nexport function concurrencyTag(key: string): string {\n return `concurrency:${key}`;\n}\n\n/** Resolve the quota that applies to one start: the per-start override, else the workflow's config. */\nexport async function resolveConcurrency(\n override: ConcurrencyQuota | undefined,\n config: ConcurrencyConfig | undefined,\n input: unknown,\n): Promise<ConcurrencyQuota | undefined> {\n if (override) return override;\n if (!config) return undefined;\n const key = config.key(input);\n if (key === undefined) return undefined;\n const limit = typeof config.limit === 'function' ? await config.limit(key) : config.limit;\n return { key, limit, countStatuses: config.countStatuses };\n}\n\n/** Count the runs matching `query` as cheaply as the store allows (count → facets → listing). */\nexport async function countRuns(\n store: StateStore,\n query: Omit<RunQuery, 'limit' | 'offset'>,\n): Promise<number> {\n if (store.countRuns) return store.countRuns(query);\n if (store.runFacets && !query.status && !query.statuses && query.origin === undefined) {\n const cells = await store.runFacets(query);\n return cells.reduce((sum, c) => sum + c.count, 0);\n }\n if (store.runFacets && query.statuses && !query.status && query.origin === undefined) {\n const { statuses, ...rest } = query;\n const cells = await store.runFacets(rest);\n return cells.filter((c) => statuses.includes(c.status)).reduce((sum, c) => sum + c.count, 0);\n }\n return (await store.listRuns(query)).length;\n}\n\n/**\n * Reject a start that would exceed `quota`: counts the in-flight runs carrying the quota's tag and\n * throws {@link ConcurrencyLimitError} once they reach the limit.\n *\n * A SOFT cap under a race: the count and the run's creation are separate statements, so N starts\n * racing on the last free slot can each see it free (the same guarantee a hand-rolled\n * `SELECT count(*)` gate gives). It is exact whenever starts for a key are not simultaneous, and the\n * overshoot is bounded by the number of truly concurrent starts. Use `singleton` when you need a\n * strict, queueing per-key limit instead of a rejecting one.\n */\nexport async function assertConcurrency(\n store: StateStore,\n workflow: string,\n quota: ConcurrencyQuota,\n): Promise<void> {\n const active =\n quota.limit <= 0\n ? 0\n : await countRuns(store, {\n tag: concurrencyTag(quota.key),\n statuses: [...(quota.countStatuses ?? DEFAULT_CONCURRENCY_STATUSES)],\n });\n if (quota.limit <= 0 || active >= quota.limit) {\n throw new ConcurrencyLimitError(workflow, quota.key, quota.limit, active);\n }\n}\n","import { FatalError } from './errors';\nimport type { InternalWorkflowCtx } from './workflow-ctx';\n\n/** One operation on a durable entity: mutate `state` in place and/or return a result. */\nexport type EntityHandler<S = unknown> = (state: S, arg: unknown) => unknown | Promise<unknown>;\n\n/** A durable keyed entity (a virtual object): per-key serialized handlers over durable state. */\nexport interface EntityConfig<S = unknown> {\n /** Build the initial state for a fresh key. */\n initialState: () => S;\n /** Operation handlers, keyed by op name. Each runs serially per key, exactly once. */\n handlers: Record<string, EntityHandler<S>>;\n}\n\n/** The slice of the engine the entity subsystem needs (so it stays a standalone module). */\nexport interface EntityHost {\n register(\n name: string,\n version: string,\n fn: (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>,\n ): void;\n signalWithStart(\n workflow: string,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n ): Promise<{ runId: string }>;\n getEvent<T>(runId: string, key: string): Promise<T | undefined>;\n signal(token: string, payload: unknown): Promise<unknown>;\n}\n\nconst ENTITY_WORKFLOW = '__entity';\nconst entityRunId = (name: string, key: string): string => `entity:${name}:${key}`;\n\n/**\n * Durable keyed **entities** (virtual objects): a keyed actor whose handlers run **serialized per\n * key** over **durable state**, exactly once. Each key is one long-lived run (`entity:<name>:<key>`)\n * processing ops in order. Drive it with `signal` (fire) or `ctx.callEntity` (call + await result),\n * read state with `getState`. Registers its built-in runner on construction.\n */\nexport class Entities {\n private readonly configs = new Map<string, EntityConfig>();\n\n constructor(private readonly host: EntityHost) {\n host.register(ENTITY_WORKFLOW, '1', (ctx, input) => this.run(ctx, input));\n }\n\n register<S>(name: string, config: EntityConfig<S>): void {\n this.configs.set(name, config as EntityConfig);\n }\n\n /** Deliver an op to an entity's runner, starting it on first contact. `reply` (a signal token)\n * receives the handler's result, for `ctx.callEntity`. */\n dispatch(\n name: string,\n key: string,\n op: string,\n arg: unknown,\n reply?: string,\n ): Promise<{ runId: string }> {\n const runId = entityRunId(name, key);\n return this.host.signalWithStart(ENTITY_WORKFLOW, { name, key }, runId, {\n token: runId,\n payload: { op, arg, reply },\n });\n }\n\n async signal(name: string, key: string, op: string, arg?: unknown): Promise<void> {\n await this.dispatch(name, key, op, arg);\n }\n\n getState<S = unknown>(name: string, key: string): Promise<S | undefined> {\n return this.host.getEvent<S>(entityRunId(name, key), 'state');\n }\n\n /** The built-in runner: one long-lived run per key, processing ops serially over state. */\n private async run(ctx: InternalWorkflowCtx, input: unknown): Promise<unknown> {\n const { name, key } = input as { name: string; key: string };\n const config = this.configs.get(name);\n if (!config) throw new FatalError(`entity \"${name}\" is not registered`);\n const token = entityRunId(name, key);\n let state = config.initialState();\n for (let i = 0; ; i += 1) {\n const msg = (await ctx.waitForSignal(token)) as { op: string; arg: unknown; reply?: string };\n // Run the handler and snapshot the (possibly mutated) state in ONE checkpoint, so replay\n // restores the state from the checkpoint instead of re-running the handler. `ctx.step` is now\n // ALWAYS dispatched (see WorkflowCtx.step) — this in-process capture uses the internal\n // `localStep` primitive instead (same checkpointed-once-then-replayed semantics).\n const out = await ctx.localStep(`op:${i}`, async () => {\n const handler = config.handlers[msg.op];\n if (!handler) throw new FatalError(`entity \"${name}\" has no handler for op \"${msg.op}\"`);\n const result = await handler(state, msg.arg);\n return { result, state };\n });\n state = out.state; // carry state forward (and restore it from the checkpoint on replay)\n await ctx.setEvent('state', state); // publish for getState\n if (msg.reply) {\n await ctx.localStep(`reply:${i}`, async () => {\n await this.host.signal((msg as { reply: string }).reply, out.result);\n });\n }\n }\n }\n}\n","import { SignalTimeoutError } from './errors';\nimport type { WorkflowCtx } from './interfaces';\n\n/** How `onEvent` triggers are coalesced into fewer runs (see `@Workflow({ debounce | batch })`). */\nexport type EventBatchConfig =\n | { mode: 'debounce'; windowMs: number }\n | { mode: 'batch'; maxSize: number; windowMs: number };\n\n/** The slice of the engine the accumulators need (so they stay a standalone module). */\nexport interface AccumulatorHost {\n register(\n name: string,\n version: string,\n fn: (ctx: WorkflowCtx, input: unknown) => Promise<unknown>,\n ): void;\n signalWithStart(\n workflow: string,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n ): Promise<{ runId: string }>;\n}\n\nconst accToken = (target: string): string => `__evtacc__:${target}`;\n\n/**\n * Built-in workflows that coalesce `onEvent` triggers. Each is a long-lived per-target accumulator\n * fed by `signalWithStart`: it collects payloads then starts the target once, and `continueAsNew`s to\n * re-arm for the next burst. Signal buffering keeps the re-arm race-free. Registers its runners on\n * construction.\n */\nexport class EventAccumulators {\n constructor(private readonly host: AccumulatorHost) {\n host.register('__evt_debounce', '1', (ctx, input) => this.debounce(ctx, input));\n host.register('__evt_batch', '1', (ctx, input) => this.batch(ctx, input));\n }\n\n /** Route an `onEvent` payload into its target's debounce/batch accumulator. */\n route(target: string, config: EventBatchConfig, payload: unknown): Promise<{ runId: string }> {\n const [workflow, input] =\n config.mode === 'debounce'\n ? (['__evt_debounce', { target, windowMs: config.windowMs }] as const)\n : ([\n '__evt_batch',\n { target, maxSize: config.maxSize, windowMs: config.windowMs },\n ] as const);\n return this.host.signalWithStart(workflow, input, accToken(target), {\n token: accToken(target),\n payload,\n });\n }\n\n /** Fire the target with the LAST payload once events have been quiet for `windowMs`. */\n private async debounce(ctx: WorkflowCtx, input: unknown): Promise<unknown> {\n const { target, windowMs } = input as { target: string; windowMs: number };\n const token = accToken(target);\n let last = await ctx.waitForSignal(token); // park for the first event of a burst\n for (;;) {\n try {\n last = await ctx.waitForSignal(token, { timeoutMs: windowMs }); // extend on each event\n } catch (e) {\n if (e instanceof SignalTimeoutError) break; // quiet for `windowMs` → fire\n throw e; // WorkflowSuspended / ContinueAsNew etc. must propagate\n }\n }\n await ctx.startChild(target, last);\n return ctx.continueAsNew(input); // re-arm\n }\n\n /** Fire the target with all payloads (`{ events }`) once `maxSize` or `windowMs` from the first. */\n private async batch(ctx: WorkflowCtx, input: unknown): Promise<unknown> {\n const { target, maxSize, windowMs } = input as {\n target: string;\n maxSize: number;\n windowMs: number;\n };\n const token = accToken(target);\n const events: unknown[] = [await ctx.waitForSignal(token)]; // park for the first\n const deadline = (await ctx.now()) + windowMs;\n while (events.length < maxSize) {\n const remaining = deadline - (await ctx.now());\n if (remaining <= 0) break;\n try {\n events.push(await ctx.waitForSignal(token, { timeoutMs: remaining }));\n } catch (e) {\n if (e instanceof SignalTimeoutError) break; // window elapsed → fire what we have\n throw e; // WorkflowSuspended / ContinueAsNew etc. must propagate\n }\n }\n await ctx.startChild(target, { events });\n return ctx.continueAsNew(input); // re-arm\n }\n}\n","// Named events: pub/sub on top of the signal-waiter table. A `ctx.waitForEvent(name, { match })`\n// registers a signal waiter whose token encodes the event name + match criteria (base64 so they\n// never contain the `:` delimiter); `engine.publishEvent(name, payload)` lists the waiters for that\n// name by token prefix, checks each one's match against the payload, and signals the ones that pass.\n// No schema change beyond a `listSignalWaiters(prefix)` store method.\n\nconst enc = (s: string): string => Buffer.from(s, 'utf8').toString('base64');\nconst dec = (s: string): string => Buffer.from(s, 'base64').toString('utf8');\n\n/**\n * How many candidates a buffered-event scan considers (`listBufferedEvents(name, limit)`) before\n * giving up. An event's buffer is keyed by `name` only (see {@link eventMatches}'s match-based\n * consumption), so a hot name with many distinct payloads sitting unclaimed could in principle\n * accumulate an unbounded backlog; this caps the per-scan cost regardless. Shared by the workflow-ctx\n * consumer and the engine's reconcile sweep so both see the same window.\n */\nexport const EVENT_BUFFER_SCAN_LIMIT = 50;\n\n/** The literal prefix EVERY event-waiter token starts with, regardless of `name` — `eventPrefix(name)`\n * always begins with this; exported so a caller that only needs to CLASSIFY a token (not fan out a\n * specific name) doesn't have to re-derive or duplicate the literal (see run-waiting.ts's own copy,\n * kept in sync with this one, and engine.ts's reconcile sweep). */\nexport const EVENT_TOKEN_PREFIX = 'event:';\n\n/** Token prefix for every waiter on `name` — used by `listSignalWaiters` to fan an event out. */\nexport function eventPrefix(name: string): string {\n return `${EVENT_TOKEN_PREFIX}${enc(name)}:`;\n}\n\n/** Whether `token` is an event-waiter token (vs. a plain signal / child / webhook / breakpoint one). */\nexport function isEventToken(token: string): boolean {\n return token.startsWith(EVENT_TOKEN_PREFIX);\n}\n\n/** Build the unique waiter token for one `waitForEvent` call (name + match + run position). */\nexport function eventToken(\n name: string,\n match: Record<string, unknown> | undefined,\n runId: string,\n seq: number,\n): string {\n return `${eventPrefix(name)}${enc(JSON.stringify(match ?? {}))}:${runId}#${seq}`;\n}\n\n/** The event name embedded in an event waiter token (the 2nd `:`-segment is the base64 name), so a\n * dashboard can show \"waiting on event `<name>`\" instead of the opaque token. */\nexport function eventNameOf(token: string): string {\n try {\n return dec(token.split(':')[1] ?? '');\n } catch {\n return token;\n }\n}\n\n/** The match criteria embedded in an event waiter token (the 3rd `:`-segment is the base64 match). */\nexport function eventMatchOf(token: string): Record<string, unknown> {\n try {\n return JSON.parse(dec(token.split(':')[2] ?? '')) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/** Whether `payload` satisfies a waiter's `match`: every match key deep-equals the payload's value. */\nexport function eventMatches(payload: unknown, match: Record<string, unknown>): boolean {\n const keys = Object.keys(match);\n if (keys.length === 0) return true; // no criteria → matches any payload of this name\n if (!payload || typeof payload !== 'object') return false;\n const p = payload as Record<string, unknown>;\n return keys.every((k) => JSON.stringify(p[k]) === JSON.stringify(match[k]));\n}\n","import type { FanJoin, FanWait } from './errors';\nimport type { SignalWaiter } from './interfaces';\n\n/**\n * Naming shared by `ctx.all` (which mints the ids) and the engine's join barrier (which reads them\n * back off a settling child's waiter). The child id and group are replay anchors: changing either\n * shape strands every run suspended on a fan.\n *\n * An unbounded fan names its children `<runId>.all.<firstSeq>.<i>`. A fan with a `concurrency` limit\n * dispatches in waves and puts the wave in the id, `<runId>.all.<firstSeq>.w<k>.<i>`, so the barrier\n * can wait on one wave at a time.\n */\nexport function allChildId(runId: string, firstSeq: number, index: number, wave?: number): string {\n return `${allBase(runId, firstSeq, wave)}${index}`;\n}\n\n/** The fan's `parallelGroup`. A failFast fan is marked so the barrier wakes it on the first failure. */\nexport function allGroup(firstSeq: number, mode: 'waitAll' | 'failFast'): string {\n return mode === 'failFast' ? `all:${firstSeq}:failFast` : `all:${firstSeq}`;\n}\n\n/** The waiter and checkpoint name prefixes shared by a fan's children, or one wave's. */\nexport function allWait(runId: string, firstSeq: number, wave?: number): FanWait {\n const base = allBase(runId, firstSeq, wave);\n return { waiterPrefix: `child:${base}`, checkpointPrefix: `signal:child:${base}` };\n}\n\nexport function fanJoin(waits: FanWait[]): FanJoin {\n return { waits };\n}\n\n/**\n * A settled group of children (a fan, or one wave of it) folded into a single checkpoint:\n * `fan:<child id base>`, at the first child's seq. `values` are the children's outputs in input\n * order, starting at input index `from`.\n */\nexport const FOLDED_PREFIX = 'fan:';\n\nexport interface FoldedChildren {\n from: number;\n values: unknown[];\n}\n\nexport function allFoldedName(runId: string, firstSeq: number, wave?: number): string {\n return `${FOLDED_PREFIX}${allBase(runId, firstSeq, wave)}`;\n}\n\n/** The child run ids a folded checkpoint stands for. */\nexport function foldedChildIds(checkpoint: { name: string; output?: unknown }): string[] {\n const base = checkpoint.name.slice(FOLDED_PREFIX.length);\n const { from, values } = checkpoint.output as FoldedChildren;\n return values.map((_, j) => `${base}${from + j}`);\n}\n\nfunction allBase(runId: string, firstSeq: number, wave?: number): string {\n return wave === undefined ? `${runId}.all.${firstSeq}.` : `${runId}.all.${firstSeq}.w${wave}.`;\n}\n\n/**\n * How a fan of `size` children is dispatched under a `concurrency` limit: waves of `waveSize`, at\n * most `maxWaves` of them unsettled at once, so no more than `concurrency` children run together.\n * Half-size waves let the next wave start while the slowest children of the previous one finish.\n * Undefined when the limit does not bind, which keeps the unbounded fan's ids.\n */\nexport function allWaves(\n size: number,\n concurrency: number | undefined,\n): { waveSize: number; maxWaves: number } | undefined {\n if (concurrency === undefined || concurrency >= size) return undefined;\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new Error(`ctx.all: concurrency must be a positive integer, got ${concurrency}`);\n }\n // Two half-size waves in flight: an odd limit runs one child under it, rather than leaving a whole\n // wave's worth of the window idle.\n if (concurrency === 1) return { waveSize: 1, maxWaves: 1 };\n return { waveSize: Math.floor(concurrency / 2), maxWaves: 2 };\n}\n\nconst ENGINE_CHILD_ID = /^(.+)\\.(?:all\\.\\d+\\.(?:w\\d+\\.)?\\d+|child\\.\\d+)$/;\n\n/**\n * The parent of a child run whose id the engine minted: a `ctx.all` child\n * (`<parent>.all.<seq>.<i>`, or `.w<k>.<i>` under a `concurrency` limit) or a `ctx.child` /\n * `ctx.startChild` child without an explicit id (`<parent>.child.<seq>`). Undefined for any other\n * run, including a child started with a caller-chosen id.\n */\nexport function parentRunIdOf(runId: string): string | undefined {\n return ENGINE_CHILD_ID.exec(runId)?.[1];\n}\n\nconst GROUP = /^all:(\\d+)(:failFast)?$/;\nconst REST = /^(?:w(\\d+)\\.)?\\d+$/;\n\n/**\n * The `ctx.all` fan (or, for a fan with a `concurrency` limit, the wave) a waiter belongs to, or\n * undefined for any other waiter (a lone `ctx.child`, a signal, a remote `gather_children`).\n * Requires the token and the group to agree, so a waiter that merely looks similar never holds back\n * a wake.\n */\nexport function fanOfWaiter(\n waiter: SignalWaiter,\n): { waiterPrefix: string; failFast: boolean } | undefined {\n const group = waiter.parallelGroup ? GROUP.exec(waiter.parallelGroup) : null;\n if (!group) return undefined;\n const base = `child:${waiter.runId}.all.${group[1]}.`;\n if (!waiter.token.startsWith(base)) return undefined;\n const rest = REST.exec(waiter.token.slice(base.length));\n if (!rest) return undefined;\n const waiterPrefix = rest[1] === undefined ? base : `${base}w${rest[1]}.`;\n return { waiterPrefix, failFast: group[2] !== undefined };\n}\n","/**\n * Worker/control-plane handshake descriptor — the single source of truth for routing, compatibility\n * and observability across a store-less durable cluster (design §7.1). Pure data + a deterministic,\n * order-insensitive content hash; NO transport, NO I/O. Every field is part of the cross-language\n * wire contract — the adonis + python SDKs build the byte-identical shape (design §7.8), and the\n * golden fixtures in `<repo>/fixtures/wire/` pin the exact bytes all three SDKs must agree on.\n */\n\n/**\n * One workflow a worker ANNOUNCES it can execute — the richer form of a `workflows` name.\n *\n * The rule is \"announce only what you can run\": a process publishes a registration for a workflow\n * whose body it holds and whose queue it consumes. It never publishes one for a workflow it merely\n * knows how to *route to* (an engine's `registerRemote`), because that claim says nothing about a\n * live executor existing — which is precisely the ambiguity an aggregate registry has to remove.\n *\n * Every field but `name` is optional because the SDKs hold different amounts of this. A worker that\n * knows only names (the Python `@worker.workflow(\"x\")` form, or any pre-registrations SDK) publishes\n * bare `workflows` names instead and is still a first-class announcer — see {@link WorkerDescriptor.registrations}.\n * A reader must therefore treat an absent field as \"not stated\", never as a value: the aggregate in\n * `./announced` never invents a version, a group or an origin that nobody announced.\n */\nexport interface WorkflowRegistration {\n /** Registered workflow name — the `workflow` a {@link WorkflowTask} carries. */\n name: string;\n /** Registered version, when the announcer knows one. Absent = unversioned announcement. */\n version?: string;\n /** The routing token this workflow's turns are dispatched to (the queue this worker consumes for\n * it). Absent = the announcer did not say; a reader must NOT assume the by-convention token. */\n group?: string;\n /** Capabilities a worker must advertise to run it (design §7.5), as the announcer declares them. */\n requires?: string[];\n /** The package that DECLARED the workflow (see `WorkflowRun.origin`). Absent = unknown; nothing\n * ever substitutes a default, because a wrong origin is worse than no origin. */\n origin?: string;\n}\n\n/**\n * A worker's (or control-plane's) advertised identity, wire-protocol support, feature capabilities\n * and registered handlers. Published on startup + on change (design §7.2) and consumed by\n * {@link negotiate} (compat) and the capability-aware router (design §7.5). Exactly the §7.1 shape.\n */\nexport interface WorkerDescriptor {\n /** Stable id for this process in the fleet (mirrors aviary's per-instance heartbeat key). */\n instanceId: string;\n /** Execution runtime — a `python` worker and a `node` control-plane interoperate over the wire. */\n runtime: 'node' | 'python';\n /** Which SDK + version produced this descriptor. Observability only; never gates dispatch. */\n sdk: { name: string; version: string };\n /**\n * Wire-protocol majors this side speaks. `version` is its preferred/current major; `range` is the\n * inclusive `[min, max]` band it can negotiate down/up to. Overlap of two ranges is what makes two\n * sides compatible (design §7.4); `version` is informational.\n */\n protocol: { version: number; range: [number, number] };\n /** Named features advertised: `'saga'`, `'signals'`, `'search-attr-v2'`, `'priority'`, … A modern\n * worker MAY advertise `[]` (no named features); an ABSENT field means \"legacy v1\" — see\n * {@link normalizeDescriptor}. Order-insensitive: treated as a set. */\n capabilities: string[];\n /** Registered workflow handler names → routing targets. Order-insensitive (a set). */\n workflows: string[];\n /** Registered step handler names → routing targets. Order-insensitive (a set). */\n steps: string[];\n /**\n * The richer, per-workflow ANNOUNCEMENT of what this instance can execute (name + version + group\n * + requires + origin). OPTIONAL and purely additive: an SDK that has only names keeps publishing\n * {@link workflows} and is aggregated all the same, just unversioned. An SDK that publishes this\n * SHOULD also list the same names in {@link workflows}, so a reader that predates this field still\n * sees the workflow at all.\n *\n * It rides the descriptor rather than a registry of its own so it inherits the whole liveness\n * story for free: the descriptor key is written with the heartbeat's TTL and refreshed by the same\n * beat, so an announcement from a worker that has since died EXPIRES instead of offering a choice\n * that fails at run time.\n */\n registrations?: WorkflowRegistration[];\n /** Optional routing partition (queue/group sharding). */\n partition?: string;\n /** Optional tenant namespace this instance serves. */\n namespace?: string;\n /** Process start time (epoch ms) — a restart changes it, so it participates in the content hash. */\n startedAt: number;\n}\n\n/**\n * The current wire-protocol major. The whole protocol as it exists today is defined as **v1**; the\n * handshake exists so a future **v2 breaking change** is detectable rather than silently corrupting\n * (design §7.7).\n */\nexport const CURRENT_PROTOCOL_VERSION = 1;\n\n/**\n * The protocol band assumed for a descriptor that omits `protocol` entirely — an existing aviary\n * worker that predates the handshake. Absence = **legacy v1 baseline, assume compatible** (§7.7).\n */\nexport const LEGACY_V1_PROTOCOL: WorkerDescriptor['protocol'] = { version: 1, range: [1, 1] };\n\n/**\n * The feature set a legacy (pre-handshake) worker is assumed to advertise when its `capabilities`\n * field is ABSENT. These are the durable primitives aviary has shipped since v1, so a legacy worker\n * can still be routed work that `requires` them (design §7.5/§7.7).\n *\n * CROSS-SDK CONTRACT — this list is the canonical \"what a v1 worker can do\" baseline and MUST stay\n * byte-identical across the adonis + nestjs + python SDKs. It is the ACTUAL aviary durable v1\n * execution surface (each name maps to a shipped primitive: saga/compensation, signals,\n * search-attributes, priority/fairness, entities, child-workflows, singleton gating, cron schedules,\n * continue-as-new, queries, cooperative cancellation). `search-attr-v2` is a MODERN capability layered\n * on top and is deliberately NOT in the v1 baseline — a v1 worker only guarantees the v1\n * `search-attributes` surface.\n */\nexport const LEGACY_V1_CAPABILITIES: readonly string[] = Object.freeze([\n 'saga',\n 'signals',\n 'search-attributes',\n 'priority',\n 'entities',\n 'child-workflows',\n 'singleton',\n 'schedules',\n 'continue-as-new',\n 'queries',\n 'cancellation',\n]);\n\n/**\n * A raw, possibly-partial descriptor as it may arrive off the wire from an older SDK: `protocol`\n * and/or `capabilities` may be missing. {@link normalizeDescriptor} fills the legacy-v1 defaults.\n */\nexport type RawWorkerDescriptor = Omit<Partial<WorkerDescriptor>, 'instanceId' | 'runtime'> & {\n instanceId: string;\n runtime: 'node' | 'python';\n};\n\n/**\n * True when a descriptor predates the handshake — it carries no `protocol` field. Such a descriptor\n * is treated as legacy v1 and assumed compatible (design §7.7).\n */\nexport function isLegacyDescriptor(raw: RawWorkerDescriptor | WorkerDescriptor): boolean {\n return (raw as Partial<WorkerDescriptor>).protocol === undefined;\n}\n\n/**\n * Fill legacy-v1 defaults so downstream logic always sees a complete {@link WorkerDescriptor}:\n * - absent `protocol` → {@link LEGACY_V1_PROTOCOL} (assume-compatible v1 baseline),\n * - absent `capabilities` → {@link LEGACY_V1_CAPABILITIES} (a modern `[]` is preserved as-is),\n * - absent `workflows`/`steps` → `[]`, absent `sdk` → an `unknown` marker, absent `startedAt` → `0`.\n *\n * The undefined-vs-`[]` distinction is deliberate: an absent field means \"legacy, doesn't advertise\n * this axis\"; an explicit empty array means \"modern SDK that genuinely advertises nothing\". The same\n * reasoning keeps `registrations` ABSENT when it was absent (rather than defaulting to `[]`): \"this\n * SDK does not announce registrations\" and \"this SDK announces none\" are different facts, and only\n * the second one licenses a reader to conclude the worker serves nothing. (No SDK publishes `[]`\n * today — {@link describeWorker} and the Python builder both OMIT the field when there is nothing to\n * announce, so a worker with no workflows keeps its pre-announcement bytes and ETag — but a reader\n * must not collapse the two cases on that basis.)\n */\nexport function normalizeDescriptor(raw: RawWorkerDescriptor | WorkerDescriptor): WorkerDescriptor {\n return {\n instanceId: raw.instanceId,\n runtime: raw.runtime,\n sdk: raw.sdk ?? { name: 'unknown', version: '0' },\n protocol: raw.protocol ?? { ...LEGACY_V1_PROTOCOL },\n capabilities: raw.capabilities ?? [...LEGACY_V1_CAPABILITIES],\n workflows: raw.workflows ?? [],\n steps: raw.steps ?? [],\n ...(raw.registrations !== undefined ? { registrations: raw.registrations } : {}),\n ...(raw.partition !== undefined ? { partition: raw.partition } : {}),\n ...(raw.namespace !== undefined ? { namespace: raw.namespace } : {}),\n startedAt: raw.startedAt ?? 0,\n };\n}\n\n/**\n * Compact, liveness lifecycle status carried on the cheap steady-state heartbeat (design §7.2).\n * Distinct from aviary's rich `WorkerStatus` object (owned by the transport layer): this is the\n * lightweight two-tier advertisement, whose job is to carry the {@link descriptorHash} ETag.\n */\nexport type WorkerLifecycle = 'up' | 'draining' | 'quiescing' | 'stopped';\n\n/**\n * The two-tier heartbeat payload (design §7.2): a cheap `{ ts, status, descriptorHash }` beaten every\n * ~10s. The `descriptorHash` is an **ETag** — the control-plane re-reads the full (expensive)\n * descriptor only when this hash changes, keeping steady-state chatter tiny.\n */\nexport interface HeartbeatStatus {\n /** Beat time, epoch ms. */\n ts: number;\n /** Compact lifecycle status. */\n status: WorkerLifecycle;\n /** ETag over the full descriptor — see {@link descriptorHash}. */\n descriptorHash: string;\n}\n\n/**\n * Canonical, order-insensitive projection of the `registrations` announcement: each entry gets a\n * FIXED key order with absent fields collapsed to `null` (so present-with-undefined and absent\n * agree), `requires` sorted + de-duplicated, and the entries themselves de-duplicated and sorted by\n * their own canonical JSON. Announcement order therefore cannot change the hash — only the announced\n * CONTENT can, which is exactly when a control plane should re-read.\n */\nfunction canonicalizeRegistrations(regs: readonly WorkflowRegistration[]): unknown[] {\n const canonical = regs.map((r) => ({\n name: r.name,\n version: r.version ?? null,\n group: r.group ?? null,\n requires: r.requires ? [...new Set(r.requires)].sort() : null,\n origin: r.origin ?? null,\n }));\n const byJson = new Map<string, unknown>();\n for (const entry of canonical) byJson.set(JSON.stringify(entry), entry);\n return [...byJson.keys()].sort().map((k) => byJson.get(k));\n}\n\n/** Canonical, order-insensitive projection of a descriptor used for hashing. The three set-valued\n * fields are sorted + de-duplicated so member order can never change the hash; scalar fields are\n * taken verbatim; optional fields collapse to `null` so present-with-undefined and absent agree.\n *\n * `registrations` is the ONE key emitted conditionally: a descriptor that does not announce them\n * hashes to BYTE-IDENTICAL bytes as before this field existed, so every already-published ETag —\n * and the pinned cross-language golden hash — is unchanged. A descriptor that DOES announce them\n * hashes differently, which is the point: changing what a worker serves must change its ETag. */\nfunction canonicalizeForHash(d: WorkerDescriptor): unknown {\n const set = (xs: string[]): string[] => [...new Set(xs)].sort();\n // Keys are emitted in a FIXED order (this literal's order) so the stringify below is stable\n // regardless of the input object's key insertion order.\n return {\n instanceId: d.instanceId,\n runtime: d.runtime,\n sdk: { name: d.sdk.name, version: d.sdk.version },\n protocol: { version: d.protocol.version, range: [d.protocol.range[0], d.protocol.range[1]] },\n capabilities: set(d.capabilities),\n workflows: set(d.workflows),\n steps: set(d.steps),\n ...(d.registrations !== undefined\n ? { registrations: canonicalizeRegistrations(d.registrations) }\n : {}),\n partition: d.partition ?? null,\n namespace: d.namespace ?? null,\n startedAt: d.startedAt,\n };\n}\n\n/**\n * Deterministic 64-bit FNV-1a hash of a string → 16-char lowercase hex. Chosen over a crypto digest\n * because it is trivially reproducible in every SDK (TS/Python/…) with no dependency, keeping the\n * ETag scheme portable for cross-language conformance (design §7.8).\n */\nfunction fnv1a64Hex(input: string): string {\n const OFFSET = 0xcbf29ce484222325n;\n const PRIME = 0x100000001b3n;\n const MASK = 0xffffffffffffffffn;\n let hash = OFFSET;\n for (let i = 0; i < input.length; i += 1) {\n hash ^= BigInt(input.charCodeAt(i) & 0xff);\n // charCodeAt can exceed a byte; fold the high byte in too so non-ASCII still contributes.\n hash ^= BigInt((input.charCodeAt(i) >> 8) & 0xff);\n hash = (hash * PRIME) & MASK;\n }\n return hash.toString(16).padStart(16, '0');\n}\n\n/**\n * Stable ETag over a descriptor's content (design §7.2). **Order-insensitive** over the set-valued\n * fields (`capabilities`/`workflows`/`steps`) — the same members in any order yield the same hash —\n * and stable across the object's key insertion order. Any change to a routing/compat-relevant field\n * (including `startedAt` on restart) changes the hash, which is what triggers a full re-read.\n *\n * Accepts a raw/partial descriptor too: it is normalized first, so a legacy descriptor hashes as its\n * v1 baseline.\n */\nexport function descriptorHash(descriptor: RawWorkerDescriptor | WorkerDescriptor): string {\n const canonical = canonicalizeForHash(normalizeDescriptor(descriptor));\n return fnv1a64Hex(JSON.stringify(canonical));\n}\n\n/**\n * Build the compact two-tier heartbeat for a descriptor, stamping the ETag (design §7.2). `ts`\n * defaults to now and `status` to `'up'`.\n */\nexport function heartbeatStatus(\n descriptor: RawWorkerDescriptor | WorkerDescriptor,\n opts: { ts?: number; status?: WorkerLifecycle } = {},\n): HeartbeatStatus {\n return {\n ts: opts.ts ?? Date.now(),\n status: opts.status ?? 'up',\n descriptorHash: descriptorHash(descriptor),\n };\n}\n\n/**\n * Build a worker's own {@link WorkerDescriptor} in the exact §7.1 shape every SDK publishes — the\n * single builder both TS advertisers use (the BullMQ transport's in-app worker and the standalone\n * `runRedisWorker`), so two processes in the same fleet cannot drift into two dialects of the same\n * wire.\n *\n * Set-valued fields are sorted here (not just in the hash projection) so the published BYTES are\n * stable across registration order too — a re-registration in a different order must not look like a\n * change to a reader diffing the raw value. `partition` and `namespace` are omitted when empty, and\n * `namespace` additionally when it is `default`, keeping a single-tenant deployment byte-identical\n * to the un-namespaced scheme. `capabilities` is the canonical v1 baseline this protocol guarantees.\n */\nexport function describeWorker(opts: {\n instanceId: string;\n runtime: 'node' | 'python';\n sdk: { name: string; version: string };\n steps: string[];\n workflows?: string[] | undefined;\n /** What this instance announces it can EXECUTE — see {@link WorkflowRegistration}. Omitted from\n * the descriptor entirely when absent or empty, so a worker with nothing to announce keeps the\n * pre-registrations bytes (and therefore the pre-registrations hash). */\n registrations?: readonly WorkflowRegistration[] | undefined;\n startedAt: number;\n partition?: string | undefined;\n namespace?: string | undefined;\n}): WorkerDescriptor {\n const version = CURRENT_PROTOCOL_VERSION;\n const registrations = [...(opts.registrations ?? [])].sort((a, b) =>\n `${a.name}@${a.version ?? ''}`.localeCompare(`${b.name}@${b.version ?? ''}`),\n );\n return {\n instanceId: opts.instanceId,\n runtime: opts.runtime,\n sdk: { name: opts.sdk.name, version: opts.sdk.version },\n protocol: { version, range: [version, version] },\n capabilities: [...LEGACY_V1_CAPABILITIES],\n workflows: [...(opts.workflows ?? [])].sort(),\n steps: [...opts.steps].sort(),\n ...(registrations.length > 0 ? { registrations } : {}),\n ...(opts.partition ? { partition: opts.partition } : {}),\n ...(opts.namespace && opts.namespace !== 'default' ? { namespace: opts.namespace } : {}),\n startedAt: opts.startedAt,\n };\n}\n","/**\n * The announced workflow registry (design §7.9) — the aggregate answer to \"what workflows exist in\n * this deployment?\", built ONLY from what live workers say about themselves.\n *\n * ## Why this is announced, not inferred\n *\n * `WorkflowEngine.workflowBody(name, version)` answers for the process that asks, and a missing body\n * is ambiguous by design: it means \"not registered here\", but equally \"registered via\n * `registerRemote` against another SDK\" or \"a group this pod resolves by convention against a live\n * worker\". A picker built on that inference would offer different options depending on which replica\n * served the request. So the registry is not derived from any engine's registry: a worker publishes\n * what it can execute ({@link WorkerDescriptor.registrations}, or bare `workflows` names), and this\n * module folds those statements together. Every entry is therefore a fact somebody asserted, and the\n * aggregate is the same on every pod because every pod reads the same published statements.\n *\n * The announcer is always the process that CONSUMES the queue, never the engine that dispatches to\n * it — including when the two share a process (the co-located in-app worker announces; the engine\n * beside it does not). One consequence is worth stating plainly rather than leaving to be\n * rediscovered: a pure operator (`store` with no `connection`) runs its bodies inline, consumes no\n * queue, and therefore announces NOTHING. Its workflows are real and startable through its own\n * `start()`, but they are not in this registry, because nothing about them is externally addressable\n * for a picker to point at.\n *\n * ## Liveness\n *\n * There is no expiry logic here because there is no state here. An announcement lives on the\n * descriptor key, which is written with the worker-heartbeat TTL and refreshed by the same beat; a\n * worker that dies stops refreshing and its key expires, taking its announcements with it. The\n * resolution of that liveness is therefore the TTL (35s against a 10s beat), so an entry can name a\n * worker that died within the last beat window — the same staleness the capability router already\n * accepts when it reads descriptors to decide whether to dispatch. A caller that needs a stronger\n * guarantee should not seek it here: dispatch to a dead worker parks the run `blocked`/`pending` on\n * its queue and the existing worker-health surface reports it. What this design DOES rule out is the\n * unbounded failure — an announcement that outlives its worker forever.\n *\n * ## Disagreement\n *\n * Two live workers can announce the same `name@version` with different groups, origins or capability\n * demands. The aggregate keeps EVERY distinct claim and reports the axes they differ on\n * ({@link AnnouncedWorkflow.disagreements}); it never merges them into one value and never picks a\n * winner, because either choice would make a caller act on a claim nobody made. Silence is not a\n * claim: a worker that announced no origin does not disagree with one that did.\n *\n * ## Steps are deliberately out of scope\n *\n * There is no equivalent registry for steps, and this is not an omission to be fixed later. A step is\n * not addressable from outside a run: it is identified by its `(runId, seq)` position in one\n * workflow's history, `ctx.step` is only callable from inside a replaying body, and no engine entry\n * point starts a step on its own. \"Call this step\" is therefore not something the engine can do, so a\n * picker offering steps would be offering an operation that does not exist. Step HANDLER names are\n * still advertised (`WorkerDescriptor.steps`) — that is a routing/capability fact used to decide\n * whether a dispatched step can be run, not an invocable catalog.\n *\n * ## The floor: a live worker that announces nothing\n *\n * An SDK old enough to predate the descriptor advertisement publishes only its TTL'd liveness\n * heartbeat — one key per routing token it consumes. Read strictly, such a fleet announces nothing\n * and this registry would be empty while work is being served. That answer is not merely unhelpful,\n * it CONTRADICTS the engine beside it: `resolveRemoteByConvention` routes a call to `X` the moment a\n * token named `X` heartbeats, so the deployment already treats liveness as sufficient to CALL a\n * workflow while claiming to know nothing when asked to LIST one. Both answers come out of the same\n * Redis.\n *\n * So the heartbeat is folded in as a second, weaker tier of evidence ({@link AnnouncedWorkflow.evidence}\n * `'observed'`): the entry exists because a live token of that name exists, which is exactly — no more\n * and no less — the condition under which convention routing would resolve it. Listing it therefore\n * cannot introduce a failure the dispatcher did not already have. What it CANNOT do is state a\n * version, an origin, a runtime, or even that the token serves a workflow rather than a step handler\n * of the same name: none of that is in a heartbeat, and every one of those stays un-stated rather than\n * being guessed. A descriptor always wins — a token an announcement already covers is never re-added\n * as an observation.\n */\n\nimport type { RawWorkerDescriptor, WorkerDescriptor, WorkflowRegistration } from './descriptor';\nimport { normalizeDescriptor } from './descriptor';\n\n/** One live worker's claim about one workflow: the registration plus who announced it. */\nexport interface WorkflowAnnouncement extends WorkflowRegistration {\n /** The announcing worker's instance id. */\n instanceId: string;\n /** The announcing worker's runtime — how a Python-served workflow is told from a Node-served one. */\n runtime: 'node' | 'python';\n}\n\n/** An axis on which the live announcers of one workflow do not agree. `values` holds every distinct\n * DECLARED value (sorted); an announcer that stated nothing on the axis contributes nothing. */\nexport interface Disagreement {\n axis: 'group' | 'origin' | 'requires';\n values: string[];\n}\n\n/**\n * How strong the fleet's claim about a workflow is. The two tiers are NOT interchangeable and a\n * caller must not read them as the same fact:\n *\n * - `'declared'` — at least one live worker published a descriptor naming this workflow. Everything\n * populated on the entry was STATED by that worker; everything absent it declined to state.\n * - `'observed'` — nobody described it. What exists is a live routing token of this name, which is\n * precisely the condition `resolveRemoteByConvention` uses to route a call, so the name IS\n * reachable. Nothing else is known: no version, no origin, no runtime, and no assurance that the\n * worker consuming that token serves a WORKFLOW there rather than a step handler of the same name.\n * An entry like this is a live queue, not a promise.\n */\nexport type AnnouncementEvidence = 'declared' | 'observed';\n\n/** One workflow the live fleet announces, folded across every worker that announced it. */\nexport interface AnnouncedWorkflow {\n /** What kind of claim this entry rests on — see {@link AnnouncementEvidence}. A caller that shows\n * a version, an origin or a runtime must check this first: an `'observed'` entry has none of\n * them, and the emptiness is a fact about the fleet, not a rendering gap. */\n evidence: AnnouncementEvidence;\n /** `name@version`, or the bare `name` when no announcer stated a version. Stable sort key. */\n key: string;\n name: string;\n /** Absent when no announcer stated one — never inferred from another announcer's version. */\n version?: string;\n /** Every distinct routing group announced (sorted). Empty = nobody stated one. On an `'observed'`\n * entry this is the token the heartbeat was published UNDER — not a claim by anybody, but the\n * queue a call would actually land on, which is the one thing an observation does establish. */\n groups: string[];\n /** Every distinct declaring package announced (sorted). Empty = nobody stated one. */\n origins: string[];\n /** Every distinct capability demand announced, each de-duplicated + sorted. Empty = nobody stated\n * one. Two entries here means two workers demand different capabilities for the same version. */\n requires: string[][];\n /** Runtimes of the live announcers (sorted, de-duplicated). EMPTY on an `'observed'` entry: a\n * heartbeat does not say what runtime wrote it, and the instance id's shape is a convention, not\n * a statement, so it is not read as one. */\n runtimes: ('node' | 'python')[];\n /** Instance ids of the live workers announcing it (sorted, de-duplicated). Its length is how many\n * workers can currently run this workflow — `1` is a single point of failure, and it is never 0\n * (an entry exists only because somebody announced it, or because somebody is beating on it). */\n instances: string[];\n /** The axes the announcers differ on, empty when they speak with one voice. A caller that must\n * pick a single target has to resolve these itself — the registry refuses to guess. */\n disagreements: Disagreement[];\n}\n\n/**\n * What one descriptor announces. `registrations` is authoritative when present; any `workflows` name\n * it does not cover is still announced as a bare, unversioned claim, so a worker that describes some\n * of its workflows richly and others by name alone is reported in full rather than in part.\n *\n * A descriptor with neither field announces nothing — including the control plane's own descriptor,\n * which is a router, not an executor.\n */\nexport function announcementsOf(\n raw: RawWorkerDescriptor | WorkerDescriptor,\n): WorkflowAnnouncement[] {\n const d = normalizeDescriptor(raw);\n const identity = { instanceId: d.instanceId, runtime: d.runtime };\n const announcements = (d.registrations ?? []).map((reg) => ({ ...reg, ...identity }));\n const covered = new Set(announcements.map((a) => a.name));\n for (const name of d.workflows) {\n if (!covered.has(name)) announcements.push({ name, ...identity });\n }\n return announcements;\n}\n\n/** `name@version`, or the bare name when unversioned — the identity two announcements are folded on. */\nfunction announcementKey(a: WorkflowRegistration): string {\n return a.version === undefined ? a.name : `${a.name}@${a.version}`;\n}\n\n/** Sorted, de-duplicated members of `values`, dropping the un-stated ones. */\nfunction stated(values: readonly (string | undefined)[]): string[] {\n return [...new Set(values.filter((v): v is string => v !== undefined))].sort();\n}\n\n/**\n * Fold every live descriptor's announcements into one entry per `name@version`, sorted by key.\n *\n * Pure: it holds nothing and caches nothing, so no pod ever carries a growing table of the fleet's\n * registrations — the caller reads the live descriptors it already knows how to read, folds them\n * here, and drops the result. The work is O(descriptors × announcements) per call, on demand.\n *\n * The same instance announcing the same workflow twice (a worker publishes its descriptor under\n * every routing token it consumes, so the same bytes arrive several times) folds to ONE announcer:\n * `instances` is a set, so it counts workers, not keys.\n */\nexport function aggregateAnnouncements(\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n): AnnouncedWorkflow[] {\n const byKey = new Map<string, WorkflowAnnouncement[]>();\n for (const descriptor of descriptors) {\n for (const announcement of announcementsOf(descriptor)) {\n const key = announcementKey(announcement);\n const bucket = byKey.get(key);\n if (bucket) bucket.push(announcement);\n else byKey.set(key, [announcement]);\n }\n }\n\n const out: AnnouncedWorkflow[] = [];\n for (const [key, announcements] of byKey) {\n const groups = stated(announcements.map((a) => a.group));\n const origins = stated(announcements.map((a) => a.origin));\n // A capability demand is a SET, so it is compared as its canonical (sorted, de-duplicated) form:\n // two workers demanding ['saga','signals'] and ['signals','saga'] agree, and must not be reported\n // as a disagreement over the same demand written two ways.\n const requiresByJson = new Map<string, string[]>();\n for (const a of announcements) {\n if (a.requires === undefined) continue;\n const canonical = [...new Set(a.requires)].sort();\n requiresByJson.set(JSON.stringify(canonical), canonical);\n }\n // Ordered by the same rendering `disagreements` uses, so the two lists read in step.\n const requires = [...requiresByJson.values()].sort((x, y) =>\n x.join(',').localeCompare(y.join(',')),\n );\n\n const disagreements: Disagreement[] = [];\n if (groups.length > 1) disagreements.push({ axis: 'group', values: groups });\n if (origins.length > 1) disagreements.push({ axis: 'origin', values: origins });\n if (requires.length > 1) {\n disagreements.push({ axis: 'requires', values: requires.map((r) => r.join(',')) });\n }\n\n const first = announcements[0];\n if (!first) continue;\n out.push({\n evidence: 'declared',\n key,\n name: first.name,\n ...(first.version !== undefined ? { version: first.version } : {}),\n groups,\n origins,\n requires,\n runtimes: [...new Set(announcements.map((a) => a.runtime))].sort(),\n instances: [...new Set(announcements.map((a) => a.instanceId))].sort(),\n disagreements,\n });\n }\n return out.sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * The part of one live worker heartbeat this registry can read: the routing token the beat was\n * published under, and which process published it. That is genuinely all a heartbeat holds — it is\n * the cheap tier of the two-tier advertisement, and its job is liveness, not description.\n *\n * Structurally satisfied by `WorkerHeartbeat` (the transport-facing shape, which also carries a beat\n * time and an execution snapshot). Declared here rather than imported so this module keeps its \"pure\n * data, no transport\" footing and `interfaces.ts` can keep importing FROM it.\n */\nexport interface HeartbeatSighting {\n /** The routing token the beat was published under (already partition-suffixed when partitioned). */\n group: string;\n /** The beating process's instance id. */\n instanceId: string;\n}\n\n/**\n * The weaker tier: one entry per live routing token that NO descriptor accounts for.\n *\n * `covered` holds every token the declared announcements already explain — both the sanitized form of\n * each announced NAME and every group any announcer stated. A token in that set is dropped, so a\n * fleet that describes itself properly gets exactly the same registry it got before this tier\n * existed, and a worker is never counted twice under two kinds of evidence.\n *\n * Everything an observation cannot know stays empty rather than being filled with a plausible guess:\n * no version (so nothing can be pinned against it), no origin, no requires, no runtime. The `name` is\n * the token itself, which equals the workflow's name for every name a queue token can round-trip —\n * `sanitizeQueueToken` rewrites `:` to `-` and that rewrite is not invertible, so a workflow named\n * `orders:fulfill` is observed as `orders-fulfill`. Stated here because a picker showing that string\n * should show what the queue is really called, not a reconstruction that might be wrong.\n */\nexport function observedAnnouncements(\n heartbeats: readonly HeartbeatSighting[],\n covered: ReadonlySet<string>,\n): AnnouncedWorkflow[] {\n const byToken = new Map<string, Set<string>>();\n for (const beat of heartbeats) {\n if (!beat.group || covered.has(beat.group)) continue;\n const instances = byToken.get(beat.group);\n if (instances) instances.add(beat.instanceId);\n else byToken.set(beat.group, new Set([beat.instanceId]));\n }\n return [...byToken.entries()]\n .map(([group, instances]) => ({\n evidence: 'observed' as const,\n key: group,\n name: group,\n groups: [group],\n origins: [],\n requires: [],\n runtimes: [],\n instances: [...instances].sort(),\n disagreements: [],\n }))\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * Every routing token a live descriptor already ACCOUNTS FOR, and which therefore needs no\n * observation — for either of the two opposite reasons.\n *\n * - A token some worker announced as a WORKFLOW: already in the registry, richer than an\n * observation could ever be, and re-adding it would count one worker twice.\n * - A token some worker declared as a STEP HANDLER (`WorkerDescriptor.steps`): it must be left OUT,\n * because a step is not addressable from outside a run and offering one as callable would be\n * offering an operation the engine does not have. Route-by-handler gives every step its own queue,\n * so without this the liveness floor turns a fleet's entire step surface into fake workflows.\n *\n * That second exclusion is a DECLARED negative — the worker said \"this name is a step\" — which is\n * exactly the sort of fact an observation cannot supply for itself, and the clearest illustration of\n * what the two tiers are each worth. A worker on an SDK too old to describe itself declares neither\n * its workflows nor its steps, so every one of its tokens stays observed and indistinguishable: its\n * step queues are listed alongside its workflow queues because nothing published says which is\n * which. That is a fair report of the fleet, not a defect in the read.\n *\n * `sanitize` is injected so this module keeps no dependency on the queue layer; a declared name is\n * covered in its bare token form and, for a partitioned worker, in the suffixed form its queues\n * actually carry.\n */\nexport function coveredTokens(\n announced: readonly AnnouncedWorkflow[],\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n sanitize: (name: string) => string,\n): Set<string> {\n const tokens = new Set<string>();\n for (const entry of announced) {\n tokens.add(sanitize(entry.name));\n for (const group of entry.groups) tokens.add(group);\n }\n for (const raw of descriptors) {\n const d = normalizeDescriptor(raw);\n for (const step of d.steps) {\n const token = sanitize(step);\n tokens.add(token);\n if (d.partition) tokens.add(`${token}@${d.partition}`);\n }\n }\n return tokens;\n}\n","/**\n * The workflow directory — {@link ./announced}'s registry plus the thing an empty registry could\n * never say: WHY it is empty.\n *\n * ## The three states an empty list used to collapse\n *\n * \"What workflows can I call?\" has three honest answers, and returning `[]` for all of them is the\n * bug this module exists to fix. They are not shades of the same answer; they call for three\n * different actions from whoever asked.\n *\n * 1. **This process cannot ask.** No transport here can introspect the advertisement or liveness\n * keyspace — a pure in-process pool advertises nothing and scans nothing. Workers may well be\n * running; nobody looked. ({@link WorkflowDirectory.supported} is `false`.) The action is to\n * configure a transport, or to stop treating this pod's answer as the deployment's answer.\n * 2. **Nothing is live.** The fleet WAS asked and the fleet is empty. ({@link WorkflowDirectory.supported}\n * is `true`, `workflows` is `[]`.) The action is to start a worker.\n * 3. **Here it is.** ({@link WorkflowDirectory.supported} is `true`, `workflows` is populated.)\n *\n * There is a fourth that hides inside the second and is the most expensive to debug, because it\n * looks exactly like \"nobody is running\" from the caller's side: **a worker is live on a partition\n * this engine does not serve.** A worker started with a partition consumes `<token>@<partition>`,\n * convention resolution computes the token for THIS engine's namespace, misses, and reports absence.\n * The heartbeat keyspace is shared, so the evidence is right there — and\n * {@link WorkflowDirectory.otherPartitions} reports it instead of letting the caller conclude that\n * nothing exists.\n *\n * ## Why a sentence rides along\n *\n * Every field here is structured and a caller can branch on all of it. {@link WorkflowDirectory.detail}\n * exists anyway because the three states are only useful if the human reading the picker learns which\n * one they are in, and a UI that has to re-derive that prose from booleans will re-derive it\n * differently in each place it is shown. The sentence is written once, next to the logic that decides\n * which state it is.\n */\n\nimport type { AnnouncedWorkflow, HeartbeatSighting } from './announced';\nimport { aggregateAnnouncements, coveredTokens, observedAnnouncements } from './announced';\nimport type { RawWorkerDescriptor, WorkerDescriptor } from './descriptor';\n\n/** The namespace a descriptor or a bare routing token belongs to when it states none. Mirrors\n * `tenantGroup`'s default-is-bare rule, so a single-tenant deployment reads as `'default'`\n * everywhere rather than as a special case. */\nexport const DEFAULT_PARTITION = 'default';\n\n/** Live workers seen on a partition the asking engine does not serve — the case that otherwise reads\n * identically to \"nothing is running\". */\nexport interface PartitionSighting {\n /** The partition suffix carried by the tokens (never this engine's own). */\n partition: string;\n /** The routing tokens live on it, as published (sorted). */\n groups: string[];\n /** The instance ids beating there (sorted). */\n instances: string[];\n}\n\n/** What the live fleet can be asked, and what it answered. See the module docblock for the states. */\nexport interface WorkflowDirectory {\n /**\n * Could this process ask the fleet at all?\n *\n * `false` means no transport here can read the advertisement or liveness keyspace, so `workflows`\n * is empty because nothing was asked — NOT because nothing is running. `true` means the read\n * happened and `workflows` is the answer, including when it is empty.\n */\n supported: boolean;\n /** Everything callable in this engine's partition, declared and observed alike. */\n workflows: AnnouncedWorkflow[];\n /** Live workers on OTHER partitions (empty for an operator engine, which serves them all). */\n otherPartitions: PartitionSighting[];\n /** One sentence saying which state this is and what it implies. Written for a human. */\n detail: string;\n}\n\n/** The partition a routing token belongs to: the suffix after the LAST `@`, or {@link DEFAULT_PARTITION}\n * for a bare token. Matches how `tenantGroup` builds the token and how `workerHealth` takes it apart. */\nexport function partitionOfToken(token: string): string {\n const at = token.lastIndexOf('@');\n return at === -1 ? DEFAULT_PARTITION : token.slice(at + 1);\n}\n\n/**\n * Fold live descriptors and live heartbeats into the directory for one engine.\n *\n * `namespace` is the asking engine's, and `undefined` means an operator that serves every partition\n * (\"ver tudo = ausência de namespace\"): it filters nothing and reports no foreign partitions, because\n * none of them are foreign to it. A namespaced engine sees only its own partition's workers, and\n * everything else it can see is reported as a sighting rather than silently dropped — dropping is\n * what made a misconfigured partition indistinguishable from an empty fleet.\n *\n * Pure and holds nothing: the caller does the two live reads it already knows how to do, folds them\n * here, and drops the result.\n */\nexport function buildWorkflowDirectory(input: {\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[];\n heartbeats: readonly HeartbeatSighting[];\n namespace: string | undefined;\n /** Whether ANY transport in the pool could perform the reads above. */\n supported: boolean;\n /** The queue-token form of a workflow name — injected so this module needs no queue dependency. */\n sanitize: (name: string) => string;\n}): WorkflowDirectory {\n const { descriptors, heartbeats, namespace, supported, sanitize } = input;\n if (!supported) {\n return {\n supported: false,\n workflows: [],\n otherPartitions: [],\n detail:\n 'No transport in this process can read what the fleet advertises, so nothing here was asked and this list is empty for that reason alone. Workers may well be running. A workflow can still be called by name.',\n };\n }\n\n const mine = namespace === undefined ? undefined : namespace;\n const ownDescriptors =\n mine === undefined\n ? descriptors\n : descriptors.filter((d) => (d.namespace ?? DEFAULT_PARTITION) === mine);\n const ownBeats: HeartbeatSighting[] = [];\n const foreign = new Map<string, { groups: Set<string>; instances: Set<string> }>();\n for (const beat of heartbeats) {\n if (!beat.group) continue;\n const partition = partitionOfToken(beat.group);\n if (mine === undefined || partition === mine) {\n ownBeats.push(beat);\n continue;\n }\n const seen = foreign.get(partition);\n if (seen) {\n seen.groups.add(beat.group);\n seen.instances.add(beat.instanceId);\n } else {\n foreign.set(partition, {\n groups: new Set([beat.group]),\n instances: new Set([beat.instanceId]),\n });\n }\n }\n\n const declared = aggregateAnnouncements(ownDescriptors);\n const observed = observedAnnouncements(\n ownBeats,\n coveredTokens(declared, ownDescriptors, sanitize),\n );\n const workflows = [...declared, ...observed].sort((a, b) => a.key.localeCompare(b.key));\n const otherPartitions: PartitionSighting[] = [...foreign.entries()]\n .map(([partition, seen]) => ({\n partition,\n groups: [...seen.groups].sort(),\n instances: [...seen.instances].sort(),\n }))\n .sort((a, b) => a.partition.localeCompare(b.partition));\n\n return {\n supported: true,\n workflows,\n otherPartitions,\n detail: describeDirectory(workflows, otherPartitions, mine),\n };\n}\n\n/** A few names plus a count, for prose. Route-by-handler gives every step its own queue, so one\n * partitioned worker can be beating on dozens of tokens and inlining them all makes the sentence\n * unreadable — measured at 17 on a single live worker. The complete list stays on\n * {@link PartitionSighting.groups}, where a caller that wants it can read it in full. */\nfunction summarize(names: readonly string[], limit = 3): string {\n if (names.length <= limit) return names.join(', ');\n return `${names.slice(0, limit).join(', ')} and ${names.length - limit} more`;\n}\n\n/** The one sentence a picker shows. Says which of the states the reader is in, and — when nothing is\n * callable but something IS beating elsewhere — names the partition, because that is the difference\n * between \"start a worker\" and \"the worker you started is on the wrong partition\". */\nfunction describeDirectory(\n workflows: readonly AnnouncedWorkflow[],\n otherPartitions: readonly PartitionSighting[],\n namespace: string | undefined,\n): string {\n const here = namespace === undefined ? 'this deployment' : `partition \"${namespace}\"`;\n const elsewhere =\n otherPartitions.length === 0\n ? ''\n : ` Live workers were seen on ${otherPartitions\n .map((p) => `\"${p.partition}\" (${summarize(p.groups)})`)\n .join(\n ', ',\n )}, which ${here} does not route to — a worker on the wrong partition looks exactly like no worker at all, so it is named here rather than left out.`;\n\n if (workflows.length === 0) {\n return `The fleet was asked just now and nothing is live in ${here}, so this list is empty because the deployment is empty — not because the question could not be put.${elsewhere}`;\n }\n const observed = workflows.filter((w) => w.evidence === 'observed').length;\n const declaredNote =\n observed === 0\n ? ''\n : ` ${observed} of them ${observed === 1 ? 'is' : 'are'} known only from a live queue: the worker serving ${observed === 1 ? 'it' : 'them'} publishes no description, so ${observed === 1 ? 'its' : 'their'} version, origin and runtime are genuinely unknown and a version pinned against ${observed === 1 ? 'it' : 'them'} cannot be checked.`;\n return `Every workflow a live worker in ${here} can execute, read just now. A worker that stops beating drops off this list within about half a minute.${declaredNote}${elsewhere}`;\n}\n","/**\n * Bilateral compatibility negotiation between two handshake descriptors (design §7.3/§7.4). Pure\n * logic: given a local and a remote {@link WorkerDescriptor}, compute the negotiated session (highest\n * common protocol major + capability intersection) and classify it into one of three outcomes with a\n * precise, structured reason — never a bare boolean (design §7.6).\n */\n\nimport { type RawWorkerDescriptor, type WorkerDescriptor, normalizeDescriptor } from './descriptor';\n\n/**\n * The three compatibility outcomes (design §7.4):\n * - `compatible` — protocol ranges intersect + full capability parity → dispatch freely.\n * - `degraded` — ranges intersect but a capability is missing on one side → dispatch, but route\n * capability-requiring work only to capable workers (soft warning).\n * - `incompatible` — no protocol-range overlap → do NOT dispatch; red flag with the exact reason.\n */\nexport type NegotiationOutcome = 'compatible' | 'degraded' | 'incompatible';\n\n/** Structured failure/warning payload — carries the precise delta so a diagnostics event can render\n * it on the timeline + dashboard health panel (design §7.6). Never a bare boolean. */\nexport interface NegotiationReason {\n /** Stable machine code for alerting/telescope. */\n code: 'protocol.incompatible' | 'capability.unavailable';\n /** Human-readable one-liner (dashboard/telescope copy). */\n message: string;\n /** The exact delta: which protocol ranges failed to overlap, or which capabilities are missing. */\n detail: {\n localRange?: [number, number];\n remoteRange?: [number, number];\n /** Capabilities the local side advertises that the remote lacks. */\n missingOnRemote?: string[];\n /** Capabilities the remote side advertises that the local lacks. */\n missingOnLocal?: string[];\n /** Explicitly-required capabilities not satisfied by the negotiated session. */\n missingRequired?: string[];\n };\n}\n\n/** The negotiated session + full delta between two sides. Carries both normalized descriptors so a\n * downstream diagnostics event can attach them wholesale (design §7.6). */\nexport interface NegotiationResult {\n outcome: NegotiationOutcome;\n /** Highest common protocol major, or `null` when ranges do not overlap (incompatible). */\n negotiatedProtocol: number | null;\n protocol: { localRange: [number, number]; remoteRange: [number, number] };\n capabilities: {\n /** Intersection — the capabilities the negotiated session can rely on everywhere. */\n shared: string[];\n /** Local advertises, remote lacks. */\n missingOnRemote: string[];\n /** Remote advertises, local lacks. */\n missingOnLocal: string[];\n };\n /** Present for `degraded` + `incompatible`; absent for `compatible`. */\n reason?: NegotiationReason;\n local: WorkerDescriptor;\n remote: WorkerDescriptor;\n}\n\nexport interface NegotiateOptions {\n /**\n * Capabilities the local side needs the negotiated session to provide. A required capability the\n * remote lacks degrades the session (dispatch generally, but capability-requiring runs park via\n * the router, design §7.5) — it never, on its own, makes the pair *incompatible*: only a protocol\n * range gap does that (design §7.4).\n */\n required?: string[];\n}\n\nconst rangesOverlap = (a: [number, number], b: [number, number]): boolean =>\n Math.max(a[0], b[0]) <= Math.min(a[1], b[1]);\n\nconst difference = (a: string[], b: string[]): string[] => {\n const bset = new Set(b);\n return [...new Set(a)].filter((x) => !bset.has(x)).sort();\n};\n\nconst intersection = (a: string[], b: string[]): string[] => {\n const bset = new Set(b);\n return [...new Set(a)].filter((x) => bset.has(x)).sort();\n};\n\n/**\n * Negotiate compatibility between `local` and `remote` (design §7.3/§7.4). Accepts raw/partial\n * descriptors (a missing `protocol`/`capabilities` is normalized to the legacy-v1 baseline, so a\n * legacy peer negotiates as **assume-compatible**, design §7.7).\n *\n * Outcome logic:\n * 1. no protocol-range overlap → `incompatible` (`protocol.incompatible`);\n * 2. else if a `required` capability is missing on the remote → `degraded` (`capability.unavailable`);\n * 3. else if the capability sets differ at all (either direction) → `degraded`;\n * 4. else full parity → `compatible`.\n *\n * **Bilateral-symmetric** on outcome for the parity path: `negotiate(a, b).outcome ===\n * negotiate(b, a).outcome` (the `missingOnLocal`/`missingOnRemote` delta swaps). `required` is the\n * caller's own need and intentionally asymmetric.\n */\nexport function negotiate(\n localRaw: RawWorkerDescriptor | WorkerDescriptor,\n remoteRaw: RawWorkerDescriptor | WorkerDescriptor,\n opts: NegotiateOptions = {},\n): NegotiationResult {\n const local = normalizeDescriptor(localRaw);\n const remote = normalizeDescriptor(remoteRaw);\n const localRange = local.protocol.range;\n const remoteRange = remote.protocol.range;\n\n const shared = intersection(local.capabilities, remote.capabilities);\n const missingOnRemote = difference(local.capabilities, remote.capabilities);\n const missingOnLocal = difference(remote.capabilities, local.capabilities);\n const capabilities = { shared, missingOnRemote, missingOnLocal };\n\n // (1) Protocol range gap → incompatible. This is the ONLY path that blocks dispatch outright.\n if (!rangesOverlap(localRange, remoteRange)) {\n return {\n outcome: 'incompatible',\n negotiatedProtocol: null,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'protocol.incompatible',\n message:\n `no common protocol major: local speaks [${localRange[0]}, ${localRange[1]}], ` +\n `remote speaks [${remoteRange[0]}, ${remoteRange[1]}]`,\n detail: { localRange, remoteRange },\n },\n local,\n remote,\n };\n }\n\n const negotiatedProtocol = Math.min(localRange[1], remoteRange[1]);\n\n // (2) A required capability the remote cannot provide → degraded (router parks the specific run).\n const required = opts.required ?? [];\n const missingRequired = difference(required, remote.capabilities);\n if (missingRequired.length > 0) {\n return {\n outcome: 'degraded',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'capability.unavailable',\n message: `remote is missing required capability(ies): ${missingRequired.join(', ')}`,\n detail: { missingRequired, missingOnRemote, missingOnLocal },\n },\n local,\n remote,\n };\n }\n\n // (3) Any capability asymmetry → degraded (soft; route capability-requiring work carefully).\n if (missingOnRemote.length > 0 || missingOnLocal.length > 0) {\n const parts: string[] = [];\n if (missingOnRemote.length > 0) parts.push(`remote lacks ${missingOnRemote.join(', ')}`);\n if (missingOnLocal.length > 0) parts.push(`local lacks ${missingOnLocal.join(', ')}`);\n return {\n outcome: 'degraded',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'capability.unavailable',\n message: `capability mismatch: ${parts.join('; ')}`,\n detail: { missingOnRemote, missingOnLocal },\n },\n local,\n remote,\n };\n }\n\n // (4) Ranges overlap + full capability parity → compatible.\n return {\n outcome: 'compatible',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n local,\n remote,\n };\n}\n","/**\n * Capability-aware routing (design §7.5). A workflow/step handler may declare\n * `requires: ['saga', 'search-attr-v2']`; the control-plane dispatches only to workers whose\n * descriptor advertises every required capability. If no live capable worker exists the run must\n * **park as `blocked`** with a precise reason (visible in the dashboard) — never a silent hang.\n *\n * Pure logic: no transport, no store. Consumers (the dispatcher/provider) feed live descriptors in.\n */\n\nimport { type RawWorkerDescriptor, type WorkerDescriptor, normalizeDescriptor } from './descriptor';\n\n/** A handler's capability demand — either a bare list, or anything carrying a `requires` array\n * (a workflow/step ref). An absent/empty list means \"runs anywhere\" (design §7.5). */\nexport type CapabilityRequirement = string[] | { requires?: string[] };\n\n/** Normalize the two accepted shapes to a de-duplicated list of required capability names. */\nexport function requiredCapabilities(handler: CapabilityRequirement): string[] {\n const list = Array.isArray(handler) ? handler : (handler.requires ?? []);\n return [...new Set(list)];\n}\n\n/**\n * Can `worker` run a handler with these requirements? True iff the worker's (normalized) descriptor\n * advertises **every** required capability. A legacy worker (no `capabilities` field) is normalized\n * to the v1 baseline first (design §7.7), so it can still run baseline-only work.\n */\nexport function canRoute(\n handler: CapabilityRequirement,\n worker: RawWorkerDescriptor | WorkerDescriptor,\n): boolean {\n const required = requiredCapabilities(handler);\n if (required.length === 0) return true;\n const advertised = new Set(normalizeDescriptor(worker).capabilities);\n return required.every((cap) => advertised.has(cap));\n}\n\n/**\n * The capabilities a handler requires that `worker` does NOT advertise — the precise routing delta.\n * Empty iff {@link canRoute} is true.\n */\nexport function missingCapabilities(\n handler: CapabilityRequirement,\n worker: RawWorkerDescriptor | WorkerDescriptor,\n): string[] {\n const advertised = new Set(normalizeDescriptor(worker).capabilities);\n return requiredCapabilities(handler).filter((cap) => !advertised.has(cap));\n}\n\n/** Filter a fleet down to the workers that can run a handler (design §7.5). */\nexport function capableWorkers<T extends RawWorkerDescriptor | WorkerDescriptor>(\n handler: CapabilityRequirement,\n workers: readonly T[],\n): T[] {\n return workers.filter((w) => canRoute(handler, w));\n}\n\n/** A run is dispatchable — at least one live worker can execute the handler. */\nexport interface RoutableResolution {\n status: 'routable';\n /** The normalized subset of the fleet that can run it. */\n workers: WorkerDescriptor[];\n requires: string[];\n}\n\n/** No live capable worker — the run parks as `blocked` with a human reason (design §7.5). */\nexport interface BlockedResolution {\n status: 'blocked';\n /** Exactly the dashboard copy: `blocked: no compatible worker (requires <caps>)`. */\n reason: string;\n requires: string[];\n}\n\nexport type RoutingResolution = RoutableResolution | BlockedResolution;\n\n/**\n * Decide whether a handler can be dispatched to the given live fleet (design §7.5). Returns\n * `routable` with the capable subset, or `blocked` with a precise reason when nobody can run it —\n * so the run parks visibly instead of hanging silently. An empty fleet always blocks.\n */\nexport function resolveRouting(\n handler: CapabilityRequirement,\n workers: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n): RoutingResolution {\n const requires = requiredCapabilities(handler);\n const capable = capableWorkers(handler, workers).map(normalizeDescriptor);\n\n if (capable.length > 0) {\n return { status: 'routable', workers: capable, requires };\n }\n\n const suffix = requires.length > 0 ? ` (requires ${requires.join(', ')})` : '';\n return {\n status: 'blocked',\n reason: `blocked: no compatible worker${suffix}`,\n requires,\n };\n}\n","/**\n * Capability- & protocol-aware dispatch planning (design §7.5/§7.6). Sits BETWEEN the pure handshake\n * (`resolveRouting`/`negotiate`, `./{routing,negotiate}`) and the engine's dispatch path: given a\n * step's/workflow's required capabilities and the LIVE worker descriptors for its routing token,\n * decide whether a live worker can actually run it — and if not, produce the LOUD, structured reason\n * the engine parks the run `blocked` with (never a silent hang into a queue nobody consumes).\n *\n * Pure logic + a small control-plane descriptor factory: no transport, no store, no I/O. The engine\n * feeds in descriptors it read off the broker and acts on the returned plan.\n */\n\nimport {\n CURRENT_PROTOCOL_VERSION,\n type RawWorkerDescriptor,\n type WorkerDescriptor,\n normalizeDescriptor,\n} from './descriptor';\nimport { negotiate } from './negotiate';\nimport { canRoute, requiredCapabilities } from './routing';\n\n/**\n * Build the control-plane's OWN handshake descriptor — the side the engine negotiates AGAINST each\n * worker (design §7.3). The CP advertises the protocol band it speaks so a worker stuck on an\n * incompatible major is detected instead of dispatched into (design §7.4). Capabilities default to\n * empty (the CP demands nothing of itself); `partition`/`namespace` scope it to a pool when set.\n *\n * The CP is not a worker, so `workflows`/`steps` are empty and `runtime` is `node`. `startedAt`\n * participates only in the descriptor hash (irrelevant for negotiation), so it defaults to `0` unless\n * a caller wants a stable identity.\n */\nexport function controlPlaneDescriptor(opts: {\n instanceId: string;\n /** SDK identity for observability (never gates dispatch). */\n sdk?: { name: string; version: string };\n /** Protocol majors the CP can negotiate. Defaults to the current single-major band `[v, v]`. */\n protocol?: { version: number; range: [number, number] };\n /** Capabilities the CP itself advertises (rarely needed; the CP is a router, not an executor). */\n capabilities?: string[];\n partition?: string | undefined;\n namespace?: string | undefined;\n startedAt?: number;\n}): WorkerDescriptor {\n const version = CURRENT_PROTOCOL_VERSION;\n return {\n instanceId: opts.instanceId,\n runtime: 'node',\n sdk: opts.sdk ?? { name: '@dudousxd/nestjs-durable-core', version: String(version) },\n protocol: opts.protocol ?? { version, range: [version, version] },\n capabilities: opts.capabilities ?? [],\n workflows: [],\n steps: [],\n ...(opts.partition !== undefined ? { partition: opts.partition } : {}),\n ...(opts.namespace !== undefined ? { namespace: opts.namespace } : {}),\n startedAt: opts.startedAt ?? 0,\n };\n}\n\n/** The structured delta a blocked-dispatch diagnostics event carries (design §7.6) — enough for the\n * telescope timeline + dashboard health panel to render exactly WHY nobody could run the work, never\n * a bare boolean. Serializable (plain data), so it rides an `EngineEvent`/control-plane message. */\nexport interface DispatchDiagnostics {\n /** Which machine code fired — a missing capability vs. an unbridgeable protocol gap. */\n code: 'capability.unavailable' | 'protocol.incompatible';\n /** The routing token the work would have been dispatched to. */\n token: string;\n /** The capabilities the handler required (de-duplicated). */\n requires: string[];\n /** How many live workers were advertising on this token at decision time. */\n liveWorkers: number;\n /** Required capabilities NOT advertised by ANY live worker (the `capability.unavailable` delta). */\n missingCapabilities?: string[];\n /** The protocol band the control-plane speaks (the `protocol.incompatible` delta). */\n controlPlaneRange?: [number, number];\n /** Protocol bands of the capable-but-incompatible workers (the `protocol.incompatible` delta). */\n workerRanges?: [number, number][];\n /** The control-plane descriptor negotiated against (attached wholesale for observability). */\n controlPlane: WorkerDescriptor;\n /** The live worker descriptors considered (attached wholesale — the full picture on the timeline). */\n workers: WorkerDescriptor[];\n}\n\n/** At least one live worker can run the handler — dispatch proceeds as today. */\nexport interface RoutableDispatch {\n status: 'routable';\n /** The normalized subset that is BOTH capable and protocol-compatible. */\n workers: WorkerDescriptor[];\n}\n\n/** No live worker can run the handler — the engine parks the run `blocked` with this reason/delta. */\nexport interface BlockedDispatch {\n status: 'blocked';\n code: 'capability.unavailable' | 'protocol.incompatible';\n /** Dashboard/telescope copy, e.g. `blocked: no compatible worker (requires saga)`. */\n reason: string;\n requires: string[];\n diagnostics: DispatchDiagnostics;\n}\n\nexport type DispatchPlan = RoutableDispatch | BlockedDispatch;\n\n/**\n * Thrown from deep in a `ctx.step` dispatch when {@link planDispatch} returns `blocked`, so the\n * engine's run-execution catch can park the run `blocked` (with the carried plan) instead of writing\n * a `pending` checkpoint + dispatching into a queue no live worker consumes. Distinct from\n * `WorkflowSuspended` — a blocked run is re-driven by the blocked-recovery poll, not a durable timer.\n */\nexport class WorkflowBlocked extends Error {\n constructor(readonly plan: BlockedDispatch) {\n super(plan.reason);\n this.name = 'WorkflowBlocked';\n }\n}\n\n/**\n * Decide whether a handler requiring `requires` can be dispatched to a token whose LIVE fleet is\n * `liveDescriptors`, negotiating each candidate against the control-plane descriptor `cp`\n * (design §7.4/§7.5).\n *\n * A worker is dispatchable iff it is BOTH capability-capable ({@link canRoute}) AND\n * protocol-compatible ({@link negotiate} outcome ≠ `incompatible`). If ≥1 such worker exists →\n * `routable`. Otherwise `blocked`, with the reason discriminated:\n * - some workers had the capability but ALL are protocol-incompatible → `protocol.incompatible`;\n * - otherwise (no live worker advertises every required capability) → `capability.unavailable`.\n *\n * Precondition (enforced by the caller): `liveDescriptors` is NON-EMPTY. An empty fleet means \"no\n * descriptors published\" — the legacy/pre-handshake path — where the guard is intentionally skipped so\n * existing workers keep flowing (design §7.7); the engine never calls this with an empty fleet.\n */\nexport function planDispatch(\n requires: string[],\n liveDescriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n cp: WorkerDescriptor,\n token: string,\n): DispatchPlan {\n const required = requiredCapabilities({ requires });\n const workers = liveDescriptors.map(normalizeDescriptor);\n const capable = workers.filter((w) => canRoute({ requires }, w));\n const compatible = capable.filter((w) => negotiate(cp, w).outcome !== 'incompatible');\n\n if (compatible.length > 0) return { status: 'routable', workers: compatible };\n\n // Blocked. Which failure? Capable-but-incompatible → protocol; no capable at all → capability.\n if (capable.length > 0) {\n const workerRanges = capable.map((w) => w.protocol.range);\n return {\n status: 'blocked',\n code: 'protocol.incompatible',\n reason: `blocked: no protocol-compatible worker${\n required.length > 0 ? ` (requires ${required.join(', ')})` : ''\n }`,\n requires: required,\n diagnostics: {\n code: 'protocol.incompatible',\n token,\n requires: required,\n liveWorkers: workers.length,\n controlPlaneRange: cp.protocol.range,\n workerRanges,\n controlPlane: cp,\n workers,\n },\n };\n }\n\n // Capability gap: required caps advertised by NO live worker.\n const advertised = new Set(workers.flatMap((w) => w.capabilities));\n const missingCapabilities = required.filter((cap) => !advertised.has(cap));\n return {\n status: 'blocked',\n code: 'capability.unavailable',\n reason: `blocked: no compatible worker${\n required.length > 0 ? ` (requires ${required.join(', ')})` : ''\n }`,\n requires: required,\n diagnostics: {\n code: 'capability.unavailable',\n token,\n requires: required,\n liveWorkers: workers.length,\n missingCapabilities,\n controlPlane: cp,\n workers,\n },\n };\n}\n","import type { z } from 'zod';\nimport type { WorkerDescriptor } from './handshake/descriptor';\nimport type { DispatchDiagnostics } from './handshake/dispatch-routing';\nimport type { StandardSchemaV1 } from './standard-schema';\nimport type { StepRef } from './step-name-symbol';\nimport type { WorkflowClass, WorkflowInputOf, WorkflowOutputOf } from './workflow-ref';\n\n/**\n * Core type contracts for nestjs-durable.\n *\n * These are intentionally framework-agnostic: `@dudousxd/nestjs-durable-core` knows only\n * these interfaces, never a concrete transport, store or ORM. Adapters implement them.\n */\n\n// ---------------------------------------------------------------------------\n// Runs & checkpoints — the durable state owned by the orchestrator\n// ---------------------------------------------------------------------------\n\nexport type RunStatus =\n /** Created + enqueued by `start`, not yet picked up — a worker will lease and execute it. */\n | 'pending'\n | 'running'\n | 'suspended'\n /**\n * Compensating cancel in progress: `cancel(runId, { compensate: true })` has been requested and the\n * saga undo is running in the background. NON-TERMINAL — the run is still in-flight (counted by the\n * admission gate, re-driven by recovery if the engine crashes mid-compensation), and flips to\n * `cancelled` once compensation completes. A non-compensating cancel skips this and goes straight to\n * `cancelled`.\n */\n | 'cancelling'\n /**\n * No live worker on the run's next-dispatch group is BOTH capability-capable and protocol-compatible\n * (handshake design §7.5). NON-TERMINAL — the run wrote no `pending` checkpoint and dispatched\n * nothing; it carries a `wakeAt` so the blocked-recovery poll re-drives it to re-check the live\n * fleet, and proceeds the moment a capable+compatible worker appears. Only engaged when descriptors\n * are actually published (a legacy/pre-handshake fleet skips the guard, design §7.7).\n */\n | 'blocked'\n | 'completed'\n | 'failed'\n | 'cancelled'\n /** Dead-letter: recovery gave up after `maxRecoveryAttempts` (a poison pill). Terminal; inspect it. */\n | 'dead';\n\n/** One execution of a workflow. The unit of durability and the unit shown in the dashboard. */\nexport interface WorkflowRun {\n id: string;\n /** Registered workflow name, e.g. `checkout`. */\n workflow: string;\n /** Code version at start; old runs must resume on the version they began on. */\n workflowVersion: string;\n status: RunStatus;\n /** Serialized workflow input (the args the run was started with). */\n input: unknown;\n /** Serialized workflow output, once `completed`. */\n output?: unknown;\n /** Structured error, once `failed`. */\n error?: StepError | undefined;\n /** When `suspended` on a durable sleep: epoch ms at which the run becomes due to resume. */\n wakeAt?: number | undefined;\n /** Recovery lease owner (engine instance id) while a run is being resumed. */\n lockedBy?: string | undefined;\n /** Recovery lease expiry (epoch ms); another instance may take over once it passes. */\n lockedUntil?: number | undefined;\n /** How many times crash-recovery has picked this run up — caps poison pills (see maxRecoveryAttempts). */\n recoveryAttempts?: number | undefined;\n /** Searchable labels: the workflow's static `@Workflow({ tags })` merged with the run's start-time tags. */\n tags?: string[] | undefined;\n /** Typed, queryable run data (e.g. `{ amount: 200, tier: 'pro' }`) — see {@link RunQuery.attributes}. */\n searchAttributes?: SearchAttributes | undefined;\n /**\n * The worker-pool partition this run belongs to. Stamped at creation from the creating engine's\n * `namespace` (default `'default'`). A worker only picks up / recovers / resumes-timers-for /\n * times-out runs in its own namespace. `undefined` on a run created before this field existed; the\n * store persists it as `'default'`. Read paths (dashboard, `getRun`) are NOT namespace-scoped.\n */\n namespace?: string | undefined;\n /**\n * The npm package that DECLARED this run's workflow — e.g. `@dudousxd/nestjs-catalog-pipeline` for\n * a workflow shipped by a library, or the host app's own `package.json` `name` for one written in\n * the app. This is a CODE-PROVENANCE axis (\"which lib owns this body\"), NOT a tenancy axis — for\n * that, see {@link namespace}.\n *\n * Stamped at creation from the workflow's registration, exactly as {@link namespace} is stamped\n * from the creating engine. It is DERIVED, never caller input: `StartOptions` has no `origin`, so\n * nothing a caller passes to `start` can make a run claim another lib's name.\n *\n * `undefined` means UNKNOWN — never \"the app\". It is what you get for a run created before this\n * field existed, for a registration path that carries no origin (`registerRemote`, convention\n * routing, a synthesized remote child, or a bare `engine.register` with no `origin` option), and\n * for a workflow whose declaring package could not be resolved with confidence. A wrong origin is\n * worse than an absent one: a filter that silently drops runs looks exactly like runs that never\n * existed, so callers must render unknown as unknown and never fold it into a real package.\n */\n origin?: string | undefined;\n /**\n * Dispatch priority for a REMOTE run (one advanced by a {@link WorkflowExecutor} over a broker):\n * carried onto each {@link WorkflowTask} so an urgent child workflow can jump ahead of enqueued\n * lower-priority ones at the worker. Higher wins; absent = unprioritised. Best-effort ordering, not\n * durable state required for correctness — a transport without priority support ignores it.\n */\n priority?: number | undefined;\n /**\n * REMOTE workflow turn awaiting a decision: the `taskId` of the turn the engine dispatched to a\n * workflow worker and then SUSPENDED on. Set by the dispatch-and-suspend path; matched by\n * {@link WorkflowEngine.completeRemoteDecision} so ONLY the decision for the currently-awaited turn\n * is applied (a stale/duplicate/foreign decision is dropped), then cleared the moment it is applied.\n * This is what makes a workflow-turn decision multi-instance safe: any engine instance that receives\n * the decision looks the run up by `decision.runId` and applies it durably, instead of resolving an\n * in-memory promise that only the dispatching instance held. Absent on non-remote / not-awaiting runs.\n */\n awaitingDecisionTaskId?: string | undefined;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * WHAT an event-parked suspended run is waiting on, resolved for display — the engine keeps one\n * generic `suspended` status (it's what drives recovery/timers/queries), but to a human \"waiting on\n * signal `approve`\" reads very differently from \"waiting on webhook `stripe-cb`\". Computed by the\n * store-backed gateway from the run's signal waiters (`listSignalWaiters`, ONE bulk scan), so the\n * dashboard can NAME the wait in a list row without fetching each run's timeline. `on` is derived from\n * the waiter token's prefix (see `classifyWaiterToken`): `wh:<runId>:<seq>` ⇒ `webhook`, `child:<id>`\n * ⇒ `child`, `bp:<runId>:<seq>` ⇒ `breakpoint` (a `ctx.breakpoint` DOES register a signal waiter —\n * same machinery, `engine.continue` resumes it — so it's classified here, not left to fall through to\n * the generic `signal` case with the raw token as its ugly display name), `event:<name>:…` ⇒ `signal`\n * (name decoded), anything else ⇒ `signal` (the token IS the signal name).\n *\n * Deliberately EVENT-only (no timer/step): `wakeAt` alone can't tell a real `ctx.sleep` from the\n * reconcile-fallback `wakeAt` an event/step suspend now carries, and the store exposes no cheap bulk\n * checkpoint scan to disambiguate — so the client shows a non-event suspend with a live worker as\n * `running` (it flips off \"no worker\" the moment a worker returns) rather than guessing \"sleeping\".\n * The detail view (which has the timeline) still distinguishes sleep vs in-flight step precisely.\n */\nexport interface RunWaiting {\n on: 'signal' | 'webhook' | 'child' | 'breakpoint';\n /**\n * The token/name the run is parked on — the signal name, webhook token, or awaited child id. For a\n * breakpoint this is always the literal `'breakpoint'`: the real label (if any) lives on the pending\n * `breakpoint`/`breakpoint:<label>` checkpoint, which the detail view's timeline already shows —\n * naming it here would need an extra per-run checkpoint read, defeating the bulk waiter scan.\n */\n name: string;\n}\n\nexport type StepKind = 'local' | 'remote' | 'sleep' | 'signal';\n\n/**\n * The recorded result of a single step at a deterministic logical position (`seq`).\n * On replay, a `completed` checkpoint means the step is NOT re-executed — its `output` is\n * returned. A non-terminal checkpoint (`pending`/`running`) does not short-circuit: the step is\n * re-awaited (remote) or re-run (local).\n */\nexport interface StepCheckpoint {\n runId: string;\n /** Deterministic logical position of the step within the run. */\n seq: number;\n /** Registered step name (matches the remote handler name for remote steps). */\n name: string;\n kind: StepKind;\n /** Stable id passed to remote workers so they can dedupe a re-delivered task. */\n stepId: string;\n /**\n * `pending` = a remote step dispatched and awaiting its worker result (the run is durably\n * suspended, not held in memory); it becomes `completed`/`failed` when the result arrives.\n * `running` = a local step whose body is executing in-process right now (see `trackStepStart`);\n * it's overwritten by `completed`/`failed` when the body settles, and on a crash mid-body it\n * simply re-runs on replay (only `completed` short-circuits).\n */\n status: 'pending' | 'running' | 'completed' | 'failed';\n /** What the step was called with — the `ctx.step` (dispatched) args for a remote step (a local step has none). */\n input?: unknown;\n output?: unknown;\n error?: StepError | undefined;\n attempts: number;\n /** For remote steps: which worker group ran it. */\n workerGroup?: string | undefined;\n /** Structured events/logs the step emitted (sub-step outcomes, debug/error lines). */\n events?: StepEvent[] | undefined;\n /** For sleep steps: epoch ms the sleep elapses at. */\n wakeAt?: number | undefined;\n /**\n * Set on the running placeholder checkpoints of the children dispatched by one `ctx.all` call —\n * a shared tag (`all:<firstSeq>`) grouping the N siblings so the dashboard can render them as one\n * parallel fan-out. Optional and additive: absent on every non-`all` checkpoint. Mirrors the\n * Python SDK's `parallelGroup`.\n */\n parallelGroup?: string | undefined;\n /**\n * When the step entered the system: for a remote step, when the engine dispatched it to the\n * transport; for a local step, when it began. Queue-wait time = `startedAt − enqueuedAt`.\n */\n enqueuedAt: Date;\n /** When processing actually began: worker pickup for a remote step, execution start for a local one. */\n startedAt: Date;\n finishedAt: Date;\n}\n\n/**\n * A structured event a step (or its worker) emits while running — a log line and/or a sub-step\n * outcome. The dashboard renders these under the step, so you can see what happened inside a step\n * that the workflow treats as one unit (e.g. which of N parallel sub-processes ok/failed/skipped).\n */\nexport interface StepEvent {\n /** Epoch ms. */\n at: number;\n level: 'debug' | 'info' | 'warn' | 'error';\n message: string;\n /** Stable run identity for a sub-process. Distinct invocations of the same `name` carry distinct\n * ids, so their phases and log trails never collapse into one. Absent on events emitted by the\n * legacy `sub()` path, which keys by `name` instead. */\n subId?: string;\n /** For a sub-step/sub-process within the step: its name. */\n name?: string;\n /** Open, consumer-defined grouping label for a sub-process (e.g. a handler/lane). The dashboard\n * groups rows by it. The library never interprets it. */\n group?: string;\n /** For a sub-step: its terminal outcome (closed enum — drives colour + aggregation). */\n status?: 'ok' | 'failed' | 'skipped';\n /** Open, consumer-defined intermediate phase label for a sub-process transition. Carries no\n * terminal `status`; the library timestamps and orders it but never interprets it. */\n phase?: string;\n /** For a log line emitted *inside* a sub-process: that owning sub-process's name, so the dashboard\n * can group a step's log trail under each sub-process instead of one flat list. Set on logs (no\n * `status`); a worker stamps it from the sub-process it's running.\n * @deprecated Superseded by `subId` for run-distinct grouping; kept so existing workers/runs render. */\n process?: string;\n /** Optional structured payload. `data.durationMs` (number) overrides the derived duration. */\n data?: unknown;\n}\n\n/**\n * Handed to a local step's body (`ctx.step(name, (log) => …)`) so it can record what happened\n * inside the step — debug/info/warn/error lines and per-sub-process outcomes. The events are\n * checkpointed with the step and rendered under it in the dashboard. The remote/cross-language\n * counterpart is the worker attaching the same `StepEvent[]` to its `StepResult` (see the Python\n * SDK's `StepContext`), so observability is symmetric regardless of where the step ran.\n */\nexport interface StepLogger {\n debug(message: string, data?: unknown): void;\n info(message: string, data?: unknown): void;\n warn(message: string, data?: unknown): void;\n error(message: string, data?: unknown): void;\n /** Record a sub-step / sub-process outcome (e.g. one of N parallel p-processes). */\n sub(name: string, status: 'ok' | 'failed' | 'skipped', message?: string, data?: unknown): void;\n /** Record a sub-process event. Typically pass `phase` for an intermediate transition (carrying no\n * terminal status), or `status` for the terminal outcome — the type permits either; the engine\n * interprets which is set. `id` is the run identity (distinct per invocation); `group` is an\n * open grouping label. */\n subEvent(e: {\n id: string;\n name: string;\n group?: string | undefined;\n phase?: string | undefined;\n status?: 'ok' | 'failed' | 'skipped' | undefined;\n message?: string | undefined;\n data?: unknown;\n }): void;\n /**\n * Ergonomic sub-process lifecycle: run `body`, timing it, and record a terminal `ok` with the\n * measured `durationMs` on success — or `failed` (with the error message) if it throws, then\n * re-throw. `sp.phase(label)` records an intermediate transition; `sp.skip(reason)` a terminal\n * `skipped`. Logs emitted inside `body` are tagged to this sub-process so the dashboard groups\n * them under it. Returns whatever `body` returns. The TS twin of the Python SDK's `sub_process`.\n *\n * ```ts\n * const rows = await log.subProcess('fetch-data', async () => readEverything());\n * await log.subProcess('export-file', () => upload(rows));\n * ```\n */\n subProcess<T>(\n name: string,\n body: (sp: SubProcessHandle) => Promise<T> | T,\n opts?: { group?: string; id?: string },\n ): Promise<T>;\n}\n\n/** The handle a {@link StepLogger.subProcess} body receives to mark phases / a non-`ok` outcome. */\nexport interface SubProcessHandle {\n /** Record an intermediate phase transition (a consumer-defined label, no terminal status). */\n phase(phase: string, data?: unknown): SubProcessHandle;\n /** Record a terminal `skipped` outcome (e.g. nothing to do / validation failed). */\n skip(reason?: string, data?: unknown): void;\n /** Record a terminal `failed` outcome explicitly (the wrapper also does this if the body throws). */\n fail(reason?: string, data?: unknown): void;\n}\n\nexport interface StepError {\n message: string;\n /** Optional machine-readable code, e.g. `declined`, `timeout`. */\n code?: string | undefined;\n /** Whether the engine should treat this as retryable. */\n retryable?: boolean | undefined;\n stack?: string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// StateStore — where runs and checkpoints live (Postgres / MySQL / SQLite via ORM adapters)\n// ---------------------------------------------------------------------------\n\nexport interface StateStore {\n /**\n * Provision the tables/collections this store needs, idempotently. Called on boot when the\n * module's `autoSchema` is on. Optional: stores that need no setup (in-memory) omit it.\n */\n ensureSchema?(): Promise<void>;\n\n /**\n * Atomically read active runs sharing workflow/tag in this store's read scope, preserve durable\n * admitted holders, and claim a free slot for an eligible FIFO waiter. The claim persists the\n * reserved SINGLETON_ADMITTED_TAG in tags. Execution lease expiry never releases a slot; terminal\n * status does. Optional for general stores, required when using singleton workflows. Implement\n * with a database transaction that serializes competing claims BEFORE reading; list/update alone\n * is unsafe across engine instances. If retryWakeAt is supplied, denial must atomically suspend\n * the still-active candidate with that wakeAt while the same locks are held. Never overwrite a\n * cancelling or terminal run on denial. Return false for missing/terminal/out-of-scope runs.\n */\n tryAdmitSingleton?(\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ): Promise<boolean>;\n\n createRun(run: WorkflowRun): Promise<void>;\n updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;\n getRun(runId: string): Promise<WorkflowRun | null>;\n\n /**\n * Hard-delete a run and all of its rows — the run plus its checkpoints, signal waiters, and\n * normalized search-attribute rows. Unlike a cancelled run (which stays as terminal history), a\n * deleted run is GONE: it no longer appears in {@link getRun} or {@link listRuns}. This removes\n * exactly the one run — the engine's {@link WorkflowEngine.deleteRun} handles the child cascade.\n * No-op if the run doesn't exist. (Token-keyed buffered signals are transient and left alone.)\n */\n deleteRun(runId: string): Promise<void>;\n\n /**\n * Hard-delete up to `limit` terminal runs that fall OUTSIDE `policy` (oldest / over the count cap\n * first), cascading to their child rows exactly like {@link deleteRun}. Returns how many runs were\n * deleted — call again while it returns `limit` to drain a large backlog in bounded batches.\n *\n * A policy with a {@link RetentionPolicy.scope} only ever selects (and counts, for `maxCount`) runs\n * matching that scope.\n *\n * Optional: only adapters that implement a bulk prune provide it; the retention poller no-ops with a\n * warning when the configured store omits it. See {@link RetentionPolicy} for the keep/prune rule.\n */\n pruneTerminalRuns?(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number>;\n\n /**\n * Hard-delete a BATCH of runs and all of their rows in one go — exactly {@link deleteRun} applied to\n * every id (checkpoints, signal waiters, attribute rows, then the runs), but as a handful of\n * `IN (...)` statements in one transaction instead of four round-trips per run. Ids that don't exist\n * are ignored. Like {@link deleteRun} it removes exactly the listed runs; the engine's\n * `purgeRuns` walks the child edges first.\n *\n * Optional: a store that omits it still works — the engine falls back to one {@link deleteRun} per id.\n */\n deleteRuns?(runIds: string[]): Promise<void>;\n\n getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;\n /**\n * Persist a checkpoint and advance the run atomically. Durable semantics depend on this\n * being a single transaction; stores without transactions cannot give the strong guarantee.\n */\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;\n\n /** Used by recovery on boot to find runs to resume (crashed, left `running`). */\n listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;\n\n /** The oldest `pending` runs awaiting dispatch (FIFO, by `createdAt`), capped at `limit`. */\n listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;\n\n /** Suspended runs whose durable timer is due (`wakeAt <= nowMs`), ready to resume. */\n listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;\n\n /**\n * Atomically acquire the recovery lease on a run for `owner` until `leaseUntilMs`, but only if\n * it is currently unlocked or its lease has expired (`<= nowMs`). Returns whether it was\n * acquired — so concurrent engine instances never recover the same run twice.\n */\n tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;\n\n /** Release a run's recovery lease so another instance can pick it up (e.g. once it suspends). */\n releaseRunLock(runId: string): Promise<void>;\n\n /**\n * Extend a run's lease to `leaseUntilMs`, but ONLY if `owner` still holds it — so a live worker\n * heartbeating its long run keeps the lease, while a dead worker's lease still expires and gets\n * reclaimed. Returns false if the lease was lost (taken over or released).\n */\n renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;\n\n /** Record that a run is suspended waiting for an external signal `token`. */\n putSignalWaiter(waiter: SignalWaiter): Promise<void>;\n /** Atomically take (and remove) the run waiting on `token`, if any. */\n takeSignalWaiter(token: string): Promise<SignalWaiter | null>;\n /** List waiters whose `token` starts with `prefix` — used to fan out an event to its subscribers. */\n listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;\n /**\n * Whether run `runId` still has at least one waiter whose `token` starts with `tokenPrefix` (an\n * exact prefix: `%`/`_` in the prefix are literal characters, not wildcards). The `ctx.all` join\n * barrier asks this after each child settles, so it must stay O(1)-ish however many siblings are\n * still waiting — answer it with a bounded lookup, never by listing the whole group.\n *\n * Optional: a store without it keeps `ctx.all` correct, but the parent replays once per settled\n * child instead of once per fan.\n */\n hasSignalWaiter?(runId: string, tokenPrefix: string): Promise<boolean>;\n /**\n * The waiters of the given runs. Lets the engine and the dashboard read what a page of runs (or\n * one run's children) is waiting on without scanning every waiter in the store, which a wide fan\n * fills with one row per running child. Callers pass ids in bounded batches.\n *\n * Optional: without it those reads fall back to {@link listSignalWaiters} over every waiter.\n */\n listSignalWaitersByRun?(runIds: string[]): Promise<SignalWaiter[]>;\n /**\n * Register a batch of awaited children: for each entry, put `waiter` and upsert `checkpoint` (the\n * parent's `running` placeholder for that child). `ctx.all` calls it once per chunk of a fan, so a\n * wide fan costs a handful of round trips instead of two per child.\n *\n * Every entry's waiter must be durable no later than its checkpoint: the engine reads an existing\n * placeholder as proof the waiter was put, and never re-puts it. Writing both in one transaction\n * satisfies that.\n *\n * Optional: without it the engine puts each waiter, then saves each checkpoint.\n */\n registerChildWaits?(entries: ChildWait[]): Promise<void>;\n /**\n * Atomically replace run `runId`'s checkpoints with `seq` in `[fromSeq, toSeq]` by the single\n * checkpoint `into`, whose `seq` lies in that range. `ctx.all` folds a settled group of children\n * into one checkpoint this way, so every later turn of the parent loads one row instead of one per\n * child. A delete over a contiguous seq range, served by the `(runId, seq)` primary key.\n *\n * Optional: without it a settled fan keeps one checkpoint per child.\n */\n compactCheckpoints?(\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ): Promise<void>;\n\n /**\n * Delete the EXACT waiter row — `token` AND `runId` AND `seq` must all match — no-op if absent.\n * Unlike {@link takeSignalWaiter}, which deletes ANY row for `token` (fine when the caller just won\n * the race to consume it), this is for a caller removing its OWN registration after resolving the\n * wait some other way (a buffered hit, a timeout): blind `takeSignalWaiter(token)` there could steal\n * a DIFFERENT run's waiter that has since claimed the same token (`token` is the store's primary key,\n * so a later `putSignalWaiter` for the same token replaces the row). The exact-match variant only\n * ever removes the row this caller itself put there.\n */\n removeSignalWaiter(waiter: SignalWaiter): Promise<void>;\n\n /**\n * Buffer a signal whose waiter hasn't arrived yet, so the next `waitForSignal(token)` consumes it\n * instead of it being lost (FIFO per token). Makes signals reliable regardless of timing and\n * powers `signalWithStart`.\n */\n bufferSignal(token: string, payload: unknown): Promise<void>;\n /** Take the oldest buffered signal for `token` (FIFO), or null if none is buffered. */\n takeBufferedSignal(token: string): Promise<{ payload: unknown } | null>;\n\n /**\n * Buffer a published event that matched NO live waiter, so a LATER `ctx.waitForEvent(name, { match })`\n * still consumes it instead of it being silently dropped — the events analog of {@link bufferSignal}'s\n * reliability contract for signals, but MATCH-based rather than token-based: an event's buffer is keyed\n * by `name` alone (many waiters can share a name with different `match` criteria), so consumption is\n * list ({@link listBufferedEvents}) + evaluate the WAITER's own match predicate + claim\n * ({@link removeBufferedEvent}) — never a blind take, because the store has no way to know which\n * candidate a given waiter wants. `input.id` is minted by the caller (engine.publishEvent) so\n * {@link removeBufferedEvent} can later target this exact row.\n */\n bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void>;\n /**\n * Buffered events for `name`, OLDEST (`publishedAt`) first, capped at `limit`. A waiter scans these,\n * evaluates its own `eventMatches(payload, match)` locally, and claims the one it wants via\n * {@link removeBufferedEvent} — the match predicate belongs to the WAITER, never the store.\n */\n listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>>;\n /**\n * Atomically delete the buffered event `id`. Returns `true` iff a row was actually deleted, `false`\n * if it was already gone (claimed by a concurrent waiter, reclaimed by `engine.publishEvent`'s own\n * late re-check, or pruned as expired) — the arbiter under concurrency: whichever caller's delete\n * returns `true` is the one that gets to deliver the payload; every other caller backs off.\n */\n removeBufferedEvent(id: string): Promise<boolean>;\n\n /**\n * Run `work` in a SINGLE store transaction — giving it the store-native transaction handle (`raw`)\n * for the caller's own DB writes plus a `saveCheckpoint` that commits IN THE SAME transaction, so a\n * business write and the step's \"done\" checkpoint are atomic (exactly-once). Optional — only the SQL\n * adapters implement it; `ctx.transaction` errors on a store without it.\n */\n transaction?<T>(work: (tx: StoreTransaction) => Promise<T>): Promise<T>;\n\n // Persisted schedules (optional) — see {@link ScheduleRecord}. A store implements all five or none;\n // `engine.schedules` refuses to run on a store without them.\n\n /** Insert or fully replace the schedule `record.id`. */\n saveSchedule?(record: ScheduleRecord): Promise<void>;\n /** The schedule `id`, or null. */\n getSchedule?(id: string): Promise<ScheduleRecord | null>;\n /**\n * Patch the schedule `id`. With `expectedNextFireAt`, a compare-and-set: the patch applies only if\n * the stored `nextFireAt` still equals it (`null` matching `NULL`), which is how two schedulers racing\n * on the same due schedule agree on who advanced it. Returns whether a row was updated.\n */\n updateSchedule?(\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ): Promise<boolean>;\n /** Delete the schedule `id`. Returns whether it existed. Its past runs are left alone. */\n deleteSchedule?(id: string): Promise<boolean>;\n /** Schedules matching `query`, ordered by `nextFireAt` ascending (never-firing last), then `id`. */\n listSchedules?(query: ScheduleQuery): Promise<ScheduleRecord[]>;\n\n // Dashboard queries\n listRuns(query: RunQuery): Promise<WorkflowRun[]>;\n\n /**\n * How many runs match `query` — a single `COUNT(*)` over the same predicates {@link listRuns}\n * applies, without materializing a row. What the start-time concurrency quota asks on every start\n * (`tag = concurrency:<key> AND status IN (...)`), so it must stay an aggregate, not a listing.\n *\n * Optional: a store that omits it still works — the engine falls back to summing {@link runFacets}\n * cells, then to counting a {@link listRuns} result.\n */\n countRuns?(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number>;\n\n /**\n * Count the runs matching `query`, grouped by `(status, origin)` — the totals behind a console's\n * status and origin chips, in ONE aggregate instead of a full listing the caller counts in memory.\n * This is what lets a run list be paginated at all: `listRuns` can return 100 rows while the chips\n * still say how many of the 9,000 are failed.\n *\n * Cells with a zero count are simply absent. Optional: a store that omits it still works — callers\n * fall back to counting a {@link listRuns} result, which is correct but unbounded.\n */\n runFacets?(query: RunFacetQuery): Promise<RunFacetRow[]>;\n\n /**\n * The distinct values of ONE filter axis over the runs matching `query`, with counts — what a\n * console's tenant/tag/attribute pickers list instead of asking an operator to type a value blind.\n *\n * Scoped by the SAME predicates the list is under (`query`), so the options narrow as the operator\n * narrows: picking a tenant leaves the tag picker offering only tags that tenant's runs actually\n * carry, and a picker never offers a value that would return an empty list.\n *\n * Bounded by {@link RunValueFacetOptions} — read its `scan` note before trusting a `tag` count.\n *\n * Optional: a store that omits it still works — the console falls back to free-text entry for these\n * filters, which is what it had before pickers existed.\n */\n runValueFacets?(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]>;\n listCheckpoints(runId: string): Promise<StepCheckpoint[]>;\n\n /**\n * The LATEST checkpoint for `runId` whose `name` equals `name` exactly (highest `seq` wins), or\n * `undefined` if none. A targeted read that avoids fetching + deserializing every checkpoint just to\n * keep one match — the store does the filter (`WHERE name = … ORDER BY seq DESC LIMIT 1`). Preserves\n * the \"last in seq order wins\" semantics the engine relies on for `getEvent` (a re-published key\n * overwrites the prior value at a higher seq, so the highest-seq match is the current value).\n *\n * Optional: a store that omits it still works — the engine falls back to {@link listCheckpoints}\n * plus an in-JS filter that produces the identical result.\n */\n getLatestCheckpointByName?(runId: string, name: string): Promise<StepCheckpoint | undefined>;\n\n /**\n * All checkpoints for `runId` whose `name` starts with ANY of `prefixes`, ordered by `seq` ascending\n * (same order as {@link listCheckpoints}). A targeted read that avoids scanning every checkpoint just\n * to keep the prefix matches — the store does the filter (`WHERE name LIKE 'prefix%' …`). Used by the\n * run-tree to find a parent's child edges (`signal:child:` / `spawn:` checkpoints) without loading the\n * whole history. An empty `prefixes` array matches nothing.\n *\n * Optional: a store that omits it still works — the engine falls back to {@link listCheckpoints}\n * plus an in-JS prefix scan that produces the identical result.\n */\n listCheckpointsByNamePrefix?(runId: string, prefixes: string[]): Promise<StepCheckpoint[]>;\n}\n\n/**\n * A persisted schedule as the STORE sees it: a handful of queryable columns plus two JSON documents\n * the store keeps verbatim (`spec`, `state`) and never interprets. The engine's schedule client owns\n * their meaning (cron/interval math, overlap, catch-up) — so a store only has to persist rows and\n * answer \"which unpaused schedules are due by T\".\n */\nexport interface ScheduleRecord {\n /** Caller-chosen, stable id (e.g. `digest:user-42`) — also part of every run id it starts. */\n id: string;\n /** Partition: the namespace its runs are stamped with, and which schedulers fire it. */\n namespace: string;\n /** Registered workflow name the schedule starts. */\n workflow: string;\n /** A paused schedule is never due. */\n paused: boolean;\n /** Epoch ms at which it is next due (jitter included), or null when it will never fire again. */\n nextFireAt: number | null;\n /** Labels to list/filter schedules by (also stamped onto the runs it starts). */\n tags?: string[] | undefined;\n /** The schedule's definition — opaque to the store. */\n spec: Record<string, unknown>;\n /** The schedule's bookkeeping (last fire, last run id, last error…) — opaque to the store. */\n state: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Filter for {@link StateStore.listSchedules}. Every predicate is ANDed; absent = unrestricted. */\nexport interface ScheduleQuery {\n namespace?: string | undefined;\n workflow?: string | undefined;\n /** Only schedules carrying this tag. */\n tag?: string | undefined;\n paused?: boolean | undefined;\n /** Only DUE schedules: unpaused, `nextFireAt <= dueBy`. */\n dueBy?: number | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n}\n\n/** The terminal run statuses — a run in one of these is finished and will never change on its own.\n * Only these are eligible for retention pruning (a {@link RetentionPolicy} targeting a non-terminal\n * status would race the engine and delete live work). */\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\n 'completed',\n 'failed',\n 'cancelled',\n 'dead',\n];\n\n/**\n * One retention rule for hard-pruning terminal run history. Within `statuses` (terminal only), a run\n * is KEPT only if it satisfies EVERY bound you set, and pruned the moment it violates any:\n * - `maxAge` — prune runs whose `updatedAt` (≈ the time they reached terminal) is older than\n * `now - maxAge`. A number is milliseconds; a string is an `ms`-style duration parsed by\n * {@link parseDuration} (`'7d'`, `'2w'`, `'90m'` — note `'m'` is MINUTES; use `'30d'` for a month).\n * - `maxCount` — keep only the `maxCount` most-recent (by `updatedAt`) runs in the status set; prune\n * everything past that.\n *\n * Set one or both (both = the most-restrictive wins: capped at `maxCount` rows AND nothing older than\n * `maxAge`). Statuses not named by any policy are never pruned.\n */\nexport interface RetentionPolicy {\n statuses: RunStatus[];\n maxAge?: number | string;\n maxCount?: number;\n /**\n * Confine the policy to the runs matching these predicates (same semantics as the {@link RunQuery}\n * fields of the same names) — e.g. `{ namespace: 'acme' }` for one tenant, `{ tags: ['chat'] }` for\n * one kind of run, `{ workflows: ['report', 'report.branch'] }` for a workflow family. Absent = every\n * run in `statuses`. `maxCount` is then counted WITHIN the scope (\"keep acme's newest 100\").\n *\n * A scope matches runs by their own row, so a child run is only covered if it matches too (children\n * inherit their parent's `namespace`, but not its `tags`) — scope by `namespace` or by `workflows`\n * when a whole run tree must age out together.\n */\n scope?: RunScope | undefined;\n}\n\n/**\n * The run predicates a bulk operation (a scoped {@link RetentionPolicy}, `engine.purgeRuns`) is\n * confined to — the identity axes of a {@link RunQuery}: which tenant (`namespace`), which kind of\n * run (`workflow`/`tags`), which business entity (`attributes`). Status, origin and paging are left\n * out on purpose: each bulk operation owns its own status rule.\n */\nexport type RunScope = Pick<\n RunQuery,\n 'workflow' | 'workflows' | 'tag' | 'tags' | 'namespace' | 'namespaces' | 'attributes'\n>;\n\n/** True when `scope` sets at least one predicate — a bulk delete refuses an empty (match-all) scope. */\nexport function isNonEmptyRunScope(scope: RunScope | undefined): boolean {\n if (!scope) return false;\n return (\n scope.workflow !== undefined ||\n scope.workflows !== undefined ||\n scope.tag !== undefined ||\n scope.tags !== undefined ||\n scope.namespace !== undefined ||\n scope.namespaces !== undefined ||\n (scope.attributes !== undefined && scope.attributes.length > 0)\n );\n}\n\n/** Typed, queryable per-run data — exact values for `eq`/`ne`, numbers/strings for range ops. */\nexport type SearchAttributes = Record<string, string | number | boolean>;\n\n/**\n * A Standard Schema (https://standardschema.dev — implemented by zod 3.24+, valibot, arktype, …)\n * whose validated OUTPUT is search-attribute-shaped: flat `string`/`number`/`boolean` values only.\n * Declared via `@Workflow({ searchAttributes })`, this makes `ctx.upsertSearchAttributes` reject any\n * write whose merged result doesn't conform. The `Output extends SearchAttributes` bound is enforced\n * structurally at the declaration site — a schema whose inferred output has a nested object/array\n * value (e.g. `z.object({ meta: z.object({ ... }) })`) fails to satisfy this type, so it's a\n * compile-time error to declare it as a `searchAttributes` schema, not a runtime surprise.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n *\n * const orderAttrs = z.object({\n * tier: z.enum(['free', 'pro']),\n * amount: z.number(),\n * rushOrder: z.boolean().optional(),\n * });\n *\n * @Workflow({ name: 'checkout', searchAttributes: orderAttrs })\n * class CheckoutWorkflow {\n * async run(ctx: WorkflowCtx<InferSearchAttributes<typeof orderAttrs>>, input: CheckoutInput) {\n * await ctx.upsertSearchAttributes({ tier: input.tier, amount: input.total });\n * }\n * }\n * ```\n */\nexport type SearchAttributesSchema<A extends SearchAttributes = SearchAttributes> =\n StandardSchemaV1<unknown, A>;\n\n/** Infer the validated OUTPUT shape of a {@link SearchAttributesSchema} — the typed attributes a\n * workflow declares via `@Workflow({ searchAttributes })`. Feed it straight into `WorkflowCtx<A>`:\n * `WorkflowCtx<InferSearchAttributes<typeof mySchema>>`. */\nexport type InferSearchAttributes<S extends StandardSchemaV1<unknown, SearchAttributes>> =\n StandardSchemaV1.InferOutput<S>;\n\nexport type AttributeOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in';\n\n/** One value a search attribute can hold, and so one operand a predicate compares against. */\nexport type AttributeValue = string | number | boolean;\n\n/**\n * One predicate over a run's {@link SearchAttributes}; a {@link RunQuery} ANDs them all.\n *\n * The scalar ops carry a single `value`. `in` carries a SET of values matched as OR, and it needs to\n * exist as its own op because ORing inside ONE predicate is the only way to express \"tier is pro or\n * enterprise\": two `eq` predicates on the same key are ANDed like every other pair, which no run can\n * satisfy. An empty `values` matches nothing, mirroring {@link RunQuery.statuses}.\n */\nexport type AttributeFilter =\n | { key: string; op: Exclude<AttributeOp, 'in'>; value: AttributeValue; values?: never }\n | { key: string; op: 'in'; values: AttributeValue[]; value?: never };\n\n/** The single-operand members of {@link AttributeFilter} — every op except the `in` set. */\nexport type ScalarAttributeFilter = Exclude<AttributeFilter, { op: 'in' }>;\n\nexport interface RunQuery {\n workflow?: string | undefined;\n /**\n * Match any of these workflows (`workflow IN (...)`). Same shape as {@link statuses}: ORed with\n * each other, ANDed with everything else, and further narrowed by a concurrent single `workflow`.\n * Empty array = matches nothing.\n */\n workflows?: string[] | undefined;\n status?: RunStatus | undefined;\n /**\n * Match any of these statuses (a `status IN (...)` filter). ORed together, and ANDed with the other\n * predicates. Use this instead of issuing one {@link listRuns} call per status — e.g. the singleton\n * admission gate counts `running` + `suspended` in-flight runs in a single scan. If both `status` and\n * `statuses` are set, both must hold (the single `status` further narrows the set). Empty array =\n * matches nothing.\n */\n statuses?: RunStatus[] | undefined;\n /** Only runs carrying this tag (exact match against {@link WorkflowRun.tags}). */\n tag?: string | undefined;\n /**\n * Only runs carrying ANY of these tags. A run's tags are already a set, so the useful multi-value\n * question is \"in this set\", not \"has all of them\" — an operator picking `etl` and `nightly` from a\n * facet list means the union, and asking for their intersection through this field would return\n * nothing for tags that never co-occur. ANDed with a concurrent single `tag`; empty = matches nothing.\n */\n tags?: string[] | undefined;\n /**\n * Typed/range predicates over {@link WorkflowRun.searchAttributes}, ANDed together (e.g. `amount`\n * >= 200 and `tier` = 'pro'). Applied in-process after the coarse filters, so pair with\n * `workflow`/`status`/`tag` to bound the scan on large stores.\n */\n attributes?: AttributeFilter[] | undefined;\n /** Restrict to runs in this namespace (exact match), ANDed with the other predicates. */\n namespace?: string | undefined;\n /** Restrict to runs in ANY of these namespaces (`namespace IN (...)`), so a console can compare a\n * few tenants side by side. ANDed with a concurrent single `namespace`; empty = matches nothing. */\n namespaces?: string[] | undefined;\n /**\n * Restrict to runs whose workflow was declared by this package (exact match against\n * {@link WorkflowRun.origin}), ANDed with the other predicates.\n *\n * A run with NO origin (unknown — see the field) matches no `origin` VALUE at all, so a UI facet\n * built on this must keep an \"all origins\" option: filtering by any single package silently hides\n * every unattributed run, which reads to an operator as \"those runs do not exist\". `null` selects\n * exactly that absent bucket (`origin IS NULL`), so a paginated console can offer an \"unknown\"\n * facet without having to hold every run in the browser to find them.\n */\n origin?: string | null | undefined;\n /**\n * Restrict to runs from ANY of these origins. `null` is a member like any other — it selects the\n * unattributed bucket — so `['@acme/billing', null]` is \"this package's runs plus the ones nothing\n * could attribute\", which the single {@link origin} cannot express at all. ANDed with a concurrent\n * single `origin`; empty = matches nothing.\n */\n origins?: Array<string | null> | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n}\n\n/**\n * The predicates a {@link RunFacetRow} count is taken over — a {@link RunQuery} minus the axes the\n * facets THEMSELVES report (`status`/`origin`) and minus paging. Keeping them out of the type is\n * what makes the counts answerable in one query: a console narrows by tag/tenant/attribute, and the\n * one call back tells it how the matching runs split across every status and every origin at once.\n */\nexport type RunFacetQuery = Omit<RunQuery, 'status' | 'statuses' | 'origin' | 'limit' | 'offset'>;\n\n/**\n * One `(status, origin)` cell of {@link StateStore.runFacets} — a `GROUP BY` row, not a page of runs.\n * A console pivots these into its status chips and its origin chips, so both stay exact while the\n * list itself is paginated. `origin` is `null` for runs carrying none (see {@link WorkflowRun.origin});\n * that bucket is a real, countable answer here rather than the absence a value-match cannot express.\n */\nexport interface RunFacetRow {\n status: RunStatus;\n origin: string | null;\n count: number;\n}\n\n/**\n * Which axis {@link StateStore.runValueFacets} enumerates the distinct VALUES of. Every member is an\n * axis {@link RunQuery} can then filter by, which is the point: the answer to \"what can I pick here\"\n * has to be spendable as a predicate, or a console is offering choices that return nothing.\n *\n * `attributeKey` lists the search-attribute keys in use (the left-hand side of a predicate);\n * `attributeValue` lists the values recorded under ONE key (its right-hand side).\n */\nexport type RunValueAxis =\n | { field: 'workflow' | 'status' | 'origin' | 'namespace' | 'tag' | 'attributeKey' }\n | { field: 'attributeValue'; key: string };\n\n/**\n * One distinct value of a {@link RunValueAxis} and how many of the matching runs carry it — the rows\n * behind a console's value picker. `value` is `null` only where the axis itself has an absent bucket\n * (a run with no `origin`); a count is never zero, since a value with no runs produces no row.\n */\nexport interface RunValueFacetRow {\n value: string | null;\n count: number;\n}\n\n/**\n * The order {@link StateStore.runValueFacets} returns rows in, and the reason a caller can page\n * them: most runs first, ties broken alphabetically, the absent bucket (`null`) last — and tags the\n * engine mints one of per key after everything else, since they otherwise crowd out every tag a\n * human wrote (see `ENGINE_MINTED_TAG_PREFIXES`).\n *\n * Fixed, not incidental: an unordered listing cannot be paged, because page two would be taken over\n * a different arrangement of the same rows and would both repeat and skip.\n */\nexport type RunValueFacetOrder = 'engine-tags-last, count desc, value asc, null last';\n\n/**\n * How much of the store {@link StateStore.runValueFacets} may read to answer.\n *\n * `limit` bounds the ROWS RETURNED (highest count first): tag and attribute-value cardinality is\n * unbounded in principle — a run tagged `singleton:<key>` mints a new tag per key — so a picker asks\n * for the top slice rather than the whole domain, and keeps free text for everything else.\n *\n * `scan` bounds the RUNS READ, for a store that cannot group an axis in the database and has to\n * count it in memory instead. Those axes report over the newest `scan` matching runs rather than\n * over all of them — a bounded, deliberately approximate answer, where the alternative is a full\n * scan on every keystroke.\n *\n * Which axes those are is a property of the ADAPTER, not of the axis: the column axes are a `GROUP\n * BY` everywhere, and an adapter that can expand a JSON array and join its attribute side table (the\n * MikroORM one does) answers `tag` and the attribute axes exactly too, ignoring `scan` entirely.\n */\nexport interface RunValueFacetOptions {\n limit?: number | undefined;\n scan?: number | undefined;\n /**\n * How many rows to skip, for a picker that pages as it scrolls. Meaningful only because the\n * ordering is fixed (see {@link RunValueFacetRow}), so page two continues page one instead of\n * re-shuffling it.\n *\n * On an axis answered from a bounded scan rather than a `GROUP BY` (see {@link scan}), paging is\n * over that window: values outside it were never candidates on page one either.\n */\n offset?: number | undefined;\n /**\n * Narrow to values CONTAINING this text, case-insensitively — what a picker's search box sends.\n *\n * Server-side on purpose. A picker that filters an already-fetched page can only search what it\n * happened to receive, so a rare value is unfindable precisely when searching is the only way to\n * reach it: the top slice it was cut from is the reason the operator is typing.\n */\n search?: string | undefined;\n}\n\n/** The transaction handle `StateStore.transaction` hands to its work callback. */\nexport interface StoreTransaction {\n /** The store-native transaction handle (TypeORM `EntityManager`, Prisma tx client, MikroORM `EntityManager`,\n * Drizzle tx) — do your business DB writes on THIS so they commit atomically with the checkpoint. */\n readonly raw: unknown;\n /** Persist the step checkpoint inside this transaction. */\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;\n}\n\n/** Binds an external signal `token` to the suspended run/step position waiting for it. */\n/** Options for {@link WorkflowCtx.all}. */\nexport interface AllOptions {\n /** `waitAll` (default) or `failFast` — see {@link WorkflowCtx.all}. */\n mode?: 'waitAll' | 'failFast';\n /**\n * The most children running at once. Unset sends the whole fan immediately. When set, children go\n * out in waves of `floor(concurrency / 2)`, two at a time (an odd limit runs one child under it):\n * a new wave starts as soon as an earlier one settles, so one slow child does not idle the rest of\n * the window. Each settled wave costs the parent one turn.\n *\n * Part of the fan's identity: child ids carry the wave, so changing it for an in-flight run is a\n * non-deterministic change like changing `inputs`.\n */\n concurrency?: number;\n}\n\n/** One child of a fan as {@link StateStore.registerChildWaits} writes it. */\nexport interface ChildWait {\n waiter: SignalWaiter;\n checkpoint: StepCheckpoint;\n}\n\nexport interface SignalWaiter {\n token: string;\n runId: string;\n seq: number;\n /**\n * The parallel-fan group this waiter belongs to, carried from the awaiting command so the resolving\n * `signal:<token>` checkpoint (notably `signal:child:<id>` for an awaited child run) can be tagged\n * with it. A worker's `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` with the same\n * group; without threading it through the waiter, the child-await checkpoint comes out untagged and the\n * dashboard renders the fan as a sequential chain instead of one parallel group. Undefined for an\n * ordinary (non-fan) signal/child await.\n */\n parallelGroup?: string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Transport — how a remote task travels to a worker and the result returns\n// ---------------------------------------------------------------------------\n\n/**\n * A DB-less tenant worker → control plane request to start a run. Published by a worker that has\n * no direct DB access (the hosted-control-plane tenant model) onto the\n * `<effectivePrefix>-start-run` queue; the control plane consumes it and turns it into a durable\n * run (P4 of the tenants plan).\n *\n * The `tenant` identifies the namespace that owns the run (maps to the engine's `namespace`); it\n * is separate from the wire-level key prefix so a single transport can serve multiple tenants.\n */\nexport interface StartRunMessage {\n tenant: string;\n /** Registered workflow name. */\n workflow: string;\n input: unknown;\n /** Optional caller-supplied run id (idempotency key). The engine generates one if absent. */\n runId?: string | undefined;\n /** Tags to stamp on the run (merged with the workflow's static @Workflow tags). */\n tags?: string[] | undefined;\n /** Typed, queryable run data to stamp on the run (same as {@link StartOptions.searchAttributes}). */\n searchAttributes?: SearchAttributes | undefined;\n}\n\n/**\n * A tenant worker → control plane read/control request over the shared transport. Enqueued on\n * `<effectivePrefix>-run-request`; the control plane's `onRunRequest` consumer answers it, scoped to\n * `tenant`, and publishes a {@link RunReply} on `<effectivePrefix>-run-reply` correlated by `requestId`.\n */\nexport interface RunRequest {\n /** Correlation id minted by the tenant; the matching {@link RunReply} carries it back. */\n requestId: string;\n /** The requesting tenant — the operator scopes the run's namespace to this. */\n tenant: string;\n body: RunRequestKind;\n}\n\n/** The discriminated verb + args of a {@link RunRequest}. Mirrors the tenant-facing `RunGateway`. */\nexport type RunRequestKind =\n | { kind: 'getRunDetail'; runId: string }\n | { kind: 'listRuns'; query: RunQuery }\n | { kind: 'runFacets'; query: RunFacetQuery }\n | {\n kind: 'runValueFacets';\n axis: RunValueAxis;\n query: RunFacetQuery;\n opts?: RunValueFacetOptions | undefined;\n }\n // Per-group worker health — the operator answers it scoped to the requester's own groups (see\n // `RunRequestResponder`), so a tenant's Workers panel shows ITS queues, never another tenant's.\n | { kind: 'workerHealth' }\n | { kind: 'cancel'; runId: string; opts?: { compensate?: boolean } }\n | { kind: 'retry'; runId: string }\n | { kind: 'continue'; runId: string }\n | { kind: 'retryWithInput'; runId: string; input: unknown }\n | { kind: 'redispatch'; runId: string }\n // Bulk, not runId-bearing (like `listRuns`/`workerHealth`) — the operator answers it in one shot\n // and filters the result to runs the requester's tenant actually owns (see `RunRequestResponder`).\n | { kind: 'waitingFor'; runIds: string[] };\n\n/** The control plane's answer to a {@link RunRequest}, correlated by `requestId`. */\nexport interface RunReply {\n requestId: string;\n result: RunReplyResult;\n}\n\n/** Success carries the verb's payload (JSON-serialised); failure carries a re-throwable error. */\nexport type RunReplyResult =\n | { ok: true; data: unknown }\n | { ok: false; error: { message: string; code?: string } };\n\n/** A lifecycle event re-published to a single tenant's channel (`<effectivePrefix>-tenant-events-<tenant>`)\n * so a store-less tenant can live-tail ITS OWN runs. Scoped by the run's namespace at publish time. */\nexport interface TenantEvent {\n tenant: string;\n event: EngineEvent;\n}\n\n/** A unit of work dispatched to a remote worker. This is the documented wire payload. */\nexport interface RemoteTask {\n runId: string;\n seq: number;\n /** Handler name the worker registered, e.g. `payments.charge-card`. */\n name: string;\n stepId: string;\n /** Worker group expected to handle this task. */\n group: string;\n input: unknown;\n /** W3C traceparent so the worker can continue the distributed trace. */\n traceparent?: string | undefined;\n /**\n * Opaque context carrier (tenant / user / correlation ids) the worker re-exposes to the step\n * handler, for cross-process propagation alongside the {@link traceparent}. The engine treats it\n * as a pass-through object and never inspects its shape — the producer (e.g. `@dudousxd/nestjs-context`)\n * owns the keys. Absent when no `context` provider is configured.\n */\n context?: Record<string, unknown> | undefined;\n /**\n * Id of the transport this task was dispatched on (when the engine runs a pool — see\n * {@link NamedTransport}). A worker that consumes several transports replies via the matching one,\n * so failover is symmetric without the worker choosing a transport. Absent for a single transport.\n */\n transport?: string | undefined;\n /**\n * Admission priority carried through to the broker (BullMQ job `priority`) so a transport that\n * supports priority ordering lets an urgent task jump ahead of already-enqueued lower-priority\n * ones at the worker. Mirrors the per-call `priority` from `ctx.step(..., { priority })`. Higher\n * wins; absent means default/unprioritised. Transports without priority support ignore it.\n */\n priority?: number | undefined;\n attempt: number;\n}\n\nexport interface StepResult {\n runId: string;\n seq: number;\n stepId: string;\n status: 'completed' | 'failed';\n output?: unknown;\n error?: StepError | undefined;\n /** Epoch ms when the worker began processing — lets the engine report queue-wait time. */\n startedAt?: number | undefined;\n /** Structured events the worker emitted while running the step (sub-step outcomes, logs). */\n events?: StepEvent[] | undefined;\n}\n\nexport interface Heartbeat {\n runId: string;\n seq: number;\n /**\n * The in-flight step this beat keeps alive. ABSENT for a RUN-scoped (workflow-turn) heartbeat: a\n * worker replaying a long workflow turn beats for its `runId` so the engine rearms the run's\n * `advance` deadline (see `WorkflowEngineDeps.remoteAdvanceSilenceMs`). The engine then keys the\n * liveness reset by `runId` instead of `stepId`.\n */\n stepId?: string | undefined;\n group: string;\n}\n\n// ---------------------------------------------------------------------------\n// Polyglot workflows — the workflow-task / commands protocol\n//\n// A workflow authored in a non-TS SDK (e.g. Python) runs coordinator-driven: the engine stays the\n// sole owner of the durable state + recovery/timers and advances the run one TURN at a time by\n// dispatching a {@link WorkflowTask} (the run's history) to a workflow worker, which REPLAYS the\n// function locally and returns a {@link WorkflowDecision} (the commands it produced). The engine\n// applies the decision (persist checkpoints, dispatch steps, schedule timers, settle the run). The\n// worker never touches the store. See docs/plans/2026-06-15-polyglot-workflows-protocol.md.\n// ---------------------------------------------------------------------------\n\n/** engine → workflow worker: advance this run one turn by replaying the function against `history`. */\nexport interface WorkflowTask {\n /** Dedupe id for this turn (a re-delivered task must be idempotent). */\n taskId: string;\n runId: string;\n /** Registered workflow name + the version the run started on — replay must use that version. */\n workflow: string;\n workflowVersion: string;\n input: unknown;\n /** Completed durable ops so far, ordered by seq — what the worker replays its results from. */\n history: HistoryEvent[];\n /** Signals delivered to the run but not yet consumed, so `wait_signal` resolves on replay. */\n pendingSignals?: Array<{ seq: number; signal: string; payload: unknown }>;\n group: string;\n /** Id of the transport this task was dispatched on (pool failover) — see {@link NamedTransport}. */\n transport?: string;\n traceparent?: string;\n /**\n * Admission priority carried to the broker (BullMQ job `priority`) so an urgent child workflow can\n * jump ahead of already-enqueued lower-priority ones at the worker. Higher wins; absent means\n * default/unprioritised. Transports without priority support ignore it.\n */\n priority?: number | undefined;\n attempt: number;\n}\n\n/** One resolved durable op in a run's history — a superset of a completed {@link StepCheckpoint}. */\nexport interface HistoryEvent {\n seq: number;\n kind: 'step' | 'call' | 'timer' | 'signal' | 'child';\n name?: string | undefined;\n /** Resolved value: a step/call output, a child run's output, a signal payload. */\n output?: unknown;\n /** Set when the op resolved to a failure (e.g. a failed remote step the workflow may catch). */\n error?: StepError | undefined;\n}\n\n/** A decision the workflow function produced at a `seq` that was not yet in history. */\nexport type WorkflowCommand =\n /** `ctx.step(handlerOrName, input)` — dispatch a step (by typed handler reference or by name) and\n * await it. A worker's `ctx.gather_calls([...])` fan-out tags every dispatched call with the same\n * `parallelGroup` so the dashboard renders the dispatched steps as one parallel fan (parity with\n * the gathered `recordStep` / `startChild` tags). Undefined for a lone sequential `ctx.step`. */\n | {\n kind: 'call';\n seq: number;\n name: string;\n group: string;\n input: unknown;\n parallelGroup?: string;\n }\n /** `ctx.step(name, body)` — a LOCAL step the worker already ran this turn; the engine persists its\n * result so replay returns it instead of re-running (durability for side-effectful work).\n * `startedAt`/`finishedAt` (epoch ms) carry the step's real wall-clock window so the dashboard\n * shows a true duration instead of 0ms, and `events` carry the sub-process/log trail the step\n * emitted (so each handler's p-processes show under it). All optional for back-compat. */\n | {\n kind: 'recordStep';\n seq: number;\n name: string;\n output?: unknown;\n error?: StepError;\n startedAt?: number;\n finishedAt?: number;\n events?: StepEvent[];\n /** A worker's `ctx.gather([...])` tags every step in the parallel fan with the same group, so the\n * engine carries it onto the checkpoint and the dashboard renders the fan as one group. */\n parallelGroup?: string;\n }\n /** `ctx.sleep(ms)` — a durable timer of `ms` duration. The engine computes the absolute deadline\n * (now + ms) when it applies the command, so the worker never reads the clock (determinism). */\n | { kind: 'sleep'; seq: number; ms: number }\n /** `ctx.wait_signal(name)` — block until a signal `name` is delivered to the run. */\n | { kind: 'waitSignal'; seq: number; signal: string }\n /** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle. A worker's\n * `ctx.all([...])` fan-out tags every dispatched child with the same `parallelGroup` so the\n * dashboard can render the fan as one group (parity with the gathered `recordStep` tag). */\n | {\n kind: 'startChild';\n seq: number;\n workflow: string;\n input: unknown;\n parallelGroup?: string;\n };\n\n/** workflow worker → engine: the result of replaying one turn of a remote workflow. */\nexport interface WorkflowDecision {\n taskId: string;\n runId: string;\n /** `continue` = produced `commands` and is blocked on an await; otherwise the run settles.\n * `cancelled` = the worker bailed at an op boundary because the run was cancelled mid-turn. */\n status: 'continue' | 'completed' | 'failed' | 'cancelled';\n /** New durable ops the replay produced this turn (status === 'continue'), ordered by seq. */\n commands: WorkflowCommand[];\n /** Final workflow output (status === 'completed'). */\n output?: unknown;\n /** Terminal error (status === 'failed'). */\n error?: StepError;\n}\n\n/**\n * workflow worker → engine: a LOCAL step's lifecycle, streamed AS IT HAPPENS (not batched into the\n * turn's final {@link WorkflowDecision}). A Python `@workflow` runs its `ctx.step`s inline over one\n * turn that can last minutes; without this the engine learns of the steps only when the turn ends,\n * so the dashboard shows nothing mid-run. The worker emits `running` when a step's body starts and\n * `completed`/`failed` when it settles; the engine checkpoints each immediately, so a step appears\n * in-flight and then resolves live. The turn's final `recordStep` command re-persists the same\n * checkpoint idempotently (replay history), so this is purely additive observability.\n */\nexport interface WorkflowStepEvent {\n runId: string;\n seq: number;\n name: string;\n phase: 'running' | 'completed' | 'failed';\n /** Epoch ms the step body began (all phases) and settled (`completed`/`failed`). */\n startedAt: number;\n finishedAt?: number;\n /** The replayed result / failure for the settled phases. */\n output?: unknown;\n error?: StepError;\n /** Sub-process + log trail the step emitted so far (the handler's p-processes). */\n events?: StepEvent[];\n /** A worker's `ctx.gather([...])` fan tags every step's lifecycle with the same group so the\n * dashboard renders the live fan-out as one group (parity with the `recordStep` tag). */\n parallelGroup?: string | undefined;\n}\n\n/**\n * Advances a workflow run one turn. The engine has one per workflow: the default {@link InProcess}\n * one runs a registered TS function with the in-process replay machinery; a remote one dispatches a\n * {@link WorkflowTask} to a worker (Python) and awaits its {@link WorkflowDecision}. Either way the\n * engine applies the returned decision — so recovery, timers, singleton and dead-letter stay engine\n * concerns, identical for in-process and remote workflows.\n */\nexport interface WorkflowExecutor {\n /**\n * INLINE replay: advance the turn and RETURN its decision (the in-process executor runs the\n * registered TS function synchronously). The engine awaits this under the run's lease. Provide this\n * OR {@link dispatch} — exactly one. An executor with only `advance` is single-instance by nature\n * (the decision is produced in-process, not delivered over a broker).\n */\n advance?(\n run: WorkflowRun,\n history: HistoryEvent[],\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<WorkflowDecision>;\n /**\n * DISPATCH-AND-SUSPEND (broker-backed, multi-instance safe): enqueue the turn to a worker under the\n * ENGINE-SUPPLIED `taskId`, WITHOUT awaiting the decision. The engine generates `taskId`, records it\n * on the run as the awaited marker, AND releases the run's lease — all BEFORE calling this — so the\n * worker's {@link WorkflowDecision} (delivered over {@link Transport.onDecision} and applied DURABLY\n * by {@link WorkflowEngine.completeRemoteDecision}, which looks the run up by `decision.runId`) can\n * never arrive ahead of its marker or contend with a still-held lease and be dropped. This method\n * therefore ONLY enqueues — it owns no taskId generation and returns nothing. No in-memory await, so\n * the decision is never lost to a point-to-point broker handing it to a non-dispatching instance.\n * Provide this OR {@link advance} — exactly one.\n */\n dispatch?(\n run: WorkflowRun,\n history: HistoryEvent[],\n taskId: string,\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<void>;\n}\n\n/**\n * A transport in an ordered pool, identified by `id`. The engine dispatches on the first by default\n * and fails over to the next on a dispatch error; a step can pin one via `ctx.step(…, { transport })`.\n * The chosen `id` is stamped on the {@link RemoteTask} so a worker replies through the matching one.\n */\nexport interface NamedTransport {\n id: string;\n transport: Transport;\n}\n\n/**\n * Decides where a freshly-`start`ed run executes. `start` creates the run as `pending` and hands its\n * id here instead of running the body inline — so the API/caller never blocks on workflow execution.\n * The default in-process dispatcher runs it on this instance (a microtask); a broker-backed one\n * enqueues the id for a worker pool to consume (`engine.runOne(runId)`); a no-op one leaves it\n * `pending` in the store for a worker's `runPending` poll to pick up (DB-only, caller-doesn't-execute).\n */\nexport interface RunDispatcher {\n dispatch(runId: string): void | Promise<void>;\n}\n\nexport interface Transport {\n /** engine → worker */\n dispatch(task: RemoteTask): Promise<void>;\n /** worker → engine: a step finished (ok or error). */\n onResult(handler: (result: StepResult) => Promise<void>): void;\n /** worker → engine: liveness signal for an in-flight long step. */\n onHeartbeat(handler: (beat: Heartbeat) => Promise<void>): void;\n /** Release the transport's resources (broker workers, queues, connections) for a clean shutdown.\n * Optional — an in-process transport has nothing to close. Called on `onApplicationShutdown`\n * after the engine drains, so a deploy hands off instead of leaving the broker to time out. */\n close?(): Promise<void>;\n /** engine → workflow worker: dispatch a {@link WorkflowTask} (the polyglot-workflow path). Optional\n * — only transports that carry workflow tasks (BullMQ) implement it; the {@link RemoteWorkflowExecutor}\n * uses it + {@link onDecision} to advance a remote workflow over the broker. */\n dispatchWorkflowTask?(task: WorkflowTask): Promise<void>;\n /** workflow worker → engine: a replayed turn's {@link WorkflowDecision}. Pair with dispatchWorkflowTask. */\n onDecision?(handler: (decision: WorkflowDecision) => Promise<void>): void;\n /** workflow worker → engine: a LOCAL step's {@link WorkflowStepEvent}, streamed mid-turn so the\n * engine can checkpoint it live. Point-to-point (a single engine instance consumes each event and\n * persists it once — no cross-pod duplicate writes). Optional; only broker transports carry it. */\n dispatchStepEvent?(event: WorkflowStepEvent): Promise<void>;\n /** engine ← workflow worker: consume streamed {@link WorkflowStepEvent}s. Pair with dispatchStepEvent. */\n onStepEvent?(handler: (event: WorkflowStepEvent) => Promise<void>): void;\n /** Worker-health for a group: queue backlog + live worker heartbeats. Optional — only broker\n * transports (BullMQ) that can introspect the task queue and the worker-heartbeat keys implement\n * it. The engine aggregates this across its groups in {@link WorkflowEngine.workerHealth}. */\n groupHealth?(group: string): Promise<GroupHealth>;\n /** Distinct groups that currently have a live worker heartbeat — discovered from the heartbeat\n * keyspace, so a group with workers but no engine-side registration (e.g. a local-step group)\n * still surfaces. Pairs with {@link groupHealth}. */\n listWorkerGroups?(): Promise<string[]>;\n /**\n * The live handshake {@link WorkerDescriptor}s advertised for `group` (design §7.2). Optional — only\n * broker transports that carry the two-tier descriptor advertisement (BullMQ) implement it; a pure\n * in-process transport returns nothing, so the engine's routing guard stays disengaged (legacy\n * assume-compatible, design §7.7). The engine feeds these into {@link planDispatch} to decide whether\n * a run can dispatch to `group` or must park `blocked`.\n */\n readWorkerDescriptors?(group: string): Promise<WorkerDescriptor[]>;\n /**\n * Every live {@link WorkerDescriptor} in the deployment, across all groups — the read behind\n * {@link WorkflowEngine.announcedWorkflows}. Optional, same as {@link readWorkerDescriptors}: a\n * transport that cannot introspect the advertisement keyspace returns nothing and the registry is\n * simply empty.\n *\n * Deliberately NOT `listWorkerGroups()` + a read per group: a worker publishes the SAME descriptor\n * under every token it consumes, so per-group reads cost one round trip per group to re-fetch bytes\n * the caller already has. One pass over the advertisement keyspace, de-duplicated by `instanceId`,\n * answers with one scan and no per-group fan-out — and it also sees an instance whose groups the\n * caller could not have enumerated.\n */\n readAllWorkerDescriptors?(): Promise<WorkerDescriptor[]>;\n /**\n * Every live worker heartbeat in the deployment, across all groups — the LIVENESS floor under\n * {@link WorkflowEngine.workflowDirectory}. Optional, same as {@link readAllWorkerDescriptors}.\n *\n * It exists because a descriptor is the richer advertisement but not the universal one: an SDK\n * that predates the handshake beats a liveness key and publishes no descriptor at all, and reading\n * only descriptors reports such a fleet as EMPTY while it is serving work. Convention routing\n * already resolves those workers off exactly these keys, so a directory built without them\n * contradicts the dispatcher standing next to it.\n *\n * Distinct from {@link listWorkerGroups}, which answers with tokens alone: this carries the\n * instance behind each one, so the directory can say how many workers back a name and a partition\n * sighting can name who is beating there.\n */\n readAllWorkerHeartbeats?(): Promise<WorkerHeartbeat[]>;\n /**\n * DB-less tenant worker → control plane: publish a {@link StartRunMessage} requesting a new run.\n * Optional — only transports that carry the hosted-control-plane protocol (P4) implement this.\n * The message is enqueued on `<effectivePrefix>-start-run`; the control plane's\n * `onStartRun` consumer turns it into a durable run.\n */\n dispatchStartRun?(msg: StartRunMessage): Promise<void>;\n /**\n * control plane ← tenant worker: consume {@link StartRunMessage}s and start runs. Pair with\n * {@link dispatchStartRun}. Optional — only control-plane-side transports implement this.\n */\n onStartRun?(handler: (msg: StartRunMessage) => Promise<void>): void;\n /**\n * Tenant worker → control plane: publish a {@link RunRequest} (read/control) on\n * `<effectivePrefix>-run-request`. Optional — only broker transports carry it.\n */\n dispatchRunRequest?(msg: RunRequest): Promise<void>;\n /** control plane ← tenant worker: consume {@link RunRequest}s. Pair with {@link dispatchRunRequest}. */\n onRunRequest?(handler: (msg: RunRequest) => Promise<void>): void;\n /** control plane → tenant worker: publish a correlated {@link RunReply} on `<effectivePrefix>-run-reply`\n * (pub/sub; every tenant subscribes and filters by `requestId`). */\n publishRunReply?(reply: RunReply): Promise<void>;\n /** tenant worker ← control plane: consume {@link RunReply}s (filter by `requestId` client-side). */\n onRunReply?(handler: (reply: RunReply) => void): void;\n /** control plane → tenant worker: re-publish a lifecycle {@link TenantEvent} on the run's per-tenant\n * channel `<effectivePrefix>-tenant-events-<tenant>`. */\n publishTenantEvent?(evt: TenantEvent): Promise<void>;\n /** tenant worker ← control plane: subscribe to THIS tenant's event channel. Returns an unsubscribe fn. */\n onTenantEvent?(tenant: string, handler: (evt: TenantEvent) => void): () => void;\n}\n\n/** How a worker decides its concurrency, carried in {@link WorkerStatus} so a dashboard can tell a\n * fixed knob from a self-regulating one (and, for the latter, where the controller currently sits). */\nexport interface WorkerConcurrencyStatus {\n /** `fixed` = the configured `concurrency` number, never moves. `adaptive` = the controller tunes it. */\n mode: 'fixed' | 'adaptive';\n /** The concurrency ceiling in effect right now (fixed: the configured value; adaptive: the live limit). */\n limit: number;\n /** Adaptive only — the floor the controller won't go below. */\n min?: number;\n /** Adaptive only — the ceiling the controller won't exceed. */\n max?: number;\n}\n\n/** The adaptive controller's most recent limit change — the \"why did it move\" a dashboard shows so an\n * auto-tuner isn't a black box. Absent until the controller first adjusts (or for a fixed worker). */\nexport interface WorkerAdjust {\n /** Epoch ms of the adjustment. */\n at: number;\n /** Limit before this change. */\n from: number;\n /** Limit after this change. */\n to: number;\n /** Why it moved: `ram_ceiling` (hard brake), `backpressure` (errors/stall), `grow` (had headroom),\n * `shrink` (latency gradient showed queuing), `cpu_ceiling`. */\n reason: 'ram_ceiling' | 'cpu_ceiling' | 'backpressure' | 'grow' | 'shrink';\n}\n\n/** A live snapshot of a worker's execution state, carried in the worker-liveness heartbeat (so it\n * rides the existing TTL'd key — no extra round-trip) and surfaced per worker in the dashboard. Every\n * field beyond {@link concurrency}/{@link inFlight} is best-effort: a field a runtime can't measure is\n * simply omitted. The shape is shared by the TS and Python SDKs so a mixed-language group reports\n * uniformly. */\nexport interface WorkerStatus {\n /** Which SDK is running this worker — `node` (TS) or `python`. */\n runtime?: 'node' | 'python';\n /** The worker's concurrency knob and its live ceiling. */\n concurrency: WorkerConcurrencyStatus;\n /** Tasks executing right now (0..limit). With `limit`, this is the saturation a dashboard charts. */\n inFlight: number;\n /** Resident set size in bytes, if the runtime can read it. */\n rssBytes?: number;\n /** The process memory ceiling in bytes (cgroup `memory.max`, else host total), if known. */\n rssLimitBytes?: number;\n /** RSS as a percent of {@link rssLimitBytes} (0..100) — what the adaptive RAM brake watches. */\n rssPct?: number;\n /** Process CPU utilisation percent over the last control tick (0..100×cores), if measured. */\n cpuPct?: number;\n /** Completed tasks per minute over the recent window — the controller's throughput signal. */\n throughputPerMin?: number;\n /** p95 of recent task durations in ms — the latency a dashboard charts against the limit. */\n p95Ms?: number;\n /** The adaptive controller's last limit change (absent for a fixed worker or before the first move). */\n lastAdjust?: WorkerAdjust;\n}\n\n/** One worker's liveness record — a TTL'd heartbeat a worker refreshes while it's consuming. Its\n * ABSENCE (the key expired) is the signal: a worker that died or stalled stops refreshing. */\nexport interface WorkerHeartbeat {\n /** The worker group this instance serves (e.g. `pipeline`, `processing-workflows`). */\n group: string;\n /** Stable per-process id (host + pid), so N replicas of a group each show as a distinct worker. */\n instanceId: string;\n /** Epoch ms of the worker's most recent heartbeat. */\n lastBeatAt: number;\n /** The worker's live execution snapshot, when its heartbeat carries one (newer SDKs stamp a JSON\n * value; an older SDK's bare-timestamp heartbeat leaves this undefined). */\n status?: WorkerStatus;\n}\n\n/** Per-group worker-health snapshot: how much work is queued vs. how many workers are alive to do it.\n * The actionable alert state is `depth > 0 && liveWorkers.length === 0` — work piling up with no\n * consumer (exactly the failure where a worker is \"alive but not consuming\"). */\nexport interface GroupHealth {\n group: string;\n /** Outstanding jobs in the group's task queue (waiting + active + delayed + prioritized). */\n depth: number;\n /** Workers with a non-expired heartbeat for this group. */\n liveWorkers: WorkerHeartbeat[];\n /**\n * Whether this group serves a `@Workflow` body or a `@Step`/handler — route-by-handler gives each\n * its own queue, so a health list mixes both. Classified by the CONTROL PLANE from its authoritative\n * registry (`workerHealth()`): a group whose base name is a registered workflow is `'workflow'`,\n * everything else (in-process steps, remote `handle_*`) is `'step'`. `undefined` only when no\n * control-plane registry was available to classify (e.g. a transport that reports health with no\n * engine). Lets a dashboard summarise the fleet in domain terms (\"N workflows · M steps\") instead of\n * leaking the raw queue count.\n */\n kind?: 'workflow' | 'step';\n}\n\n/**\n * The **control plane** — a broadcast pub/sub across ALL engine instances (every pod), separate\n * from the {@link Transport}'s point-to-point work queues (`dispatch`/`onResult`). It carries what\n * every instance may need regardless of who runs a given run: lifecycle events (so a dashboard-only\n * pod can live-tail a run executing on a worker pod) and cancellation (so the pod actually running a\n * run learns it was cancelled elsewhere). In-process implementations broadcast locally; a\n * cross-process one (BullMQ) fans out over its broker (Redis pub/sub). Give the engine a\n * `controlPlane` to enable cross-instance events/cancellation; omit it and the engine is local-only.\n * A transport that can broadcast may implement this too and be passed as both.\n */\nexport interface ControlPlane {\n publishControl(msg: ControlMessage): Promise<void>;\n onControl(handler: (msg: ControlMessage) => void): void;\n}\n\n/** A message on the {@link ControlPlane}. `from` is the originating engine's `instanceId`, so a\n * broker that echoes a publish back to its own subscriber (e.g. Redis pub/sub) can be deduped by\n * the originator. */\nexport type ControlMessage = { from?: string } & (\n | { kind: 'event'; event: EngineEvent }\n | { kind: 'cancel'; runId: string }\n // A run was just enqueued — nudge worker instances to pick it up now instead of on the next poll.\n | { kind: 'enqueued'; runId: string }\n);\n\n// ---------------------------------------------------------------------------\n// Authoring — workflows, local steps, and typed remote steps\n// ---------------------------------------------------------------------------\n\nexport type BackoffStrategy = 'fixed' | 'exp';\n\n/**\n * Options for `ctx.child` / `ctx.startChild`. A bare string passed instead is shorthand for\n * `{ childId }`, so the existing `ctx.child(ref, input, 'my-id')` form keeps working.\n */\nexport interface ChildCallOptions {\n /** Deterministic child run id; defaults to one derived from the parent run id + call position. */\n childId?: string | undefined;\n /**\n * Pin the child to this EXACT registered version instead of the newest one — the same contract as\n * `StartOptions.version`, reached from inside a workflow body: an unregistered version fails the\n * child's start rather than quietly running a different body, and a version can only be pinned on a\n * workflow that is really registered (not on the synthesized remote/convention routes). A `ctx.child`\n * whose pinned start fails surfaces it as a failed child on the parent's waiter; a fire-and-forget\n * `ctx.startChild` buffers it until the parent joins the id.\n *\n * Replay-safe as long as you pass a CONSTANT (`{ version: '2' }`), which is the point — it names the\n * body you meant. Computing it from a live registry read at call time would make the body\n * non-deterministic, exactly like reading the clock.\n */\n version?: string | undefined;\n /**\n * Dispatch priority for a REMOTE child workflow — stamped on the child run and carried onto every\n * {@link WorkflowTask} dispatched to advance it, so an urgent child can jump ahead of enqueued\n * lower-priority ones at the worker. Higher wins; absent = unprioritised. Ignored for an in-process\n * (TS class) child, which runs in the engine and never hits a broker queue.\n */\n priority?: number | undefined;\n}\n\nexport interface StepOptions {\n /** Max attempts before the step (and run) fails. */\n retries?: number;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt). */\n backoff?: BackoffStrategy;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. */\n backoffMs?: number;\n /** Upper bound on the (exponential) backoff delay. */\n backoffMaxMs?: number;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */\n jitter?: boolean;\n /**\n * Liveness window for a dispatched step (`ctx.step`): if the worker produces no result and no\n * heartbeat within this many ms, the engine presumes it dead and fails the dispatch with a\n * `RemoteStepTimeout` (retryable — it re-dispatches per `retries`). Each heartbeat resets the\n * window. Omit to wait indefinitely.\n */\n timeoutMs?: number;\n /**\n * Capabilities a live worker MUST advertise to run this dispatched step (handshake design §7.5).\n * The control-plane routes the step only to workers whose descriptor advertises every name here;\n * if descriptors are published on the step's group but NONE is capability-capable + protocol-\n * compatible, the run parks `blocked` (never a silent hang) and the blocked-recovery poll re-drives\n * it when a capable worker appears. Absent/empty = \"runs anywhere\" (the default; backward-compatible\n * — a legacy fleet publishing no descriptors skips the guard entirely, design §7.7).\n */\n requires?: string[];\n /**\n * Saga compensation: if this step completes but the run later **fails**, the engine runs the\n * registered `compensate` callbacks in reverse order (undo what was done). Local steps only.\n * Idempotency note: a step is already deduplicated by its deterministic `stepId` (runId:seq) —\n * remote workers can use it as the idempotency key, so there's no separate key option.\n */\n compensate?: () => Promise<void>;\n}\n\n/**\n * The structural carrier a dispatched `ctx.step` call resolves to and hands the engine: `name` is\n * the routing contract (the worker registers a handler under the same name, and routing is BY that\n * name — a worker subscribes per registered handler name, not a hand-declared group). There is no\n * public factory for this anymore — a `ctx.step(ref, input)` call builds one internally from the\n * `@Step`-stamped name (see {@link StepRef}/`stepNameOf`); a `ctx.step(name, input)` call builds one\n * from the literal string. `input`/`output` are optional runtime zod schemas an authoring layer MAY\n * attach (e.g. `@Step({ input, output })`) for validation at the dispatch boundary — a bare `@Step()`\n * carries neither, and the engine skips validation when they're absent.\n */\nexport interface StepDef<TInput = unknown, TOutput = unknown> extends StepOptions {\n name: string;\n /** Optional isolation partition; routing is by `name`. Suffixes the routing token as\n * `<name>@<partition>` (via {@link tenantGroup}) — omit to route by the bare (sanitized) `name`. */\n partition?: string | undefined;\n input?: z.ZodType<TInput> | undefined;\n output?: z.ZodType<TOutput> | undefined;\n}\n\n/**\n * A durable webhook handle minted by {@link WorkflowCtx.webhook}. Hand `url` to a third party,\n * then `await wait()` — the run suspends with zero compute until the external system POSTs the\n * callback (delivered as `engine.signal(token, body)`), and resumes with the body.\n */\nexport interface DurableWebhook<TPayload = unknown> {\n /** Deterministic signal token (`wh:<runId>:<seq>`) the callback delivers on — stable across replay. */\n readonly token: string;\n /**\n * Public callback URL for `token`, built by the engine's `webhookUrl` option. Hand this to the\n * third party. `undefined` when no builder is configured (use {@link DurableWebhook.token} to\n * build your own).\n */\n readonly url?: string | undefined;\n /**\n * Suspend until the callback arrives, then resume with its payload. Waits indefinitely by default —\n * no compute consumed. Pass `{ timeoutMs }` to bound the wait: if the deadline passes first the call\n * throws a `SignalTimeoutError` (catch it in the workflow to branch) — same timeout semantics as\n * {@link WorkflowCtx.waitForSignal}. The deadline is computed once (on the first call) and persisted,\n * so a replay reuses the recorded deadline rather than recomputing it from the current clock.\n */\n wait(opts?: { timeoutMs?: number }): Promise<TPayload>;\n}\n\n/**\n * Options for a dispatched {@link WorkflowCtx.step} call. `retries`/`backoff`/`backoffMs`/\n * `backoffMaxMs`/`jitter`/`timeoutMs` are a PER-CALL override of the `@Step`-declared\n * {@link StepConfig} (see `stepConfigOf`) — the effective policy `ctx.step` builds into the dispatched\n * {@link StepDef} is `{ ...stepConfigOf(ref), ...opts }`, so a call-site value wins field-by-field. The\n * string (cross-runtime) form of `ctx.step` has no stamped `@Step` to read, so it uses these fields\n * as-is.\n */\nexport interface StepDispatchOpts {\n /** Subject the dispatch to a registered flow-control queue (concurrency / rate limit). */\n queue?: string;\n /** Admission priority within `queue`; higher is admitted first when a slot is contended\n * (default 0). No effect without a `queue`. */\n priority?: number;\n /** The fairness bucket for a queue with `fairness: 'key'` (e.g. a tenant id) — the queue\n * round-robins across distinct keys so one key can't monopolize the budget. Defaults to the run\n * id when omitted. No effect without a `queue`. */\n fairnessKey?: string;\n /** Pin the dispatch to a named transport in the pool (else the pool's first, with failover to the\n * rest). See `engine.registerQueue` / the engine's `transports` option. */\n transport?: string;\n /** Max attempts before the step (and run) fails. Overrides the `@Step`-declared value. */\n retries?: number;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt).\n * Overrides the `@Step`-declared value. */\n backoff?: BackoffStrategy;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. Overrides the\n * `@Step`-declared value. */\n backoffMs?: number;\n /** Upper bound on the (exponential) backoff delay. Overrides the `@Step`-declared value. */\n backoffMaxMs?: number;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. Overrides\n * the `@Step`-declared value. */\n jitter?: boolean;\n /** Liveness window for this dispatched step: no result/heartbeat within this many ms presumes the\n * worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per\n * `retries`). Omit to wait indefinitely. Overrides the `@Step`-declared value. */\n timeoutMs?: number;\n /** Capabilities a live worker must advertise to run this dispatch (handshake design §7.5). Overrides\n * the `@Step`-declared `requires`. Absent = inherit the def-level value (or \"runs anywhere\"). */\n requires?: string[];\n}\n\n/** What a saga undo handler receives: the compensated step's original input and its result — the\n * ONE argument a compensation `@Step` is called with, so it's self-describing on the wire (a\n * Python worker sees `{ input, output }` with no side-channel lookup needed). */\nexport interface StepUndo<TInput, TOutput> {\n input: TInput;\n output: TOutput;\n}\n\n/**\n * Derive a `ctx.step` compensation handler's expected argument from the ORIGINAL step's method\n * type, so the ref form is compile-checked against the step it undoes:\n *\n * ```ts\n * async cancelBooking(undo: UndoOf<FlightService['book']>) { ... }\n * ```\n *\n * `...rest: never[]` pins this to a single-argument method (the shape every `@Step` handler has —\n * see {@link StepRef}); `Awaited<R>` unwraps a `Promise<TOutput>` return down to `TOutput`.\n */\nexport type UndoOf<H> = H extends (input: infer I, ...rest: never[]) => infer R\n ? StepUndo<I, Awaited<R>>\n : never;\n\n/**\n * The context handed to a workflow function. Every interaction with the outside world goes\n * through it so the engine can checkpoint — the workflow body itself stays deterministic.\n *\n * Generic over `A`, the run's {@link SearchAttributes} shape — narrows {@link upsertSearchAttributes}\n * when a workflow declares a `@Workflow({ searchAttributes })` schema (pass\n * `WorkflowCtx<InferSearchAttributes<typeof mySchema>>` as the `run` method's ctx type). Defaults to\n * the untyped `SearchAttributes`, so every existing `WorkflowCtx` usage is unaffected.\n */\nexport interface WorkflowCtx<A extends SearchAttributes = SearchAttributes> {\n readonly runId: string;\n /**\n * Run a durable step — always dispatched, always engine-scheduled: the ONE step primitive (no\n * local/remote placement choice). Pass the step's method **reference** (a `@Step`-decorated\n * method, typed by its own signature — refactor-safe, autocompleted):\n *\n * ```ts\n * const r = await ctx.step(this.extraction.runExtractionPage, { page, key });\n * ```\n *\n * or its **name** for a cross-runtime handler (no JS reference to import, e.g. a Python `@step`):\n *\n * ```ts\n * const out = await ctx.step<ProcResult>('processing:proc', input);\n * ```\n *\n * Both forms dispatch identically — a step runs on whatever worker serves that name and the run\n * suspends (zero compute) until the result lands, then resumes with it (durable, replay-safe).\n *\n * `opts.compensate` registers a SAGA UNDO for this call, dispatched (durably, in reverse order\n * with every other registered undo) if the run later fails or is cancelled with\n * `{ compensate: true }`. The undo is itself a normal `@Step` — pass its reference (compile-time\n * checked: it must accept `StepUndo<TInput, TOutput>` of THIS call, see {@link UndoOf}) or its\n * name for a cross-runtime undo handler. It runs on whatever worker serves that name, called with\n * the ONE `{ input, output }` envelope — never the original handler re-invoked in-process.\n */\n step<TInput, TOutput>(\n handler: StepRef<TInput, TOutput>,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput>;\n step<TOutput = unknown, TInput = unknown>(\n name: string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput>;\n /**\n * **Exactly-once** durable step for DB work: runs `fn` and writes the step's checkpoint in ONE\n * store transaction, so the business write and the \"done\" marker commit atomically — a crash can\n * never leave the write done-but-not-checkpointed (which a plain `ctx.step` would re-run). `fn`\n * receives the store-native transaction handle (`tx` — a TypeORM/MikroORM `EntityManager`, a Prisma\n * tx client, or a Drizzle tx); do your writes on it. Needs a SQL store that supports transactions\n * (the bundled SQL adapters do); throws otherwise.\n */\n transaction<TOutput>(name: string, fn: (tx: unknown) => Promise<TOutput>): Promise<TOutput>;\n /**\n * Call a durable **entity** op and await its result — the entity (`engine.registerEntity`) runs the\n * op serialized per `key` over durable state. e.g. `await ctx.callEntity('cart', userId, 'add', item)`.\n */\n callEntity<TResult = unknown>(\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<TResult>;\n /** Send a durable entity op without awaiting a result (fire-and-forget, dispatched once). */\n signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void>;\n /**\n * Durable sleep: suspends the run for `duration` (e.g. `'30s'`, `'2h'`, `'7 days'`, or ms as a\n * number) without consuming resources, resuming automatically once the timer is due — even\n * across restarts.\n */\n sleep(duration: string | number): Promise<void>;\n /**\n * Durable sleep until an **absolute** time (a `Date` or epoch ms) — like {@link sleep} but for a\n * fixed deadline (e.g. \"resume at midnight\"). Resumes automatically once the time passes, across\n * restarts. The recorded wake time is fixed on the first run, so it's replay-stable.\n */\n sleepUntil(when: Date | number): Promise<void>;\n /**\n * End this run and **continue as a fresh execution** of the same workflow with `input` and a clean\n * history — for long-running / looping workflows that would otherwise accumulate unbounded\n * checkpoints (and slow replays). The next run gets id `<runId>~N`. Terminal: it always throws, so\n * code after it never runs. Carry forward whatever state the next iteration needs in `input`.\n */\n continueAsNew(input?: unknown): Promise<never>;\n /**\n * Suspend the run until an external `engine.signal(token, payload)` arrives (e.g. a webhook or\n * human approval), then resume with the payload. Waits indefinitely by default — no compute\n * consumed. Pass `{ timeoutMs }` to bound the wait: if the deadline passes first the call throws\n * a `SignalTimeoutError` (catch it in the workflow to branch).\n */\n waitForSignal<TPayload>(token: string, opts?: { timeoutMs?: number }): Promise<TPayload>;\n /**\n * Wait for a named **event** published via `engine.publishEvent(name, payload)`, then resume with\n * the payload. Unlike a signal (point-to-point by token), events are name-based pub/sub: pass an\n * optional `match` (a subset of the payload that must deep-equal) so a publish fans out only to the\n * runs it concerns — e.g. `ctx.waitForEvent('payment.settled', { match: { orderId } })`. `timeoutMs`\n * bounds the wait (throws `SignalTimeoutError`). No compute consumed while waiting.\n */\n waitForEvent<TPayload>(\n name: string,\n opts?: { match?: Record<string, unknown>; timeoutMs?: number },\n ): Promise<TPayload>;\n /**\n * An external task with **async completion**: run `dispatch` once (checkpointed — e.g. send to a\n * queue, kick off a non-durable worker or a foreign service like a Python process), then suspend\n * with zero compute until `engine.completeTask(runId, name, result)` (or `failTask`) reports back,\n * and resume with the result. The durable, first-class counterpart of the hand-rolled\n * \"dispatch over SQS → wait for COMPLETE_PHASE → signal\" pattern. `name` must be unique per run.\n */\n task<TResult>(\n name: string,\n dispatch: () => Promise<void>,\n options?: StepOptions,\n ): Promise<TResult>;\n /**\n * Run another registered workflow as a **tracked child** and await its result: starts it once and\n * suspends — zero compute — until the child reaches a terminal state, then resumes with the child's\n * output (or throws a FatalError if the child failed). `childId` defaults to a deterministic id\n * derived from this run and the call position, so it's stable across replay.\n *\n * Pass the child's **class** (`ctx.child(ShippingWorkflow, input)`) for a typed input + result; pass\n * a **string** name for a cross-runtime child (e.g. a Python workflow) where there's no class.\n */\n child<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n options?: string | ChildCallOptions,\n ): Promise<WorkflowOutputOf<C>>;\n child<TOutput>(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<TOutput>;\n /**\n * Start a child workflow **fire-and-forget**: dispatches it once (checkpointed, replay-safe) and\n * returns its run id immediately — the parent keeps running instead of suspending. Use it to kick\n * off side work (an audit log, a notification) you don't need to wait on, or to fan out: collect\n * the ids, then later `await ctx.child(...)` each with the same id to join (the start is idempotent\n * by id, so the child runs exactly once). Class or string ref, like {@link child}.\n */\n startChild<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n startChild(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n /**\n * Run N children of the SAME workflow **in parallel** and wait for ALL of them: dispatches one\n * child per entry in `inputs` (concurrently, each with its own durable lifecycle), suspends — zero\n * compute — until every child reaches a terminal state, then resumes with their outputs in **input\n * order**. Child ids are group-scoped and stable (`<runId>.all.<firstSeq>.<i>`), and the running\n * placeholders share a `parallelGroup` tag so the dashboard renders the fan-out as one group.\n *\n * `mode` (default `waitAll`): `waitAll` waits for all then throws an aggregate {@link GatherError}\n * if any failed; `failFast` throws as soon as a failed child is seen, and requests cancellation of\n * every sibling that hasn't completed yet (best-effort, plain cancel — no saga undo; a sibling\n * mid-step only observes it at its next checkpoint, it isn't force-killed mid-synchronous-execution,\n * so a fast sibling can still slip through and complete). Empty `inputs` returns `[]` with no side\n * effects. The wait-all / fan-out counterpart to {@link child}; parity with the Python SDK's\n * `gather_children`.\n *\n * `concurrency` caps how many children run at once (see {@link AllOptions.concurrency}).\n */\n all<C extends WorkflowClass>(\n workflow: C,\n inputs: WorkflowInputOf<C>[],\n opts?: AllOptions,\n ): Promise<WorkflowOutputOf<C>[]>;\n all<TOutput = unknown>(\n workflow: string,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<TOutput[]>;\n /**\n * Pause the run at this point until a human resumes it from the dashboard (or\n * `engine.continue(runId)`). Records a visible `pending` checkpoint so the breakpoint shows up\n * in the timeline, then suspends with zero compute — the durable equivalent of a debugger\n * breakpoint. Gate it on your own config to make breakpoints opt-in per run:\n * `if (cfg.breakAfterExtraction) await ctx.breakpoint('after-extraction')`.\n */\n breakpoint(label?: string): Promise<void>;\n /**\n * Mint a durable webhook: returns a handle with a deterministic `token` and (if the engine has a\n * `webhookUrl` builder) a public `url`. Hand the url to a third party — inside a `ctx.step` — then\n * `await handle.wait()` to suspend with zero compute until they POST the callback (the dashboard\n * turns that POST into `engine.signal(token, body)`). The first-class, replay-safe version of\n * \"expose a callback URL and wait for it\".\n */\n webhook<TPayload>(): DurableWebhook<TPayload>;\n /**\n * Publish a named, queryable value from inside the run — the latest value for `key` is readable\n * externally via `engine.getEvent(runId, key)` while the run is still in flight (progress, a\n * partial result, a status). Checkpointed and replay-safe (overwrites the previous value for the\n * same key). The read side has no effect on the run — the durable, suspend-model counterpart of a\n * Temporal query.\n */\n setEvent<TValue>(key: string, value: TValue): Promise<void>;\n /**\n * Expose a named **update point**: suspend until an external `engine.update(runId, name, arg)`\n * delivers `arg`, then resume with it. The update is run-scoped (`name` need only be unique within\n * the run) and gated by any validator registered via `engine.registerUpdateValidator` — a rejected\n * update never reaches here. Pass `{ timeoutMs }` to bound the wait (throws `SignalTimeoutError`).\n * The durable counterpart of a Temporal update handler.\n */\n onUpdate<TArg>(name: string, opts?: { timeoutMs?: number }): Promise<TArg>;\n /**\n * Guard an in-place workflow change without a new version. Wrap the changed code in\n * `if (await ctx.patched('my-change')) { …new… } else { …old… }`: a fresh run records a marker and\n * takes the new branch (`true`); a run already recorded under the old code keeps the old branch\n * (`false`), because its history has a real step where the marker would sit. The marker is\n * position-transparent for old runs (it doesn't shift their recorded steps), so guarding code is\n * replay-safe. Once every old run has drained, remove the guard (keep the new branch).\n */\n patched(id: string): Promise<boolean>;\n /**\n * Deterministic wall-clock, epoch **milliseconds** (like `Date.now()`): records the time on the\n * first run and replays the SAME value afterwards. Use this instead of `Date.now()`/`new Date()`\n * inside a workflow — a raw clock read returns a different value on every replay, which silently\n * corrupts a durable run. Returns a number so it composes in arithmetic (deadlines, elapsed);\n * for an ISO string do `new Date(await ctx.now()).toISOString()`. Every step is dispatched now\n * (see {@link step}), so a trivial timestamp capture gets this lightweight deterministic helper\n * instead of a full `@Step` + worker round-trip.\n */\n now(): Promise<number>;\n /**\n * **Deterministic capture.** Run `fn` once, checkpoint its result, and on replay return the SAME\n * value WITHOUT re-running `fn` — the durable way to bring a non-deterministic value into a workflow\n * where you control the generator: `ctx.sideEffect(() => uuidv7())`, `() => ulid()`,\n * `() => Math.random()`, a config/env read. Prefer a {@link step} for real work with side effects\n * (a DB write, an API call): `fn` here runs only once and MUST be effectively pure (it produces a\n * value; it is not re-executed on replay), like Temporal's `sideEffect`. For a plain timestamp use\n * {@link now}.\n */\n sideEffect<TValue>(fn: () => TValue | Promise<TValue>): Promise<TValue>;\n /**\n * Merge `attrs` into THIS run's {@link WorkflowRun.searchAttributes} — the indexed metadata the\n * dashboard and {@link RunQuery} filter on. Shallow merge: keys you don't pass are kept. Durable +\n * exactly-once — recorded at this position on the first run and SKIPPED on replay, so it does one\n * write, not one per turn. Use this instead of injecting the {@link StateStore} to mutate the run\n * you're executing (`@Inject(state-store)` + `store.updateRun(ctx.runId, …)` becomes\n * `ctx.upsertSearchAttributes(…)`).\n *\n * When the workflow declares a `@Workflow({ searchAttributes })` schema, the MERGED result (this\n * run's existing `searchAttributes` shallow-merged with `attrs`) is validated against it before the\n * write — an invalid merge throws, naming the workflow, the offending key(s), and the schema's\n * issues. Validation runs once, on the same first-run-only position as the write itself (skipped\n * entirely on replay, so it's never a source of nondeterminism); it must be synchronous — a schema\n * whose `validate` returns a `Promise` throws instead of being awaited. No schema declared ⇒\n * unchanged, unvalidated behavior.\n */\n upsertSearchAttributes(attrs: Partial<A>): Promise<void>;\n /**\n * Run a checkpointed step **in-process** — the escape hatch from the always-dispatched {@link step}\n * for work that must run inline in the workflow body. Like `step`, its result is a durable checkpoint\n * (returned, not re-run, on replay); unlike `step`, the body `fn` executes here rather than on a\n * worker, so it can carry an in-memory `compensate` callback for **sagas** — an undo the engine runs\n * in reverse if the run later fails (see [Sagas & compensation](/docs/reliability/sagas)). `fn`\n * receives a {@link StepLogger} for sub-process events. Prefer {@link step} for ordinary work; reach\n * for `localStep` when you need in-process execution or a compensation.\n */\n localStep<TOutput>(\n name: string,\n fn: (log: StepLogger) => Promise<TOutput>,\n options?: StepOptions,\n ): Promise<TOutput>;\n}\n\n/**\n * {@link WorkflowCtx} with ONE signature per method: the string-addressed forms of the four overloaded\n * methods (`step`, `child`, `startChild`, `all`), everything else unchanged.\n *\n * For code that drives the ctx DYNAMICALLY — an interpreter that runs a user-defined graph and only\n * ever knows workflow/step names as strings — and for test fakes. An overloaded method is awkward to\n * satisfy structurally (a fake must implement every overload, and a hand-written narrow interface\n * has to guess which overload TS will match), so depend on this instead:\n *\n * ```ts\n * type InterpreterCtx = Pick<DynamicWorkflowCtx, 'runId' | 'localStep' | 'child' | 'all' | 'sleep'>;\n * class Interpreter { constructor(private readonly ctx: InterpreterCtx) {} }\n *\n * async run(ctx: WorkflowCtx, input: Input) {\n * return new Interpreter(ctx).run(); // no cast — a WorkflowCtx IS a DynamicWorkflowCtx\n * }\n * ```\n *\n * Every `WorkflowCtx<A>` is assignable to `DynamicWorkflowCtx<A>` (guarded by\n * `dynamic-workflow-ctx.type-test.ts`), and a `Pick` of it is a plain object literal in a test.\n */\nexport interface DynamicWorkflowCtx<A extends SearchAttributes = SearchAttributes>\n extends Omit<WorkflowCtx<A>, 'step' | 'child' | 'startChild' | 'all'> {\n /** {@link WorkflowCtx.step} by step name (a cross-runtime handler, or a `@Step` by its name). */\n step<TOutput = unknown, TInput = unknown>(\n name: string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: string },\n ): Promise<TOutput>;\n /** {@link WorkflowCtx.child} by workflow name. */\n child<TOutput = unknown>(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<TOutput>;\n /** {@link WorkflowCtx.startChild} by workflow name. */\n startChild(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n /** {@link WorkflowCtx.all} by workflow name. */\n all<TOutput = unknown>(\n workflow: string,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<TOutput[]>;\n}\n\n/** Result of executing or resuming a workflow run. */\nexport interface RunResult {\n runId: string;\n status: RunStatus;\n output?: unknown;\n error?: StepError | undefined;\n}\n\n/**\n * Validates an incoming `engine.update` before it is delivered to the run. Throw (or return a\n * non-empty string) to reject — the run is left untouched. Return nothing/void to accept. May be\n * async (e.g. a business-rule check against a DB).\n */\n// A validator may return nothing (accept) or a reason string (reject); `void` is the intended\n// \"returned nothing\" case, sync or async.\nexport type UpdateValidator<TArg = unknown> =\n // biome-ignore lint/suspicious/noConfusingVoidType: `void` here means \"returned nothing\" (accept).\n (arg: TArg) => void | string | Promise<void | string>;\n\n/** Outcome of `engine.update`: rejected by the validator, or accepted and delivered. */\nexport type UpdateResult =\n | { accepted: false; reason: string }\n | { accepted: true; run: RunResult | null };\n\nexport type EngineEventType =\n | 'run.started'\n | 'run.completed'\n | 'run.failed'\n | 'run.suspended'\n | 'step.started'\n | 'step.completed'\n | 'step.failed'\n // A single step event (log line / sub-process outcome) emitted WHILE a step is still running, so\n // observers tail a long step's progress live instead of waiting for `step.completed` to deliver\n // the whole `events` array at once. Carries `event`; never persisted (live-tail only).\n | 'step.progress'\n // A run parked `blocked`: no live worker on its next-dispatch group is capability-capable +\n // protocol-compatible (handshake design §7.5/§7.6). Carries the structured `diagnostics` delta\n // (which capability/protocol gap, both descriptors) so the dashboard health panel + telescope\n // timeline render exactly WHY — never a bare boolean. The `error.code` is the machine code\n // (`capability.unavailable` / `protocol.incompatible`).\n | 'run.blocked';\n\n/**\n * A lifecycle event emitted by the engine. The observability surfaces (dashboard, OTel, the\n * Telescope integration) all subscribe to these rather than reaching into the store.\n */\nexport interface EngineEvent {\n type: EngineEventType;\n runId: string;\n workflow?: string | undefined;\n /** The run's worker-pool partition (see {@link WorkflowRun.namespace}), stamped on the `run.*`\n * lifecycle events (where the emitting call site already has the run in hand) so a tenant-event\n * re-publisher can scope without a per-event store read. Absent on `step.*` events. */\n namespace?: string | undefined;\n seq?: number | undefined;\n name?: string | undefined;\n kind?: StepKind | undefined;\n output?: unknown;\n error?: StepError | undefined;\n /** Wall-clock duration of the unit that just finished (step or run), when known. */\n durationMs?: number | undefined;\n /** For a remote step: how long it waited in the queue before a worker picked it up. */\n queueMs?: number | undefined;\n /** The live step event carried by a `step.progress` (the single log line / sub-process outcome a\n * running step just emitted). Absent on lifecycle events. */\n event?: StepEvent | undefined;\n /**\n * On a `step.started`: this dispatch is a lost-dispatch RE-DRIVE, not a first attempt — the step's\n * lease lapsed with no result and no heartbeat (the worker holding it is presumed gone), so the\n * engine re-enqueued it (see `WorkflowEngineDeps.remoteRedispatchMs`). Absent on a normal dispatch\n * and on a failure retry, so a dashboard/alert can tell \"re-driven after a lost worker\" apart from\n * \"retried after a failure\". The step's persisted event trail carries the same fact durably\n * (`step.redispatched`).\n */\n redispatched?: boolean | undefined;\n /** Capabilities the blocked dispatch required (on a `run.blocked` event). */\n requires?: string[] | undefined;\n /** The structured routing delta on a `run.blocked` event (design §7.6): which capability/protocol\n * gap fired, how many live workers were considered, and both descriptors — enough for the health\n * panel/telescope to render the reason. Absent on all other event types. */\n diagnostics?: DispatchDiagnostics | undefined;\n at: Date;\n}\n\nexport type EngineListener = (event: EngineEvent) => void;\n\n/** What a {@link StepInterceptor} is told about the local step it is wrapping. */\nexport interface StepInvocation {\n readonly runId: string;\n readonly workflow: string;\n /** The step name passed to `ctx.step(name, ...)` (also `'now'`/`'random'`/`'uuid'` internals). */\n readonly stepName: string;\n /** The step's logical position within the run. */\n readonly seq: number;\n /** 1-based attempt number — increments across `ctx.step` retries. */\n readonly attempt: number;\n}\n\n/**\n * Wraps the **real execution** of a local `ctx.step` (Template/Nest-style onion middleware). Call\n * `next()` to run the step body (or the next interceptor) and return — or transform — its result;\n * throw to fail the step. First-registered runs outermost. Interceptors fire only when a step\n * actually executes, NOT on replay (a replayed step returns its recorded output without running),\n * so they see true execution timing. Register with `engine.use`.\n */\nexport type StepInterceptor = (\n invocation: StepInvocation,\n next: () => Promise<unknown>,\n) => Promise<unknown>;\n","/**\n * Compute the worker group a tenant's run dispatches to. Mirrors the transport's\n * default-is-bare rule (unset/empty/`'default'` ⇒ bare): a\n * `tenant` of `undefined`, `''`, or `'default'` is the bare `baseGroup`, so a single-tenant\n * deployment (or the `'default'` tenant of a multi-tenant one) stays byte-identical to today.\n * Any other tenant suffixes the group as `<baseGroup>@<tenant>`, so an operator control plane\n * (namespace: undefined) can route each tenant's run to its own worker pool.\n */\nexport function tenantGroup(baseGroup: string, tenant: string | undefined): string {\n return tenant !== undefined && tenant !== '' && tenant !== 'default'\n ? `${baseGroup}@${tenant}`\n : baseGroup;\n}\n\n/**\n * Sanitize a handler/workflow name for use as a BullMQ queue token: BullMQ forbids `:` in queue\n * names (it uses the colon internally as a key separator), so every `:` is replaced with `-`. `.`\n * is legal in a BullMQ queue name and is left as-is — step/workflow names commonly use it as a\n * namespacing separator (e.g. `payments.charge-card`).\n */\nexport function sanitizeQueueToken(name: string): string {\n return name.replace(/:/g, '-');\n}\n","import type {\n HistoryEvent,\n Transport,\n WorkflowExecutor,\n WorkflowRun,\n WorkflowTask,\n} from './interfaces';\nimport { sanitizeQueueToken, tenantGroup } from './tenant-group';\n\n/**\n * A {@link WorkflowExecutor} backed by a {@link Transport}: it advances a remote workflow by\n * DISPATCHING a {@link WorkflowTask} over the broker under the ENGINE-SUPPLIED `taskId`, WITHOUT\n * awaiting the decision. Pass one to `engine.registerRemote(name, version, { group, executor })` so a\n * workflow authored in another SDK (e.g. the Python `durable-worker`) is driven over Redis/BullMQ.\n *\n * Routes by NAME, not a hand-declared group: the dispatched task's routing token is\n * `tenantGroup(sanitizeQueueToken(name), partition)` — the same formula a {@link import('./interfaces').StepDef}\n * uses — so `partition` is an optional isolation suffix, not a separate identity. Omit it to route by\n * the bare (sanitized) `name`.\n *\n * Multi-instance safe by construction: the executor holds NO in-memory state correlating a dispatched\n * turn to its decision. The engine records the `taskId` on the run as the awaited marker AND releases\n * the run's lease BEFORE calling `dispatch`, so the worker's {@link import('./interfaces').WorkflowDecision},\n * delivered over the transport's `onDecision` and applied DURABLY (by run id) on whatever engine\n * instance consumes it — even one that did not dispatch the turn — can never arrive ahead of its marker\n * or contend with a still-held lease and be dropped. A point-to-point broker can therefore hand the\n * decision to any instance without it being dropped (the bug this design fixes).\n *\n * Recovery-safe: if the engine crashes (or a decision is genuinely lost because the worker died), the\n * suspended turn's heartbeat-rearmed window (`remoteAdvanceSilenceMs`) lapses and the timer poller\n * re-dispatches a fresh task with the same history — the worker's replay is deterministic, so it\n * returns the same decision; a late decision for the old `taskId` no longer matches the run's\n * currently-awaited turn and is dropped.\n */\nexport class RemoteWorkflowExecutor implements WorkflowExecutor {\n constructor(\n private readonly transport: Transport,\n private readonly name: string,\n private readonly partition?: string | undefined,\n // Accepted for source compatibility; liveness now lives on the engine's suspended-turn window\n // (`remoteAdvanceSilenceMs`) + recovery re-drive, not an in-memory per-turn timeout.\n _opts: { timeoutMs?: number } = {},\n ) {}\n\n /**\n * Enqueue one workflow turn under the engine-supplied `taskId`. Does NOT await the decision — the\n * engine has already suspended the run on `taskId` and applies the decision durably via `onDecision`.\n */\n async dispatch(\n run: WorkflowRun,\n history: HistoryEvent[],\n taskId: string,\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<void> {\n if (!this.transport.dispatchWorkflowTask) {\n throw new Error('transport does not support workflow tasks (dispatchWorkflowTask)');\n }\n const task: WorkflowTask = {\n taskId,\n runId: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n input: run.input,\n history,\n ...(pendingSignals ? { pendingSignals } : {}),\n group: tenantGroup(sanitizeQueueToken(this.name), this.partition),\n priority: run.priority,\n attempt: 1,\n };\n await this.transport.dispatchWorkflowTask(task);\n }\n}\n","import { EVENT_TOKEN_PREFIX, eventNameOf } from './events';\nimport type { RunWaiting, SignalWaiter, StateStore, WorkflowRun } from './interfaces';\n\n// Waiter-token prefixes the engine stamps (see `workflow-ctx.ts`): a webhook mints `wh:<runId>:<seq>`,\n// an awaited child parks on `child:<id>`, a `ctx.breakpoint` mints `bp:<runId>:<seq>` (see\n// `breakpointToken` in `protocol.ts`), a named event on `event:<b64 name>:…`. A plain\n// `ctx.waitForSignal(name)` uses `name` verbatim as the token, so an unrecognised token IS the signal\n// name.\nconst WEBHOOK_PREFIX = 'wh:';\nconst CHILD_PREFIX = 'child:';\nconst BREAKPOINT_PREFIX = 'bp:';\nconst EVENT_PREFIX = EVENT_TOKEN_PREFIX;\n\n/**\n * Resolve WHAT a suspended run is parked on from the token of the {@link SignalWaiter} it registered.\n * The token prefix carries the kind — no extra store lookup and no new persisted field. Used by the\n * store-backed run gateway to stamp {@link RunWaiting} onto each listed run so the dashboard can name\n * the wait in a row without fetching that run's timeline.\n *\n * `ctx.breakpoint` reuses the signal-waiter machinery (`engine.continue` resumes it via `signal()`\n * like any other), so without this case it would fall through to the generic `signal` branch with the\n * raw `bp:<runId>:<seq>` token as its display name — a real bug. Named `'breakpoint'` here instead;\n * the token carries no separate label to recover cheaply (see {@link RunWaiting.name}).\n */\nexport function classifyWaiterToken(token: string): RunWaiting {\n if (token.startsWith(WEBHOOK_PREFIX)) return { on: 'webhook', name: token };\n if (token.startsWith(BREAKPOINT_PREFIX)) return { on: 'breakpoint', name: 'breakpoint' };\n if (token.startsWith(CHILD_PREFIX))\n return { on: 'child', name: token.slice(CHILD_PREFIX.length) };\n if (token.startsWith(EVENT_PREFIX)) return { on: 'signal', name: eventNameOf(token) };\n return { on: 'signal', name: token };\n}\n\n/**\n * Resolve a suspended run's {@link RunWaiting} from the pending signal waiters (indexed by `runId`).\n * Event-only by design (see {@link RunWaiting}): a `waitForSignal`/`waitForEvent`/webhook/awaited-child\n * suspend registers a waiter and gets named here; every other suspend (a bare `ctx.sleep`, an in-flight\n * remote step, a reconcile-parked orphan) returns `undefined`, so the client layers its own display\n * state (no-worker, singleton, running) on top — none of which can be told apart from `wakeAt` alone.\n */\nexport function resolveRunWaiting(\n run: WorkflowRun,\n waiterByRun: ReadonlyMap<string, SignalWaiter>,\n): RunWaiting | undefined {\n if (run.status !== 'suspended') return undefined;\n const waiter = waiterByRun.get(run.id);\n return waiter ? classifyWaiterToken(waiter.token) : undefined;\n}\n\nconst RUN_ID_BATCH = 500;\n\n/**\n * The signal waiters of `runIds`: through the store's {@link StateStore.listSignalWaitersByRun} in\n * bounded batches, or, for a store without it, one scan of every waiter filtered to those runs.\n */\nexport async function listSignalWaitersOfRuns(\n store: StateStore,\n runIds: readonly string[],\n): Promise<SignalWaiter[]> {\n const unique = [...new Set(runIds)];\n if (unique.length === 0) return [];\n if (!store.listSignalWaitersByRun) {\n const ids = new Set(unique);\n return (await store.listSignalWaiters('')).filter((w) => ids.has(w.runId));\n }\n const out: SignalWaiter[] = [];\n for (let at = 0; at < unique.length; at += RUN_ID_BATCH) {\n out.push(...(await store.listSignalWaitersByRun(unique.slice(at, at + RUN_ID_BATCH))));\n }\n return out;\n}\n\n/** Index signal waiters by `runId`, keeping the first seen per run (a run parks on one waiter at a\n * time in the sequential case; the earliest is the one it's blocked on). */\nexport function indexWaitersByRun(waiters: readonly SignalWaiter[]): Map<string, SignalWaiter> {\n const byRun = new Map<string, SignalWaiter>();\n for (const w of waiters) if (!byRun.has(w.runId)) byRun.set(w.runId, w);\n return byRun;\n}\n","import { createRequire } from 'node:module';\nimport { resolveCronParse } from './cron-compat';\nimport type { WorkflowEngine } from './engine';\n\n// Resolve the optional `cron-parser` peer dependency in a way that works in BOTH the ESM and CJS\n// builds of this package (dual publish). `createRequire(import.meta.url)` gives a real `require` in\n// ESM output; in the CJS build, tsup's banner shims `import.meta.url` to the file URL, so the same\n// call resolves there too. This keeps the load synchronous (no async leak into the scheduler API).\nconst nodeRequire = createRequire(import.meta.url);\n\nexport interface ScheduledWorkflow {\n /** Stable key identifying this schedule — part of the deterministic run id. */\n key: string;\n workflow: string;\n input?: unknown;\n /** Start one run every `everyMs`. Mutually exclusive with `cron`. */\n everyMs?: number;\n /**\n * A cron expression (5 fields `m h dom mon dow`, or 6 with leading seconds) evaluated in\n * {@link ScheduledWorkflow.timezone}. Mutually exclusive with `everyMs`. Needs the optional peer\n * dependency `cron-parser`.\n */\n cron?: string;\n /** IANA timezone the `cron` fires in (e.g. `America/Sao_Paulo`). Defaults to UTC. */\n timezone?: string;\n /** Temporarily stop firing this schedule (kept registered). Defaults to false. */\n paused?: boolean;\n /**\n * What to do when the previous window's run hasn't finished yet (fixed-interval schedules only):\n * `'allow'` (default) starts the new window anyway; `'skip'` skips it while the prior run is still\n * `running`/`suspended`, so a slow run can't pile up overlapping executions.\n */\n overlap?: 'allow' | 'skip';\n /**\n * Randomly delay the dispatch by up to this many ms BEFORE firing, to spread load when many\n * instances tick on the same boundary (avoids a thundering herd). Opt-in; absent = fire immediately.\n *\n * This is dispatch-path jitter only — it does NOT affect the run id (still the time bucket), so\n * idempotency is unchanged: two instances jittering the same window still start it exactly once.\n * (The engine forbids `Math.random` inside workflow code; the scheduler dispatch path is not\n * workflow code, so jitter here is fine.)\n */\n jitter?: number;\n /**\n * Enqueue windows that were missed while the scheduler was down, instead of silently skipping\n * them. Opt-in; absent = only the current window fires. `maxCatchup` bounds how many PRIOR windows\n * are backfilled (a long outage can't flood the system). Backfilled runs use each missed window's\n * deterministic bucket run id, so `engine.start` idempotency skips any that already ran.\n */\n backfill?: { maxCatchup: number };\n}\n\n/** Injectable dispatch-path effects (kept out of the deterministic run-id logic). Defaults to real\n * `Math.random` + `setTimeout`; overridden in tests so jitter is deterministic and instant. */\nexport interface RunSchedulesOptions {\n random?: () => number;\n sleep?: (ms: number) => Promise<void>;\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));\n\n/** Deterministic run id for a fixed-interval schedule's current time window. */\nexport function scheduledRunId(key: string, everyMs: number, nowMs: number): string {\n return `sched:${key}:${Math.floor(nowMs / everyMs)}`;\n}\n\nlet cronParser: unknown;\nfunction loadCronParser(): unknown {\n if (cronParser !== undefined) return cronParser;\n try {\n // Lazy + optional: core stays dependency-free; only users who schedule by cron need this.\n cronParser = nodeRequire('cron-parser');\n } catch {\n throw new Error(\n 'cron schedules need the optional peer dependency \"cron-parser\" — install it (e.g. `npm i cron-parser`).',\n );\n }\n return cronParser;\n}\n\n/**\n * Epoch ms of the most recent cron fire at or before `nowMs`, evaluated in `timezone` (default UTC).\n * This is the deterministic \"bucket\" a cron run is keyed on, so polling repeatedly within an\n * interval resolves to the same fire time — and thus the same idempotent run id.\n */\nexport function prevCronFireMs(expr: string, nowMs: number, timezone = 'UTC'): number {\n const parse = resolveCronParse(loadCronParser());\n if (!parse) {\n throw new Error(\n 'the installed \"cron-parser\" exposes neither v4\\'s parseExpression nor v5\\'s CronExpressionParser.parse — the supported range is ^4.0.0 || ^5.0.0.',\n );\n }\n // `+1` makes a fire landing exactly on `nowMs` count as \"at or before now\", not the prior one.\n return parse(expr, { currentDate: new Date(nowMs + 1), tz: timezone })\n .prev()\n .toDate()\n .getTime();\n}\n\n/**\n * Epoch ms of the first cron fire STRICTLY after `afterMs`, evaluated in `timezone` (default UTC) —\n * the forward counterpart of {@link prevCronFireMs}, used by persisted schedules to compute when a\n * schedule is next due.\n */\nexport function nextCronFireMs(expr: string, afterMs: number, timezone = 'UTC'): number {\n const parse = resolveCronParse(loadCronParser());\n if (!parse) {\n throw new Error(\n 'the installed \"cron-parser\" exposes neither v4\\'s parseExpression nor v5\\'s CronExpressionParser.parse — the supported range is ^4.0.0 || ^5.0.0.',\n );\n }\n return parse(expr, { currentDate: new Date(afterMs), tz: timezone })\n .next()\n .toDate()\n .getTime();\n}\n\n/** The deterministic, idempotent run id for a schedule at `nowMs` — its current fire window. */\nfunction scheduleRunIdAt(s: ScheduledWorkflow, nowMs: number): string {\n if (s.cron != null) return `sched:${s.key}:${prevCronFireMs(s.cron, nowMs, s.timezone)}`;\n if (s.everyMs != null) return scheduledRunId(s.key, s.everyMs, nowMs);\n throw new Error(`schedule \"${s.key}\" needs either \"everyMs\" or \"cron\"`);\n}\n\n/**\n * The run ids this schedule should fire at `nowMs`: the current window, plus — when `backfill` is set\n * — up to `maxCatchup` prior windows that may have been missed. Oldest-first, so a backfill catches\n * up in chronological order. Ids are the same deterministic buckets `scheduleRunIdAt` produces, so\n * `engine.start` idempotency drops any window that already ran.\n */\nfunction scheduleRunIdsAt(s: ScheduledWorkflow, nowMs: number): string[] {\n const current = scheduleRunIdAt(s, nowMs);\n if (!s.backfill || s.backfill.maxCatchup <= 0) return [current];\n\n const ids: string[] = [];\n if (s.everyMs != null) {\n const bucket = Math.floor(nowMs / s.everyMs);\n const oldest = Math.max(0, bucket - s.backfill.maxCatchup);\n for (let b = oldest; b < bucket; b += 1) ids.push(`sched:${s.key}:${b}`);\n } else if (s.cron != null) {\n // Walk back through prior cron fire times (most-recent missed first), then reverse to oldest-first.\n const prior: string[] = [];\n let cursor = prevCronFireMs(s.cron, nowMs, s.timezone);\n for (let i = 0; i < s.backfill.maxCatchup; i += 1) {\n // `cursor` (exclusive) → the fire strictly before it.\n const before = prevCronFireMs(s.cron, cursor - 1, s.timezone);\n prior.push(`sched:${s.key}:${before}`);\n cursor = before;\n }\n ids.push(...prior.reverse());\n }\n ids.push(current);\n return ids;\n}\n\n/**\n * Start each schedule's current-window run. The run id is the time bucket (a fixed-interval index,\n * or the cron fire time) and `engine.start` is idempotent, so firing this on an interval — or\n * racing two instances on the same tick — starts **each window exactly once**. Wire it to a\n * `setInterval`, the durable timer poller, or `@nestjs/schedule`. Returns the run ids for the\n * current windows.\n */\nexport async function runSchedules(\n engine: Pick<WorkflowEngine, 'start' | 'getRun'>,\n schedules: readonly ScheduledWorkflow[],\n nowMs: number,\n opts?: RunSchedulesOptions,\n): Promise<string[]> {\n const random = opts?.random ?? Math.random;\n const sleep = opts?.sleep ?? defaultSleep;\n const ids: string[] = [];\n for (const s of schedules) {\n if (s.paused) continue;\n // overlap:'skip' (fixed-interval): don't start this window while the previous window's run is\n // still in-flight, so a slow run can't pile up. Interval-only — cron windows aren't adjacent ids.\n if (s.overlap === 'skip' && s.everyMs) {\n const prevBucket = Math.floor(nowMs / s.everyMs) - 1;\n if (prevBucket >= 0) {\n const prev = await engine.getRun(`sched:${s.key}:${prevBucket}`);\n if (prev && (prev.status === 'running' || prev.status === 'suspended')) continue;\n }\n }\n // Dispatch-path jitter (not workflow code): spread same-boundary ticks across instances. Applied\n // once per schedule, before firing — the run ids below are unaffected, so idempotency holds.\n if (s.jitter && s.jitter > 0) await sleep(Math.floor(random() * s.jitter));\n for (const runId of scheduleRunIdsAt(s, nowMs)) {\n await engine.start(s.workflow, s.input, runId);\n ids.push(runId);\n }\n }\n return ids;\n}\n","/**\n * Reading a cron expression across both cron-parser majors.\n *\n * The peer range is `^4.0.0 || ^5.0.0` and the two majors do not share an entry\n * point: v4 exports `parseExpression`, v5 replaced it with\n * `CronExpressionParser.parse`. Typing the module as\n * `typeof import('cron-parser')` pins it to whichever major is dev-installed and\n * makes the other one a compile error — which is how the scheduler shipped\n * calling only v4 while advertising both, so every v5 install failed at runtime\n * with \"parser.parseExpression is not a function\": a message that reads as a\n * missing dependency rather than as the wrong major.\n *\n * Deliberately NOT re-exported from `index.ts`. This is interop plumbing, not\n * public API; the spec imports it from this path directly.\n */\n\nexport interface CronOptions {\n currentDate: Date;\n tz: string;\n}\n\nexport interface CronFire {\n prev(): { toDate(): Date };\n next(): { toDate(): Date };\n}\n\nexport type ParseCron = (expr: string, options: CronOptions) => CronFire;\n\n/**\n * Anything `Reflect.get` can read a member off.\n *\n * Admits functions as well as objects, because cron-parser v4's CommonJS export\n * *is* a function carrying `parseExpression` as a property — an object-only\n * guard rejects the very major this range exists to support.\n */\nfunction isIndexable(value: unknown): value is object {\n return (typeof value === 'object' && value !== null) || typeof value === 'function';\n}\n\n/** ESM/CJS interop: a `require` can hand back the namespace with the module under `default`. */\nexport function unwrapDefault(module_: unknown): unknown {\n if (!isIndexable(module_)) return module_;\n if (Reflect.get(module_, 'parseExpression') !== undefined) return module_;\n if (Reflect.get(module_, 'CronExpressionParser') !== undefined) return module_;\n const inner = Reflect.get(module_, 'default');\n return inner === undefined ? module_ : inner;\n}\n\n/** v4: `parseExpression(expr, options)`. */\nexport function v4Entry(module_: unknown): ParseCron | undefined {\n if (!isIndexable(module_)) return undefined;\n const parse = Reflect.get(module_, 'parseExpression');\n if (typeof parse !== 'function') return undefined;\n return (expr, options) => parse.call(module_, expr, options);\n}\n\n/** v5: `CronExpressionParser.parse(expr, options)`. */\nexport function v5Entry(module_: unknown): ParseCron | undefined {\n if (!isIndexable(module_)) return undefined;\n const parser = Reflect.get(module_, 'CronExpressionParser');\n if (!isIndexable(parser)) return undefined;\n const parse = Reflect.get(parser, 'parse');\n if (typeof parse !== 'function') return undefined;\n return (expr, options) => parse.call(parser, expr, options);\n}\n\n/**\n * The parse entry point of whichever major is installed.\n *\n * v4 is tried first only because it is the cheaper check; a module cannot\n * present both entry points, so the order carries no meaning beyond that.\n */\nexport function resolveCronParse(module_: unknown): ParseCron | undefined {\n const resolved = unwrapDefault(module_);\n return v4Entry(resolved) ?? v5Entry(resolved);\n}\n","import type { ConcurrencyQuota } from './concurrency';\nimport { parseDuration } from './duration';\nimport type { StartOptions } from './engine';\nimport type {\n RunResult,\n RunStatus,\n ScheduleQuery,\n ScheduleRecord,\n SearchAttributes,\n StateStore,\n WorkflowRun,\n} from './interfaces';\nimport { TERMINAL_RUN_STATUSES } from './interfaces';\nimport { nextCronFireMs, prevCronFireMs } from './scheduler';\nimport { type WorkflowRef, workflowName } from './workflow-ref';\n\n/**\n * A schedule definition — what `engine.schedules.create/upsert` take. Temporal-style: a persisted,\n * runtime-managed recurring start of `workflow` with `input`, fired by every driving engine's timer\n * poll (safe with many workers: each window's run id is deterministic, `start` is idempotent, and\n * advancing the schedule is a compare-and-set).\n */\nexport interface ScheduleOptions {\n /** Stable id, unique per store (e.g. `digest:user-42`). Part of every run id it starts. */\n id: string;\n /** The workflow to start — a registered name or `@Workflow` class. */\n workflow: WorkflowRef;\n /** The input every run starts with. */\n input?: unknown;\n /** Cron expression (5 fields, or 6 with leading seconds). Needs the `cron-parser` peer. */\n cron?: string | undefined;\n /** Fixed interval (`'15m'`, or ms), windows aligned to the epoch. Exclusive with `cron`. */\n every?: string | number | undefined;\n /** IANA timezone the cron is evaluated in (e.g. `America/Sao_Paulo`). Default UTC. */\n timezone?: string | undefined;\n /**\n * Delay each fire by up to this much (`'30s'` or ms) — a stable per-(schedule, window) offset, so\n * thousands of schedules on the same cron don't all start in the same second.\n */\n jitter?: string | number | undefined;\n /**\n * The previous run of this schedule is still in flight when the next window comes due:\n * `'allow'` (default) starts the new one anyway; `'skip'` skips that window.\n */\n overlap?: 'allow' | 'skip' | undefined;\n /**\n * Windows missed while nothing polled (all schedulers down): `'latest'` (default) fires the most\n * recent missed window once; `'skip'` drops them and waits for the next window. Never more than one\n * catch-up run per schedule.\n */\n catchup?: 'latest' | 'skip' | undefined;\n /** Create paused (never due until `resume`). On `upsert`, omit to keep the current paused state. */\n paused?: boolean | undefined;\n /** Free-form note shown with the schedule (why it exists / why it's paused). */\n note?: string | undefined;\n /** Namespace of the schedule and of the runs it starts. Defaults to the engine's own namespace. */\n namespace?: string | undefined;\n /** Labels to find the schedule by — also stamped on every run it starts (plus `schedule:<id>`). */\n tags?: string[] | undefined;\n /** Search attributes stamped on every run it starts. */\n searchAttributes?: SearchAttributes | undefined;\n /** Dispatch priority for the runs it starts. */\n priority?: number | undefined;\n /**\n * A start-time concurrency quota applied to every run it starts (see `StartOptions.concurrency`):\n * a window whose start would exceed it is recorded as the schedule's `lastError` and skipped, and\n * the schedule moves on to its next window.\n */\n concurrency?: ConcurrencyQuota | undefined;\n}\n\n/** A schedule as `engine.schedules.get/list` describe it. */\nexport interface ScheduleDescription {\n id: string;\n workflow: string;\n input: unknown;\n namespace: string;\n cron?: string | undefined;\n everyMs?: number | undefined;\n timezone?: string | undefined;\n jitterMs?: number | undefined;\n overlap: 'allow' | 'skip';\n catchup: 'latest' | 'skip';\n paused: boolean;\n note?: string | undefined;\n tags?: string[] | undefined;\n searchAttributes?: SearchAttributes | undefined;\n priority?: number | undefined;\n concurrency?: ConcurrencyQuota | undefined;\n /** When it is next due (jitter included), or null if it never fires again / paused. */\n nextFireAt: Date | null;\n /** The last window it fired for, and the run that window started. */\n lastFireAt?: Date | undefined;\n lastRunId?: string | undefined;\n /** How many windows it has fired (manual triggers excluded). */\n fires: number;\n /** The last start failure (e.g. a concurrency limit), cleared by the next successful start. */\n lastError?: string | undefined;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Filter for `engine.schedules.list`. */\nexport type ScheduleListQuery = Omit<ScheduleQuery, 'dueBy'>;\n\n/** Thrown by `engine.schedules.create` when the id is taken (use `upsert` to replace). */\nexport class ScheduleAlreadyExistsError extends Error {\n constructor(readonly scheduleId: string) {\n super(`schedule \"${scheduleId}\" already exists`);\n this.name = 'ScheduleAlreadyExistsError';\n }\n}\n\n/** Thrown by `engine.schedules.*` on an id that doesn't exist. */\nexport class ScheduleNotFoundError extends Error {\n constructor(readonly scheduleId: string) {\n super(`schedule \"${scheduleId}\" not found`);\n this.name = 'ScheduleNotFoundError';\n }\n}\n\n/** The persisted definition (`ScheduleRecord.spec`). Versioned so the shape can evolve. */\ninterface SpecDoc {\n v: 1;\n input?: unknown;\n cron?: string;\n everyMs?: number;\n timezone?: string;\n jitterMs?: number;\n overlap: 'allow' | 'skip';\n catchup: 'latest' | 'skip';\n note?: string;\n searchAttributes?: SearchAttributes;\n priority?: number;\n concurrency?: ConcurrencyQuota;\n}\n\n/** The persisted bookkeeping (`ScheduleRecord.state`). */\ninterface StateDoc {\n /** The nominal window `nextFireAt` belongs to (nextFireAt = window + jitter). */\n window?: number | null | undefined;\n lastFireAt?: number | undefined;\n lastRunId?: string | undefined;\n fires?: number | undefined;\n lastError?: string | undefined;\n}\n\n/** The engine surface the schedule client drives. */\nexport interface ScheduleHost {\n start(workflow: string, input: unknown, runId: string, opts?: StartOptions): Promise<RunResult>;\n getRun(runId: string): Promise<WorkflowRun | null>;\n}\n\n/** Engine-level knobs for the client. */\nexport interface ScheduleClientOptions {\n /** The engine's namespace: the default for new schedules, and which ones `tick` fires. */\n namespace?: string | undefined;\n clock?: (() => number) | undefined;\n}\n\nconst DEFAULT_NAMESPACE = 'default';\n/** How late a window may fire under `catchup: 'skip'` and still count as on time (plus jitter). */\nconst ON_TIME_GRACE_MS = 60_000;\nconst TICK_BATCH = 100;\n\n/**\n * Persisted, runtime-managed schedules — `engine.schedules`. Unlike the code-registered\n * `schedules` module option, these live in the store: create/update/pause/delete them at runtime\n * (one per user, per tenant, per automation…), and every driving engine's timer poll fires the due\n * ones via {@link tick}.\n *\n * Multi-worker safety comes from two properties, not from a lock: a window's run id is deterministic\n * (`sched:<id>:<windowMs>`), so racing starts of the same window collapse into one run; and a\n * schedule is advanced with a compare-and-set on its `nextFireAt`, so exactly one poller moves it on.\n * A crash between starting the run and advancing the schedule just re-fires the (idempotent) start.\n */\nexport class ScheduleClient {\n constructor(\n private readonly store: StateStore,\n private readonly host: ScheduleHost,\n private readonly options: ScheduleClientOptions = {},\n ) {}\n\n private now(): number {\n return (this.options.clock ?? Date.now)();\n }\n\n /** Whether the store persists schedules (implements the schedule methods). */\n get supported(): boolean {\n const s = this.store;\n return !!(\n s.saveSchedule &&\n s.getSchedule &&\n s.updateSchedule &&\n s.deleteSchedule &&\n s.listSchedules\n );\n }\n\n private requireStore(): Required<\n Pick<\n StateStore,\n 'saveSchedule' | 'getSchedule' | 'updateSchedule' | 'deleteSchedule' | 'listSchedules'\n >\n > {\n if (!this.supported) {\n throw new Error(\n 'persisted schedules need a store that implements saveSchedule/getSchedule/updateSchedule/deleteSchedule/listSchedules — every bundled store adapter does; this one does not',\n );\n }\n const s = this.store;\n return {\n saveSchedule: (r) => (s.saveSchedule as NonNullable<StateStore['saveSchedule']>).call(s, r),\n getSchedule: (id) => (s.getSchedule as NonNullable<StateStore['getSchedule']>).call(s, id),\n updateSchedule: (id, patch, expected) =>\n (s.updateSchedule as NonNullable<StateStore['updateSchedule']>).call(\n s,\n id,\n patch,\n expected,\n ),\n deleteSchedule: (id) =>\n (s.deleteSchedule as NonNullable<StateStore['deleteSchedule']>).call(s, id),\n listSchedules: (q) =>\n (s.listSchedules as NonNullable<StateStore['listSchedules']>).call(s, q),\n };\n }\n\n /** Create a schedule. Throws {@link ScheduleAlreadyExistsError} if the id is taken. */\n async create(opts: ScheduleOptions): Promise<ScheduleDescription> {\n const store = this.requireStore();\n if (await store.getSchedule(opts.id)) throw new ScheduleAlreadyExistsError(opts.id);\n return this.write(opts, null);\n }\n\n /**\n * Create the schedule, or replace the definition of an existing one (its history — last fire, last\n * run, fire count — is kept). The next fire is recomputed from now under the new definition, so a\n * window that already fired is never fired again by an upsert.\n */\n async upsert(opts: ScheduleOptions): Promise<ScheduleDescription> {\n const store = this.requireStore();\n return this.write(opts, await store.getSchedule(opts.id));\n }\n\n /** The schedule `id`, or null. */\n async get(id: string): Promise<ScheduleDescription | null> {\n const record = await this.requireStore().getSchedule(id);\n return record ? describe(record) : null;\n }\n\n /** Schedules matching `query`, soonest-due first. */\n async list(query: ScheduleListQuery = {}): Promise<ScheduleDescription[]> {\n return (await this.requireStore().listSchedules(query)).map(describe);\n }\n\n /** Delete the schedule. Runs it already started are left alone. Returns whether it existed. */\n delete(id: string): Promise<boolean> {\n return this.requireStore().deleteSchedule(id);\n }\n\n /** Stop firing until {@link resume}. `note` records why (shown by `get`/`list`). */\n async pause(id: string, note?: string): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const record = await this.mustGet(id);\n const spec = { ...(record.spec as unknown as SpecDoc) };\n if (note !== undefined) spec.note = note;\n await store.updateSchedule(id, {\n paused: true,\n spec: spec as unknown as Record<string, unknown>,\n updatedAt: new Date(this.now()),\n });\n return describe(await this.mustGet(id));\n }\n\n /**\n * Fire again from the next window after now — the windows skipped while paused are NOT caught up.\n */\n async resume(id: string): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const record = await this.mustGet(id);\n const spec = record.spec as unknown as SpecDoc;\n const window = nextWindowAfter(spec, this.now());\n await store.updateSchedule(id, {\n paused: false,\n nextFireAt: window === null ? null : window + jitterFor(record.id, window, spec),\n state: { ...record.state, window } as Record<string, unknown>,\n updatedAt: new Date(this.now()),\n });\n return describe(await this.mustGet(id));\n }\n\n /**\n * Start one run of the schedule right now, outside its cadence (paused or not). The run id is\n * `sched:<id>:manual:<nowMs>`; it doesn't move the schedule's next fire.\n */\n async trigger(id: string): Promise<RunResult> {\n const record = await this.mustGet(id);\n const runId = `sched:${id}:manual:${this.now()}`;\n return this.host.start(record.workflow, specOf(record).input, runId, startOptions(record));\n }\n\n /**\n * Fire every due schedule (in this engine's namespace; all namespaces for an operator engine):\n * start its window's run and advance it to the next window. Called by the NestJS timer poller on\n * each tick when `persistedSchedules` is on; call it yourself from any other driver. Returns the\n * run ids started (or re-found, for an idempotent re-fire).\n */\n async tick(nowMs: number = this.now()): Promise<string[]> {\n const store = this.requireStore();\n const started: string[] = [];\n for (let round = 0; round < 50; round++) {\n const due = await store.listSchedules({\n dueBy: nowMs,\n namespace: this.options.namespace,\n limit: TICK_BATCH,\n });\n for (const record of due) {\n const runId = await this.fire(record, nowMs);\n if (runId) started.push(runId);\n }\n if (due.length < TICK_BATCH) break;\n }\n return started;\n }\n\n /** Fire one due schedule and advance it. Returns the run id started, if any. */\n private async fire(record: ScheduleRecord, nowMs: number): Promise<string | undefined> {\n const store = this.requireStore();\n const spec = specOf(record);\n const state = record.state as StateDoc;\n let latest: number;\n let next: number | null;\n try {\n // The most recent window at or before now — the one (and only one) a late poll fires.\n latest = latestWindowAtOrBefore(spec, nowMs);\n next = nextWindowAfter(spec, latest);\n } catch (error) {\n // A definition that no longer evaluates (bad cron/timezone): stop it, loudly, instead of\n // failing on every tick forever.\n await store.updateSchedule(\n record.id,\n {\n paused: true,\n nextFireAt: null,\n state: { ...state, lastError: `invalid schedule: ${errorMessage(error)}` },\n updatedAt: new Date(nowMs),\n },\n record.nextFireAt,\n );\n return undefined;\n }\n const window = state.window ?? latest;\n const jitter = spec.jitterMs ?? 0;\n const onTime = nowMs - latest <= ON_TIME_GRACE_MS + jitter;\n let runId: string | undefined;\n let lastError: string | undefined;\n let fired = false;\n const skipMissed = spec.catchup === 'skip' && !onTime;\n const beforeWindow = latest < window; // clock skew: not actually due yet\n if (!skipMissed && !beforeWindow && !(await this.overlapping(spec, state))) {\n runId = `sched:${record.id}:${latest}`;\n try {\n await this.host.start(record.workflow, spec.input, runId, startOptions(record));\n fired = true;\n } catch (error) {\n // A racing poller may have created the same (deterministic) run first: that's a success.\n if (await this.host.getRun(runId)) fired = true;\n else lastError = errorMessage(error);\n }\n }\n const nextState: StateDoc = {\n ...state,\n window: next,\n ...(fired ? { lastFireAt: latest, lastRunId: runId, fires: (state.fires ?? 0) + 1 } : {}),\n lastError: fired ? undefined : (lastError ?? state.lastError),\n };\n await store.updateSchedule(\n record.id,\n {\n nextFireAt: next === null ? null : next + jitterFor(record.id, next, spec),\n state: stripUndefined(nextState) as Record<string, unknown>,\n updatedAt: new Date(nowMs),\n },\n record.nextFireAt,\n );\n return fired ? runId : undefined;\n }\n\n /** `overlap: 'skip'` and the previous run of this schedule is still in flight. */\n private async overlapping(spec: SpecDoc, state: StateDoc): Promise<boolean> {\n if (spec.overlap !== 'skip' || !state.lastRunId) return false;\n const prev = await this.host.getRun(state.lastRunId);\n return !!prev && !TERMINAL_RUN_STATUSES.includes(prev.status as RunStatus);\n }\n\n private async mustGet(id: string): Promise<ScheduleRecord> {\n const record = await this.requireStore().getSchedule(id);\n if (!record) throw new ScheduleNotFoundError(id);\n return record;\n }\n\n private async write(\n opts: ScheduleOptions,\n existing: ScheduleRecord | null,\n ): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const spec = toSpec(opts);\n const now = this.now();\n // An upsert that doesn't say otherwise keeps a paused schedule paused.\n const paused = opts.paused ?? existing?.paused ?? false;\n const window = nextWindowAfter(spec, now); // also validates the cron/timezone up front\n const record: ScheduleRecord = {\n id: opts.id,\n namespace: opts.namespace ?? this.options.namespace ?? DEFAULT_NAMESPACE,\n workflow: workflowName(opts.workflow),\n paused,\n nextFireAt: window === null ? null : window + jitterFor(opts.id, window, spec),\n tags: opts.tags,\n spec: spec as unknown as Record<string, unknown>,\n state: stripUndefined({\n ...((existing?.state as StateDoc | undefined) ?? {}),\n window,\n }) as Record<string, unknown>,\n createdAt: existing?.createdAt ?? new Date(now),\n updatedAt: new Date(now),\n };\n await store.saveSchedule(record);\n return describe(record);\n }\n}\n\nfunction toSpec(opts: ScheduleOptions): SpecDoc {\n if ((opts.cron == null) === (opts.every == null)) {\n throw new Error(`schedule \"${opts.id}\" needs exactly one of \"cron\" or \"every\"`);\n }\n const everyMs = opts.every != null ? parseDuration(opts.every) : undefined;\n if (everyMs !== undefined && !(everyMs > 0)) {\n throw new Error(`schedule \"${opts.id}\": \"every\" must be a positive duration`);\n }\n const jitterMs = opts.jitter != null ? parseDuration(opts.jitter) : undefined;\n return stripUndefined({\n v: 1 as const,\n input: opts.input,\n cron: opts.cron,\n everyMs,\n timezone: opts.timezone,\n jitterMs: jitterMs && jitterMs > 0 ? jitterMs : undefined,\n overlap: opts.overlap ?? 'allow',\n catchup: opts.catchup ?? 'latest',\n note: opts.note,\n searchAttributes: opts.searchAttributes,\n priority: opts.priority,\n concurrency: opts.concurrency,\n }) as SpecDoc;\n}\n\nfunction specOf(record: ScheduleRecord): SpecDoc {\n return record.spec as unknown as SpecDoc;\n}\n\n/** The latest window at or before `atMs`. */\nfunction latestWindowAtOrBefore(spec: SpecDoc, atMs: number): number {\n if (spec.cron != null) return prevCronFireMs(spec.cron, atMs, spec.timezone);\n const every = spec.everyMs as number;\n return Math.floor(atMs / every) * every;\n}\n\n/** The first window strictly after `afterMs`. */\nfunction nextWindowAfter(spec: SpecDoc, afterMs: number): number | null {\n if (spec.cron != null) return nextCronFireMs(spec.cron, afterMs, spec.timezone);\n const every = spec.everyMs as number;\n return (Math.floor(afterMs / every) + 1) * every;\n}\n\n/** A stable offset in `[0, jitterMs)` per (schedule, window): FNV-1a over the pair. */\nfunction jitterFor(id: string, window: number, spec: SpecDoc): number {\n const max = spec.jitterMs ?? 0;\n if (max <= 0) return 0;\n let h = 0x811c9dc5;\n for (const ch of `${id}@${window}`) {\n h ^= ch.charCodeAt(0);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h % max;\n}\n\nfunction startOptions(record: ScheduleRecord): StartOptions {\n const spec = specOf(record);\n return stripUndefined({\n tags: [...(record.tags ?? []), `schedule:${record.id}`],\n namespace: record.namespace,\n searchAttributes: spec.searchAttributes,\n priority: spec.priority,\n concurrency: spec.concurrency,\n }) as StartOptions;\n}\n\nfunction describe(record: ScheduleRecord): ScheduleDescription {\n const spec = specOf(record);\n const state = record.state as StateDoc;\n return stripUndefined({\n id: record.id,\n workflow: record.workflow,\n input: spec.input,\n namespace: record.namespace,\n cron: spec.cron,\n everyMs: spec.everyMs,\n timezone: spec.timezone,\n jitterMs: spec.jitterMs,\n overlap: spec.overlap ?? 'allow',\n catchup: spec.catchup ?? 'latest',\n paused: record.paused,\n note: spec.note,\n tags: record.tags,\n searchAttributes: spec.searchAttributes,\n priority: spec.priority,\n concurrency: spec.concurrency,\n nextFireAt: record.paused || record.nextFireAt == null ? null : new Date(record.nextFireAt),\n lastFireAt: state.lastFireAt != null ? new Date(state.lastFireAt) : undefined,\n lastRunId: state.lastRunId,\n fires: state.fires ?? 0,\n lastError: state.lastError,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }) as ScheduleDescription;\n}\n\nfunction stripUndefined<T extends object>(o: T): T {\n return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as T;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { type RunStatus, TERMINAL_RUN_STATUSES, type WorkflowRun } from './interfaces';\n\n/** Reserved engine metadata: a durable singleton slot, independent of the execution lease. */\nexport const SINGLETON_ADMITTED_TAG = 'durable:singleton:admitted';\nexport const SINGLETON_ACTIVE_STATUSES: RunStatus[] = [\n 'pending',\n 'running',\n 'suspended',\n 'blocked',\n 'cancelling',\n];\n\n/** Call only inside a store's atomic admission transaction/critical section. */\nexport function singletonAdmissionTags(\n runs: WorkflowRun[],\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n): string[] | null {\n if (!Number.isInteger(limit) || limit < 1)\n throw new Error('singleton limit must be a positive integer');\n const active = runs.filter(\n (run) =>\n run.workflow === workflow &&\n SINGLETON_ACTIVE_STATUSES.includes(run.status) &&\n run.tags?.includes(tag),\n );\n const candidate = active.find((run) => run.id === runId);\n if (!candidate) return null;\n if (candidate.tags?.includes(SINGLETON_ADMITTED_TAG)) return candidate.tags;\n if (candidate.status === 'cancelling') return null;\n const holders = active.filter((run) => run.tags?.includes(SINGLETON_ADMITTED_TAG));\n const remaining = limit - holders.length;\n if (remaining <= 0) return null;\n const waiters = active\n .filter((run) => !run.tags?.includes(SINGLETON_ADMITTED_TAG))\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));\n if (!waiters.slice(0, remaining).some((run) => run.id === runId)) return null;\n return [...(candidate.tags ?? []), SINGLETON_ADMITTED_TAG];\n}\n\n/** Terminal runs release admission, including when later resumed directly rather than requeued. */\nexport async function clearTerminalSingletonAdmission(\n runId: string,\n patch: Partial<WorkflowRun>,\n getRun: (id: string) => Promise<WorkflowRun | null>,\n): Promise<Partial<WorkflowRun>> {\n if (!patch.status || !TERMINAL_RUN_STATUSES.includes(patch.status)) return patch;\n const tags = 'tags' in patch ? patch.tags : (await getRun(runId))?.tags;\n return { ...patch, tags: tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG) };\n}\n\n/** Persist denial while admission locks are held; a cancelling/terminal run must never revive. */\nexport function singletonAdmissionDenialPatch(\n runs: WorkflowRun[],\n runId: string,\n tag: string,\n workflow: string,\n retryWakeAt?: number,\n): { status: 'suspended'; wakeAt: number; updatedAt: Date } | undefined {\n if (retryWakeAt === undefined) return undefined;\n const candidate = runs.find(\n (run) =>\n run.id === runId &&\n run.workflow === workflow &&\n run.tags?.includes(tag) &&\n SINGLETON_ACTIVE_STATUSES.includes(run.status),\n );\n if (!candidate || candidate.status === 'cancelling') return undefined;\n return { status: 'suspended', wakeAt: retryWakeAt, updatedAt: new Date() };\n}\n","import type { SingletonConfig } from './engine';\nimport { SingletonQueueFullError } from './errors';\nimport type { StateStore, WorkflowRun } from './interfaces';\nimport { SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG } from './singleton-admission';\n\nconst SINGLETON_RETRY_MS = 1000;\n/**\n * Max jitter (ms, each direction) added to {@link SINGLETON_RETRY_MS} so a queue of N gated runs\n * doesn't wake in lockstep and stampede the admission scan. Each retry picks an independent offset\n * in `[-SINGLETON_RETRY_JITTER_MS, +SINGLETON_RETRY_JITTER_MS]`.\n */\nconst SINGLETON_RETRY_JITTER_MS = 250;\n\nexport interface SingletonGateDeps {\n store: Pick<StateStore, 'listRuns' | 'updateRun' | 'tryAdmitSingleton'>;\n clock: () => number;\n /** Hand a gated run to the run dispatcher (fire-and-forget, like the engine's other dispatches). */\n dispatch: (runId: string) => void;\n /** Resolve a settled run's singleton config from the engine's workflow registry. */\n configFor: (run: WorkflowRun) => SingletonConfig | undefined;\n}\n\n/**\n * Per-key serialization for singleton workflows — start-time back-pressure, durable atomic\n * admission, and notify-on-release wakeups. Extracted from {@link WorkflowEngine} so the whole\n * singleton feature lives in one place instead of being smeared across `start`, `execute`, both run\n * loops, and `cancel`.\n */\nexport class SingletonGate {\n constructor(private readonly deps: SingletonGateDeps) {}\n\n /** The tag a singleton run carries, so the gate can find others sharing its key. */\n tag(cfg: SingletonConfig, input: unknown): string {\n if (!this.deps.store.tryAdmitSingleton) {\n throw new Error(\n 'Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission',\n );\n }\n return `singleton:${cfg.key(input)}`;\n }\n\n /** Next wake time for a gated run: the base retry delay jittered to avoid a wakeup stampede. */\n retryWakeAt(): number {\n return (\n this.deps.clock() +\n SINGLETON_RETRY_MS +\n Math.floor((Math.random() * 2 - 1) * SINGLETON_RETRY_JITTER_MS)\n );\n }\n\n /**\n * Reject a start that would grow the same-key backlog past `limit + maxQueueDepth` (counting\n * `pending`/`running`/`suspended`/`blocked`/`cancelling` runs sharing the key in one scan). No-op when no `maxQueueDepth`\n * is configured.\n */\n async assertCapacity(workflow: string, cfg: SingletonConfig, input: unknown): Promise<void> {\n if (cfg.maxQueueDepth == null) return;\n const cap = (cfg.limit ?? 1) + cfg.maxQueueDepth;\n const queued = await this.deps.store.listRuns({\n tag: this.tag(cfg, input),\n workflow,\n statuses: SINGLETON_ACTIVE_STATUSES,\n });\n if (queued.length >= cap) {\n throw new SingletonQueueFullError(workflow, cfg.key(input), cfg.maxQueueDepth);\n }\n }\n\n /** Preserve durable holders and atomically claim one of the remaining slots. */\n async admit(run: WorkflowRun, cfg: SingletonConfig): Promise<boolean> {\n if (!this.deps.store.tryAdmitSingleton) {\n throw new Error(\n 'Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission',\n );\n }\n const admitted = await this.deps.store.tryAdmitSingleton(\n run.id,\n this.tag(cfg, run.input),\n run.workflow,\n cfg.limit ?? 1,\n this.retryWakeAt(),\n );\n if (admitted && !run.tags?.includes(SINGLETON_ADMITTED_TAG)) {\n run.tags = [...(run.tags ?? []), SINGLETON_ADMITTED_TAG];\n }\n return admitted;\n }\n\n /**\n * Notify-on-release: a singleton run settled (freeing a slot), so dispatch the oldest gated\n * (`suspended` + same tag) waiters now instead of waiting for their ~1s retry timer. Each re-checks\n * admission in the executor and runs only if it actually wins a slot, so FIFO/race-free guarantees\n * hold; the durable timer remains the cross-instance/crash fallback.\n */\n async wakeNext(settled: WorkflowRun): Promise<void> {\n const cfg = this.deps.configFor(settled);\n if (!cfg) return;\n const tag = settled.tags?.find((t) => t.startsWith('singleton:'));\n if (!tag) return;\n const gated = (\n await this.deps.store.listRuns({ tag, workflow: settled.workflow, statuses: ['suspended'] })\n ).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));\n for (const next of gated.slice(0, cfg.limit ?? 1)) {\n // Stamp a due-NOW wakeAt as the run is handed over. `dispatch` goes through the configured\n // `runDispatcher`, which may legitimately be a NO-OP (an API/dashboard pod that must not run\n // workflows still settles runs it observes, so it still lands here), which makes the durable\n // timer the only guaranteed pickup: a `suspended` run carrying no `wakeAt` is invisible to\n // every poll path — `listPendingRuns`, `listIncompleteRuns` and `listDueTimers` alike — and\n // never resumes. A dispatch + timer double-drive is safe: the run lock admits one executor and\n // the loser's pickup is a cheap no-op.\n await this.deps.store\n .updateRun(next.id, { wakeAt: this.deps.clock(), updatedAt: new Date() })\n .catch(() => undefined);\n this.deps.dispatch(next.id);\n }\n }\n}\n","import type { WorkerDescriptor } from './handshake/descriptor';\nimport type {\n GroupHealth,\n Heartbeat,\n NamedTransport,\n RemoteTask,\n StartRunMessage,\n StepResult,\n Transport,\n WorkerHeartbeat,\n WorkflowDecision,\n WorkflowStepEvent,\n} from './interfaces';\n\n/**\n * An ordered pool of named transports. The engine dispatches on the first and fails over to the\n * next on a dispatch error; a step can pin one by id. Pure transport plumbing — no run lifecycle —\n * so it lives apart from the engine.\n */\nexport class TransportPool {\n constructor(private readonly transports: NamedTransport[]) {}\n\n get size(): number {\n return this.transports.length;\n }\n\n /**\n * The primary (first) transport — the one `dispatch` prefers when no `preferId` is pinned. A\n * {@link RemoteWorkflowExecutor} built by `engine.remote()` rides it (it needs a single\n * `dispatchWorkflowTask`/`onDecision` Transport, not the whole failover pool). Throws if the pool\n * is empty — there is nothing to dispatch a remote workflow over.\n */\n get primary(): Transport {\n const first = this.transports[0];\n if (!first) {\n throw new Error(\n 'no transport configured — engine.remote() needs a transport (or transports)',\n );\n }\n return first.transport;\n }\n\n /** Register the engine's result/heartbeat/step-event handlers on EVERY transport — a result can come\n * back on whichever one delivered the task, so failover stays symmetric. `onStepEvent` is wired only\n * on transports that carry streamed workflow step lifecycle (BullMQ); others simply skip it. */\n bind(\n onResult: (result: StepResult) => Promise<void>,\n onHeartbeat: (beat: Heartbeat) => Promise<void>,\n onStepEvent?: (event: WorkflowStepEvent) => Promise<void>,\n onDecision?: (decision: WorkflowDecision) => Promise<void>,\n ): void {\n for (const { transport } of this.transports) {\n transport.onResult(onResult);\n transport.onHeartbeat(onHeartbeat);\n if (onStepEvent && transport.onStepEvent) {\n transport.onStepEvent(onStepEvent);\n }\n // A workflow-turn decision can come back on whichever transport carried the task — and on\n // whichever ENGINE INSTANCE consumes it (point-to-point), which may NOT be the dispatcher. The\n // engine applies it durably by run id, so binding it here (like onResult) is multi-instance safe.\n if (onDecision && transport.onDecision) {\n transport.onDecision(onDecision);\n }\n }\n }\n\n /**\n * Dispatch `task` over the pool: try the preferred (or first) transport, fail over to the next on\n * a dispatch error, and stamp the task with the id of the transport that accepted it (so a worker\n * replies on the matching one). Throws if every transport fails.\n */\n async dispatch(task: Omit<RemoteTask, 'transport'>, preferId?: string): Promise<void> {\n let lastErr: unknown;\n for (const { id, transport } of this.ordered(preferId)) {\n try {\n await transport.dispatch({ ...task, transport: id });\n return;\n } catch (err) {\n lastErr = err;\n }\n }\n throw lastErr ?? new Error('no transport accepted the dispatch');\n }\n\n /** Worker-health for `group`, merged across every transport that can report it (a group's queue\n * and its workers may live on any pinned transport). Undefined when no transport implements\n * `groupHealth` (e.g. a pure in-process transport — nothing to introspect). */\n async groupHealth(group: string): Promise<GroupHealth | undefined> {\n const reports: GroupHealth[] = [];\n for (const { transport } of this.transports) {\n if (transport.groupHealth) reports.push(await transport.groupHealth(group));\n }\n if (reports.length === 0) return undefined;\n return {\n group,\n depth: reports.reduce((sum, r) => sum + r.depth, 0),\n liveWorkers: reports.flatMap((r) => r.liveWorkers),\n };\n }\n\n /**\n * Register a control-plane `start-run` consumer on every transport that carries the channel. Only\n * control-plane-side transports implement {@link Transport.onStartRun}; a transport without it is\n * skipped, so a plain worker/in-process pool is a no-op. Mirrors {@link bind}'s per-transport wiring.\n */\n onStartRun(handler: (msg: StartRunMessage) => Promise<void>): void {\n for (const { transport } of this.transports) {\n transport.onStartRun?.(handler);\n }\n }\n\n /**\n * The live handshake descriptors advertised for `group` (design §7.2), merged across every transport\n * that can report them. Returns `[]` when NO transport implements\n * {@link Transport.readWorkerDescriptors} (a pure in-process pool) OR when descriptors are supported\n * but none is published — both are the \"guard disengaged / legacy assume-compatible\" case, so the\n * engine's routing guard treats an empty result identically (design §7.7).\n */\n async readWorkerDescriptors(group: string): Promise<WorkerDescriptor[]> {\n const descriptors: WorkerDescriptor[] = [];\n for (const { transport } of this.transports) {\n if (transport.readWorkerDescriptors) {\n descriptors.push(...(await transport.readWorkerDescriptors(group)));\n }\n }\n return descriptors;\n }\n\n /**\n * Every live descriptor in the deployment, merged across every transport that can report them and\n * de-duplicated by `instanceId` — one worker publishes the same descriptor under each token it\n * consumes, and it must count once. Returns `[]` when no transport implements\n * {@link Transport.readAllWorkerDescriptors} (a pure in-process pool advertises nothing).\n *\n * First writer wins on a duplicate id: the copies are the same bytes by construction (one process,\n * one descriptor, published N times), so there is nothing to choose between. Two DIFFERENT\n * processes sharing an `instanceId` would collapse into one here — that is a misconfiguration the\n * fleet already suffers from (they also share heartbeat and descriptor keys, so they overwrite each\n * other's advertisement), not something this read can repair.\n */\n async readAllWorkerDescriptors(): Promise<WorkerDescriptor[]> {\n const byInstance = new Map<string, WorkerDescriptor>();\n for (const { transport } of this.transports) {\n if (!transport.readAllWorkerDescriptors) continue;\n for (const descriptor of await transport.readAllWorkerDescriptors()) {\n if (!byInstance.has(descriptor.instanceId))\n byInstance.set(descriptor.instanceId, descriptor);\n }\n }\n return [...byInstance.values()];\n }\n\n /**\n * Every live worker heartbeat in the deployment, merged across every transport that can report\n * them and de-duplicated by `(group, instanceId)` — the same worker is one beat per token, and two\n * transports scanning the same keyspace must not double-count it.\n *\n * Returns `[]` when no transport implements {@link Transport.readAllWorkerHeartbeats}, which is\n * indistinguishable from \"nothing is beating\" on its own — {@link introspectsFleet} is what tells\n * those apart, and the directory reads it rather than guessing from an empty array.\n */\n async readAllWorkerHeartbeats(): Promise<WorkerHeartbeat[]> {\n const seen = new Map<string, WorkerHeartbeat>();\n for (const { transport } of this.transports) {\n if (!transport.readAllWorkerHeartbeats) continue;\n for (const beat of await transport.readAllWorkerHeartbeats()) {\n const key = `${beat.group}\u0000${beat.instanceId}`;\n if (!seen.has(key)) seen.set(key, beat);\n }\n }\n return [...seen.values()];\n }\n\n /**\n * Can ANY transport here introspect the fleet — descriptors or heartbeats? This is the difference\n * between \"the fleet is empty\" and \"nobody asked\", and it is a property of the POOL rather than of\n * a read's result, so it stays answerable when both reads legitimately come back empty.\n */\n get introspectsFleet(): boolean {\n return this.transports.some(\n ({ transport }) => transport.readAllWorkerDescriptors || transport.readAllWorkerHeartbeats,\n );\n }\n\n /** Distinct worker groups with a live heartbeat, merged across every transport that can report it. */\n async listWorkerGroups(): Promise<string[]> {\n const groups = new Set<string>();\n for (const { transport } of this.transports) {\n if (transport.listWorkerGroups) {\n for (const g of await transport.listWorkerGroups()) groups.add(g);\n }\n }\n return [...groups];\n }\n\n /**\n * The first transport (in pool order) reporting a LIVE heartbeat for `group` — the one a\n * convention-routed remote workflow must dispatch on. In a mixed pool (e.g. a tenant-scoped\n * control plane pairing its namespaced transport with a bare-prefix one for operator-convention\n * tenant workers), each transport sees a DIFFERENT keyspace: dispatching on `primary` while the\n * live worker heartbeats on another transport parks the task on a queue nobody consumes. Returns\n * `undefined` when no transport reports the group (mirrors the merged `listWorkerGroups` miss).\n */\n async transportWithLiveGroup(group: string): Promise<Transport | undefined> {\n for (const { transport } of this.transports) {\n if (!transport.listWorkerGroups) continue;\n if ((await transport.listWorkerGroups()).includes(group)) return transport;\n }\n return undefined;\n }\n\n /** Pinned `preferId` first, then the rest (failover order). */\n private ordered(preferId?: string): NamedTransport[] {\n if (!preferId) return this.transports;\n const pref = this.transports.filter((t) => t.id === preferId);\n if (pref.length === 0) throw new Error(`transport \"${preferId}\" is not registered`);\n return [...pref, ...this.transports.filter((t) => t.id !== preferId)];\n }\n}\n","/**\n * Cross-package step-name stamp. The `@Step` decorator (`@dudousxd/nestjs-durable`) writes a\n * method's derived routing name under this key; core's `ctx.step` reads it (via {@link stepNameOf})\n * to route a method-reference call to the same handler a worker registers by name.\n *\n * `Symbol.for` (the GLOBAL registry), NOT a plain `Symbol()` — so a duplicate copy of this module\n * (pnpm peer-dependency multiplexing, or a dual ESM/CJS load) still reads the SAME key. A plain\n * `Symbol()` would mint a distinct token per copy, so a decorator running against one core instance\n * could stamp a name core's `ctx.step` (a different instance) can never read back. Mirrors the\n * `STATE_STORE` token fix in `./tokens.ts`.\n */\nexport const DURABLE_STEP_NAME = Symbol.for('durable.step.name');\n\n/**\n * Cross-package step-DISPATCH-POLICY stamp. `@Step({ retries, backoff, backoffMs, backoffMaxMs,\n * jitter, timeoutMs })` (`@dudousxd/nestjs-durable`) writes the def-level durable-retry/liveness\n * policy under this key; core's `ctx.step` reads it (via {@link stepConfigOf}) and merges it with any\n * per-call {@link StepDispatchOpts} override to build the dispatched {@link StepDef}. Same\n * `Symbol.for` rationale as {@link DURABLE_STEP_NAME} — a duplicate copy of this module (pnpm\n * peer-dependency multiplexing, dual ESM/CJS) must still read back the SAME key.\n */\nexport const DURABLE_STEP_CONFIG = Symbol.for('durable.step.config');\n\n/**\n * The def-level durable-dispatch policy a `@Step(...)` can stamp on a method: retry/backoff and the\n * remote-liveness `timeoutMs` — the dispatch-relevant subset of the engine's `StepOptions`. Read off\n * a handler reference via {@link stepConfigOf}; a per-call {@link StepDispatchOpts} passed to\n * `ctx.step(ref, input, opts)` overrides these field-by-field.\n */\nexport interface StepConfig {\n /** Max attempts before the step (and run) fails. */\n retries?: number | undefined;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt). */\n backoff?: 'fixed' | 'exp' | undefined;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. */\n backoffMs?: number | undefined;\n /** Upper bound on the (exponential) backoff delay. */\n backoffMaxMs?: number | undefined;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */\n jitter?: boolean | undefined;\n /** Liveness window for the dispatched step: no result/heartbeat within this many ms presumes the\n * worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per\n * `retries`). Omit to wait indefinitely. */\n timeoutMs?: number | undefined;\n /** Capabilities a live worker must advertise to run this step (handshake design §7.5). The\n * control-plane routes the step only to capable+compatible workers; if descriptors are published\n * on its group but none qualifies, the run parks `blocked`. Absent/empty = \"runs anywhere\". */\n requires?: string[] | undefined;\n}\n\nfunction isStepConfig(value: unknown): value is StepConfig {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * A method carrying its `@Step`-stamped routing name (and, optionally, its dispatch policy).\n * `ctx.step(ref, input)` reads the name via {@link stepNameOf} — the reference itself is never\n * invoked directly by the caller's process (the worker serving that name re-resolves the real\n * handler from DI), so an unbound `this` on `ref` is irrelevant; `ref` is purely a typed,\n * refactor-safe handle onto the stamped name (and policy).\n */\nexport type StepRef<TInput = unknown, TOutput = unknown> = ((\n input: TInput,\n) => Promise<TOutput> | TOutput) & {\n [DURABLE_STEP_NAME]?: string | undefined;\n [DURABLE_STEP_CONFIG]?: StepConfig | undefined;\n};\n\n/** Read the `@Step`-stamped routing name off a function ref. `undefined` for anything unstamped\n * (including a plain string — {@link stepNameOf} only reads function refs; a caller passing a\n * string already has the routing name and dispatches it directly). */\nexport function stepNameOf(ref: unknown): string | undefined {\n if (typeof ref !== 'function') return undefined;\n const stamped = (ref as { [DURABLE_STEP_NAME]?: unknown })[DURABLE_STEP_NAME];\n return typeof stamped === 'string' ? stamped : undefined;\n}\n\n/** Read the `@Step`-stamped dispatch policy off a function ref. `undefined` for anything unstamped\n * (including a plain string — a cross-runtime string-name call has no def-level policy to read; pass\n * it via {@link StepDispatchOpts} instead). */\nexport function stepConfigOf(ref: unknown): StepConfig | undefined {\n if (typeof ref !== 'function') return undefined;\n const stamped = (ref as { [DURABLE_STEP_CONFIG]?: unknown })[DURABLE_STEP_CONFIG];\n return isStepConfig(stamped) ? stamped : undefined;\n}\n","import { currentStepScope, runInStepScope } from './ambient-ctx';\nimport { runInStepLogger } from './ambient-step';\nimport { backoffDelay } from './backoff';\nimport { instantCheckpoint } from './checkpoints';\nimport { unwrapCompletion } from './completion';\nimport { parseDuration } from './duration';\nimport {\n ContinueAsNew,\n FatalError,\n GatherError,\n NestedWorkflowCallError,\n NonDeterminismError,\n SignalTimeoutError,\n WorkflowSuspended,\n} from './errors';\nimport { EVENT_BUFFER_SCAN_LIMIT, eventMatches, eventToken } from './events';\nimport {\n FOLDED_PREFIX,\n type FoldedChildren,\n allChildId,\n allFoldedName,\n allGroup,\n allWait,\n allWaves,\n fanJoin,\n} from './fan-join';\nimport type {\n AllOptions,\n ChildCallOptions,\n ChildWait,\n DurableWebhook,\n SearchAttributes,\n SearchAttributesSchema,\n StateStore,\n StepCheckpoint,\n StepDef,\n StepDispatchOpts,\n StepError,\n StepEvent,\n StepInvocation,\n StepKind,\n StepLogger,\n StepOptions,\n StepUndo,\n WorkflowCtx,\n} from './interfaces';\nimport { breakpointToken } from './protocol';\nimport { createStepLogger } from './step-logger';\nimport { type StepConfig, type StepRef, stepConfigOf, stepNameOf } from './step-name-symbol';\nimport { type WorkflowRef, workflowName } from './workflow-ref';\n\n/** Normalize the `ctx.child`/`ctx.startChild` 3rd arg: a bare string is shorthand for `{ childId }`. */\n/** How many children of a fan are registered per store round trip. */\nconst FAN_CHUNK = 500;\n/** The smallest fan whose settled waves are folded; a smaller one keeps per-child detail for the dashboard. */\nconst FOLD_MIN_FAN = 100;\n\nfunction normalizeChildOptions(options?: string | ChildCallOptions): ChildCallOptions {\n return typeof options === 'string' ? { childId: options } : (options ?? {});\n}\n\n/** Render a Standard Schema issue `path` (a mix of raw keys and `{ key }` segments) as a dotted\n * string, for a `searchAttributes` validation error — `['amount']` → `'amount'`, `[]`/`undefined` →\n * `'(root)'` (the merged object itself failed, not one of its keys). */\nfunction formatIssuePath(\n path: ReadonlyArray<PropertyKey | { readonly key: PropertyKey }> | undefined,\n): string {\n if (!path || path.length === 0) return '(root)';\n return path\n .map((segment) => String(typeof segment === 'object' ? segment.key : segment))\n .join('.');\n}\n\n/**\n * Merge a `@Step`-declared {@link StepConfig} with a per-call {@link StepDispatchOpts} override into\n * the dispatch-relevant `StepOptions` subset of a {@link StepDef} (`retries`/`backoff`/`backoffMs`/\n * `backoffMaxMs`/`jitter`/`timeoutMs`), `opts` winning field-by-field. Omits every field neither side\n * set — required under `exactOptionalPropertyTypes` (an explicit `undefined` value is a type error).\n */\nfunction resolveStepPolicy(\n config: StepConfig | undefined,\n opts: StepDispatchOpts | undefined,\n): StepOptions {\n const policy: StepOptions = {};\n const retries = opts?.retries ?? config?.retries;\n if (retries !== undefined) policy.retries = retries;\n const backoff = opts?.backoff ?? config?.backoff;\n if (backoff !== undefined) policy.backoff = backoff;\n const backoffMs = opts?.backoffMs ?? config?.backoffMs;\n if (backoffMs !== undefined) policy.backoffMs = backoffMs;\n const backoffMaxMs = opts?.backoffMaxMs ?? config?.backoffMaxMs;\n if (backoffMaxMs !== undefined) policy.backoffMaxMs = backoffMaxMs;\n const jitter = opts?.jitter ?? config?.jitter;\n if (jitter !== undefined) policy.jitter = jitter;\n const timeoutMs = opts?.timeoutMs ?? config?.timeoutMs;\n if (timeoutMs !== undefined) policy.timeoutMs = timeoutMs;\n const requires = opts?.requires ?? config?.requires;\n if (requires !== undefined) policy.requires = requires;\n return policy;\n}\n\n/**\n * A saga undo registered by a completed step, kept with its step name for visibility on failure.\n * Two shapes, pushed onto the SAME `compensations` stack so the engine unwinds them together in one\n * strict reverse-completion order, regardless of which kind each one is:\n * - `fn`: a LOCAL undo (`ctx.localStep`'s `compensate` closure) — run in-process.\n * - `dispatch`: a DISPATCHED undo (`ctx.step`'s `compensate` ref/string) — an ordinary `@Step` def\n * the engine dispatches to a worker at unwind time, called with the `StepUndo` envelope (`args`).\n */\nexport type Compensation =\n | { name: string; fn: () => Promise<void> }\n | {\n name: string;\n dispatch: {\n def: StepDef<StepUndo<unknown, unknown>, unknown>;\n args: StepUndo<unknown, unknown>;\n };\n };\n\n/** A finished local step the host should checkpoint and announce (completed or failed). */\nexport interface StepRecord {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n input?: unknown;\n events?: StepEvent[] | undefined;\n attempts: number;\n enqueuedAt: Date;\n startedAt: Date;\n workerGroup?: string | undefined;\n}\n\n/**\n * The narrow surface {@link createWorkflowCtx} needs from the engine — the seam between the\n * authoring API (this module) and the orchestrator (the engine owns lifecycle: emitting events,\n * suspending/resuming runs, dispatching remote steps).\n */\nexport interface CtxHost {\n readonly store: StateStore;\n /**\n * Per-execution checkpoint snapshot, loaded ONCE at execution start (the completed prefix this\n * replay walks). Lets each primitive read the prefix from memory instead of a per-call DB SELECT\n * (the O(N²) replay-reads fix). A seq ABSENT from the map is NOT cached — the primitive falls back\n * to the live store, so the checkpoint this resume is waking on (signal/timer/child, written after\n * the snapshot) is always read fresh. New checkpoints written during this execution are inserted\n * into the map so any later same-execution read sees them. Undefined ⇒ always hit the store.\n */\n readonly replay?: Map<number, StepCheckpoint> | undefined;\n clock(): number;\n webhookUrl?: ((token: string) => string) | undefined;\n /** Mark a local step's body as started — emits `step.started` and (optionally) a `running` checkpoint. */\n startStep(step: StepRecord): Promise<void>;\n completeStep(step: StepRecord & { output: unknown }): Promise<void>;\n failStep(step: StepRecord & { error: StepError }): Promise<void>;\n callRemote<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n queue?: string,\n transport?: string,\n admission?: { priority?: number | undefined; fairnessKey?: string | undefined },\n ): Promise<TOutput>;\n /** Start a child run once, deferred so it can't reentrantly resume a still-running parent.\n * `version` pins the child to that exact registered version (see `StartOptions.version`); omitted,\n * the child starts on the newest registered one. */\n startChild(\n workflow: string,\n input: unknown,\n id: string,\n priority?: number,\n version?: string,\n ): void;\n /**\n * Best-effort cancel of a child run — deferred for the SAME reason as `startChild` (so ctx code\n * can't reentrantly mutate engine state while the parent's own step is still executing\n * synchronously). Plain cancel, no saga undo; used by `ctx.all`'s `failFast` mode to stop the\n * surviving siblings once one has failed. Cancelling an already-terminal/cancelled run is a no-op\n * (`engine.cancel`'s own idempotency guard), so a replay that re-issues the same calls is safe.\n * Optional: hosts that never construct a `ctx.all` failFast call (e.g. test fakes) can omit it.\n */\n cancelChild?(childId: string): void;\n /** Shallow-merge `attrs` into the run's `searchAttributes` (see {@link WorkflowCtx.upsertSearchAttributes}). */\n upsertSearchAttributes(runId: string, attrs: SearchAttributes): Promise<void>;\n /** Deliver an op to a durable entity (deferred), optionally with a `reply` token for the result. */\n signalEntity?(name: string, key: string, op: string, arg: unknown, reply?: string): void;\n /** Run a local step body through the registered step interceptors (identity if none). */\n interceptStep?<T>(invocation: StepInvocation, body: () => Promise<T>): Promise<T>;\n}\n\n/** The per-run logical position counter. `rewind()` gives a position back (see `ctx.patched`). */\nclass Position {\n private seq = -1;\n next(): number {\n this.seq += 1;\n return this.seq;\n }\n rewind(): void {\n this.seq -= 1;\n }\n /** The position the NEXT primitive would claim, without claiming it. */\n peek(): number {\n return this.seq + 1;\n }\n}\n\n/**\n * Back-compat alias of {@link WorkflowCtx}. `localStep` — the checkpointed in-process step primitive\n * used for saga compensation — is now part of the public {@link WorkflowCtx}, so this type adds\n * nothing; it is kept only so internal consumers (the durable-entity runner) keep compiling.\n */\nexport type InternalWorkflowCtx = WorkflowCtx;\n\n/**\n * Build the {@link WorkflowCtx} handed to a workflow body. Every primitive is a closure over the\n * position counter (the per-run logical position) and the saga `compensations` stack, so `task`/\n * `child` compose `step`/`waitForSignal` directly. All durability goes through {@link CtxHost}, so\n * the workflow body stays deterministic.\n */\nexport function createWorkflowCtx(\n host: CtxHost,\n runId: string,\n compensations: Compensation[],\n workflow = '',\n searchAttributesSchema?: SearchAttributesSchema,\n): InternalWorkflowCtx {\n const { store, replay } = host;\n const pos = new Position();\n // This ctx's identity in the ambient step scope (see `runInStepScope`): lets a primitive tell \"I am\n // being called from inside one of MY step bodies\" apart from another run's body executing inline.\n const scopeOwner = {};\n\n // Read the checkpoint at `seq`: from the per-execution snapshot when present (no DB round-trip),\n // otherwise from the live store. Absence in the snapshot means \"written after the snapshot\" (the\n // signal/timer/child this resume wakes on, or nothing yet) — those MUST hit the store. Identical\n // behaviour to a raw `store.getCheckpoint`, just memoized for the completed prefix.\n const readCheckpoint = (seq: number): Promise<StepCheckpoint | null> | StepCheckpoint => {\n const hit = replay?.get(seq);\n if (hit !== undefined) return hit;\n return store.getCheckpoint(runId, seq);\n };\n\n // Persist a checkpoint AND reflect it in the snapshot, so a later same-execution read of this seq\n // (e.g. a re-read within the same call) sees it instead of falling back to the store.\n const writeCheckpoint = async (cp: StepCheckpoint): Promise<void> => {\n await store.saveCheckpoint(cp);\n replay?.set(cp.seq, cp);\n };\n\n // The in-process local-step runner: checkpointed, replayed, retried. No longer publicly exposed as\n // `ctx.step` (that name is now the ALWAYS-dispatched form below) — this backs the library's own\n // internal primitives that need a checkpointed in-process body: `ctx.task`'s dispatch step and the\n // deterministic capture helpers `ctx.now`/`ctx.sideEffect`.\n const localStep = async <T>(\n name: string,\n fn: (log: StepLogger) => Promise<T>,\n options?: StepOptions,\n ): Promise<T> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') {\n // Register the compensation on replay too, so a saga undoes ALL completed steps — even\n // those done in an earlier (since-suspended) pass — not just the ones run this pass.\n if (options?.compensate) compensations.push({ name, fn: options.compensate });\n return existing.output as T;\n }\n const maxAttempts = Math.max(1, options?.retries ?? 1);\n const startedAt = new Date();\n // Announce the body has begun (and, when enabled, checkpoint it `running`) so the step is\n // visible in flight — not only once it settles. Skipped on replay: a completed step returns\n // above before reaching here, so this fires once, when the body actually first runs.\n await host.startStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n });\n for (let attempt = 1; ; attempt += 1) {\n // Events are scoped per attempt — a retry starts a clean log, so the checkpoint reflects\n // only the attempt that actually completed (or the final failing one).\n const events: StepEvent[] = [];\n try {\n const invocation: StepInvocation = {\n runId,\n workflow,\n stepName: name,\n seq: current,\n attempt,\n };\n // The SAME logger goes to the body's argument and into the ambient storage, so code deep\n // inside the step emits into this attempt's `events` without the handle being threaded\n // down through every signature (see `ambient-step.ts`).\n const body = () => {\n const logger = createStepLogger(events, host.clock);\n return runInStepScope(scopeOwner, name, () => runInStepLogger(logger, () => fn(logger)));\n };\n const output = host.interceptStep\n ? await host.interceptStep(invocation, body)\n : await body();\n await host.completeStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n output,\n events,\n attempts: attempt,\n enqueuedAt: startedAt,\n startedAt,\n });\n if (options?.compensate) compensations.push({ name, fn: options.compensate });\n return output;\n } catch (err) {\n if (err instanceof FatalError || attempt >= maxAttempts) {\n await host.failStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n error: {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n },\n events,\n attempts: attempt,\n enqueuedAt: startedAt,\n startedAt,\n });\n throw err;\n }\n // Wait out the backoff before the next attempt (no-op when backoffMs is unset).\n const wait = backoffDelay(attempt, options);\n if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));\n }\n }\n };\n\n // Exactly-once DB step: run the body and write the step checkpoint in ONE store transaction, so the\n // business write commits atomically with the \"done\" marker (a plain step checkpoints AFTER the body,\n // so a crash in between re-runs it). Replay returns the recorded output without re-running.\n const transaction = async <T>(name: string, fn: (tx: unknown) => Promise<T>): Promise<T> => {\n if (!store.transaction) {\n throw new Error(\n 'ctx.transaction needs a store that supports transactions (the SQL adapters do). Use ctx.step for non-transactional work.',\n );\n }\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') return existing.output as T;\n return store.transaction(async (tx) => {\n const output = await runInStepScope(scopeOwner, name, () => fn(tx.raw));\n const cp = instantCheckpoint({ runId, seq: current, name, kind: 'local', output });\n await tx.saveCheckpoint(cp);\n // Reflect the committed checkpoint in the snapshot, keeping the writeback invariant uniform.\n replay?.set(current, cp);\n return output;\n });\n };\n\n // Shared by sleep / sleepUntil: record a durable timer at this position and suspend until `wakeAt`\n // (epoch ms). The wakeAt is computed by the caller — but only used on the first run; on replay the\n // recorded checkpoint's wakeAt wins, so a clock change can't shift an already-scheduled timer.\n const suspendUntil = async (wakeAt: () => number): Promise<void> => {\n const current = pos.next();\n const now = host.clock();\n const existing = await readCheckpoint(current);\n if (existing) {\n // Timer already recorded: resume if due, otherwise re-suspend cheaply.\n if (now >= (existing.wakeAt ?? 0)) return;\n throw new WorkflowSuspended(existing.wakeAt ?? now);\n }\n const at = wakeAt();\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: 'sleep', kind: 'sleep', wakeAt: at }),\n );\n throw new WorkflowSuspended(at);\n };\n\n const sleep = (duration: string | number): Promise<void> =>\n suspendUntil(() => host.clock() + parseDuration(duration));\n\n const sleepUntil = (when: Date | number): Promise<void> =>\n suspendUntil(() => (typeof when === 'number' ? when : when.getTime()));\n\n // End this run and hand off to a fresh execution (clean history) with the new input. Terminal —\n // it always throws, so any code after it in the workflow is unreachable.\n const continueAsNew = (input?: unknown): Promise<never> => {\n throw new ContinueAsNew(input);\n };\n\n // NOTE (determinism): a bounded wait consumes TWO logical positions (deadline + wait), an\n // unbounded one consumes ONE. So adding or removing `{ timeoutMs }` on an existing `waitForSignal`\n // shifts the seq of every later step — treat it as a workflow-version change for in-flight runs.\n // Consume a buffered signal (one delivered before this run was waiting), recording it as the\n // signal checkpoint at `seq` so it resumes immediately instead of suspending. Replay-safe: the\n // checkpoint makes the consumption deterministic.\n const consumeBuffered = async <T>(token: string, seq: number): Promise<{ value: T } | null> => {\n const buffered = await store.takeBufferedSignal(token);\n if (!buffered) return null;\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq,\n name: `signal:${token}`,\n kind: 'signal',\n output: buffered.payload,\n }),\n );\n return { value: buffered.payload as T };\n };\n\n // Consume a buffered EVENT matching `match` (one published with no live waiter — see\n // engine.publishEvent's buffering), recording it as the resolving `signal:<token>` checkpoint at\n // `seq` so replay is deterministic — the event analog of `consumeBuffered` above, but match-aware:\n // an event's buffer is keyed by NAME only (many waiters can share a name with different `match`\n // criteria), so consumption scans the oldest candidates and evaluates each one's match HERE — the\n // match predicate belongs to the WAITER, never the store (see events.ts / interfaces.ts). A hit\n // atomically claims that one row via `removeBufferedEvent`'s boolean return, which arbitrates a\n // concurrent claim (notably engine.publishEvent's own late re-check reaching the same row first —\n // see the wiring in engine.ts); losing that race tries the NEXT oldest candidate instead of giving\n // up, so a later non-matching buffered event never blocks an earlier matching one behind it.\n const consumeBufferedEvent = async <T>(\n name: string,\n match: Record<string, unknown> | undefined,\n token: string,\n seq: number,\n ): Promise<{ value: T } | null> => {\n const candidates = await store.listBufferedEvents(name, EVENT_BUFFER_SCAN_LIMIT);\n for (const candidate of candidates) {\n if (!eventMatches(candidate.payload, match ?? {})) continue;\n if (!(await store.removeBufferedEvent(candidate.id))) continue; // raced away — try the next\n // Resolved it ourselves — remove OUR OWN waiter row via the exact match (not\n // `takeSignalWaiter(token)`; harmless here since an event token is unique per call, but exact\n // removal keeps this symmetric with the signal-side precedent in `waitForSignal` above).\n await store.removeSignalWaiter({ token, runId, seq });\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq,\n name: `signal:${token}`,\n kind: 'signal',\n output: candidate.payload,\n }),\n );\n return { value: candidate.payload as T };\n }\n return null;\n };\n\n // Durably stamp the deadline for a BOUNDED wait, ONCE: the first run computes `clock() + timeoutMs`\n // and records it as a timer checkpoint at `deadlineSeq`; every later replay reads the SAME recorded\n // `wakeAt` back instead of recomputing it — so a slow replay (or a clock that moved between the\n // original run and the replay) can never shift an already-scheduled deadline. `label` only affects\n // the checkpoint's `name` (cosmetic, for the dashboard timeline) — the shared mechanic behind every\n // bounded-wait primitive (`waitForSignal`, `waitForEvent`, `DurableWebhook.wait`).\n const stampDeadline = async (\n deadlineSeq: number,\n label: string,\n timeoutMs: number,\n ): Promise<number> => {\n const recorded = await readCheckpoint(deadlineSeq);\n const deadline = recorded?.wakeAt ?? host.clock() + timeoutMs;\n if (!recorded) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: deadlineSeq,\n name: `timeout:${label}`,\n kind: 'sleep',\n wakeAt: deadline,\n }),\n );\n }\n return deadline;\n };\n\n const waitForSignal = async <T>(token: string, opts?: { timeoutMs?: number }): Promise<T> => {\n if (opts?.timeoutMs == null) {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n const buffered = await consumeBuffered<T>(token, current);\n if (buffered) return buffered.value;\n // Register, THEN check the buffer again before suspending — closes the lost-wake window\n // between the check above and this registration: a signal delivered in that sliver found no\n // waiter (we hadn't registered yet) and no buffer either by the time IT checked, so it buffered\n // the payload; without this re-check we'd suspend with the payload sitting unpaired forever.\n // (Registering UNCONDITIONALLY before even the first check — instead of only on a miss like\n // here — reopens a worse window: a token an entity loop reuses across iterations would expose\n // a \"this turn is about to self-resolve from the buffer\" waiter row to a concurrent signal for\n // the NEXT iteration's payload, which can steal it via engine.signal's plain takeSignalWaiter\n // and misdeliver. Checking first, so we only ever register when we're sure no buffer already\n // existed, avoids that.) See the interleaving proof at engine.signal for the mirror-image\n // take→buffer→re-take on the signaling side that this pairs with.\n await store.putSignalWaiter({ token, runId, seq: current });\n const lateBuffered = await consumeBuffered<T>(token, current);\n if (lateBuffered) {\n // Resolved it ourselves — remove OUR OWN row via the exact match, not\n // `takeSignalWaiter(token)`, which deletes ANY row for this token and could steal a\n // different run's waiter that has since claimed the same token.\n await store.removeSignalWaiter({ token, runId, seq: current });\n return lateBuffered.value;\n }\n throw new WorkflowSuspended();\n }\n const timeoutMs = opts.timeoutMs;\n const deadlineSeq = pos.next();\n const waitSeq = pos.next();\n // The run also gets a run-level wakeAt (via WorkflowSuspended) so the timer poller resumes it at\n // the deadline.\n const deadline = await stampDeadline(deadlineSeq, token, timeoutMs);\n const waited = await readCheckpoint(waitSeq);\n if (waited && waited.status === 'completed') return waited.output as T;\n const buffered = await consumeBuffered<T>(token, waitSeq);\n if (buffered) return buffered.value;\n if (host.clock() >= deadline) {\n // A PRIOR replay of this same call may have already registered the waiter (below) before this\n // one found the deadline past — clean up that exact row (own token/runId/seq only; a plain\n // `takeSignalWaiter(token)` could otherwise steal a different run's waiter on the same token).\n // A no-op if nothing was ever registered.\n await store.removeSignalWaiter({ token, runId, seq: waitSeq }).catch(() => undefined);\n throw new SignalTimeoutError(token, timeoutMs);\n }\n // Same reorder as the unbounded arm above: check, THEN register, THEN re-check before suspending.\n await store.putSignalWaiter({ token, runId, seq: waitSeq });\n const lateBuffered = await consumeBuffered<T>(token, waitSeq);\n if (lateBuffered) {\n await store.removeSignalWaiter({ token, runId, seq: waitSeq });\n return lateBuffered.value;\n }\n throw new WorkflowSuspended(deadline);\n };\n\n // Wait for a named event delivered by engine.publishEvent(name, payload). Like waitForSignal, but\n // name-based pub/sub with optional `match` filtering — the token embeds name + match (see events.ts),\n // so a publish fans out to the runs whose match the payload satisfies.\n //\n // Buffering (reliable events — mirrors signalWithStart's reliability contract for signals, see the\n // \"Semantics\" doc on engine.publishEvent): a publish that finds no live waiter buffers ONE copy, and\n // this call's post-registration scan is what consumes it. UNLIKE waitForSignal, this registers its\n // waiter FIRST and scans the buffer only ONCE after — no separate \"check before registering\" pass.\n // That's deliberate, not an oversight: waitForSignal's own token is a caller-chosen string an entity\n // loop can legitimately REUSE across iterations, so registering before checking would expose a\n // \"this turn is about to self-resolve\" waiter row to a concurrent signal for the NEXT iteration's\n // token, which could steal it via engine.signal's plain takeSignalWaiter. An event token embeds this\n // call's OWN `runId#seq` (see eventToken in events.ts) — nothing else, ever, mints the same token —\n // so that hazard cannot arise here, and a single check-after-register closes the lost-wake window\n // symmetrically with engine.publishEvent's own buffer-then-recheck (see its wiring in engine.ts).\n const waitForEvent = async <T>(\n name: string,\n opts?: { match?: Record<string, unknown>; timeoutMs?: number },\n ): Promise<T> => {\n if (opts?.timeoutMs == null) {\n const current = pos.next();\n const token = eventToken(name, opts?.match, runId, current);\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n await store.putSignalWaiter({ token, runId, seq: current });\n const bufferedHit = await consumeBufferedEvent<T>(name, opts?.match, token, current);\n if (bufferedHit) return bufferedHit.value;\n throw new WorkflowSuspended();\n }\n const timeoutMs = opts.timeoutMs;\n const deadlineSeq = pos.next();\n const waitSeq = pos.next();\n const token = eventToken(name, opts.match, runId, waitSeq);\n const deadline = await stampDeadline(deadlineSeq, `event:${name}`, timeoutMs);\n const waited = await readCheckpoint(waitSeq);\n if (waited && waited.status === 'completed') return waited.output as T;\n if (host.clock() >= deadline) {\n // Exact removal (see waitForSignal above) — takeSignalWaiter(token) deletes ANY row for this\n // token and could steal a different run's waiter registered on it after ours timed out.\n await store.removeSignalWaiter({ token, runId, seq: waitSeq }).catch(() => undefined);\n throw new SignalTimeoutError(`event:${name}`, timeoutMs);\n }\n await store.putSignalWaiter({ token, runId, seq: waitSeq });\n const bufferedHit = await consumeBufferedEvent<T>(name, opts.match, token, waitSeq);\n if (bufferedHit) return bufferedHit.value;\n throw new WorkflowSuspended(deadline);\n };\n\n // An external task = a checkpointed dispatch + a wait for its async-completion `Completion`\n // (delivered by engine.completeTask/failTask). The whole \"fire at a foreign system, suspend,\n // resume when it reports back\" pattern as one call.\n const task = async <T>(\n name: string,\n dispatch: () => Promise<void>,\n options?: StepOptions,\n ): Promise<T> => {\n await localStep(`task:dispatch:${name}`, dispatch, options);\n return unwrapCompletion<T>(await waitForSignal(`task:${runId}:${name}`), `task \"${name}\"`);\n };\n\n // Child workflow (await result): start it once, then suspend on a `child:<id>` waiter the child\n // signals on its terminal state (see engine.notifyParent).\n const child = async <T>(\n workflow: WorkflowRef,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<T> => {\n const { childId, priority, version } = normalizeChildOptions(options);\n const current = pos.next();\n const id = childId ?? `${runId}.child.${current}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') {\n return unwrapCompletion<T>(existing.output, `child \"${id}\"`);\n }\n // A placeholder proves the waiter was put; re-putting it could leave one for a child that\n // already settled after this execution's snapshot, which nothing would ever take.\n if (!existing) await store.putSignalWaiter({ token: `child:${id}`, runId, seq: current });\n // Lost-wake guard (mirrors the engine's remote `startChild` command path): the child may have\n // ALREADY completed while no waiter was registered — e.g. this run failed on the child's\n // failure, the child was retried to completion, and this run is now being retried — leaving its\n // completion BUFFERED. Consume it here or the re-registered waiter waits forever for a signal\n // that already fired. Resolve exactly as engine.signal would: overwrite the placeholder with\n // the completed signal checkpoint, then unwrap.\n const buffered = await store.takeBufferedSignal(`child:${id}`);\n if (buffered) {\n await store.removeSignalWaiter({ token: `child:${id}`, runId, seq: current });\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: `signal:child:${id}`,\n kind: 'signal',\n output: buffered.payload,\n }),\n );\n return unwrapCompletion<T>(buffered.payload, `child \"${id}\"`);\n }\n if (!(await store.getRun(id)))\n host.startChild(workflowName(workflow), input, id, priority, version);\n // Make the awaited child visible in the parent's timeline WHILE it runs: a `running` placeholder\n // at this seq with the same `signal:child:<id>` name the signal resolution later overwrites as\n // `completed`. So the dashboard shows the child node (and can inline-expand it) live, instead of\n // it appearing only when it finishes. Written once (skipped on replay, where `existing` is set);\n // `running` is ignored by replay history, so it never short-circuits determinism.\n if (!existing) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: `signal:child:${id}`,\n kind: 'signal',\n status: 'running',\n }),\n );\n }\n throw new WorkflowSuspended(\n undefined,\n fanJoin([{ waiterPrefix: `child:${id}`, checkpointPrefix: `signal:child:${id}` }]),\n );\n };\n\n // Parallel child workflows (wait-all): dispatch N children CONCURRENTLY and wait for ALL their\n // outputs. Reserves a contiguous position block in list order FIRST (the determinism anchor), then\n // dispatches every not-yet-completed item and suspends once. The engine's join barrier holds the\n // parent's wake until the fan's last waiter is consumed (or, for failFast, the first failure), so\n // the parent replays about once per fan rather than once per child — the fan stays O(N).\n // With `concurrency`, children go out in waves and the parent wakes once per settled wave to send\n // the next one. When all resolve, outputs are returned in INPUT order (waitAll), or a GatherError\n // is thrown carrying the per-item failures. Parity with the Python SDK's `gather_children`.\n const all = async <T = unknown>(\n workflow: WorkflowRef,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<T[]> => {\n // Empty: reserve no positions and produce no side effects (degenerate identity).\n if (inputs.length === 0) return [];\n const mode = opts?.mode ?? 'waitAll';\n const name = workflowName(workflow);\n const waves = allWaves(inputs.length, opts?.concurrency);\n // Reserve the whole block in list order BEFORE any dispatch — replay re-derives identical seqs.\n const positions = inputs.map(() => pos.next());\n const firstSeq = positions[0] as number;\n const group = allGroup(firstSeq, mode);\n const waveOf = (i: number) => (waves ? Math.floor(i / waves.waveSize) : undefined);\n const id = (i: number) => allChildId(runId, firstSeq, i, waveOf(i));\n const { checkpoints: existing, folded } = await readFan(positions, [\n allWait(runId, firstSeq).checkpointPrefix,\n allFoldedName(runId, firstSeq),\n ]);\n // The unbounded fan is a single wave.\n const waveCount = waves ? Math.ceil(inputs.length / waves.waveSize) : 1;\n const waveItems = (k: number): number[] => {\n if (!waves) return inputs.map((_, i) => i);\n const from = k * waves.waveSize;\n return inputs.map((_, i) => i).slice(from, from + waves.waveSize);\n };\n\n // failFast: bail the moment any already-completed item is a failed Completion.\n if (mode === 'failFast') {\n for (let i = 0; i < inputs.length; i += 1) {\n const cp = existing[i];\n const c =\n cp?.status === 'completed' ? (cp.output as { ok?: boolean; error?: string }) : null;\n if (c && c.ok === false) {\n // Cancel every sibling that hasn't completed yet — plain cancel, no saga undo. Best-effort:\n // a sibling mid-step only observes the cancellation at its NEXT checkpoint (it isn't\n // force-killed mid-synchronous-execution), so a fast-enough sibling can still slip through\n // and complete before it notices. `cancelChild` is deferred (like `startChild`), and\n // cancelling an already-terminal/cancelled run is a no-op, so replaying this branch after a\n // resume (which re-executes this loop and re-issues the same cancels) is safe.\n for (let j = 0; j < inputs.length; j += 1) {\n if (j !== i && existing[j]?.status !== 'completed') host.cancelChild?.(id(j));\n }\n throw new GatherError(\n [{ index: i, id: id(i), error: c.error ?? 'unknown' }],\n inputs.length,\n );\n }\n }\n }\n\n // Fold every wave whose children all succeeded into one checkpoint, so the parent's later turns\n // load one row for it instead of one per child. A wave with a failure keeps its per-child\n // checkpoints: requeue resets exactly those to retry the failed children.\n if (store.compactCheckpoints && inputs.length >= FOLD_MIN_FAN) {\n for (let k = 0; k < waveCount; k += 1) {\n const items = waveItems(k);\n const first = items[0] as number;\n const last = items[items.length - 1] as number;\n if (folded[first]) continue;\n const values: unknown[] = [];\n for (const i of items) {\n const c = existing[i]?.status === 'completed' ? existing[i]?.output : undefined;\n if (!c || typeof c !== 'object' || (c as { ok?: boolean }).ok !== true) break;\n values.push((c as { value?: unknown }).value);\n }\n if (values.length < items.length) continue;\n const into = instantCheckpoint({\n runId,\n seq: positions[first] as number,\n name: allFoldedName(runId, firstSeq, waves ? k : undefined),\n kind: 'signal',\n output: { from: first, values } satisfies FoldedChildren,\n parallelGroup: group,\n });\n await store.compactCheckpoints(\n runId,\n positions[first] as number,\n positions[last] as number,\n into,\n );\n for (const i of items) replay?.delete(positions[i] as number);\n replay?.set(into.seq, into);\n }\n }\n\n // A wave has been sent once any of its children has a checkpoint. Send more waves until\n // `maxWaves` are unsettled, in order.\n const sent = (k: number) => waveItems(k).some((i) => existing[i]);\n const settled = (k: number) => waveItems(k).every((i) => existing[i]?.status === 'completed');\n const active: number[] = [];\n let unsettled = 0;\n for (let k = 0; k < waveCount; k += 1) {\n if (settled(k)) continue;\n if (sent(k) || unsettled < (waves?.maxWaves ?? 1)) {\n active.push(k);\n unsettled += 1;\n }\n }\n\n if (active.length > 0) {\n const toRegister: number[] = [];\n const toEnsure: number[] = [];\n for (const k of active) {\n for (const i of waveItems(k)) {\n const cp = existing[i];\n if (cp?.status === 'completed') continue;\n // A placeholder proves its waiter was put (registerChildWaits writes the waiter first), so\n // a replay never re-puts it. A child that settled after this execution's snapshot has\n // already consumed its waiter; re-putting it would leave one nothing ever takes, and the\n // join barrier would wait on it forever.\n (cp ? toEnsure : toRegister).push(i);\n }\n }\n for (let at = 0; at < toRegister.length; at += FAN_CHUNK) {\n const chunk = toRegister.slice(at, at + FAN_CHUNK);\n const entries = chunk.map((i) => ({\n // Carry the fan `group` onto the waiter too: the child's terminal `signal:child:`\n // checkpoint is (re)written by engine.signal when the child notifies the parent,\n // OVERWRITING the running placeholder at the same seq — so without this the resolved\n // checkpoint would lose the group and the dashboard would render the resolved fan as a\n // sequential chain.\n waiter: {\n token: `child:${id(i)}`,\n runId,\n seq: positions[i] as number,\n parallelGroup: group,\n },\n checkpoint: instantCheckpoint({\n runId,\n seq: positions[i] as number,\n name: `signal:child:${id(i)}`,\n kind: 'signal',\n status: 'running',\n parallelGroup: group,\n }),\n }));\n await registerChildWaits(entries);\n // `start` is idempotent by id, so a child a crashed turn already started is not doubled.\n for (const i of chunk) host.startChild(name, inputs[i], id(i));\n }\n // A placeholder written by a turn that crashed before the deferred start ran: start it now.\n for (let at = 0; at < toEnsure.length; at += FAN_CHUNK) {\n await Promise.all(\n toEnsure.slice(at, at + FAN_CHUNK).map(async (i) => {\n if (!(await store.getRun(id(i)))) host.startChild(name, inputs[i], id(i));\n }),\n );\n }\n }\n if (active.length > 0) {\n throw new WorkflowSuspended(\n undefined,\n fanJoin(active.map((k) => allWait(runId, firstSeq, waves ? k : undefined))),\n );\n }\n\n // All resolved: build outputs in INPUT order, aggregating any failures.\n const outputs: T[] = [];\n const failures: { index: number; id: string; error: string }[] = [];\n for (let i = 0; i < inputs.length; i += 1) {\n const c = existing[i]?.output as { ok?: boolean; value?: T; error?: string } | null;\n if (c && typeof c === 'object' && 'ok' in c && c.ok === false) {\n failures.push({ index: i, id: id(i), error: c.error ?? 'unknown' });\n outputs.push(undefined as T);\n } else {\n outputs.push((c as { value?: T } | null)?.value as T);\n }\n }\n if (failures.length > 0) throw new GatherError(failures, inputs.length);\n return outputs;\n };\n\n // A fan's checkpoints: from the replay snapshot, plus ONE prefix query for any the snapshot does\n // not hold (on the first dispatch, all of them) instead of a lookup per child. A folded checkpoint\n // is expanded back into one completed checkpoint per child it stands for; `folded` marks those.\n const readFan = async (\n positions: number[],\n prefixes: string[],\n ): Promise<{ checkpoints: (StepCheckpoint | null)[]; folded: boolean[] }> => {\n const checkpoints = positions.map((seq) => replay?.get(seq) ?? null);\n const folded = positions.map(() => false);\n const expand = () => {\n for (let i = 0; i < checkpoints.length; i += 1) {\n const cp = checkpoints[i];\n if (!cp?.name.startsWith(FOLDED_PREFIX) || folded[i]) continue;\n const fold = cp.output as Partial<FoldedChildren> | null | undefined;\n // A malformed fold must stop the replay: treating it as absent would re-dispatch every child\n // it stands for.\n if (!fold || typeof fold.from !== 'number' || !Array.isArray(fold.values)) {\n throw new Error(`ctx.all: folded checkpoint \"${cp.name}\" at seq ${cp.seq} is malformed`);\n }\n const { from, values } = fold as FoldedChildren;\n values.forEach((value, j) => {\n checkpoints[from + j] = {\n ...cp,\n seq: positions[from + j] as number,\n output: { ok: true, value },\n };\n folded[from + j] = true;\n });\n }\n };\n expand();\n const missing = positions.filter((_, i) => !checkpoints[i]);\n if (missing.length === 0) return { checkpoints, folded };\n if (missing.length > 1 && store.listCheckpointsByNamePrefix) {\n const bySeq = new Map<number, StepCheckpoint>();\n for (const cp of await store.listCheckpointsByNamePrefix(runId, prefixes)) {\n bySeq.set(cp.seq, cp);\n }\n positions.forEach((seq, i) => {\n checkpoints[i] ??= bySeq.get(seq) ?? null;\n });\n } else {\n await Promise.all(\n positions.map(async (seq, i) => {\n checkpoints[i] ??= await readCheckpoint(seq);\n }),\n );\n }\n expand();\n return { checkpoints, folded };\n };\n\n const registerChildWaits = async (entries: ChildWait[]): Promise<void> => {\n if (store.registerChildWaits) {\n await store.registerChildWaits(entries);\n } else {\n await Promise.all(\n entries.map(async (e) => {\n await store.putSignalWaiter(e.waiter);\n await store.saveCheckpoint(e.checkpoint);\n }),\n );\n }\n for (const e of entries) replay?.set(e.checkpoint.seq, e.checkpoint);\n };\n\n // Child workflow (fire-and-forget): dispatch it once and return its id WITHOUT suspending. The\n // start is checkpointed at this position so replay returns the same id without re-dispatching, and\n // is idempotent by id, so `child(..., sameId)` later joins the same run rather than starting a new\n // one (start + join scatter-gather).\n const startChild = async (\n workflow: WorkflowRef,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string> => {\n const { childId, priority, version } = normalizeChildOptions(options);\n const current = pos.next();\n const id = childId ?? `${runId}.child.${current}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as string;\n if (!(await store.getRun(id)))\n host.startChild(workflowName(workflow), input, id, priority, version);\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: `spawn:${id}`, kind: 'local', output: id }),\n );\n return id;\n };\n\n // Call a durable entity op and await its result: register a reply waiter at this position, dispatch\n // the op with the reply token, and suspend until the entity signals the result back (checkpointed,\n // so replay returns it without re-dispatching).\n const callEntity = async <R>(\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<R> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as R;\n const reply = `entityreply:${runId}:${current}`;\n await store.putSignalWaiter({ token: reply, runId, seq: current });\n host.signalEntity?.(name, key, op, arg, reply);\n throw new WorkflowSuspended();\n };\n\n // Send a durable entity op without awaiting a result — dispatched once (checkpointed, replay-safe).\n const signalEntity = async (\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return;\n host.signalEntity?.(name, key, op, arg);\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: `entitysig:${name}:${key}`, kind: 'local' }),\n );\n };\n\n // A breakpoint = a visible `pending` checkpoint + a signal waiter the dashboard resumes via\n // `engine.continue`. Reuses the signal machinery, so resume overwrites the pending checkpoint\n // with a completed one and the run replays past it.\n const breakpoint = async (label?: string): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return;\n if (!existing) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: label ? `breakpoint:${label}` : 'breakpoint',\n kind: 'signal',\n status: 'pending',\n }),\n );\n await store.putSignalWaiter({ token: breakpointToken(runId, current), runId, seq: current });\n }\n throw new WorkflowSuspended();\n };\n\n // Guard an in-place change: a fresh run records a `patch:<id>` marker here and takes the new\n // branch; a run recorded under the OLD code finds a real step at this position instead, so we\n // rewind the logical position (the marker is transparent to it) and return false — its replay\n // reads that old step next and follows the old branch. No position shift → no corruption.\n const patched = async (id: string): Promise<boolean> => {\n const marker = `patch:${id}`;\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing) {\n if (existing.name === marker) return true;\n if (existing.name.startsWith('patch:')) {\n throw new NonDeterminismError(runId, current, marker, existing.name);\n }\n pos.rewind(); // not a marker: an old run's step lives here — give the position back to it\n return false;\n }\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: marker, kind: 'local', output: true }),\n );\n return true;\n };\n\n // An update point: suspend on a run-scoped `update:<runId>:<name>` token that engine.update\n // delivers to (after its validator passes). Reuses the signal machinery; run-scoped like task/child.\n const onUpdate = <T>(name: string, opts?: { timeoutMs?: number }): Promise<T> =>\n waitForSignal<T>(`update:${runId}:${name}`, opts);\n\n // A queryable named value: a checkpoint whose `name` is `event:<key>`, so the latest value for a\n // key is just the highest-seq such checkpoint (read by engine.getEvent). Replay-idempotent.\n const setEvent = async (key: string, value: unknown): Promise<void> => {\n const current = pos.next();\n const name = `event:${key}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') return; // replay: already published\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name, kind: 'local', output: value }),\n );\n };\n\n // A durable webhook reserves a logical position NOW to mint a stable token, so the url can be\n // handed to a third party before `wait()` suspends. `wait()` then parks on that same position\n // until the callback lands as engine.signal(token, body) — single position, replay-safe. The\n // deadline (when `wait({ timeoutMs })` is used) is a SEPARATE, later position — reserved lazily by\n // `wait()` itself, not at mint time, since the mint site has no `opts` to know a timeout was\n // requested. That's fine: `wait()` runs in the same deterministic order on every replay, so the\n // deadline seq it claims is stable too.\n const webhook = <T>(): DurableWebhook<T> => {\n const current = pos.next();\n const token = `wh:${runId}:${current}`;\n const wait = async (opts?: { timeoutMs?: number }): Promise<T> => {\n // A bounded wait claims its deadline position UNCONDITIONALLY, before the completed-replay\n // early return: the same `wait({ timeoutMs })` call re-runs on every replay, so the position\n // walk must be identical whether the callback has landed yet or not. (Claiming it lazily after\n // the early return would shift every later primitive by one on the post-callback replay and\n // trip the NonDeterminism guard on the stamped `timeout:*` checkpoint.)\n const timeoutMs = opts?.timeoutMs;\n const deadlineSeq = timeoutMs == null ? -1 : pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n if (timeoutMs == null) {\n await store.putSignalWaiter({ token, runId, seq: current });\n throw new WorkflowSuspended();\n }\n const deadline = await stampDeadline(deadlineSeq, token, timeoutMs);\n if (host.clock() >= deadline) {\n await store.takeSignalWaiter(token).catch(() => undefined);\n throw new SignalTimeoutError(token, timeoutMs);\n }\n await store.putSignalWaiter({ token, runId, seq: current });\n throw new WorkflowSuspended(deadline);\n };\n return { token, url: host.webhookUrl?.(token), wait };\n };\n\n // Deterministic capture: run `fn` once, checkpoint its output, and replay the SAME value verbatim\n // afterwards (fn is NOT re-run on replay). The general primitive for any non-deterministic value the\n // author controls the generator for — `ctx.sideEffect(() => uuidv7())`, `() => Math.random()`, a\n // config/env read. A raw `Date.now()`/`Math.random()` in a workflow body differs across replays and\n // corrupts the run; this captures it deterministically.\n const sideEffect = <T>(fn: () => T | Promise<T>): Promise<T> =>\n localStep('sideEffect', async () => fn());\n // `now` is the one ubiquitous convenience (a single obvious implementation, epoch ms like\n // `Date.now()`); everything else uses `sideEffect` so the author picks the generator.\n const now = () => localStep('now', async () => host.clock());\n\n // Merge into this run's searchAttributes exactly once: a checkpoint at this position marks it done,\n // so a replay SKIPS the write (mirrors `transaction` / the instant primitives) instead of re-merging\n // on every turn. Nondeterminism-guarded by the recorded marker name.\n const upsertSearchAttributes = async (attrs: SearchAttributes): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing) {\n if (existing.name !== 'searchAttributes') {\n throw new NonDeterminismError(runId, current, 'searchAttributes', existing.name);\n }\n // Replayed: the write already happened on a prior turn — skip it, and (deliberately) skip\n // re-validating too. Validation only ever needs to run once, at the position it's recorded;\n // re-running it on replay would be redundant at best and, for a schema whose rules change\n // between deploys, a source of a replay throwing on history a live run already accepted.\n return;\n }\n if (searchAttributesSchema) {\n // The schema describes the whole run's search-attribute shape (optional keys included), so\n // validate the MERGED result — this call's `attrs` shallow-merged onto what's already on the\n // run — not `attrs` alone. Mirrors the merge `host.upsertSearchAttributes` itself performs;\n // read here is best-effort (not transactional with the host's own read+write), same as that\n // merge already is.\n const run = await store.getRun(runId);\n const merged = { ...(run?.searchAttributes ?? {}), ...attrs };\n const result = searchAttributesSchema['~standard'].validate(merged);\n if (result instanceof Promise) {\n throw new Error(\n `workflow \"${workflow}\": ctx.upsertSearchAttributes schema validation must be synchronous (the searchAttributes schema's \\`~standard.validate\\` returned a Promise) — replay-determinism requires a sync validator; drop any async refinement from the schema passed to @Workflow({ searchAttributes }).`,\n );\n }\n if (result.issues) {\n const offendingKeys = [\n ...new Set(result.issues.map((issue) => formatIssuePath(issue.path))),\n ];\n const details = result.issues\n .map((issue) => `${formatIssuePath(issue.path)}: ${issue.message}`)\n .join('; ');\n throw new Error(\n `workflow \"${workflow}\": ctx.upsertSearchAttributes rejected by its searchAttributes schema — ` +\n `offending key(s) ${offendingKeys.join(', ')} — ${details}`,\n );\n }\n }\n await host.upsertSearchAttributes(runId, attrs);\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: 'searchAttributes',\n kind: 'local',\n output: attrs,\n }),\n );\n };\n\n // Resolve a `ctx.step(..., { compensate })` ref/string into the undo's own dispatchable StepDef —\n // same routing-name resolution as the step it's attached to (see `step` below), but its dispatch\n // policy comes ONLY from its own `@Step`-stamped config (stepConfigOf), never the compensated\n // call's per-call `opts`: the undo is a separately-declared handler with its own retry/backoff, not\n // an extension of the step it undoes. The string form (cross-runtime, unchecked) has no stamped\n // config, so it dispatches with engine defaults. Takes `unknown` (like `stepNameOf`/`stepConfigOf`\n // themselves) rather than a `StepRef<StepUndo<TInput, TOutput>, ...>` — the caller's TInput/TOutput\n // are call-site type parameters with no runtime shape to check here; the compile-time contract is\n // already enforced by `WorkflowCtx.step`'s overload signature (interfaces.ts) that typed `opts`.\n function resolveCompensateDef(compensate: unknown): StepDef<StepUndo<unknown, unknown>, unknown> {\n const name = typeof compensate === 'string' ? compensate : stepNameOf(compensate);\n if (name === undefined) {\n throw new Error(\n 'ctx.step: compensate handler is not a @Step reference (no stamped step name) — pass a @Step-decorated method or a step name string',\n );\n }\n const config = typeof compensate === 'string' ? undefined : stepConfigOf(compensate);\n return { name, ...resolveStepPolicy(config, undefined) };\n }\n\n // ONE durable step primitive: always dispatched, always engine-scheduled — no local/remote\n // placement choice for the workflow author (see `WorkflowCtx.step`). Resolve the routing name off\n // a `@Step`-stamped handler reference, or take it literally for the cross-runtime string form; the\n // reference itself is NEVER invoked here — only its stamped name (and dispatch policy) is read (the\n // serving worker re-resolves the real handler from DI), so an unbound `this` on `handlerOrName` is\n // irrelevant. The effective durable-retry/liveness policy is `{ ...stepConfigOf(handlerOrName),\n // ...opts }` — the `@Step`-declared def-level policy, with a per-call `opts` field winning wherever\n // it's set. The string form has no stamped config, so it uses `opts` only. Carrying this policy onto\n // the `StepDef` re-enables `callRemote`'s durable retry/backoff and liveness-timeout branches (see\n // `engine.ts`), which were otherwise orphaned.\n function step<TInput, TOutput>(\n handlerOrName: StepRef<TInput, TOutput> | string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput> {\n const name = typeof handlerOrName === 'string' ? handlerOrName : stepNameOf(handlerOrName);\n if (name === undefined) {\n throw new Error(\n 'ctx.step: handler is not a @Step reference (no stamped step name) — pass a @Step-decorated method or a step name string',\n );\n }\n const config = typeof handlerOrName === 'string' ? undefined : stepConfigOf(handlerOrName);\n const def: StepDef<TInput, TOutput> = { name, ...resolveStepPolicy(config, opts) };\n return host\n .callRemote(runId, pos.next(), def, input, opts?.queue, opts?.transport, {\n priority: opts?.priority,\n fairnessKey: opts?.fairnessKey,\n })\n .then((output) => {\n // `callRemote` resolves ONLY once this step is durably complete — the replay-completed branch\n // (a checkpointed output) or the in-memory `timeoutMs` liveness path once the live result\n // lands (engine.ts). Register the compensation HERE, after that resolution, so a saga only\n // ever undoes steps that actually finished. Mirrors `localStep`'s rebuild-on-replay: the\n // workflow body re-passes `compensate` on every replay of a completed call, and `input`/\n // `output` come straight from this call (the checkpointed ones on replay) — no store-schema\n // change needed to carry the undo's args.\n if (opts?.compensate) {\n compensations.push({\n name,\n dispatch: { def: resolveCompensateDef(opts.compensate), args: { input, output } },\n });\n }\n return output;\n });\n }\n\n // Fail fast when a primitive is called from INSIDE one of this ctx's step bodies (directly, or via\n // a `MyWorkflow.start()`/`.execute()` static resolving the ambient ctx). The step replays from its\n // checkpoint without re-running its body, so the nested call's journal position would never be\n // claimed again and every later position would shift — a NonDeterminismError on the next replay,\n // far from the cause. See {@link NestedWorkflowCallError}.\n //\n // Versioning: a run journaled BEFORE this guard existed may legitimately re-run such a body (its\n // step never completed) with the nested call already recorded at the position it would claim. That\n // position being occupied means the history predates the guard — let the call through so the\n // existing journal keeps replaying exactly as it was written. Only a call that would write NEW\n // history is refused. The check costs nothing outside a step body (the common path is a sync\n // pass-through, so primitive timing is unchanged).\n const nestedStep = (): string | undefined => {\n const scope = currentStepScope();\n return scope !== undefined && scope.owner === scopeOwner ? scope.step : undefined;\n };\n const guard = <F extends (...args: never[]) => Promise<unknown>>(primitive: string, fn: F): F =>\n ((...args: Parameters<F>) => {\n const stepName = nestedStep();\n if (stepName === undefined) return fn(...args);\n return (async () => {\n if (await readCheckpoint(pos.peek())) return fn(...args);\n throw new NestedWorkflowCallError(runId, primitive, stepName);\n })();\n }) as F;\n // `webhook` is synchronous (it returns a handle): same rule, checked against the replay snapshot.\n const guardedWebhook = <T>(): DurableWebhook<T> => {\n const stepName = nestedStep();\n if (stepName !== undefined && !replay?.get(pos.peek())) {\n throw new NestedWorkflowCallError(runId, 'webhook', stepName);\n }\n return webhook<T>();\n };\n\n return {\n runId,\n step: guard('step', step as (...args: never[]) => Promise<unknown>) as typeof step,\n localStep: guard('localStep', localStep),\n upsertSearchAttributes: guard('upsertSearchAttributes', upsertSearchAttributes),\n transaction: guard('transaction', transaction),\n callEntity: guard('callEntity', callEntity),\n signalEntity: guard('signalEntity', signalEntity),\n sleep: guard('sleep', sleep),\n sleepUntil: guard('sleepUntil', sleepUntil),\n continueAsNew,\n waitForSignal: guard('waitForSignal', waitForSignal),\n waitForEvent: guard('waitForEvent', waitForEvent),\n task: guard('task', task),\n child: guard('child', child),\n all: guard('all', all),\n startChild: guard('startChild', startChild),\n breakpoint: guard('breakpoint', breakpoint),\n webhook: guardedWebhook,\n setEvent: guard('setEvent', setEvent),\n onUpdate: guard('onUpdate', onUpdate),\n patched: guard('patched', patched),\n now: guard('now', now),\n sideEffect: guard('sideEffect', sideEffect),\n };\n}\n","import { type AdmissionBackend, InMemoryAdmissionBackend } from './admission';\nimport { runInWorkflowCtx } from './ambient-ctx';\nimport { backoffDelay } from './backoff';\nimport { instantCheckpoint, lostStepEvent, stepCheckpoint } from './checkpoints';\nimport { type Completion, isFailedCompletion } from './completion';\nimport {\n type ConcurrencyConfig,\n type ConcurrencyQuota,\n assertConcurrency,\n concurrencyTag,\n resolveConcurrency,\n} from './concurrency';\nimport { parseDuration } from './duration';\nimport { Entities, type EntityConfig } from './entities';\nimport {\n ContinueAsNew,\n type FanJoin,\n FatalError,\n NonDeterminismError,\n RemoteStepTimeout,\n RemoteWorkflowTimeout,\n SignalTimeoutError,\n WorkflowSuspended,\n} from './errors';\nimport { EventAccumulators, type EventBatchConfig } from './event-accumulators';\nimport {\n EVENT_BUFFER_SCAN_LIMIT,\n eventMatchOf,\n eventMatches,\n eventNameOf,\n eventPrefix,\n isEventToken,\n} from './events';\nimport { runDurableExecution } from './execution-hooks';\nimport { FOLDED_PREFIX, fanOfWaiter, foldedChildIds } from './fan-join';\nimport {\n type AnnouncedWorkflow,\n type BlockedDispatch,\n type DispatchPlan,\n type WorkerDescriptor,\n WorkflowBlocked,\n type WorkflowDirectory,\n aggregateAnnouncements,\n buildWorkflowDirectory,\n controlPlaneDescriptor,\n planDispatch,\n} from './handshake/index';\nimport type {\n ControlPlane,\n EngineEvent,\n EngineListener,\n GroupHealth,\n NamedTransport,\n RemoteTask,\n RunDispatcher,\n RunQuery,\n RunResult,\n RunStatus,\n SearchAttributes,\n SearchAttributesSchema,\n SignalWaiter,\n StateStore,\n StepCheckpoint,\n StepDef,\n StepError,\n StepEvent,\n StepInterceptor,\n StepInvocation,\n StepKind,\n StepResult,\n StepUndo,\n Transport,\n UpdateResult,\n UpdateValidator,\n WorkflowCommand,\n WorkflowCtx,\n WorkflowDecision,\n WorkflowExecutor,\n WorkflowRun,\n WorkflowStepEvent,\n} from './interfaces';\nimport type { HistoryEvent, RunScope } from './interfaces';\nimport { TERMINAL_RUN_STATUSES, isNonEmptyRunScope } from './interfaces';\nimport { breakpointToken, stepId } from './protocol';\nimport type { QueueConfig } from './queue';\nimport { RemoteWorkflowExecutor } from './remote-workflow-executor';\nimport { indexWaitersByRun, listSignalWaitersOfRuns } from './run-waiting';\nimport { ScheduleClient } from './schedules';\nimport { SINGLETON_ADMITTED_TAG } from './singleton-admission';\nimport { SingletonGate } from './singleton-gate';\nimport { sanitizeQueueToken, tenantGroup } from './tenant-group';\nimport { TransportPool } from './transport-pool';\nimport {\n type Compensation,\n type CtxHost,\n type InternalWorkflowCtx,\n type StepRecord,\n createWorkflowCtx,\n} from './workflow-ctx';\nimport {\n type WorkflowClass,\n type WorkflowInputOf,\n type WorkflowRef,\n workflowName,\n} from './workflow-ref';\n\n// The engine ALWAYS runs a body with the InternalWorkflowCtx `createWorkflowCtx` produces (it carries\n// the internal `localStep` the entity runner + capture helpers need). Public authors type their body\n// with the narrower `WorkflowCtx`; contravariance keeps those assignable to this param, so the internal\n// type never leaks into the public authoring surface while `EntityHost.register` still lines up.\ntype WorkflowFn = (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>;\n\n/**\n * Options for {@link WorkflowEngine.start}.\n *\n * Note the absence of `origin`: {@link WorkflowRun.origin} says which PACKAGE declared the workflow,\n * which is a property of the registered code, not of whoever started it. It is taken from the\n * registration and nothing here can override it — otherwise one caller could label its runs as\n * another lib's, and an origin filter would quietly lie.\n */\nexport interface StartOptions {\n /**\n * Start THIS registered version instead of the newest one. Omit (the default) and the run starts on\n * the newest registered version, exactly as it always has — this option only ever narrows.\n *\n * Resolved against the by-name@version registry, so it pins anything explicitly registered:\n * {@link WorkflowEngine.register}, {@link WorkflowEngine.registerRemote}, {@link WorkflowEngine.remote}.\n * A version that is NOT registered throws before a run row is created and NEVER falls back to\n * `latest` — a silent fallback is the exact failure this option exists to prevent (a caller that\n * asked for `name@3` and got `name@4` has no way to tell, and its run is already going).\n *\n * NOT available on the two SYNTHESIZED registration paths, which exist precisely because nothing is\n * registered: a child inheriting its remote ancestor's routing (see `findInheritedRegistration`),\n * and convention routing to a live worker group of the same name (`resolveRemoteByConvention`).\n * Both INVENT the version they stamp — the ancestor's, and the `'1'` convention default — as a\n * routing placeholder; neither is evidence that the worker has a body at the version you asked for.\n * A pinned start that reaches them therefore throws rather than pretending to have honoured the pin.\n * To pin a cross-SDK workflow, register it for real — `engine.remote('name', { version: '2', group })`\n * — which puts `name@2` in the registry and pins like any other registration.\n */\n version?: string | undefined;\n /** Run-scoped tags, merged with the workflow's static `@Workflow({ tags })` onto the run. */\n tags?: string[] | undefined;\n /** Typed, queryable run data stamped on the run (e.g. `{ amount: 200, tier: 'pro' }`). */\n searchAttributes?: SearchAttributes | undefined;\n /**\n * Dispatch priority for a remote run — stamped on the run and carried onto every {@link WorkflowTask}\n * the engine dispatches to advance it. Higher wins; absent = unprioritised. See {@link WorkflowRun.priority}.\n */\n priority?: number | undefined;\n /**\n * Override the namespace stamped on the run. Defaults to the engine's own `namespace`. Set by the\n * control plane when it starts a run on behalf of a tenant (a {@link StartRunMessage}'s `tenant`\n * maps here), so one DB-less-tenant-facing engine can create runs across many namespaces.\n */\n namespace?: string | undefined;\n /**\n * A start-time concurrency quota for this start — at most `limit` runs sharing `key` in flight;\n * over it, `start` throws {@link ConcurrencyLimitError} and creates nothing. Overrides the\n * workflow's registered `concurrency`. See {@link ConcurrencyQuota}.\n */\n concurrency?: ConcurrencyQuota | undefined;\n}\n\n/**\n * Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).\n * Excess runs are admitted in creation order, `limit` at a time; the rest wait (suspended) and retry\n * admission on a timer until a slot frees. The store atomically reserves durable slots before\n * ordering unadmitted waiters by `(createdAt, id)`, so later starts cannot displace a holder.\n */\nexport interface SingletonConfig {\n /** Derive the serialization key from the workflow input. */\n key: (input: unknown) => string;\n /** Max concurrent runs sharing the key. Default 1 (a mutex). */\n limit?: number;\n /**\n * Max GATED (waiting-for-admission) runs allowed to queue behind the `limit` in-flight ones. When\n * set, `start` rejects with {@link SingletonQueueFullError} once in-flight + gated reaches\n * `limit + maxQueueDepth` — back-pressure against an unbounded same-key backlog. Omit for the\n * default unbounded queue. Counts pending/running/suspended/blocked/cancelling runs sharing the key.\n */\n maxQueueDepth?: number;\n}\n\n/** Union of a workflow's static tags and a run's start-time tags, de-duplicated, or undefined if none. */\nfunction mergeTags(staticTags?: string[], runTags?: string[]): string[] | undefined {\n if (!staticTags?.length && !runTags?.length) return undefined;\n return [...new Set([...(staticTags ?? []), ...(runTags ?? [])])];\n}\n\n/** A breakpoint checkpoint's `name` is `breakpoint` (or `breakpoint:<label>`). This name — not the\n * reused `signal` kind — is the explicit marker the dashboard and `continue()` detect it by. */\nconst BREAKPOINT = 'breakpoint';\nconst isBreakpoint = (cp: { status: string; name: string }): boolean =>\n cp.status === 'pending' && cp.name.startsWith(BREAKPOINT);\n\ninterface RegisteredWorkflow {\n name: string;\n version: string;\n fn: WorkflowFn;\n /** Static `@Workflow({ tags })` — merged with per-run tags onto each run at start. */\n tags?: string[] | undefined;\n /** Per-key serialization (a durable mutex). See {@link SingletonConfig}. */\n singleton?: SingletonConfig | undefined;\n /** Start-time concurrency quota (reject over the limit). See {@link ConcurrencyConfig}. */\n concurrency?: ConcurrencyConfig | undefined;\n /** Max wall-clock lifetime (ms) before a run is cancelled by `sweepTimeouts`. */\n executionTimeoutMs?: number | undefined;\n /** Validate the input at start; throw to reject before a run is created. Validator-agnostic. */\n validateInput?: ((input: unknown) => void | Promise<void>) | undefined;\n /** Typed/validated `searchAttributes` shape. When set, `ctx.upsertSearchAttributes` validates the\n * merged result against it (see `createWorkflowCtx`). See `WorkflowMeta.searchAttributes`. */\n searchAttributesSchema?: SearchAttributesSchema | undefined;\n /** Event names that start a fresh run of this workflow when published. See `publishEvent`. */\n onEvent?: string[] | undefined;\n /** Coalesce `onEvent` triggers: debounce (fire once it's quiet) or batch (fire on size/window). */\n eventBatch?: EventBatchConfig | undefined;\n /** Set for a workflow advanced by DISPATCH instead of an inline `fn`: a cross-SDK (e.g. Python)\n * body via {@link WorkflowEngine.registerRemote}, OR a group-served TS body via\n * `register(..., { group, executor })`. The engine hands the run's history to `executor` (which\n * dispatches a workflow task to `group`) rather than running `fn` in-process. See\n * {@link WorkflowExecutor}. */\n remote?: { group: string; executor: WorkflowExecutor };\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake design §7.5).\n * Enforced before each remote turn's dispatch: if descriptors are published on its group but none is\n * capable+compatible, the run parks `blocked`. Absent/empty = \"runs anywhere\". */\n requires?: string[] | undefined;\n /** True when `fn` is a real in-process body (`register`), false/absent for a body-less remote whose\n * `fn` is the throwing stub (`registerRemote` / a synthesized remote child). Gates\n * {@link WorkflowEngine.workflowBody} so an in-app worker only ever gets a runnable body. */\n hasBody?: boolean | undefined;\n /** The package that declared this workflow, stamped onto every run it starts. See\n * {@link WorkflowRun.origin}. Absent = unknown; the engine never substitutes a default. */\n origin?: string | undefined;\n /**\n * Whether {@link version} is a fact somebody stated or the engine's placeholder.\n *\n * Only ever `false` on a registration synthesized by convention resolution against a fleet that\n * announced no version. Every other registration carries the version its author wrote, so the\n * field is absent (= stated) and nothing changes for them.\n *\n * It exists because the alternative — a `'1'` that nobody chose, indistinguishable from a `'1'`\n * somebody did — is what let a version pin pass by construction. See {@link VERSION_UNDECLARED_TAG}.\n */\n versionDeclared?: boolean | undefined;\n}\n\n/**\n * Stamped on a run whose workflow version NOBODY declared: a remote resolved by convention, served\n * by a worker that announces no version for it (an SDK too old to publish a descriptor, or a body\n * whose author simply never stated one).\n *\n * ## Why a run has to carry this\n *\n * Such a run's `workflowVersion` is `'1'`, the engine's convention default. That value is a routing\n * placeholder, not an observation — and read back later it is indistinguishable from a worker that\n * genuinely declared version `'1'`. Any check comparing an authored pin against it therefore passes\n * whenever the pin is `'1'` and fails whenever it is not, regardless of what the callee actually is.\n * A check that cannot fail is worse than no check, because it reads as a guarantee.\n *\n * The tag is the difference, carried ON the run so a retrospective check needs no second read: a\n * caller that pinned a version can see that the version it is comparing against was never stated,\n * and say so, instead of reporting a match it did not really make. It is deliberately a tag rather\n * than a new column — every store already persists and queries tags, so this needs no migration and\n * shows up in run listings and dashboards for free. Follows the `singleton:<key>` precedent for an\n * engine-stamped reserved tag.\n *\n * A run whose callee DOES declare a version never carries it; that run's version is the declared one\n * and a pin against it is genuinely checked.\n */\nexport const VERSION_UNDECLARED_TAG = 'version:undeclared';\n\nconst versionKey = (name: string, version: string): string => `${name}@${version}`;\n\n/**\n * The routing token a dispatched step lands on: the step's own name, suffixed by the tenant the RUN\n * belongs to. `runNamespace` — not the executing engine's namespace — is the tenant axis, because an\n * operator (namespace unset) drives runs of EVERY tenant: deriving the token from the engine would\n * send a tenant's work to the operator's own bare pool. This mirrors what an out-of-process worker\n * already does for the bodies it replays (it stamps its own partition onto each emitted `call`\n * command, see the worker SDK's `resolveCallGroup`) — the in-process executor had no equivalent,\n * which is exactly the gap this closes.\n *\n * An explicit {@link StepDef.partition} still wins, so a step pinned to a dedicated pool stays pinned.\n * `tenantGroup` maps `undefined`/`''`/`'default'` to the BARE token, so a single-tenant deployment\n * (and every `default`-namespace run) keeps byte-identical wire names.\n */\nfunction stepGroup(step: { name: string; partition?: string | undefined }, runNamespace?: string) {\n return tenantGroup(sanitizeQueueToken(step.name), step.partition ?? runNamespace);\n}\n\n/** The id for the next continuation of a run: `r` → `r~1` → `r~2` … (stable, traceable lineage). */\nfunction nextContinuationId(runId: string): string {\n const m = runId.match(/^(.*)~(\\d+)$/);\n return m ? `${m[1]}~${Number(m[2]) + 1}` : `${runId}~1`;\n}\n\n/** True when version `a` is newer than `b` (numeric when both parse as numbers, else natural sort). */\nfunction isNewerVersion(a: string, b: string): boolean {\n const na = Number(a);\n const nb = Number(b);\n if (!Number.isNaN(na) && !Number.isNaN(nb)) return na > nb;\n return a.localeCompare(b, undefined, { numeric: true }) > 0;\n}\n\n/** What a remote worker hands back: the output plus when it actually began (for queue-wait timing). */\ninterface RemoteResolution {\n output: unknown;\n startedAt?: number | undefined;\n events?: StepEvent[] | undefined;\n}\n\ninterface PendingRemote {\n resolve: (result: RemoteResolution) => void;\n reject: (error: Error) => void;\n}\n\n/** A terminal/suspended transition handed to {@link WorkflowEngine.settleRun}. */\ntype RunOutcome =\n | { kind: 'completed'; output: unknown }\n | { kind: 'failed'; error: StepError }\n | { kind: 'suspended'; wakeAt?: number | undefined }\n | { kind: 'blocked'; blocked: BlockedDispatch };\n\n/**\n * What {@link WorkflowEngine.unwindCompensations} returns when the run must keep waiting on a\n * dispatched compensation — `wakeAt` set while backing off a durable retry (the due-timer poller\n * re-drives it once elapsed), absent while freshly dispatched/in flight (only the worker's result,\n * via `completeRemoteResult`, re-drives it). `undefined` (no `UnwindPending`) means every\n * compensation resolved. Deliberately NOT a `RunResult`: the two callers persist \"still unwinding\"\n * differently (a plain `suspended` run for the failure path; `cancelling` held as-is for the cancel\n * path — see `compensateAndCancel`), so the settling is left to them.\n */\ninterface UnwindPending {\n wakeAt?: number | undefined;\n}\n\nexport interface WorkflowEngineDeps {\n store: StateStore;\n /** A single task transport. Shorthand for a one-entry `transports` pool (id `default`). */\n transport?: Transport | undefined;\n /**\n * An ordered pool of named transports. The engine dispatches on the first and fails over to the\n * next on a dispatch error; a step pins one via `ctx.step(step, input, { transport: id })`. Use\n * this instead of `transport` for failover / multi-broker setups.\n */\n transports?: NamedTransport[] | undefined;\n /**\n * Cross-instance broadcast pub/sub for lifecycle events + cancellation (see {@link ControlPlane}).\n * Separate from the task `transport`; omit for a single-instance / local-only setup. A transport\n * that can also broadcast may be passed here as well.\n */\n controlPlane?: ControlPlane | undefined;\n /** Epoch-ms clock; injectable for tests. Defaults to `Date.now`. */\n clock?: (() => number) | undefined;\n /**\n * Flow-control admission backend for `ctx.step(step, input, { queue })`. Defaults to an in-process\n * {@link InMemoryAdmissionBackend} (per-instance caps). Inject a store/Redis-backed backend to make\n * concurrency / rate-limit / ordering GLOBAL across engine replicas.\n */\n admission?: AdmissionBackend | undefined;\n /** Unique id for this engine instance, used for recovery leases. Defaults to a random id. */\n instanceId?: string | undefined;\n /**\n * Worker-pool partition for this engine. Stamped on every run it creates; the poll paths\n * (`runPending`/`recoverIncomplete`/`resumeDueTimers`/`sweepTimeouts`) only act on runs in this\n * namespace. Set distinct values to safely share ONE state store across non-interchangeable pools\n * (e.g. local dev vs a cluster). **Omit it to make this engine an OPERATOR** — an unset namespace\n * drives/recovers/resumes runs of EVERY namespace (the poll filters no-op, the resume/decision\n * guards fall through) and leaves the transport on its bare prefix. This is the hosted control\n * plane: \"ver tudo = ausência de namespace\".\n */\n namespace?: string | undefined;\n /** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */\n leaseMs?: number | undefined;\n /**\n * Cap how many times crash-recovery may pick up the same still-`running` run before giving up and\n * moving it to the `dead` dead-letter state (a poison pill that crashes the process every boot).\n * Omit for unlimited (the default — recovery always retries).\n */\n maxRecoveryAttempts?: number | undefined;\n /**\n * Opt-in liveness deadline (ms) for a remote workflow `advance`. If the worker neither returns a\n * decision NOR sends a run-scoped {@link Heartbeat} within this window, the engine presumes it dead:\n * it rejects the advance with {@link RemoteWorkflowTimeout}, releases the lease, and lets recovery\n * re-drive (replaying completed steps from history). Each beat REARMS the window, so a worker still\n * legitimately replaying a long turn (it keeps beating) is never re-driven — closing the duplicate-\n * side-effect hazard a fixed {@link RemoteWorkflowExecutor} `timeoutMs` cannot avoid. Omit (default)\n * for the prior unbounded await — byte-identical behavior when unset. If a `RemoteWorkflowExecutor` is\n * ALSO constructed with its own `timeoutMs`, the shorter of the two deadlines wins; prefer setting only\n * one (this rearmed window for heartbeat-aware workers, or the fixed `timeoutMs` otherwise).\n */\n remoteAdvanceSilenceMs?: number | undefined;\n /**\n * Fallback re-drive window (ms) for a run that SUSPENDS with no natural timer — i.e. it's waiting on\n * an EVENT to wake it (a child's completion, a signal, a remote step with no `timeoutMs`) rather than\n * a `ctx.sleep`. Those events re-drive the run directly; but if the wake is LOST (the delivering pod\n * crashed / rolled mid-handoff), the run would otherwise sit `suspended` forever with `wakeAt: null` —\n * invisible to both the timer poller (no `wakeAt`) and crash-recovery (no lease). This stamps a\n * fallback `wakeAt` so {@link resumeDueTimers} re-drives it after the window; the re-drive is an\n * idempotent replay (a still-pending dependency re-suspends via the checkpoint guard, a settled one\n * advances), so it's a safe self-heal, not a retry that can double-dispatch. The primary event path\n * still wins first for a healthy run (it re-drives long before this fires), so this only ever fires\n * for a genuinely-orphaned run. Default 5min; set `0` to disable (the prior wake-forever behavior).\n */\n reconcileMs?: number | undefined;\n /**\n * Retention for a BUFFERED event that no `waitForEvent` ever claims (see\n * {@link WorkflowEngine.publishEvent}'s buffering — a publish matching no live waiter keeps ONE\n * copy around for a later matching wait). Default `undefined`: keep it until consumed, same as\n * {@link StateStore.bufferSignal}'s buffered signals — no silent expiry. Set a duration (ms) to\n * have the {@link resumeDueTimers} reconcile pass prune rows past `publishedAt + eventBufferTtlMs`\n * as it encounters them. Scoped to event NAMES the current reconcile tick's registered waiters\n * reference (the sweep has no reason to otherwise enumerate every buffered name) — a name with a\n * stale buffered event but zero waiters ever registered against it is not visited by this pass; that\n * is an accepted gap given `listBufferedEvents` is name-scoped by design (see interfaces.ts), not a\n * bug to route around here.\n */\n eventBufferTtlMs?: number | undefined;\n /**\n * Opt-in self-heal window (ms) for a remote step with NO `timeoutMs` whose dispatched job was LOST —\n * the worker crashed mid-step leaving no result, or the transport dropped the job (a Redis\n * flush/eviction, or BullMQ moving a stalled job to `failed` and removing it). The `pending`\n * checkpoint then has no result to resume on, and — BY DESIGN (see {@link reconcileMs}) — the\n * reconcile re-drive re-suspends a still-pending step rather than re-dispatching, so a slow-but-live\n * worker is never double-run. That safety means a genuinely-lost dispatch would otherwise hang\n * forever. When set, a reconcile re-drive that finds a remote step still `pending` PAST this window\n * re-dispatches it (bumping `attempts`, bounded by {@link remoteRedispatchMax}). Off by default:\n * re-dispatch can double-run a step whose original job is merely slow, so the window MUST exceed the\n * longest such step and the step MUST be idempotent. Prefer a per-step `timeoutMs` (tighter,\n * heartbeat-aware) where you can; this is the store-driven net for no-timeout steps that must\n * survive a lost dispatch. {@link WorkflowEngine.redispatchPending} is the manual counterpart.\n */\n remoteRedispatchMs?: number | undefined;\n /**\n * Max times {@link remoteRedispatchMs} re-dispatches one lost remote step before giving up and\n * failing it as a {@link RemoteStepError} (`code: 'remote_step_lost'`), so the run fails / dead-letters\n * instead of re-dispatching forever. Default 10. Ignored when `remoteRedispatchMs` is unset.\n */\n remoteRedispatchMax?: number | undefined;\n /**\n * How long (ms) a run parked `blocked` (no capability-capable + protocol-compatible live worker,\n * handshake design §7.5) waits before the blocked-recovery poll re-drives it to re-check the live\n * fleet. Default 5000. The run proceeds the moment a capable+compatible worker appears; until then it\n * re-parks with a fresh `wakeAt` each poll. Only relevant once a step/workflow declares `requires`\n * AND descriptors are published (a legacy fleet never parks blocked).\n */\n blockedPollMs?: number | undefined;\n /**\n * Build the public callback URL for a `ctx.webhook()` token (e.g.\n * ``(t) => `https://api.example.com/durable/webhooks/${t}` ``). Populates\n * {@link DurableWebhook.url}. Omit if you build URLs yourself from the token.\n */\n webhookUrl?: ((token: string) => string) | undefined;\n /**\n * Provide the current W3C `traceparent` to stamp on each dispatched {@link RemoteTask}, so a\n * worker (including the Python SDK) continues the distributed trace. Keep core OTel-free: supply\n * `otelTraceparent` from `@dudousxd/nestjs-durable-otel`, or your own context reader. Omit to send none.\n */\n traceparent?: (() => string | undefined) | undefined;\n /**\n * Provide an opaque context carrier (tenant / user / correlation ids) to attach to each dispatched\n * {@link RemoteTask} as its `context`, so a worker (including the Python SDK) re-exposes it to the\n * step handler — cross-process propagation alongside the {@link traceparent}. Keep core dependency-free:\n * supply this from `@dudousxd/nestjs-context` or your own request-scoped reader. The engine never\n * inspects the returned object's shape. Omit to send none.\n *\n * Re-evaluated at each (re)dispatch — including a retry or a resume that the engine drives AFTER a\n * crash/scale-down, which runs OUTSIDE the originating request scope. On such a path this provider\n * may return empty or stale values (the request-scoped tenant/user is gone). Treat the carrier as\n * best-effort correlation/propagation metadata only — do NOT treat it as an authorization boundary.\n */\n context?: (() => Record<string, unknown> | undefined) | undefined;\n /**\n * Re-hydrate the originating context around a LOCAL step body, so a `@DurableStep` reader sees the\n * tenant / user / correlation ids that were live when the run was started — even on a path the\n * engine drives outside the originating request scope (a resume after crash/scale-down, a timer).\n * Given the carrier produced by {@link context} (may be empty/undefined) and the step body `fn`, it\n * runs `fn` with that context ambiently established (e.g. inside `@dudousxd/nestjs-context`'s ALS)\n * and returns its result. Keep core dependency-free: supply this from the nestjs wiring (which owns\n * nestjs-context) or your own ALS bridge. The handler signature is unchanged — re-hydration is\n * ambient. Default: passthrough (`(_, fn) => fn()`), so behavior is byte-identical when unset.\n */\n rehydrate?: (<T>(carrier: Record<string, unknown> | undefined, fn: () => T) => T) | undefined;\n /**\n * Attempts for each saga compensation when the run fails (a transient undo — e.g. a refund API\n * hiccup — gets another try). Default 1 (no retry). Compensations must be idempotent.\n */\n compensationRetries?: number | undefined;\n /**\n * Persist a `running` checkpoint when a local step's body begins, so an in-flight step shows up\n * in the dashboard (and a fresh page load / REST query) the moment it starts — not only once it\n * completes. The `step.started` lifecycle event is emitted either way (the live SSE view always\n * sees the start); this flag only controls the extra checkpoint write. Default `true`. Set\n * `false` on hot paths with many short local steps to halve their checkpoint writes — you keep\n * the live event but lose reload-survivable in-flight visibility.\n */\n trackStepStart?: boolean | undefined;\n /**\n * Where a freshly-`start`ed run executes (see {@link RunDispatcher}). Defaults to in-process: the\n * run executes on this instance asynchronously (a microtask), so `start` returns without blocking.\n * Pass a no-op dispatcher on a caller that must NOT run workflows (e.g. an API/dashboard pod), and\n * run `runPending` on a worker pod to pick those up; or a broker-backed one for a worker pool.\n */\n runDispatcher?: RunDispatcher | undefined;\n}\n\n/** Thrown by {@link WorkflowEngine.resume} when the run belongs to a different namespace. */\nclass NamespaceMismatch extends Error {\n constructor() {\n super('namespace-mismatch');\n }\n}\n\n/**\n * The orchestrator. Owns workflow state and replays runs deterministically: each step's\n * result is checkpointed, so on resume a completed step returns its saved output instead of\n * re-executing. Remote steps are dispatched over the Transport; their results checkpoint the\n * same way local steps do.\n */\nexport class WorkflowEngine {\n private readonly store: StateStore;\n /** Ordered transport pool (dispatch + failover). Empty = no remote steps. */\n private readonly pool: TransportPool;\n private readonly controlPlane?: ControlPlane | undefined;\n private readonly clock: () => number;\n private readonly instanceId: string;\n private readonly namespace: string | undefined;\n private readonly leaseMs: number;\n private readonly maxRecoveryAttempts?: number | undefined;\n private readonly remoteAdvanceSilenceMs?: number | undefined;\n private readonly reconcileMs: number | undefined;\n private readonly eventBufferTtlMs: number | undefined;\n private readonly remoteRedispatchMs: number | undefined;\n private readonly remoteRedispatchMax: number;\n /** How long a `blocked` run waits before the recovery poll re-checks the live fleet (design §7.5). */\n private readonly blockedPollMs: number;\n /** This engine's control-plane handshake descriptor — negotiated against each worker (design §7.3). */\n private readonly cpDescriptor: WorkerDescriptor;\n private readonly webhookUrl?: ((token: string) => string) | undefined;\n private readonly traceparent?: (() => string | undefined) | undefined;\n private readonly context?: (() => Record<string, unknown> | undefined) | undefined;\n /** Establish the originating context ambiently around a local step body (see {@link WorkflowEngineDeps.rehydrate}). Default passthrough. */\n private readonly rehydrate: <T>(carrier: Record<string, unknown> | undefined, fn: () => T) => T;\n private readonly compensationRetries: number;\n /** Persist a `running` checkpoint at the start of a local step body (see {@link WorkflowEngineDeps.trackStepStart}). */\n private readonly trackStepStart: boolean;\n /** Where a freshly-started run executes — in-process by default (see {@link RunDispatcher}). */\n private readonly runDispatcher: RunDispatcher;\n\n /** Per-key serialization for singleton workflows (admission, back-pressure, notify-on-release). */\n private readonly singletons: SingletonGate;\n /**\n * Persisted, runtime-managed schedules: create/upsert/pause/resume/delete/list/trigger them, and\n * `tick()` fires the due ones (the NestJS timer poller does it when `persistedSchedules` is on).\n * Needs a store that persists schedules — every bundled adapter does. See {@link ScheduleClient}.\n */\n readonly schedules: ScheduleClient;\n /** Every registered workflow, keyed by `name@version` — so old versions stay runnable. */\n private readonly workflows = new Map<string, RegisteredWorkflow>();\n /** The newest registered version per workflow name — used to `start` new runs. */\n private readonly latest = new Map<string, RegisteredWorkflow>();\n /** Event name → workflow names started when that event is published (see `onEvent`). */\n private readonly eventTriggers = new Map<string, Set<string>>();\n /** Durable-entity subsystem (registers the `__entity` runner; see `registerEntity`). */\n private readonly entities: Entities;\n /** Event debounce/batch accumulators (register the `__evt_*` runners; see `accumulators.route`). */\n private readonly accumulators: EventAccumulators;\n /** In-flight remote steps awaiting a worker result, keyed by stepId. */\n private readonly pending = new Map<string, PendingRemote>();\n /** \"Reset the liveness timer\" callbacks keyed by the beat's target — a stepId (in-flight remote step)\n * or a runId (in-flight remote workflow turn) — invoked when a matching heartbeat arrives. The two id\n * shapes don't collide in practice: a stepId is `${runId}:${seq}`, a run key is the bare runId. */\n private readonly heartbeatResets = new Map<string, () => void>();\n private readonly listeners = new Set<EngineListener>();\n /** Step interceptors (onion middleware around real local-step execution), first = outermost. */\n private readonly interceptors: StepInterceptor[] = [];\n /** Callbacks notified (on any instance) when a run is cancelled — for cooperative cancellation. */\n private readonly cancelListeners = new Set<(runId: string) => void>();\n /** Callbacks notified when a run is enqueued elsewhere — for low-latency cross-pod dispatch. */\n private readonly enqueuedListeners = new Set<(runId: string) => void>();\n /** Notified when a run is dead-lettered (moved to `dead`) — a hook for a DLQ handler. */\n private readonly deadListeners = new Set<(run: WorkflowRun) => void>();\n /** Validators gating `engine.update`, keyed by `<workflow>:<updateName>`. */\n private readonly updateValidators = new Map<string, UpdateValidator>();\n /** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */\n private readonly cancelRequested = new Set<string>();\n /** Flow-control admission backend for remote steps (see {@link registerQueue}). */\n private readonly admission: AdmissionBackend;\n /** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */\n private readonly queueWaiters = new Map<string, Set<string>>();\n /** Which queue a dispatched step took a slot from, by stepId — so the result can release it. */\n private readonly stepQueue = new Map<string, string>();\n /** Executions currently in flight, so a graceful shutdown can wait for them to settle. */\n private readonly inflight = new Set<Promise<RunResult>>();\n private draining = false;\n\n constructor(deps: WorkflowEngineDeps) {\n this.store = deps.store;\n this.pool = new TransportPool(\n deps.transports ?? (deps.transport ? [{ id: 'default', transport: deps.transport }] : []),\n );\n this.controlPlane = deps.controlPlane;\n this.clock = deps.clock ?? Date.now;\n this.admission = deps.admission ?? new InMemoryAdmissionBackend(this.clock);\n // Wake this instance's admission-blocked runs the moment a slot frees anywhere in the fleet,\n // instead of waiting for their retry tick. Best-effort (the retry tick remains the guarantee).\n this.admission.onFreed?.((queue) => this.wakeQueueWaiters(queue));\n this.instanceId = deps.instanceId ?? globalThis.crypto.randomUUID();\n this.namespace = deps.namespace;\n // The engine's namespace deliberately does NOT touch the transport(s). The two tenancy axes are\n // orthogonal and encode differently ON PURPOSE (the cross-SDK canonical wire convention):\n // - `namespace` scopes the STORE (which runs this engine drives/recovers) and stamps every run\n // it starts; per-run routing then suffixes GROUP tokens (`<name>@<tenant>`, see tenantGroup)\n // on the transport's own prefix — the same convention every worker SDK (Python, the TS\n // tenant role) speaks natively.\n // - Whole-DEPLOYMENT isolation on a shared broker is the transport's `prefix`/`namespace`\n // constructor options — explicit, never inferred from the engine.\n // (An earlier design auto-folded a scoped engine's namespace into the transport prefix,\n // producing a keyspace no tenant worker could see — the tenant ended up encoded twice, once in\n // the prefix and once in the group suffix, and cross-runtime discovery silently failed.)\n this.leaseMs = deps.leaseMs ?? 30_000;\n this.maxRecoveryAttempts = deps.maxRecoveryAttempts;\n this.remoteAdvanceSilenceMs = deps.remoteAdvanceSilenceMs;\n // Default 5min; an explicit 0 disables the fallback (opt back into wake-forever-on-lost-event).\n this.reconcileMs = deps.reconcileMs === undefined ? 300_000 : deps.reconcileMs || undefined;\n // Opt-in: unset (or 0) keeps buffered events around forever, same as buffered signals.\n this.eventBufferTtlMs = deps.eventBufferTtlMs || undefined;\n // Opt-in: unset (or 0) leaves the by-design \"re-suspend a lost dispatch, never re-dispatch\" behavior.\n this.remoteRedispatchMs = deps.remoteRedispatchMs || undefined;\n this.remoteRedispatchMax = Math.max(1, deps.remoteRedispatchMax ?? 10);\n this.blockedPollMs = deps.blockedPollMs ?? 5000;\n // The control-plane descriptor this engine negotiates against each worker's advertised descriptor\n // (design §7.3): it speaks the current protocol band and is scoped to this engine's namespace so a\n // pool-mismatched worker isn't considered. Capabilities empty — the CP routes, it doesn't execute.\n this.cpDescriptor = controlPlaneDescriptor({\n instanceId: `cp-${this.instanceId}`,\n ...(this.namespace !== undefined ? { namespace: this.namespace } : {}),\n });\n this.webhookUrl = deps.webhookUrl;\n this.traceparent = deps.traceparent;\n this.context = deps.context;\n // Default passthrough: with no bridge supplied, a local step body runs exactly as before.\n this.rehydrate = deps.rehydrate ?? ((_carrier, fn) => fn());\n this.compensationRetries = Math.max(1, deps.compensationRetries ?? 1);\n this.trackStepStart = deps.trackStepStart ?? true;\n // Default: execute the run on this instance, asynchronously, so `start` never blocks on the body.\n // A failed pickup is swallowed here (the run stays `pending` for a `runPending` poll to retry);\n // run failures themselves are handled inside `execute` and surfaced as the run's `failed` state.\n this.runDispatcher = deps.runDispatcher ?? {\n dispatch: (runId) => queueMicrotask(() => void this.runOne(runId).catch(() => {})),\n };\n this.singletons = new SingletonGate({\n store: this.store,\n clock: this.clock,\n dispatch: (runId) => {\n this.runDispatcher.dispatch(runId);\n },\n configFor: (run) =>\n (\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n this.latest.get(run.workflow)\n )?.singleton,\n });\n this.schedules = new ScheduleClient(\n this.store,\n {\n start: (workflow, input, runId, opts) => this.start(workflow, input, runId, opts),\n getRun: (runId) => this.store.getRun(runId),\n },\n { namespace: this.namespace, clock: this.clock },\n );\n this.pool.bind(\n async (result) => {\n // In-memory path (a `timeoutMs` step awaiting on THIS instance): resolve its pending promise.\n const waiter = this.pending.get(result.stepId);\n if (waiter) {\n this.pending.delete(result.stepId);\n if (result.status === 'completed') {\n waiter.resolve({\n output: result.output,\n startedAt: result.startedAt,\n events: result.events,\n });\n } else {\n waiter.reject(new RemoteStepError(result.error));\n }\n return;\n }\n // Durable path: no in-memory waiter (the step suspended the run, possibly on another\n // instance) → complete the checkpoint and resume the run here.\n await this.completeRemoteResult(result);\n },\n // A heartbeat resets the liveness window for whatever it targets: an in-flight long STEP (keyed\n // by stepId, see callRemote) or — when stepId is absent — the in-flight workflow TURN (keyed by\n // runId). For an INLINE-advance turn the reset is an in-memory callback; without one (the step\n // or turn suspended durably, possibly on another instance) the beat rearms the DURABLE deadline\n // instead: the suspended turn's `wakeAt` for a run-scoped beat, the step's lease for a\n // step-scoped one — either way keeping a live worker's work from being presumed lost.\n async (beat) => {\n const reset = this.heartbeatResets.get(beat.stepId ?? beat.runId);\n if (reset) {\n reset();\n return;\n }\n if (beat.stepId === undefined) {\n await this.rearmDecisionDeadline(beat.runId);\n return;\n }\n await this.rearmStepLease(beat.runId, beat.seq);\n },\n // A remote workflow worker streams each local step's lifecycle (running → completed/failed) so\n // it's checkpointed live, not all-at-once when the long turn ends.\n async (event) => {\n await this.persistStepEvent(event);\n },\n // A workflow-turn DECISION delivered over the broker — applied durably (by run id) on whatever\n // instance consumes it, NOT correlated to an in-memory promise on the dispatcher. This is the\n // multi-instance fix: a point-to-point broker may hand the decision to a non-dispatching instance.\n async (decision) => {\n await this.completeRemoteDecision(decision);\n },\n );\n // Control-plane start-run: a DB-less tenant worker publishes a StartRunMessage and this\n // (control-plane) engine turns it into a durable run stamped with the tenant's namespace. Guarded\n // by the transport's `onStartRun` capability (like the other optional transport hooks) — a pool\n // whose transport can't carry the channel simply never registers, so a worker-only engine no-ops.\n this.pool.onStartRun(async (message) => {\n await this.start(\n message.workflow,\n message.input,\n message.runId ?? globalThis.crypto.randomUUID(),\n {\n namespace: message.tenant,\n tags: message.tags,\n searchAttributes: message.searchAttributes,\n },\n );\n });\n // Control plane: re-broadcast lifecycle events from OTHER instances to this instance's\n // subscribers (cross-pod live-tail), and act on cancellations issued elsewhere. A broker may\n // echo our own publish back — ignore those (we already handled them locally) to avoid duplicates.\n this.controlPlane?.onControl((msg) => {\n if (msg.from === this.instanceId) return;\n if (msg.kind === 'event') {\n // `at` may be a string after JSON transit (Redis) — normalize back to a Date.\n this.deliver({ ...msg.event, at: new Date(msg.event.at) });\n } else if (msg.kind === 'cancel') {\n this.notifyCancelled(msg.runId);\n } else if (msg.kind === 'enqueued') {\n // A run was enqueued on another instance — let worker subscribers pick it up immediately\n // instead of waiting for the next poll. (Self-broadcasts are already filtered above.)\n for (const fn of this.enqueuedListeners) {\n try {\n fn(msg.runId);\n } catch {\n /* an enqueue listener must not break the engine */\n }\n }\n }\n });\n this.accumulators = new EventAccumulators(this);\n this.entities = new Entities(this);\n }\n\n /**\n * Register a **durable entity** (a virtual object): a keyed actor whose `handlers` run **serialized\n * per key** over **durable state**, exactly once. Drive it with `signalEntity` (fire) /\n * `ctx.callEntity` (call + await result) and read its state with `getEntityState`. See {@link Entities}.\n */\n registerEntity<S>(name: string, config: EntityConfig<S>): void {\n this.entities.register(name, config);\n }\n\n /** Send an operation to an entity (fire-and-forget). Ordered + exactly-once per key. */\n signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void> {\n return this.entities.signal(name, key, op, arg);\n }\n\n /** Read an entity's current durable state (published after each op), or undefined if it has none yet. */\n getEntityState<S = unknown>(name: string, key: string): Promise<S | undefined> {\n return this.entities.getState<S>(name, key);\n }\n\n /**\n * Be notified when a run is enqueued on ANOTHER instance (via the control plane), so a worker can\n * pick it up at once — e.g. `engine.onEnqueued((runId) => engine.runOne(runId))`. Returns an\n * unsubscribe function. Only wire this on instances that should execute runs (workers).\n */\n onEnqueued(listener: (runId: string) => void): () => void {\n this.enqueuedListeners.add(listener);\n return () => this.enqueuedListeners.delete(listener);\n }\n\n /** Fire cooperative-cancellation listeners for `runId` (a worker bridge aborts in-flight work). */\n private notifyCancelled(runId: string): void {\n for (const fn of this.cancelListeners) {\n try {\n fn(runId);\n } catch {\n /* a cancel listener must not break the engine */\n }\n }\n }\n\n /**\n * Register a workflow version. Register multiple versions of the same name to keep in-flight\n * runs working across a breaking change: old runs resume on the version they started on, new\n * runs start on the newest registered version.\n *\n * GROUP-SERVED (uniform dispatch, opt-in): pass `{ group, executor }` to have the engine DISPATCH\n * this workflow's turns to a worker `group` (via `executor.advance`) instead of running `fn`\n * inline — exactly as {@link registerRemote} does for a cross-SDK (e.g. Python) body, EXCEPT the\n * body is a TS `fn` the engine retains so an IN-APP worker on `group` can fetch it by name\n * ({@link workflowBody}) and run it. This is \"one app, both roles\": the same process owns the\n * engine AND consumes its own group. Recovery, timers, singleton, cancel and dead-lettering stay\n * engine concerns, identical to a remote run. OMIT `group`/`executor` (the default) to keep the\n * inline fast path — `fn` runs in-process and the run pays zero dispatch round-trips. The first\n * step toward routing every run through a group with no local/remote flag (Phase 3).\n */\n register(\n name: string,\n version: string,\n fn: WorkflowFn,\n opts?: {\n tags?: string[] | undefined;\n singleton?: SingletonConfig | undefined;\n /** Start-time concurrency quota — see {@link ConcurrencyConfig}. */\n concurrency?: ConcurrencyConfig | undefined;\n executionTimeout?: string | number | undefined;\n validateInput?: ((input: unknown) => void | Promise<void>) | undefined;\n /** Typed/validated `searchAttributes` shape — see `RegisteredWorkflow.searchAttributesSchema`. */\n searchAttributesSchema?: SearchAttributesSchema | undefined;\n onEvent?: string[] | undefined;\n eventBatch?: EventBatchConfig | undefined;\n /** Worker group to DISPATCH this workflow's turns to (uniform dispatch). Requires `executor`.\n * Omit for the default inline fast path. See the method doc. */\n group?: string | undefined;\n /** Advances a turn by dispatching a {@link WorkflowTask} to `group`. Requires `group`. For an\n * in-app worker, pair a transport-backed {@link RemoteWorkflowExecutor} (group consumed by a\n * worker that calls {@link workflowBody}) so the retained `fn` runs through the transport hop. */\n executor?: WorkflowExecutor | undefined;\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5).\n * Only meaningful with `group`/`executor` (a remote/group-served workflow). Absent = runs anywhere. */\n requires?: string[] | undefined;\n /** The package that DECLARED this workflow, stamped onto every run started from it (see\n * {@link WorkflowRun.origin}). Supplied by the registering integration — `@dudousxd/nestjs-durable`\n * derives it from the `@Workflow` class's declaring file — never by whoever calls `start`. Omit\n * when it cannot be derived with confidence: absent means UNKNOWN, and an absent origin is far\n * cheaper to live with than a wrong one. */\n origin?: string | undefined;\n },\n ): void {\n // Group-served is all-or-nothing: a `group` with no `executor` (or vice-versa) is a wiring bug —\n // fail loudly at registration rather than silently falling back to the inline path at dispatch.\n if ((opts?.group == null) !== (opts?.executor == null)) {\n throw new Error(\n `workflow ${name}@${version}: register({ group, executor }) needs BOTH group and executor (or neither)`,\n );\n }\n const registered: RegisteredWorkflow = {\n name,\n version,\n fn,\n tags: opts?.tags,\n singleton: opts?.singleton,\n concurrency: opts?.concurrency,\n executionTimeoutMs:\n opts?.executionTimeout != null ? parseDuration(opts.executionTimeout) : undefined,\n validateInput: opts?.validateInput,\n searchAttributesSchema: opts?.searchAttributesSchema,\n onEvent: opts?.onEvent,\n eventBatch: opts?.eventBatch,\n requires: opts?.requires,\n origin: opts?.origin,\n // A real, retained in-process body — so `workflowBody` can hand it to an in-app worker, and so\n // it is NOT confused with the throwing stub `registerRemote` installs for a body-less remote.\n hasBody: true,\n };\n // When group-served, route DISPATCH through the executor (the same `remote` branch a Python\n // workflow takes); `fn` above stays usable for the in-app worker. Omitted = inline fast path.\n if (opts?.group != null && opts?.executor != null) {\n registered.remote = { group: opts.group, executor: opts.executor };\n }\n this.workflows.set(versionKey(name, version), registered);\n const current = this.latest.get(name);\n if (!current || isNewerVersion(version, current.version)) this.latest.set(name, registered);\n for (const event of opts?.onEvent ?? []) {\n const subscribers = this.eventTriggers.get(event) ?? new Set<string>();\n subscribers.add(name);\n this.eventTriggers.set(event, subscribers);\n }\n }\n\n /**\n * The retained in-process body for `name@version`, for an IN-APP worker that consumes this engine's\n * own group to SERVE a group-served `register(..., { group, executor })` workflow (uniform dispatch):\n * the worker fetches the body by name when it picks up the dispatched {@link WorkflowTask}, replays\n * it, and returns the {@link WorkflowDecision}. `undefined` for an unregistered name or a body-less\n * remote (a `registerRemote` / synthesized child carries only a throwing stub, never handed out).\n */\n workflowBody(name: string, version: string): WorkflowFn | undefined {\n const reg = this.workflows.get(versionKey(name, version));\n return reg?.hasBody ? reg.fn : undefined;\n }\n\n /** The registered versions of `name`, for the pinned-start error — \"2 is not registered\" is a\n * guess-the-typo error without them, and the answer (which versions this deploy actually carries)\n * is right here. `none` when the name is unknown entirely. */\n private registeredVersions(name: string): string {\n const versions = [...this.workflows.values()]\n .filter((w) => w.name === name)\n .map((w) => w.version);\n return versions.length ? versions.join(', ') : 'none';\n }\n\n /**\n * Register a workflow whose body runs in another SDK (e.g. Python). The engine owns the run exactly\n * as for a TS workflow — it persists checkpoints, recovers, runs timers — but advances it by handing\n * the run's history to `executor` (which dispatches a {@link WorkflowTask} to the worker) and applying\n * the {@link WorkflowDecision} the worker's replay returns. The worker never touches the store.\n */\n registerRemote(\n name: string,\n version: string,\n opts: {\n group: string;\n executor: WorkflowExecutor;\n tags?: string[];\n singleton?: SingletonConfig;\n concurrency?: ConcurrencyConfig;\n executionTimeout?: string | number;\n validateInput?: (input: unknown) => void | Promise<void>;\n /** Capabilities a live worker must advertise to run this remote workflow's turns (handshake §7.5). */\n requires?: string[];\n },\n ): void {\n const registered: RegisteredWorkflow = {\n name,\n version,\n // A remote workflow has no in-process body; execute() branches on `remote` before this is read.\n fn: () => {\n throw new Error(`workflow ${name} is remote — it has no in-process body`);\n },\n tags: opts.tags,\n singleton: opts.singleton,\n concurrency: opts.concurrency,\n executionTimeoutMs:\n opts.executionTimeout != null ? parseDuration(opts.executionTimeout) : undefined,\n validateInput: opts.validateInput,\n requires: opts.requires,\n remote: { group: opts.group, executor: opts.executor },\n };\n this.workflows.set(versionKey(name, version), registered);\n const current = this.latest.get(name);\n if (!current || isNewerVersion(version, current.version)) this.latest.set(name, registered);\n }\n\n /**\n * The convenience form of {@link registerRemote}: register a workflow whose body runs on a worker\n * `group` (e.g. the Python `durable-worker`, or a separate TS worker), without hand-building a\n * {@link RemoteWorkflowExecutor}. It wires the standard broker executor — a `RemoteWorkflowExecutor`\n * over the engine's own transport, dispatching to `opts.group` — for you, so you write\n * `engine.remote('processing', { group: 'processing' })` instead of\n * `engine.registerRemote('processing', '1', { group: 'processing', executor: new RemoteWorkflowExecutor(transport, 'processing') })`.\n *\n * Defaults the version to `'1'`. All the other {@link registerRemote} options\n * (`tags` / `singleton` / `executionTimeout` / `validateInput`) pass straight through. Reach for the\n * low-level {@link registerRemote} when you need a custom {@link WorkflowExecutor} (a different\n * transport, a fixed `timeoutMs`, a polyglot stub) — `remote()` is the standard wiring on the rails.\n */\n remote(\n name: string,\n opts: {\n /** Worker group this workflow's turns are dispatched to (also the executor's target group). */\n group: string;\n /** Workflow version. Defaults to `'1'`. */\n version?: string;\n tags?: string[];\n singleton?: SingletonConfig;\n concurrency?: ConcurrencyConfig;\n executionTimeout?: string | number;\n validateInput?: (input: unknown) => void | Promise<void>;\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5). */\n requires?: string[];\n },\n ): void {\n const { group, version, ...rest } = opts;\n const executor = new RemoteWorkflowExecutor(this.pool.primary, group);\n this.registerRemote(name, version ?? '1', { group, executor, ...rest });\n }\n\n /**\n * Register a flow-control queue referenced by `ctx.step(step, input, { queue })`. Caps concurrent\n * in-flight steps and/or the admission rate; blocked calls re-suspend and retry, so the limit is\n * durable. Per engine instance (see {@link QueueConfig}). Registering the same name replaces it.\n */\n registerQueue(config: QueueConfig): void {\n this.admission.register(config);\n }\n\n /** Subscribe to lifecycle events. Returns an unsubscribe function. */\n subscribe(listener: EngineListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Register a {@link StepInterceptor} — onion middleware run around the real execution of every\n * local `ctx.step` (timing, logging, tracing, error enrichment, context propagation). First\n * registered is outermost; interceptors fire only when a step executes, never on replay. Returns\n * an unsubscribe function.\n */\n use(interceptor: StepInterceptor): () => void {\n this.interceptors.push(interceptor);\n return () => {\n const i = this.interceptors.indexOf(interceptor);\n if (i >= 0) this.interceptors.splice(i, 1);\n };\n }\n\n /**\n * Fold the registered interceptors around a local step body (identity when there are none), then\n * run the whole thing inside the re-hydrated originating context. The carrier is read at execution\n * time from {@link context} — the SAME reader stamped on dispatched remote tasks — so a local step\n * sees the live tenant / user / trace ids ambiently (via the {@link rehydrate} bridge). Default\n * `rehydrate` is a passthrough, so this is byte-identical to a bare body call when unwired.\n */\n private interceptStep<T>(invocation: StepInvocation, body: () => Promise<T>): Promise<T> {\n const carrier = this.context?.();\n const run = (): Promise<T> => {\n if (this.interceptors.length === 0) return body();\n const chain = this.interceptors.reduceRight<() => Promise<unknown>>(\n (next, interceptor) => () => interceptor(invocation, next),\n body as () => Promise<unknown>,\n );\n return chain() as Promise<T>;\n };\n return this.rehydrate(carrier, run);\n }\n\n /**\n * Be notified when a run is cancelled — on ANY instance, via the transport control plane. A\n * worker bridge can use this for cooperative cancellation: abort the in-flight work for `runId`\n * instead of finishing it just to have the result discarded. Returns an unsubscribe function.\n */\n onCancel(listener: (runId: string) => void): () => void {\n this.cancelListeners.add(listener);\n return () => this.cancelListeners.delete(listener);\n }\n\n /**\n * Be notified when a run is **dead-lettered** — moved to `dead` after exceeding\n * `maxRecoveryAttempts`. The listener receives the dead run (status `dead`, with its error), so a\n * DLQ handler can do something other than just leaving it parked: alert, push to a real queue, or\n * start a dead-letter workflow (e.g. `engine.onDead((run) => engine.start('pipeline-dlq', run, ...))`).\n * Returns an unsubscribe function.\n */\n onDead(listener: (run: WorkflowRun) => void): () => void {\n this.deadListeners.add(listener);\n return () => this.deadListeners.delete(listener);\n }\n\n private notifyDead(run: WorkflowRun): void {\n for (const fn of this.deadListeners) {\n try {\n fn(run);\n } catch {\n /* a dead-letter handler must not break recovery */\n }\n }\n }\n\n /** Emit a locally-produced lifecycle event: deliver to subscribers AND broadcast it on the\n * control plane so other instances (e.g. a dashboard pod) can live-tail this run. */\n private emit(event: Omit<EngineEvent, 'at'>): void {\n const full: EngineEvent = { ...event, at: new Date() };\n this.deliver(full);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'event', event: full, from: this.instanceId })\n .catch(() => {\n // control-plane delivery is best-effort observability; never break execution\n });\n }\n }\n\n /** Deliver an event to local subscribers only (no re-broadcast) — used for both locally-produced\n * events and ones received from the control plane, so an event shows up once on every instance. */\n private deliver(event: EngineEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // a misbehaving subscriber must never break workflow execution\n }\n }\n }\n\n async start<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n async start<TInput>(\n workflow: string,\n input: TInput,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n async start(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult> {\n const name = workflowName(workflow);\n // PINNED (`opts.version`) resolves the by-name@version registry and stops there: no `latest`, and\n // none of the synthesized fallbacks below, because none of them can prove the version exists (see\n // {@link StartOptions.version}). Unpinned — every caller that has ever existed — takes `latest`\n // and the fallback chain, byte-for-byte as before.\n const pinned = opts?.version;\n let registered =\n pinned === undefined ? this.latest.get(name) : this.workflows.get(versionKey(name, pinned));\n if (!registered && pinned === undefined) {\n // An unregistered run inherits remote routing from its spawning ancestor (see\n // {@link findInheritedRegistration}): the child of a remote workflow can be started without a\n // redundant `registerRemote` for its name. The child run doesn't exist yet, but its parent\n // already wrote the `child:<runId>` waiter BEFORE calling start (the remote `startChild` command\n // and `ctx.child`/`ctx.all` all put the waiter first), so the ancestor is discoverable now.\n const ancestor = await this.findRemoteAncestor(runId);\n if (ancestor) registered = this.synthesizeRemoteChild(name, ancestor.version, ancestor);\n }\n if (!registered && pinned === undefined) {\n // Convention routing: if the transport reports a live group of the same name, synthesize a\n // remote registration on the fly.\n //\n // The `'1'` below is a FALLBACK, not the answer. It used to be the answer: this synthetic run\n // was stamped `'1'` and the resolver echoed it straight back as `registered.version`, so the\n // run row recorded a version nothing had observed — and a pin compared against it could only\n // ever pass on `'1'` and fail on everything else, whatever the worker really was. So the\n // resolver is asked to consult the fleet (`askFleetForVersion`) and this value survives only\n // when the fleet declares nothing, in which case the run is tagged {@link VERSION_UNDECLARED_TAG}\n // so a later check can tell an assumed version from a stated one.\n const conventionRun: WorkflowRun = {\n id: runId,\n workflow: name,\n workflowVersion: '1',\n status: 'pending',\n // Stamp the namespace the REAL run will carry (below) so convention routing resolves the same\n // tenant-suffixed group the run will dispatch to — an operator starting a tenant's run via the\n // `onStartRun` wire (opts.namespace = tenant) must find the live `<workflow>@<tenant>` group,\n // not the bare group. Without this the start-run entry path can't reach a suffixed-only worker.\n namespace: opts?.namespace ?? this.namespace,\n input,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n registered = await this.resolveRemoteByConvention(conventionRun, {\n askFleetForVersion: true,\n });\n }\n if (!registered) {\n throw new Error(\n pinned === undefined\n ? `workflow ${name} is not registered`\n : `workflow ${versionKey(name, pinned)} is not registered — a pinned start never falls back to the newest version (registered: ${this.registeredVersions(name)})`,\n );\n }\n // Validate the input up front — a bad payload is rejected before any run is created.\n await registered.validateInput?.(input);\n // Idempotent by run id: a redelivered trigger (at-least-once queues) or a scheduler re-tick for\n // the same id is a no-op, returning the existing run's state instead of starting a duplicate.\n const prior = await this.store.getRun(runId);\n if (prior) {\n return { runId, status: prior.status, output: prior.output, error: prior.error };\n }\n // Start-time concurrency quota (per-start override, else the workflow's): reject BEFORE creating\n // anything when the key's in-flight runs already reach the limit. See {@link ConcurrencyQuota}.\n const quota = await resolveConcurrency(opts?.concurrency, registered.concurrency, input);\n if (quota) await assertConcurrency(this.store, name, quota);\n const now = new Date();\n // A singleton workflow stamps a `singleton:<key>` tag so the admission gate (in execute) can find\n // the other in-flight runs sharing the key via a tag+status query. A convention-resolved remote\n // whose version nobody declared stamps `version:undeclared` on the same principle: the fact has\n // to travel WITH the run, because whoever checks a pin later reads the run row and nothing else.\n const stampedTags = [\n ...(opts?.tags ?? []),\n ...(registered.singleton ? [this.singletons.tag(registered.singleton, input)] : []),\n ...(quota ? [concurrencyTag(quota.key)] : []),\n ...(registered.versionDeclared === false ? [VERSION_UNDECLARED_TAG] : []),\n ];\n // Admission is owned by the store, never supplied or inherited by a fresh run.\n const tags = mergeTags(registered.tags, stampedTags)?.filter(\n (tag) => tag !== SINGLETON_ADMITTED_TAG,\n );\n // Singleton back-pressure: reject a start that would grow the same-key backlog past\n // `limit + maxQueueDepth` (no-op when no maxQueueDepth is configured).\n if (registered.singleton) {\n await this.singletons.assertCapacity(name, registered.singleton, input);\n }\n const run: WorkflowRun = {\n id: runId,\n workflow: name,\n workflowVersion: registered.version,\n status: 'pending',\n namespace: opts?.namespace ?? this.namespace,\n // DERIVED from the registration, exactly like `namespace` is derived from this engine — there is\n // deliberately no `opts.origin`, so a caller cannot label its run as another package's work.\n // `undefined` when the registration carried none (remote/convention/synthesized child, or a\n // registrar that could not resolve the declaring package): unknown, not \"the app\".\n origin: registered.origin,\n input,\n tags,\n searchAttributes: opts?.searchAttributes,\n priority: opts?.priority,\n createdAt: now,\n updatedAt: now,\n };\n await this.store.createRun(run);\n // The run is durably enqueued; a dispatcher (in-process by default) executes it — `start` does\n // NOT run the body inline. Await the terminal/suspended state with `waitForRun(runId)` if needed.\n await this.runDispatcher.dispatch(runId);\n // Nudge worker instances to pick it up now instead of on their next poll (no-op without a control\n // plane; self-receipt is filtered, so it only helps OTHER pods — e.g. an API pod's enqueue).\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'enqueued', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n return { runId, status: 'pending' };\n }\n\n /** Read a run's current persisted state (or null if unknown). A thin pass-through to the store. */\n getRun(runId: string): Promise<WorkflowRun | null> {\n return this.store.getRun(runId);\n }\n\n /**\n * Re-execute a run's body (replaying its checkpoints). This is the EXPLICIT entry point: besides\n * driving a live run, it re-drives a `failed` run — the manual retry (prefer {@link requeue}, which\n * also resets the failure state so replay re-attempts the failed parts). Completed / cancelled /\n * dead runs are never re-executed. The engine's own implicit wake-ups (signals, step results,\n * timers, redelivered dispatches) go through {@link resumeImplicit}, which treats `failed` as\n * terminal too.\n */\n resume(runId: string): Promise<RunResult> {\n return this.resumeRun(runId, true);\n }\n\n /**\n * {@link resume} for every IMPLICIT wake-up — a delivered signal/child completion, a late step\n * result, a due timer, a redelivered dispatch, a queue-slot wake. A `failed` run is terminal to\n * these: only an explicit retry ({@link requeue} / {@link resume}) may re-drive it. Otherwise a\n * stale waiter or a late result left behind by a failed run silently re-executes its body.\n */\n private resumeImplicit(runId: string): Promise<RunResult> {\n return this.resumeRun(runId, false);\n }\n\n private async resumeRun(runId: string, allowFailed: boolean): Promise<RunResult> {\n const run = await this.store.getRun(runId);\n if (!run) throw new Error(`run ${runId} not found`);\n // A definitively-finished run must not be re-executed (e.g. a worker result landing after the\n // run was cancelled, or a duplicate resume) — that would replay the body and clobber the\n // terminal state. `failed` is terminal too unless this is an explicit retry (see `resume`).\n if (\n run.status === 'cancelled' ||\n run.status === 'completed' ||\n run.status === 'dead' ||\n (run.status === 'failed' && !allowFailed)\n ) {\n return { runId, status: run.status, output: run.output, error: run.error };\n }\n // Namespace guard: release the lock and bail when this run belongs to a different worker pool.\n // Piggybacked on the existing store.getRun above — no extra async step on the happy path.\n // An undefined namespace (a store adapter that doesn't persist the field yet) is treated as\n // \"belongs to everyone\" for back-compat: don't skip it. Likewise, this ENGINE having an\n // undefined namespace means it's an operator control plane — it belongs to every namespace too,\n // so the guard never applies to it.\n if (\n this.namespace !== undefined &&\n run.namespace !== undefined &&\n run.namespace !== this.namespace\n ) {\n await this.store.releaseRunLock(runId);\n throw new NamespaceMismatch();\n }\n // Pin to the version the run STARTED on — replay is positional, so running a changed\n // workflow body against old checkpoints would corrupt the run. The direct lookup is synchronous\n // (`??` short-circuits): a registered run never awaits here, so its resume timing is unchanged —\n // only an UNREGISTERED run pays the inheritance walk (see {@link findInheritedRegistration}).\n // A failed run being explicitly retried must compete for a slot again. This also handles\n // terminal records retained from before the store cleared admission markers on settlement.\n if (run.status === 'failed' && run.tags?.includes(SINGLETON_ADMITTED_TAG)) {\n run.tags = run.tags.filter((tag) => tag !== SINGLETON_ADMITTED_TAG);\n await this.store.updateRun(run.id, { tags: run.tags });\n }\n const registered =\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n (await this.findInheritedRegistration(run)) ??\n (await this.resolveRemoteByConvention(run));\n if (!registered) {\n throw new Error(\n `workflow ${run.workflow}@${run.workflowVersion} is not registered — keep the prior version deployed so in-flight runs can drain (skew protection)`,\n );\n }\n return this.track(this.execute(run, registered.fn));\n }\n\n /**\n * The registration for an UNREGISTERED run, INHERITED from its nearest REMOTE ancestor — or\n * `undefined` if it has none (the skew-protection error case in {@link resume}). Callers check the\n * flat registry FIRST (so an explicit `registerRemote(name, …)` ALWAYS wins, and a registered run\n * never reaches here); this resolves only the new case: a child spawned by a remote workflow (e.g. a\n * Python `gather_children` / `start_child` fan-out) of a name the host never `registerRemote`-ed. It\n * is driven as a remote run on the ancestor's group + the SAME executor instance, so the host needs\n * no redundant registration per child name.\n *\n * RECOMPUTED per resume rather than memoized into `this.workflows`: a synthesized child is not a real\n * registration and must not leak into `latest`, `knownGroups`, or `sweepTimeouts` (which iterate the\n * registry); recomputing also stays correct if the ancestor's remote registration is re-pointed at a\n * new executor across a deploy. Only unregistered runs pay it, so registered workflows pay nothing.\n */\n private async findInheritedRegistration(\n run: WorkflowRun,\n ): Promise<RegisteredWorkflow | undefined> {\n const ancestor = await this.findRemoteAncestor(run.id);\n if (!ancestor) return undefined;\n return this.synthesizeRemoteChild(run.workflow, run.workflowVersion, ancestor);\n }\n\n /**\n * A throwaway {@link RegisteredWorkflow} that routes `name@version` as a remote run on the ancestor's\n * group via the ancestor's SAME executor instance. The executor is group-scoped (it dispatches a\n * {@link WorkflowTask} carrying `run.workflow`, and the worker picks the body by name), so reusing it\n * is correct AND required — a second executor on the same group would race the worker for results.\n * Only `remote` is inherited; the child gets none of the ancestor's singleton/timeout/validator, so\n * its identity stays its own.\n */\n private synthesizeRemoteChild(\n name: string,\n version: string,\n ancestor: RegisteredWorkflow,\n ): RegisteredWorkflow {\n // `ancestor` always carries `remote` (findRemoteAncestor / start only pass a remote registration);\n // the guard narrows the optional type without an unsafe cast and documents the invariant.\n const remote = ancestor.remote;\n if (!remote) throw new Error(`workflow ${ancestor.name} is not a remote workflow`);\n return {\n name,\n version,\n fn: () => {\n throw new Error(`workflow ${name} is remote — it has no in-process body`);\n },\n remote,\n };\n }\n\n /**\n * Attempt to route an unregistered workflow to the live worker group of the same name: if the\n * transport reports a live heartbeat for group `run.workflow`, synthesize a throwaway\n * {@link RegisteredWorkflow} that dispatches to that group over the primary transport. Returns\n * `undefined` when the group is not live. Always attempted — there is no opt-in flag; an explicit\n * `register`/`registerRemote` still takes precedence (this only runs when nothing is registered).\n *\n * Recomputed per call (never memoized into `this.workflows`) so it stays correct if group\n * liveness changes between calls, exactly as {@link synthesizeRemoteChild} does.\n */\n private async resolveRemoteByConvention(\n run: WorkflowRun,\n opts: { askFleetForVersion?: boolean } = {},\n ): Promise<RegisteredWorkflow | undefined> {\n // Workers register/heartbeat their liveGroups under the SANITIZED token (`sanitizeQueueToken`),\n // so the membership check must sanitize too — else a `:`-named workflow's live worker is under\n // `orders-fulfill` while this computes `orders:fulfill` and never matches.\n const group = tenantGroup(sanitizeQueueToken(run.workflow), run.namespace);\n // Resolve the TRANSPORT the group is live on, not just membership in the merged list: in a\n // mixed pool (a tenant-scoped control plane pairing its namespaced transport with a bare-prefix\n // one for operator-convention tenant workers), each transport scans a different keyspace —\n // dispatching on `primary` while the worker heartbeats on another transport would park the turn\n // on a queue nobody consumes.\n const liveTransport = await this.pool.transportWithLiveGroup(group);\n if (!liveTransport) return undefined;\n // Feed the workflow NAME + namespace-as-partition through, rather than the pre-combined\n // `group` string above — the executor computes the identical token itself (name+partition is\n // the new routing primitive; `group` here still exists only for the liveGroups membership check).\n const executor = new RemoteWorkflowExecutor(liveTransport, run.workflow, run.namespace);\n // The version a START records must come from the fleet, never from the caller. `resume` is the\n // opposite case and passes nothing: replay is positional, so a resumed run is pinned to the\n // version it BEGAN on and asking the fleet again could re-point a live run mid-flight.\n const declared = opts.askFleetForVersion\n ? await this.declaredVersion(liveTransport, group, run.workflow)\n : undefined;\n return {\n name: run.workflow,\n version: declared ?? run.workflowVersion,\n fn: () => {\n throw new Error(`remote workflow ${run.workflow} has no local body`);\n },\n hasBody: false,\n remote: { group, executor },\n ...(opts.askFleetForVersion ? { versionDeclared: declared !== undefined } : {}),\n };\n }\n\n /**\n * The version the LIVE fleet declares for `workflow` on `group`, or `undefined` when it declares\n * none — which is a fact about the fleet, not a failure to read it.\n *\n * The read is the descriptor advertisement, scoped to the one group being resolved: the workers on\n * that queue, their `registrations`, the entry whose `name` matches. That is where a version can\n * come from at all — a heartbeat has no room for one, so a worker on an SDK too old to publish a\n * descriptor declares nothing and the caller is told so rather than handed a default.\n *\n * `undefined` when the announcers DISAGREE, and deliberately: two live workers claiming different\n * versions of one name is a deployment in the middle of something, and picking either would stamp\n * a run with a version half the fleet does not serve. Undeclared is the honest reading of a\n * contradiction, and it is the reading that refuses to let a pin pass on a coin flip.\n */\n private async declaredVersion(\n transport: Transport,\n group: string,\n workflow: string,\n ): Promise<string | undefined> {\n if (!transport.readWorkerDescriptors) return undefined;\n let descriptors: WorkerDescriptor[];\n try {\n descriptors = await transport.readWorkerDescriptors(group);\n } catch {\n // A live read can fail every way a network call can. Undeclared, not thrown: this decides how a\n // version is LABELLED, and a Redis blip must not stop a run from starting.\n return undefined;\n }\n const versions = new Set<string>();\n for (const announced of aggregateAnnouncements(descriptors)) {\n if (announced.name === workflow && announced.version !== undefined) {\n versions.add(announced.version);\n }\n }\n const only = [...versions];\n return only.length === 1 ? only[0] : undefined;\n }\n\n /**\n * Walk the parent chain of `childRunId` to the nearest ancestor registered as REMOTE, returning its\n * registration (or `undefined` if there is none). The parent of an awaited child is found via its\n * live `child:<childId>` signal waiter — present for as long as the parent is suspended awaiting the\n * child, i.e. throughout the child's executable lifetime (start, every resume, crash recovery, cancel\n * cascade), which is exactly when we resolve. A registered-but-LOCAL parent stops the walk (an\n * unregistered child of a TS workflow is a genuine misconfiguration → skew error); only an\n * unregistered parent keeps walking, so a child of an inherited child still reaches the remote root.\n * `visited` guards against a pathological cyclic id graph.\n */\n private async findRemoteAncestor(\n childRunId: string,\n visited = new Set<string>(),\n ): Promise<RegisteredWorkflow | undefined> {\n if (visited.has(childRunId)) return undefined;\n visited.add(childRunId);\n const parentRunId = await this.findParentRunId(childRunId);\n if (!parentRunId) return undefined;\n const parent = await this.store.getRun(parentRunId);\n if (!parent) return undefined;\n const parentReg = this.workflows.get(versionKey(parent.workflow, parent.workflowVersion));\n if (parentReg?.remote) return parentReg;\n if (parentReg) return undefined;\n return this.findRemoteAncestor(parent.id, visited);\n }\n\n /**\n * The run that spawned `childRunId`, via its live `child:<childRunId>` signal waiter — every awaited\n * child (`ctx.child`, `ctx.all`, a remote `start_child`) suspends its parent on exactly this waiter,\n * and the waiter is written BEFORE the child is started. Only reached for an UNREGISTERED child, so\n * registered runs never pay the scan; returns `undefined` once the parent has settled the child (the\n * waiter is consumed), but by then the child is terminal and no longer resolved.\n */\n private async findParentRunId(childRunId: string): Promise<string | undefined> {\n const token = `child:${childRunId}`;\n // The token is the waiter's key: a prefix read of the token itself, filtered to the exact match.\n const waiters = await this.store.listSignalWaiters(token);\n return waiters.find((waiter) => waiter.token === token)?.runId;\n }\n\n /** Track an in-flight execution so {@link drain} can wait for it. */\n private track(p: Promise<RunResult>): Promise<RunResult> {\n this.inflight.add(p);\n const done = () => {\n this.inflight.delete(p);\n };\n void p.then(done, done);\n return p;\n }\n\n /**\n * Graceful shutdown: stop picking up new runs (recovery/timer become no-ops) and wait for\n * in-flight executions to settle, up to `timeoutMs`. Call from your app's shutdown hook so a\n * deploy hands off cleanly instead of leaving runs to the lease timeout.\n */\n async drain(timeoutMs = 10_000): Promise<void> {\n this.draining = true;\n if (this.inflight.size === 0) return;\n const timer = new Promise<void>((resolve) => {\n const t = setTimeout(resolve, timeoutMs);\n (t as { unref?: () => void }).unref?.();\n });\n await Promise.race([Promise.allSettled([...this.inflight]), timer]);\n }\n\n /**\n * Cancel in-flight runs that have outlived their workflow's `executionTimeout`. Call it from the\n * timer poller alongside {@link resumeDueTimers}. A timed-out run is moved to `cancelled` with an\n * `execution_timeout` error (terminal, so a late step result can't resurrect it), AND its children\n * are cascaded exactly as an explicit {@link cancel} cascades them.\n *\n * WHY THE TERMINAL WRITE IS DIRECT, not a call to {@link cancel}. Two reasons, both still standing:\n * the run must land with the `execution_timeout` error `cancel` knows nothing about (`cancel` writes\n * a plain `cancelled`, and the code is what a dashboard/alert distinguishes a timeout by), and this\n * is a SCAN — it walks every in-flight run of every timed workflow on every poller tick, so it must\n * not pay `cancel`'s per-run re-read and singleton/control-plane work on runs it isn't cancelling.\n * The cascade below is charged only to the runs that ACTUALLY timed out, which are rare by\n * construction; the scan itself is unchanged.\n *\n * The subtree, though, has no reason to differ, and before this it did: a timed-out parent's\n * children kept running with the parent gone and nothing pointing at them — a silent orphan you\n * could only find by reading the runs table by hand. {@link cancelChildren} is the SAME recursive\n * walk `cancel` uses, so children of children go too, and it inherits that path's two guards:\n * `cancel` returns early on a run that is already `completed`/`cancelled`/`dead` (a child that beat\n * the sweep to the finish is never clobbered, and a re-cancel is a no-op), and it writes the\n * parent's terminal status BEFORE recursing, so a cyclic parent→child graph terminates on the\n * second visit instead of looping. Two pollers sweeping the same run concurrently therefore write\n * the same terminal state twice and cascade into already-cancelled children — idempotent, not\n * corrupting. The one window it does NOT close is the pre-existing check-then-write race an\n * explicit `cancel` has always had (a child that completes between `cancel`'s read and its write);\n * closing that needs a compare-and-set in the store contract, not a change here.\n *\n * Cascade failures are swallowed per subtree for the same reason `cancelChildren` swallows them per\n * child: one unreachable child must not abort the sweep and leave every LATER timed-out run alive.\n */\n async sweepTimeouts(now: number = this.clock()): Promise<void> {\n for (const reg of new Set(this.latest.values())) {\n if (reg.executionTimeoutMs == null) continue;\n const deadline = now - reg.executionTimeoutMs;\n const inflight = [\n ...(await this.store.listRuns({\n workflow: reg.name,\n status: 'running',\n namespace: this.namespace,\n })),\n ...(await this.store.listRuns({\n workflow: reg.name,\n status: 'suspended',\n namespace: this.namespace,\n })),\n ];\n for (const run of inflight) {\n if (run.createdAt.getTime() > deadline) continue;\n const error = { message: 'execution timeout', code: 'execution_timeout' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n // The parent is terminal FIRST (above), so a child that cascades back into it stops there.\n await this.cancelChildren(run.id).catch(() => undefined);\n }\n }\n }\n\n /**\n * Resume every run left incomplete by a crash or deploy. Called on boot. Completed steps\n * replay from their checkpoints, so only the work that had not finished runs again.\n */\n async recoverIncomplete(nowMs: number = this.clock()): Promise<RunResult[]> {\n if (this.draining) return [];\n const results: RunResult[] = [];\n for (const listed of await this.store.listIncompleteRuns(this.namespace)) {\n // An IN-PROCESS turn renews its lease, so an acquirable lease means no turn is executing this\n // run right now. Skip the ones still owned. NOTE this is NOT the same as \"the worker crashed\" —\n // see the dispatched-step guard below for the case it doesn't cover.\n const acquired = await this.store.tryLockRun(\n listed.id,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) continue;\n // Decide on the run as it is NOW that the lease is held, never on the listing. The listing is a\n // snapshot taken before this loop reached the row, and a live run moves on in between: the turn\n // that was executing it (`running`) suspends and releases its lease, a fast step result resumes\n // it, it may even complete. Trusting the listed `running` then reads \"free lease, no step in\n // flight\" as a crashed turn — and the branches below count a recovery attempt, rewrite the run\n // to `pending` and re-enqueue it, i.e. start a SECOND execution beside the legitimate one (or\n // resurrect a finished run). Only a run that still reads incomplete under the lease is ours.\n const run = await this.store.getRun(listed.id);\n if (!run || (run.status !== 'running' && run.status !== 'cancelling')) {\n await this.store.releaseRunLock(listed.id);\n continue;\n }\n // NOT AN ORPHAN: a run with an in-flight (`pending`) remote step is not being executed in\n // process at all — its work is sitting on the transport, run by a worker that holds NO run\n // lease. So \"the lease is acquirable\" proves nothing about it, and by contract such a run is\n // durably SUSPENDED (see `StepCheckpoint.status`), not `running`; finding it `running` means a\n // turn ended without restoring that invariant. Counting it as a crash-recovery attempt burns\n // the poison-pill budget on a perfectly healthy run — repeat it `maxRecoveryAttempts` times and\n // the run is dead-lettered with a generic `max_recovery_attempts` error WHILE its worker is\n // still happily executing the step (observed in the wild: 10 attempts in 57s). Re-assert the\n // contract instead — park it `suspended` on the reconcile timer, which is exactly where a\n // dispatched-and-waiting run belongs: the worker's result resumes it, and `resumeDueTimers`\n // re-drives it as the safety net (replaying straight back to `callRemote`'s pending guard, or\n // re-dispatching when `remoteRedispatchMs` is set). A LOST dispatch is still not this pass's\n // job — `remoteRedispatchMs` / `redispatchPending` own that, unchanged.\n //\n // `cancelling` is deliberately excluded: it must keep its status (see below), so it stays on\n // the counted path rather than being parked `suspended` and losing the cancel intent.\n if (run.status === 'running') {\n const dispatched = await this.inFlightRemoteStep(run.id);\n if (dispatched) {\n await this.store.updateRun(run.id, {\n status: 'suspended',\n wakeAt: this.reconcileWakeAt(dispatched.wakeAt ?? undefined),\n updatedAt: new Date(),\n });\n await this.store.releaseRunLock(run.id);\n results.push({ runId: run.id, status: 'suspended' });\n continue;\n }\n }\n // Count the attempt / dead-letter a poison pill past maxRecoveryAttempts.\n const settled = await this.countRecovery(run);\n if (settled) {\n results.push(settled);\n continue;\n }\n // Re-enqueue rather than resume inline: recovery must NOT block (boot, or a poll tick) on a\n // long workflow step. A dispatcher/worker re-runs it, replaying its checkpoints.\n await this.store.releaseRunLock(run.id);\n // A `cancelling` run keeps its status (resetting to `pending` would lose the persisted cancel\n // intent and resurrect the run): the re-driven turn re-derives it from the status and finishes\n // the cancel. Every other run re-enqueues as `pending` for a clean (re)start.\n if (run.status !== 'cancelling') {\n await this.store.updateRun(run.id, { status: 'pending', updatedAt: new Date() });\n }\n await this.runDispatcher.dispatch(run.id);\n results.push({\n runId: run.id,\n status: run.status === 'cancelling' ? 'cancelling' : 'pending',\n });\n }\n return results;\n }\n\n /**\n * The remote step this run dispatched and is still awaiting a result for, if any — the signature\n * that tells {@link recoverIncomplete} \"this run's work is ON THE TRANSPORT, not in a crashed\n * process\". A `pending` remote checkpoint is written BEFORE the dispatch and settled by the\n * worker's result, so its presence is the durable marker of an in-flight dispatched step.\n */\n private async inFlightRemoteStep(runId: string): Promise<StepCheckpoint | undefined> {\n const checkpoints = await this.store.listCheckpoints(runId);\n return checkpoints.find((cp) => cp.kind === 'remote' && cp.status === 'pending');\n }\n\n /**\n * Per-recovery bookkeeping (called once the lease is held): count the attempt, or — past\n * `maxRecoveryAttempts` — move a poison pill to the `dead` dead-letter state. Returns a terminal\n * result to skip the resume, or `undefined` to proceed.\n */\n private async countRecovery(run: WorkflowRun): Promise<RunResult | undefined> {\n const attempts = (run.recoveryAttempts ?? 0) + 1;\n if (this.maxRecoveryAttempts != null && attempts > this.maxRecoveryAttempts) {\n const error = {\n message: `run exceeded maxRecoveryAttempts (${this.maxRecoveryAttempts}) — moved to dead-letter`,\n code: 'max_recovery_attempts',\n };\n await this.store.updateRun(run.id, { status: 'dead', error, updatedAt: new Date() });\n await this.store.releaseRunLock(run.id);\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n this.notifyDead({ ...run, status: 'dead', error, recoveryAttempts: attempts });\n return { runId: run.id, status: 'dead', error };\n }\n // Count BEFORE resuming, so a crash mid-resume still advances the counter.\n await this.store.updateRun(run.id, { recoveryAttempts: attempts, updatedAt: new Date() });\n return undefined;\n }\n\n /**\n * Resume every suspended run whose durable timer is due. Call periodically (a poller) and on\n * boot. A run still not due re-suspends cheaply without running new work.\n *\n * Piggy-backs the signal/event-waiter reconcile safety net (see {@link reconcileSignalWaiter}): a\n * crash between the waiter/buffer pairing ops on EITHER side (this run's own `putSignalWaiter` →\n * `takeBufferedSignal`/`listBufferedEvents`, or the other side's `takeSignalWaiter`/fan-out →\n * `bufferSignal`/`bufferEvent` → re-check — see `signal`'s interleaving proof, which `publishEvent`\n * mirrors for events) can leave both rows stranded with nothing left to pair them: the waiter's turn\n * already suspended, the other side that buffered it already returned. Event-wait suspends already\n * carry a `reconcileMs` fallback `wakeAt` (see {@link reconcileWakeAt}) precisely so they show up\n * HERE — that's what makes this due-timer pass the natural place for the sweep (and, for events, also\n * where an `eventBufferTtlMs` prune piggy-backs — see {@link reconcileBufferedEvent}). One bulk waiter\n * scan, filtered to just this tick's batch, keeps it cheap regardless of store size.\n */\n async resumeDueTimers(nowMs: number = this.clock()): Promise<RunResult[]> {\n const due = await this.store.listDueTimers(nowMs, this.namespace);\n // ALSO re-drive runs parked `blocked` whose recovery poll is due (handshake design §7.5): re-driving\n // re-checks the live fleet, so a run proceeds the moment a capable+compatible worker appears (else it\n // re-parks with a fresh `wakeAt`). `listDueTimers` targets `suspended`+`wakeAt`, so blocked runs are\n // gathered separately here rather than widening every store adapter's timer query.\n const blocked = await this.dueBlockedRuns(nowMs);\n if (due.length === 0 && blocked.length === 0) return [];\n const waiterByRun = indexWaitersByRun(\n await listSignalWaitersOfRuns(\n this.store,\n [...due, ...blocked].map((run) => run.id),\n ),\n );\n return this.resumeLeased([...due, ...blocked], nowMs, (run) =>\n this.reconcileSignalWaiter(run, waiterByRun.get(run.id)),\n );\n }\n\n /**\n * The reconcile safety net's per-run check (see {@link resumeDueTimers}): if this suspended run has\n * a registered signal OR event waiter and a matching payload is already buffered, pair and deliver\n * them directly instead of falling through to a full replay. Child/breakpoint waiter tokens are\n * never buffered (a child/breakpoint notifies via `signal` only once its counterpart is already\n * registered) — `takeBufferedSignal` on those is a guaranteed miss, so this only ever does real work\n * for a plain signal or an event waiter (classified via {@link isEventToken}).\n *\n * Also opportunistically prunes expired buffered EVENTS for this waiter's name when\n * {@link eventBufferTtlMs} is set (see its doc — scoped to names a registered waiter references in\n * this tick's batch, piggy-backing the SAME scan rather than a separate pass), even on a miss.\n *\n * Returns `undefined` (not settled — `resumeLeased` proceeds with its normal `resume`) when there's\n * no waiter or no buffered hit. Deliberately never returns `null`: a delivered signal always resumes\n * via {@link deliverSignal}, and even a `NamespaceMismatch` there is reported as a real (non-nullish)\n * result — returning `null` would read as \"not settled\" to `resumeLeased`'s `??` fallback and\n * trigger a second, redundant `resume` call on the same run.\n */\n private async reconcileSignalWaiter(\n run: WorkflowRun,\n waiter: SignalWaiter | undefined,\n ): Promise<RunResult | undefined> {\n if (!waiter) return undefined;\n if (isEventToken(waiter.token)) return this.reconcileBufferedEvent(run, waiter);\n const buffered = await this.store.takeBufferedSignal(waiter.token);\n if (!buffered) return undefined;\n await this.store.removeSignalWaiter(waiter);\n const settled = await this.deliverSignal(waiter, buffered.payload);\n return settled ?? { runId: run.id, status: run.status };\n }\n\n /**\n * The EVENT half of {@link reconcileSignalWaiter}: scan this waiter's name for a matching buffered\n * event (same list+evaluate+claim shape as `waitForEvent`'s own consumption — the match predicate\n * belongs to the waiter, never the store), pruning any expired candidates it encounters along the\n * way when {@link eventBufferTtlMs} is configured. A pruned-but-non-matching candidate does not stop\n * the scan; only a MATCHING hit (or exhausting the scan window) does.\n */\n private async reconcileBufferedEvent(\n run: WorkflowRun,\n waiter: SignalWaiter,\n ): Promise<RunResult | undefined> {\n const name = eventNameOf(waiter.token);\n const match = eventMatchOf(waiter.token);\n const candidates = await this.store.listBufferedEvents(name, EVENT_BUFFER_SCAN_LIMIT);\n const nowMs = this.clock();\n for (const candidate of candidates) {\n if (this.eventBufferTtlMs != null && nowMs - candidate.publishedAt > this.eventBufferTtlMs) {\n await this.store.removeBufferedEvent(candidate.id); // expired — prune regardless of match\n continue;\n }\n if (!eventMatches(candidate.payload, match)) continue;\n if (!(await this.store.removeBufferedEvent(candidate.id))) continue; // raced away — try the next\n await this.store.removeSignalWaiter(waiter);\n const settled = await this.deliverSignal(waiter, candidate.payload);\n return settled ?? { runId: run.id, status: run.status };\n }\n return undefined;\n }\n\n /**\n * Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so\n * exactly one instance runs it), then resumes the body. Returns the result, or null if another\n * instance holds the lease or the engine is draining. The default in-process dispatcher calls this;\n * a broker-backed worker calls it per consumed run id.\n */\n async runOne(runId: string): Promise<RunResult | null> {\n if (this.draining) return null;\n const nowMs = this.clock();\n const acquired = await this.store.tryLockRun(\n runId,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) return null;\n // resume() checks the namespace and throws NamespaceMismatch when it doesn't match — no extra\n // await before the call, so the microtask ordering (critical for cancel-safety) is unchanged.\n return this.resumeImplicit(runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * Re-enqueue a run for a worker to (re-)execute — the dispatch-model **retry**. Sets it back to\n * `pending`, clears any stale lease, and dispatches; a worker resumes it (replaying its checkpoints,\n * re-attempting the failed step). Returns the enqueued state immediately — never runs the body\n * inline — or null if the run is unknown. The dashboard \"retry\" goes through here so it can't block\n * the HTTP request on workflow execution.\n */\n async requeue(runId: string, _seen?: Set<string>): Promise<RunResult | null> {\n const seen = _seen ?? new Set<string>();\n if (seen.has(runId)) return null;\n seen.add(runId);\n const run = await this.store.getRun(runId);\n if (!run) return null;\n // A FAILED/DEAD run's replay deterministically re-throws its recorded failures — an exhausted\n // failed checkpoint rethrows, and an awaited child's failure completion rethrows through\n // unwrapCompletion — so \"retry\" without resetting that state is a no-op that re-fails in\n // milliseconds. Reset the failure state first so replay RE-EXECUTES the failed parts:\n // - a `failed` checkpoint becomes retryable-now (attempts 0, wake immediately, `retryable`\n // forced back on): the durable-retry machinery re-dispatches it as a fresh first attempt;\n // - an awaited-child `signal:child:` checkpoint holding a FAILURE completion returns to its\n // live `running` placeholder, so replay re-registers the `child:<id>` waiter — a separately\n // retried child's completion (already buffered, or still to come) then resumes this run.\n // Retry child and parent in either order; signal buffering makes it converge.\n // - the run-level `recoveryAttempts` budget goes back to zero (see the final `updateRun`).\n const resurrecting = run.status === 'failed' || run.status === 'dead';\n if (resurrecting) {\n const isFailureCompletion = (v: unknown): boolean =>\n typeof v === 'object' && v !== null && (v as { ok?: unknown }).ok === false;\n for (const cp of await this.store.listCheckpoints(runId)) {\n if (cp.status === 'failed') {\n await this.store.saveCheckpoint({\n ...cp,\n attempts: 0,\n wakeAt: this.clock(),\n ...(cp.error ? { error: { ...cp.error, retryable: true } } : {}),\n });\n } else if (\n cp.kind === 'signal' &&\n cp.name.startsWith('signal:child:') &&\n cp.status === 'completed' &&\n isFailureCompletion(cp.output)\n ) {\n // CASCADE: retrying only the parent is useless in a live engine — replay re-registers\n // the `child:<id>` waiter and the reconciler re-delivers the child's still-FAILED\n // terminal state within seconds, re-failing the parent with the same error. Requeue the\n // failed child too so the pair converges: whichever finishes the handshake last (waiter\n // registered vs completion buffered) resumes the parent.\n //\n // Exception: a SUCCESS already buffered on this token (a completed `~retry~` fix of the\n // child — see notifyParent's origin delivery) is the outcome, so re-running the failed\n // origin would be pure waste: settle the checkpoint with it right here.\n const childId = cp.name.slice('signal:child:'.length);\n // Drain-and-restore keeps relative order (a partial take+re-buffer would rotate it).\n const parked: unknown[] = [];\n for (;;) {\n const buffered = await this.store.takeBufferedSignal(`child:${childId}`);\n if (!buffered) break;\n parked.push(buffered.payload);\n }\n const successAt = parked.findIndex(\n (payload) =>\n typeof payload === 'object' &&\n payload !== null &&\n (payload as { ok?: unknown }).ok === true,\n );\n const success = successAt === -1 ? undefined : parked.splice(successAt, 1)[0];\n for (const payload of parked) await this.store.bufferSignal(`child:${childId}`, payload);\n const bufferedSuccess = success !== undefined;\n if (bufferedSuccess) {\n await this.store.saveCheckpoint({ ...cp, output: success });\n } else {\n // Back to a live `running` placeholder. Its waiter goes first: replay reads a\n // placeholder as proof its waiter exists and never re-puts it.\n await this.store.putSignalWaiter({\n token: `child:${childId}`,\n runId,\n seq: cp.seq,\n parallelGroup: cp.parallelGroup,\n });\n await this.store.saveCheckpoint({ ...cp, status: 'running', output: undefined });\n }\n if (!bufferedSuccess) {\n const child = await this.store.getRun(childId);\n if (child && (child.status === 'failed' || child.status === 'dead')) {\n await this.requeue(childId, seen);\n }\n }\n }\n }\n }\n await this.store.releaseRunLock(runId);\n // Explicit `error: undefined` CLEARS the stale failure (both stores spread the patch over the\n // run) — otherwise the dashboard keeps showing the old error while the run is re-executing.\n //\n // RESURRECTING a `failed`/`dead` run ALSO clears `recoveryAttempts`, or the retry is a lie: a run\n // dead-lettered AT the cap comes back `pending`, the very next `recoverIncomplete` pass computes\n // `maxRecoveryAttempts + 1` and kills it again within seconds — accepted retry, zero progress,\n // same generic `max_recovery_attempts` error (observed in the wild). The budget bounds ONE\n // crash-loop episode; an operator asking to resurrect a run that already came to rest is starting\n // a new one. This is the run-level half of the same \"reset the failure state\" the checkpoint loop\n // above does — the docstring promised it, the code only did the per-step part.\n //\n // ZERO, not `undefined`: the stores disagree on what an undefined patch value means. `toRunEntity`\n // skips it (`if (run.recoveryAttempts !== undefined)`) and the TypeORM adapter passes it straight\n // into `.set()`, so on both of those `undefined` would silently leave the old count in place. `0`\n // writes a real column value everywhere, and reads back identically — `countRecovery` does\n // `(run.recoveryAttempts ?? 0) + 1`.\n //\n // Gated on `resurrecting` on purpose: requeueing a run that is still `running`/`suspended` is not\n // a resurrection, and zeroing there would let a crash-looping run be kept alive forever by a\n // retry loop — the poison-pill guarantee has to survive this fix.\n await this.store.updateRun(runId, {\n status: 'pending',\n error: undefined,\n ...(resurrecting\n ? {\n recoveryAttempts: 0,\n tags: run.tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG),\n }\n : {}),\n updatedAt: new Date(),\n });\n await this.runDispatcher.dispatch(runId);\n return { runId, status: 'pending' };\n }\n\n /**\n * Explicitly re-dispatch every remote step of `runId` stuck `pending` — the OPERATOR escape hatch for\n * a run whose dispatched step job was LOST (worker crashed with no result, or a transport that dropped\n * the job). No automatic recovery re-drives these: a reconcile re-drive re-suspends a still-pending\n * step by design (unless `remoteRedispatchMs` is set), `recoverIncomplete` explicitly SKIPS a run with\n * an in-flight `pending` remote step (it re-asserts the durably-suspended invariant instead of counting\n * a recovery attempt — see there), and `requeue` just replays back to the pending guard. This\n * re-enqueues the same `stepId` so the (idempotent) step re-runs and its result resumes the run.\n * Safe to call on a healthy run — it re-runs\n * only in-flight `pending` remote steps, which are idempotent by the durable contract. Returns the\n * run's current status (with the count re-dispatched), or null if the run is unknown.\n */\n async redispatchPending(runId: string): Promise<(RunResult & { redispatched: number }) | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n const pending = (await this.store.listCheckpoints(runId)).filter(\n (cp) => cp.kind === 'remote' && cp.status === 'pending',\n );\n let redispatched = 0;\n for (const cp of pending) {\n if (!cp.stepId) continue;\n const reAttempt = cp.attempts + 1;\n const reEnqueuedAt = new Date();\n await this.store.saveCheckpoint({\n ...cp,\n attempts: reAttempt,\n enqueuedAt: reEnqueuedAt,\n startedAt: reEnqueuedAt,\n finishedAt: reEnqueuedAt,\n });\n await this.dispatchRemoteTask({\n runId,\n seq: cp.seq,\n name: cp.name,\n stepId: cp.stepId,\n group: cp.workerGroup ?? sanitizeQueueToken(cp.name),\n input: cp.input,\n attempt: reAttempt,\n });\n redispatched += 1;\n }\n return { runId, status: run.status, redispatched };\n }\n\n /**\n * **Fix-and-replay**: re-run a run (typically a `dead`/`failed` one) with a corrected `input`, as a\n * fresh run with clean history. It's a NEW run — `newRunId` defaults to `<runId>~retry~<uuid>` — so\n * the original stays inspectable. Returns the new run's id, or null if `runId` is unknown.\n */\n async retryWithInput(\n runId: string,\n input: unknown,\n newRunId?: string,\n ): Promise<{ runId: string } | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n const id = newRunId ?? `${runId}~retry~${globalThis.crypto.randomUUID().slice(0, 8)}`;\n // Inherit the original run's namespace so a retry of a tenant's run stays that tenant's — on an\n // operator (this.namespace === undefined) an unstamped retry would fall to 'default' and route to\n // the bare worker group, orphaning it if only the tenant-suffixed worker is live.\n await this.start(run.workflow, input, id, { tags: run.tags, namespace: run.namespace });\n return { runId: id };\n }\n\n /**\n * Pick up and execute every `pending` run — the poll-based side of dispatch for a worker pod with\n * no broker. Runs enqueued by other pods (or by a caller using a no-op dispatcher) sit `pending`\n * in the store until polled; leasing ensures exactly one pod runs each. Call periodically alongside\n * {@link resumeDueTimers}.\n */\n async runPending(nowMs: number = this.clock()): Promise<RunResult[]> {\n // Oldest-first (FIFO), capped per call so a backlog drains over several polls without one sweep\n // fetching unboundedly. A run not picked up this tick is picked up the next.\n return this.resumeLeased(await this.store.listPendingRuns(100, this.namespace), nowMs);\n }\n\n /**\n * Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or\n * suspended (handed off to a timer/signal/event). The async counterpart to dispatch: pair it with\n * `start` when a call site needs the outcome — `await start(...); const r = await waitForRun(id)`.\n */\n waitForRun(\n runId: string,\n opts?: { timeoutMs?: number; until?: 'settled' | 'terminal' },\n ): Promise<RunResult> {\n // `cancelling` is NON-terminal (the saga undo is still running), so a `waitForRun` after a\n // compensating cancel keeps waiting until the run reaches the terminal `cancelled`.\n //\n // A run in the DISPATCH-AND-SUSPEND liveness state — `suspended` while still awaiting a dispatched\n // workflow TURN's decision (`awaitingDecisionTaskId` set) — is mid-turn, NOT settled: that\n // `suspended` is the engine's re-drive marker, not a body-emitted sleep/signal suspend. Resolving on\n // it would hand back a half-applied turn (e.g. a sleep whose `wakeAt` the decision hasn't written\n // yet). Wait until the decision lands and clears the marker (a real suspend) or the run goes terminal.\n //\n // `until: 'terminal'` skips settling on a real suspend too — it resolves only on\n // completed/failed/cancelled/dead (the wait behind `MyWorkflow.execute()` outside a workflow).\n const TERMINAL: ReadonlySet<string> = new Set(['completed', 'failed', 'cancelled', 'dead']);\n const isSettled = (run: WorkflowRun): boolean =>\n opts?.until === 'terminal'\n ? TERMINAL.has(run.status)\n : run.status !== 'pending' &&\n run.status !== 'running' &&\n run.status !== 'cancelling' &&\n !(run.status === 'suspended' && run.awaitingDecisionTaskId !== undefined);\n const toResult = (run: WorkflowRun): RunResult => ({\n runId,\n status: run.status,\n output: run.output,\n error: run.error,\n });\n return new Promise<RunResult>((resolve, reject) => {\n let done = false;\n let off: () => void = () => {};\n const timer =\n opts?.timeoutMs != null\n ? setTimeout(() => {\n if (done) return;\n done = true;\n if (poller) clearInterval(poller);\n off();\n reject(new Error(`waitForRun(${runId}) timed out after ${opts.timeoutMs}ms`));\n }, opts.timeoutMs)\n : undefined;\n const finish = (run: WorkflowRun): void => {\n if (done) return;\n done = true;\n if (timer) clearTimeout(timer);\n if (poller) clearInterval(poller);\n off();\n resolve(toResult(run));\n };\n const fail = (error: unknown): void => {\n if (done) return;\n done = true;\n if (timer) clearTimeout(timer);\n if (poller) clearInterval(poller);\n off();\n reject(error);\n };\n const check = (): void => {\n if (done) return;\n void this.store.getRun(runId).then((run) => {\n if (run && isSettled(run)) finish(run);\n }, fail);\n };\n // Terminal mode also polls: cancelled/dead transitions have no `run.*` lifecycle event to\n // react to (and a resume may happen on ANOTHER instance), so events alone can miss them.\n const poller =\n opts?.until === 'terminal'\n ? (() => {\n const interval = setInterval(check, 250);\n interval.unref?.();\n return interval;\n })()\n : undefined;\n // React only to this run's settling events (not its every step event), and subscribe BEFORE the\n // initial read so a run that settles in between isn't missed.\n off = this.subscribe((ev) => {\n if (\n ev.runId === runId &&\n (ev.type === 'run.completed' || ev.type === 'run.failed' || ev.type === 'run.suspended')\n ) {\n check();\n }\n });\n check();\n });\n }\n\n /**\n * Resume each run only if this instance can acquire its recovery lease — so when several\n * replicas recover or poll at once, each run is picked up by exactly one of them.\n *\n * A run this instance cannot resume is SKIPPED, not allowed to abort the batch. The canonical\n * case is skew protection: mid-rolling-deploy a pod leases a run whose workflow it does not have\n * and `resume` throws by design — but the rest of the batch is runs it can drive perfectly well,\n * and every caller here is a recovery sweep. Letting the first such run end the loop means one\n * row stops recovery for the whole deployment, and (since the callers are pollers) sends the\n * rejection into a lifecycle hook. Skipping leaves the run locked only until its lease expires,\n * for a pod that does have the workflow — which is exactly what the skew-protection error asks\n * for. Same posture as `publishEvent`'s per-subscriber isolation.\n */\n private async resumeLeased(\n runs: WorkflowRun[],\n nowMs: number = this.clock(),\n onLocked?: (run: WorkflowRun) => Promise<RunResult | undefined>,\n ): Promise<RunResult[]> {\n if (this.draining) return []; // shutting down — don't pick up new runs\n const results: RunResult[] = [];\n for (const run of runs) {\n const acquired = await this.store.tryLockRun(\n run.id,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) continue;\n try {\n // A per-run hook (recovery counting / dead-lettering) may settle the run terminally instead.\n const settled = onLocked ? await onLocked(run) : undefined;\n results.push(settled ?? (await this.resumeImplicit(run.id)));\n } catch (error) {\n // Loud, because a skip is not nothing: the run is still there and still not progressing, and\n // the reason (a version skew, a store that just went away) is the only thing that tells an\n // operator which of those it is.\n console.error(\n `[nestjs-durable] could not resume run ${run.id} (${run.workflow}@${run.workflowVersion}); leaving it for another instance:`,\n error,\n );\n }\n }\n return results;\n }\n\n /**\n * Deliver an external signal to the run waiting on `token` and resume it with `payload`.\n * Returns the run result, or null if no run is waiting for that token.\n */\n /**\n * Publish a named event. It does two things, and returns how many runs it touched (the sum):\n * 1. **Resumes** every in-flight run waiting on it via `ctx.waitForEvent(name, { match })` whose\n * match the payload satisfies (fan-out, vs `signal`'s point-to-point token).\n * 2. **Starts** a fresh run of every workflow registered with `onEvent: [name]`, passing the\n * payload as input. Idempotent by `evt:<id>:<workflow>` — pass `opts.id` to dedupe redeliveries\n * of the same logical event (default: a fresh uuid, so each publish triggers once).\n *\n * Semantics (deliberate — mirrors `signalWithStart`'s reliability contract, so document it exactly):\n * a publish that resumes ≥1 live waiter, OR routes into an `eventBatch` accumulator / starts ≥1\n * subscriber, behaves exactly as above and is NOT buffered — fan-out stays live-only, same as\n * today. A publish that touches NEITHER — no live waiter matched, no subscriber exists/started —\n * buffers ONE copy (via {@link StateStore.bufferEvent}) unless `opts.buffer === false`, so it isn't\n * silently dropped just because nobody happened to be listening yet. That buffered copy is consumed\n * by the FIRST future `ctx.waitForEvent(name, { match })` whose match accepts its payload —\n * point-to-point on redelivery, by design (only one waiter ever gets it, even though the LIVE path\n * above is fan-out) — never by a second, later-registered onEvent subscriber (subscriber starts stay\n * live-only; `opts.id` dedupe applies to those only, unchanged). Right after buffering, this re-checks\n * `listSignalWaiters` ONCE — sandwich parity with `signal`'s own take → buffer → re-check — so a\n * waiter that registers in the sliver between the initial miss and the buffer write is still paired\n * instead of leaving both rows stranded (see `signal`'s interleaving proof; `waitForEvent`'s own\n * post-registration buffer scan is the mirror-image half of this same race).\n */\n async publishEvent(\n name: string,\n payload: unknown,\n opts?: { id?: string; buffer?: boolean },\n ): Promise<number> {\n let touched = 0;\n const waiters = await this.store.listSignalWaiters(eventPrefix(name));\n for (const w of waiters) {\n if (eventMatches(payload, eventMatchOf(w.token))) {\n await this.signal(w.token, payload);\n touched += 1;\n }\n }\n const subscribers = this.eventTriggers.get(name);\n if (subscribers?.size) {\n const eventId = opts?.id ?? globalThis.crypto.randomUUID();\n for (const workflow of subscribers) {\n // A subscriber that rejects the payload (validateInput) must not block the others or the\n // waiters — its run simply never starts, mirroring fire-and-forget dead-letter routing.\n try {\n const batch = this.latest.get(workflow)?.eventBatch;\n if (batch) {\n // Coalesce: route the event into a per-workflow accumulator (one long-lived run that\n // debounces/batches and then starts the target with the collected payload(s)).\n await this.accumulators.route(workflow, batch, payload);\n } else {\n await this.start(workflow, payload, `evt:${eventId}:${workflow}`);\n }\n touched += 1;\n } catch {\n // skip this subscriber\n }\n }\n }\n // Nobody received it live (no waiter matched, no subscriber exists/started) — buffer ONE copy\n // unless the caller opted out. `touched > 0` covers BOTH the waiter fan-out and the subscriber\n // loop above, matching the \"no one received it\" condition the semantics doc promises.\n if (touched > 0 || opts?.buffer === false) return touched;\n const bufferedId = globalThis.crypto.randomUUID();\n await this.store.bufferEvent({ name, payload, id: bufferedId, publishedAt: this.clock() });\n // Re-check: a waiter may have registered in the window between the miss above and this buffer\n // write (see the interleaving proof at `signal` — this is the events-side mirror of it). Only the\n // FIRST late-registered matching waiter is considered: only one buffered copy exists, so once a\n // claim attempt below either succeeds or finds the buffer already gone, there is nothing left for\n // any other candidate regardless.\n const lateWaiters = await this.store.listSignalWaiters(eventPrefix(name));\n const lateWaiter = lateWaiters.find((w) => eventMatches(payload, eventMatchOf(w.token)));\n if (!lateWaiter) return touched;\n if (!(await this.store.removeBufferedEvent(bufferedId))) return touched; // claimed elsewhere already\n // `takeSignalWaiter` is safe here even though it deletes ANY row for the token: an event token\n // embeds this ONE `waitForEvent` call's own `runId#seq` (see eventToken in events.ts), so no other\n // registration could ever share it.\n const waiter = await this.store.takeSignalWaiter(lateWaiter.token);\n if (waiter) {\n const settled = await this.deliverSignal(waiter, payload);\n if (settled) touched += 1;\n }\n // If `waiter` is null, that exact registration resolved itself some other way in the interim (most\n // likely its own timeout deadline landing in this same sliver) — the buffered copy is already\n // spent (claimed above), so — mirroring `signal`'s own reclaim precedent — drop it rather than\n // resuming a run a second time or re-buffering for a THIRD, unrelated waiter to pick up later.\n return touched;\n }\n\n /**\n * Deliver a signal to an already-known waiter: write its resolving `signal:<token>` checkpoint and\n * resume the run. Shared by {@link signal}'s direct hit, its post-buffer re-check reclaim, and the\n * due-timer reconcile sweep ({@link reconcileSignalWaiter}) — all three resolve a waiter the exact\n * same way.\n */\n private async deliverSignal(waiter: SignalWaiter, payload: unknown): Promise<RunResult | null> {\n await this.store.saveCheckpoint(\n instantCheckpoint({\n runId: waiter.runId,\n seq: waiter.seq,\n name: `signal:${waiter.token}`,\n kind: 'signal',\n output: payload,\n // Carry the awaiting command's fan group (set when a `ctx.gather_children`/`ctx.all` fan-out\n // registered this waiter) onto the resolving `signal:child:<id>` checkpoint, so the dashboard\n // groups the child fan-out vertically instead of rendering it as a sequential chain. Undefined\n // for an ordinary (non-fan) signal/child await.\n parallelGroup: waiter.parallelGroup,\n }),\n );\n if (await this.fanStillWaiting(waiter, payload)) {\n return { runId: waiter.runId, status: 'suspended' };\n }\n return this.resumeImplicit(waiter.runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * The `ctx.all` join barrier: true when `waiter` was one child of a fan (or of one wave of it)\n * whose siblings are still out, so waking the parent now would only replay the fan and re-suspend.\n * Skipping that wake is what keeps a fan of N children at O(N) work instead of N replays of N items.\n *\n * Safe because the LAST sibling to settle always wakes the parent: each child consumes its own\n * waiter before it asks, so whichever asks last sees none left. A failed child of a failFast fan\n * always wakes it. Anything that is not a `ctx.all` waiter, or a store that cannot answer the\n * question cheaply, wakes the parent as before.\n */\n private async fanStillWaiting(waiter: SignalWaiter, payload: unknown): Promise<boolean> {\n if (!this.store.hasSignalWaiter) return false;\n const fan = fanOfWaiter(waiter);\n if (!fan) return false;\n if (fan.failFast && isFailedCompletion(payload)) return false;\n return this.store.hasSignalWaiter(waiter.runId, fan.waiterPrefix);\n }\n\n /**\n * Re-drive a run that just suspended on awaited children (a `ctx.all` fan or wave, a `ctx.child`)\n * which, by now, have settled.\n *\n * {@link execute} drops a wake that finds the run's lease held. So if a child settles while the\n * parent is still executing (the turn that dispatched it, or one woken by an earlier child), that\n * wake is spent, and the turn suspends on a snapshot that predates the child. With the `ctx.all`\n * barrier that wake was the only one the fan would get. Nothing would wake the run until the\n * `reconcileMs` sweep, minutes later.\n *\n * Called after the turn released its lease, so any child that settles from here on wakes the run\n * itself. Only re-drives for a group with no waiter left whose checkpoints are all settled, which\n * the next turn is then guaranteed to see — so it cannot loop.\n */\n private async redriveSettledChildren(runId: string, fan: FanJoin): Promise<void> {\n if (!this.store.hasSignalWaiter) return;\n for (const wait of fan.waits) {\n if (await this.store.hasSignalWaiter(runId, wait.waiterPrefix)) continue;\n const checkpoints = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(runId, [wait.checkpointPrefix])\n : (await this.store.listCheckpoints(runId)).filter((cp) =>\n cp.name.startsWith(wait.checkpointPrefix),\n );\n if (checkpoints.length > 0 && checkpoints.every((cp) => cp.status === 'completed')) {\n await this.resumeImplicit(runId);\n return;\n }\n }\n }\n\n /**\n * Deliver an external signal to the run waiting on `token`, resume it with `payload`, and return\n * the run result — or null if no run is (or ends up) waiting for it.\n *\n * Race with the waiter side (`waitForSignal`'s check → `putSignalWaiter` → re-check, same shape in\n * the remote `waitSignal` command): a waiter can register in the sliver between this method's\n * initial `takeSignalWaiter` miss and its `bufferSignal` write, and the naive old flow (buffer and\n * return) would then leave BOTH a buffered payload and a registered waiter sitting in the store with\n * nothing left to pair them — a lost wake, forever suspended.\n *\n * The interleaving proof: the waiter side does check → put → re-check, this side does take → buffer\n * → re-check. Whichever side's SECOND look runs last is guaranteed to observe the other side's\n * write, because it always follows that write in real time:\n * - If the waiter's `put` lands before this method's first `take`, the take just finds it directly\n * (the pre-existing, non-racy path).\n * - If the waiter's `put` lands after this method's `bufferSignal`, our re-check below either sees\n * it (if `put` also lands before the re-check) or the waiter's OWN post-put re-check sees our\n * buffer (if `put` lands after our re-check but the waiter hasn't re-checked yet either — its\n * re-check strictly follows its own put).\n * - If the waiter's `put` lands between this method's `take` and its re-`take`, the re-check below\n * catches it.\n * Either way, the destructive `take*` ops (on the waiter row, on the buffer) arbitrate: whichever\n * side actually removes the row is the one that delivers, so a signal is never delivered twice.\n */\n async signal(token: string, payload: unknown): Promise<RunResult | null> {\n const waiter = await this.store.takeSignalWaiter(token);\n if (waiter) return this.deliverSignal(waiter, payload);\n // No one was waiting yet — buffer it so the next `waitForSignal(token)` consumes it instead of\n // dropping it (reliable signals; the basis of `signalWithStart`).\n await this.store.bufferSignal(token, payload);\n // Re-check: a waiter may have registered in the window between the miss above and this buffer\n // write (see the interleaving proof above).\n const lateWaiter = await this.store.takeSignalWaiter(token);\n if (!lateWaiter) return null;\n const reclaimed = await this.store.takeBufferedSignal(token);\n if (!reclaimed) {\n // The waiter side won the race to consume the buffer itself (its own checkpoint+resume already\n // delivered the payload) in the sliver between our takeSignalWaiter and takeBufferedSignal just\n // above. We've already (destructively) taken `lateWaiter` off the store, but there is nothing\n // left to deliver — drop it deliberately rather than resuming the run a second time.\n return null;\n }\n return this.deliverSignal(lateWaiter, reclaimed.payload);\n }\n\n /**\n * Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to\n * signal buffering: if the run is new (or busy / not yet waiting), the signal is buffered and\n * consumed when it reaches `waitForSignal(token)`. The canonical **durable-entity / accumulator**\n * pattern: one long-lived run per key (the `runId`) that loops on `waitForSignal`, fed events by\n * many `signalWithStart` calls. `start` is idempotent by `runId`, so concurrent callers converge on\n * one run. (Use a per-run `token`, e.g. derived from `runId`, so the signal targets this entity.)\n */\n async signalWithStart(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n opts?: StartOptions,\n ): Promise<{ runId: string }> {\n // `start` is overloaded per ref kind (class | string); a `WorkflowRef` union fits neither\n // overload, so resolve to the string overload (the engine handles both at runtime).\n await this.start(workflow as string, input, runId, opts); // idempotent: no-op if run exists\n await this.signal(signal.token, signal.payload);\n return { runId };\n }\n\n /**\n * Report the result of a `ctx.task(name, …)` back to its run (async completion). The external\n * worker that the task dispatched to calls this when done; the run resumes with `result`. Returns\n * null if no run is waiting on the task (e.g. a duplicate/late delivery) — a safe no-op.\n */\n async completeTask(runId: string, name: string, result: unknown): Promise<RunResult | null> {\n return this.signal(`task:${runId}:${name}`, {\n ok: true,\n value: result,\n } satisfies Completion<unknown>);\n }\n\n /** Report that a `ctx.task` failed — the run resumes and throws a FatalError at the task. */\n async failTask(runId: string, name: string, error: string): Promise<RunResult | null> {\n return this.signal(`task:${runId}:${name}`, { ok: false, error } satisfies Completion<never>);\n }\n\n /**\n * Notify a parent that's waiting on `runId` as a child of its terminal outcome (the `ctx.child`\n * rendezvous). A no-op when no parent is waiting, so `execute()` can call it on every run without\n * knowing about the child feature.\n */\n private notifyParent(runId: string, completion: Completion<unknown>): void {\n void this.signal(`child:${runId}`, completion).catch(() => undefined);\n // A fix-and-replay run (`<origin>~retry~<hash>`) is standalone, but its SUCCESS is the\n // origin's outcome for all practical purposes: deliver it on the ORIGIN's token too, so a\n // parent that failed on that child and is retried later consumes this success (buffered or\n // live) instead of waiting on a child nobody re-runs. Failures stay retry-only — a failed\n // fix attempt must not poison the origin's token.\n const at = runId.lastIndexOf('~retry~');\n if (at !== -1 && completion.ok) {\n void this.signal(`child:${runId.slice(0, at)}`, completion).catch(() => undefined);\n }\n }\n\n /**\n * Deferred child start shared by the in-process ctx host and the remote `startChild` command.\n * Deferred (microtask) so a fast child can't reentrantly resume a still-suspending parent. A start\n * that THROWS (unregistered/unroutable workflow, input validation, singleton back-pressure, store\n * failure) must NOT be swallowed: the parent is already suspended on `child:<childId>` (the waiter\n * is put BEFORE start on every path), so a silent drop parks it in suspended-forever, invisibly\n * re-attempting on every recovery wake — a misconfigured remote child looks exactly like a healthy\n * long wait. Instead the failure is delivered to that waiter like a failed child (notifyParent):\n * the parent resumes and fails loudly with the cause. For a fire-and-forget `ctx.startChild`\n * (spawn — no waiter) the completion is buffered; a later join by the same id consumes it and\n * correctly observes the failed start.\n */\n private startChildDeferred(\n workflow: string,\n input: unknown,\n childId: string,\n opts?: StartOptions,\n ): void {\n queueMicrotask(\n () =>\n void this.start(workflow, input, childId, opts).catch((err) => {\n const message = err instanceof Error ? err.message : String(err);\n this.notifyParent(childId, {\n ok: false,\n error: `child workflow \"${workflow}\" failed to start: ${message}`,\n });\n }),\n );\n }\n\n /**\n * Cancel a run (e.g. from the dashboard). Returns null if the run does not exist. Pass\n * `{ compensate: true }` to undo the saga first: the suspended run is resumed so its completed\n * steps' compensations run in reverse (visible as `compensate:<step>` events), then it's marked\n * cancelled. Without it, cancellation is immediate (no undo).\n */\n async cancel(runId: string, opts?: { compensate?: boolean }): Promise<RunResult | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n // Terminal runs are IMMUTABLE: cancelling one is a no-op that echoes its current state. That\n // covers EVERY terminal status — `failed` included (a timed-out run is persisted `cancelled`).\n // It must never rewrite the run (a `failed` run silently becoming `cancelled` loses its real\n // outcome) and must never reach the child cascade below: a finished parent's children can be\n // live, unrelated work — e.g. the next queued chat turn an agent queue already started as a\n // child of the turn that just failed. This also stops the cascade from looping.\n if (TERMINAL_RUN_STATUSES.includes(run.status)) {\n return { runId, status: run.status, output: run.output, error: run.error };\n }\n // Already compensating (status persisted as `cancelling`): idempotent — don't re-queue the resume,\n // and crucially don't fall through to the instant-cancel path below (which would mark `cancelled`\n // and SKIP the in-flight saga undo). A repeat cancel just echoes the in-progress status.\n if (run.status === 'cancelling') {\n return { runId, status: 'cancelling' };\n }\n // Compensating cancel: resume the run with a cancellation pending — replay re-registers the saga,\n // and at the suspension point execute() runs the undo and marks it cancelled. Run that resume in\n // the BACKGROUND so the caller (e.g. an HTTP request) never blocks on replaying the workflow +\n // compensations. `execute` holds the run's lease, so this can't double-run one a live worker owns\n // (its lease acquire fails and it no-ops); the broadcast tells that worker to abort cooperatively.\n if (opts?.compensate && (run.status === 'suspended' || run.status === 'running')) {\n this.cancelRequested.add(runId);\n // Persist `cancelling` so the dashboard/API show \"compensation in progress\" instead of a\n // misleading `running`/`suspended` while the background undo runs. NON-TERMINAL: the admission\n // gate still counts it and recovery re-drives it on crash (runExecution re-derives the cancel\n // intent from this status), so the cancel is durable; it flips to `cancelled` when the resumed\n // replay finishes compensating.\n await this.store.updateRun(runId, { status: 'cancelling', updatedAt: new Date() });\n run.status = 'cancelling';\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n queueMicrotask(() => {\n void this.resumeImplicit(runId)\n .then(() => this.notifyCancelled(runId))\n .catch(() => undefined);\n });\n await this.cancelChildren(runId, opts);\n return { runId, status: 'cancelling' };\n }\n const error = { message: 'cancelled' };\n await this.store.updateRun(runId, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n await this.cancelChildren(runId, opts);\n // Notify local cancel listeners now (a worker on this pod), and broadcast so the instance/worker\n // actually running this run learns of it and can abort cooperatively (the store already records\n // `cancelled`, but a busy worker won't re-read it).\n this.notifyCancelled(runId);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n // A cancelled singleton run frees its slot — wake the next gated waiter now (notify-on-release).\n void this.singletons.wakeNext(run).catch(() => undefined);\n return { runId, status: 'cancelled', error };\n }\n\n /**\n * Bulk-cancel every run matching a filter — e.g. cancel all `order` runs tagged `vip`, or every run\n * whose `tier` search attribute is `free`. The filter is a {@link RunQuery} (workflow / status / tag\n * / search-attribute predicates), so it reuses the same matching the dashboard list uses. Each match\n * is run through {@link cancel}, so the same plumbing applies per run: child cascade, the optional\n * saga `compensate`, local cancel listeners, and the control-plane broadcast that tells the owning\n * worker to abort. Returns one {@link RunResult} per matched run (already-finished matches report\n * their terminal status — `cancel` is a no-op on them, never clobbering a completed/dead run).\n */\n async cancelWhere(\n filter: Omit<RunQuery, 'limit' | 'offset'>,\n opts?: { compensate?: boolean },\n ): Promise<RunResult[]> {\n const runs = await this.store.listRuns(filter);\n const results: RunResult[] = [];\n for (const run of runs) {\n const r = await this.cancel(run.id, opts);\n if (r) results.push(r);\n }\n return results;\n }\n\n /**\n * Hard-delete a run and its entire subtree. Unlike {@link cancel} (which marks a run `cancelled`\n * but keeps it as history), delete REMOVES the run and all its rows (checkpoints, signal waiters,\n * search-attribute rows) — it vanishes from {@link getRun} and {@link listRuns}. Use it to purge a\n * finished run whose data is being deleted (e.g. a pipeline run whose result rows are cleared).\n *\n * Cascades depth-first via {@link getRunChildren} so children are gone before the parent (no\n * orphaned child runs). Prefer {@link cancel} first for a live run — deleting one mid-flight orphans\n * its worker (its next checkpoint write fails). Returns the number of runs deleted (0 if absent).\n */\n async deleteRun(runId: string): Promise<number> {\n const run = await this.store.getRun(runId);\n if (!run) return 0;\n // Collect children BEFORE deleting this run's checkpoints (getRunChildren reads them).\n let deleted = 0;\n for (const childId of await this.getRunChildren(runId)) {\n deleted += await this.deleteRun(childId);\n }\n await this.store.deleteRun(runId);\n return deleted + 1;\n }\n\n /**\n * Hard-delete EVERY run matching `scope` — plus, by default, each one's whole child subtree — in\n * bounded batches. The \"forget this tenant\" / \"drop this feature's history\" operation: where\n * {@link deleteRun} removes one tree you already know the id of, this drains everything a scope\n * selects (`{ namespace: 'acme' }`, `{ tag: 'tenant:acme' }`, `{ workflows: [...] }`, attribute\n * predicates …) through the store API, so no caller has to reach into the `durable_*` tables.\n *\n * - **Live runs** (not yet terminal) are {@link cancel cancelled} first (plain cancel, no saga\n * undo), which tells any worker holding one to stop, and then deleted with the rest. Pass\n * `cancelLive: false` to leave live runs (and live descendants of finished ones) alone and\n * delete terminal history only.\n * - **Children** are found through the same parent→child edges as {@link getRunChildren} and deleted\n * with their root even when they don't match `scope` themselves (children inherit `namespace`,\n * but not `tags`). `children: false` deletes exactly the matching runs.\n * - **Batched**: `batchSize` runs (default 500) per round, each round one bulk\n * {@link StateStore.deleteRuns} (falling back to per-run {@link StateStore.deleteRun}).\n *\n * An EMPTY scope is rejected — it would delete every run in the store. Returns how many runs were\n * deleted (children included).\n */\n async purgeRuns(\n scope: RunScope,\n opts?: { batchSize?: number; cancelLive?: boolean; children?: boolean },\n ): Promise<number> {\n if (!isNonEmptyRunScope(scope)) {\n throw new Error(\n 'purgeRuns: refusing an empty scope (it would delete every run) — pass at least one predicate, e.g. { namespace }',\n );\n }\n const batchSize = Math.max(1, opts?.batchSize ?? 500);\n const cancelLive = opts?.cancelLive ?? true;\n const withChildren = opts?.children ?? true;\n const statuses = cancelLive ? undefined : [...TERMINAL_RUN_STATUSES];\n let deleted = 0;\n let previous = '';\n for (;;) {\n const batch = await this.store.listRuns({ ...scope, statuses, limit: batchSize });\n if (batch.length === 0) break;\n const fingerprint = batch.map((r) => r.id).join('\\u0000');\n // Every listed run is deleted below, so the next page is new rows — the same page twice means\n // the store is not deleting (a broken adapter); stop instead of spinning forever.\n if (fingerprint === previous) {\n throw new Error('purgeRuns: the store returned the same runs after deleting them');\n }\n previous = fingerprint;\n const known = new Map(batch.map((r) => [r.id, r.status] as const));\n const ids = withChildren\n ? await this.collectSubtrees(batch.map((r) => r.id))\n : batch.map((r) => r.id);\n const doomed: string[] = [];\n for (const id of ids) {\n const status = known.has(id) ? known.get(id) : (await this.store.getRun(id))?.status;\n if (status === undefined) continue; // already gone\n if (!TERMINAL_RUN_STATUSES.includes(status)) {\n // A live descendant of a finished root: cancel it with the tree, or leave it be.\n if (!cancelLive) continue;\n await this.cancel(id).catch(() => undefined);\n }\n doomed.push(id);\n }\n await this.deleteRunIds(doomed);\n deleted += doomed.length;\n if (batch.length < batchSize) break;\n }\n return deleted;\n }\n\n /**\n * {@link purgeRuns} for one namespace — every run (and child) a tenant/partition owns. Children\n * inherit their parent's namespace, so a namespace purge is complete by construction.\n */\n purgeNamespace(\n namespace: string,\n opts?: { batchSize?: number; cancelLive?: boolean },\n ): Promise<number> {\n return this.purgeRuns({ namespace }, opts);\n }\n\n /** The given runs plus every descendant, children before parents. One waiter scan for the batch. */\n private async collectSubtrees(rootIds: string[]): Promise<string[]> {\n const prefixes = CHILD_EDGE_PREFIXES;\n const childrenOf = async (parent: string): Promise<string[]> => {\n const ids = new Set(await this.awaitedChildIds(parent));\n const cps = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(parent, prefixes)\n : (await this.store.listCheckpoints(parent)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n for (const id of childIdsOf(cps)) ids.add(id);\n return [...ids];\n };\n const ordered: string[] = [];\n const seen = new Set<string>();\n const visit = async (id: string): Promise<void> => {\n if (seen.has(id)) return;\n seen.add(id);\n for (const child of await childrenOf(id)) await visit(child);\n ordered.push(id); // post-order: children first\n };\n for (const id of rootIds) await visit(id);\n return ordered;\n }\n\n /** Bulk-delete through the store's `deleteRuns`, or one `deleteRun` per id when it has none. */\n private async deleteRunIds(ids: string[]): Promise<void> {\n if (ids.length === 0) return;\n if (this.store.deleteRuns) {\n await this.store.deleteRuns(ids);\n return;\n }\n for (const id of ids) await this.store.deleteRun(id);\n }\n\n /**\n * Cascade cancellation to a run's children — both awaited (`ctx.child`, found via its live\n * `child:<id>` waiter) and fire-and-forget (`ctx.startChild`, found via its `spawn:<id>`\n * checkpoint). Recursive, so a whole subtree is cancelled; the terminal guard in `cancel` stops it\n * at finished / already-cancelled runs (no loops, no re-cancel).\n *\n * Two callers, deliberately the same walk: an explicit {@link cancel}, and {@link sweepTimeouts}\n * when a parent hits its `executionTimeout` — a timed-out parent's subtree dies the same way an\n * explicitly cancelled one's does, or the children are orphans nobody is holding a reference to.\n */\n private async cancelChildren(\n parentRunId: string,\n opts?: { compensate?: boolean },\n ): Promise<void> {\n for (const id of await this.getRunChildren(parentRunId)) {\n await this.cancel(id, opts).catch(() => undefined);\n }\n }\n\n /**\n * The ids of the runs a run spawned — both awaited (`ctx.child`) and fire-and-forget\n * (`ctx.startChild`, found via its `spawn:<id>` checkpoint). The canonical parent→children edge,\n * used for both cancellation cascades and the dashboard run-tree.\n *\n * An awaited child is discovered two ways, because the live `child:<id>` waiter only exists WHILE\n * the parent is suspended on it: the waiter resolves and is consumed the moment the child settles,\n * so a completed parent (or a completed awaited child) would otherwise drop out of the tree. The\n * `signal:child:<id>` checkpoint (the placeholder written when the parent first awaits the child,\n * overwritten as completed/failed when it settles) persists across completion, so we read both and\n * dedupe — the edge stays stable for a finished run, not just a live one. A settled `ctx.all`\n * group folded into one `fan:` checkpoint stands for every child in it.\n */\n /** The children `parentRunId` is awaiting right now, read off its own live `child:` waiters. */\n private async awaitedChildIds(parentRunId: string): Promise<string[]> {\n return (await listSignalWaitersOfRuns(this.store, [parentRunId]))\n .filter((w) => w.token.startsWith('child:'))\n .map((w) => w.token.slice('child:'.length));\n }\n\n async getRunChildren(parentRunId: string): Promise<string[]> {\n const childIds = new Set(await this.awaitedChildIds(parentRunId));\n // Targeted read: only the child-edge checkpoints, not the whole history. Falls\n // back to a full listCheckpoints + in-JS prefix scan for a custom store that omits the method.\n const prefixes = CHILD_EDGE_PREFIXES;\n const childCheckpoints = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(parentRunId, prefixes)\n : (await this.store.listCheckpoints(parentRunId)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n for (const id of childIdsOf(childCheckpoints)) childIds.add(id);\n return [...childIds];\n }\n\n /** The worker groups this engine dispatches to: every registered remote workflow's group, plus any\n * `extra` the caller declares. Local-step groups (a group consumed by in-process `@DurableStep`\n * workers, e.g. `pipeline`) aren't derivable from registrations — pass them via `extra` so a group\n * with backlog and ZERO workers is still reported (the alert case has no heartbeat to discover). */\n knownGroups(extra: string[] = []): string[] {\n const groups = new Set<string>(extra);\n for (const def of this.workflows.values()) {\n if (def.remote?.group) groups.add(def.remote.group);\n }\n return [...groups];\n }\n\n /** Per-group worker health (queue backlog + live worker heartbeats). Covers {@link knownGroups}\n * (so a registered group with backlog and ZERO workers still reports — the alert case) UNION the\n * groups discovered from live heartbeats (so a local-step group like `pipeline`, not derivable\n * from registrations, shows once its workers beat). Empty when no transport can introspect health\n * (only the BullMQ transport implements `groupHealth`). */\n async workerHealth(extra: string[] = []): Promise<GroupHealth[]> {\n const groups = new Set([\n ...this.knownGroups(extra),\n ...(await this.pool.listWorkerGroups()),\n ...(await this.inflightStepGroups()),\n ]);\n // Classify each group workflow-vs-step from the registry (authoritative — no name heuristic): a\n // group whose base token is a registered workflow serves a `@Workflow` body; anything else (an\n // in-process `@Step`, a remote `handle_*` step) is a step. A LOCAL workflow's queue token is\n // `sanitizeQueueToken(name)`; a REMOTE one (e.g. Python) routes to its `remote.group`, which can\n // differ from the name — so seed the workflow-token set with BOTH.\n const workflowTokens = new Set<string>();\n for (const def of this.workflows.values()) {\n workflowTokens.add(sanitizeQueueToken(def.name));\n if (def.remote?.group) workflowTokens.add(def.remote.group);\n }\n const out: GroupHealth[] = [];\n for (const group of groups) {\n const health = await this.pool.groupHealth(group);\n if (!health) continue;\n const at = group.lastIndexOf('@');\n const baseToken = at === -1 ? group : group.slice(0, at);\n out.push({ ...health, kind: workflowTokens.has(baseToken) ? 'workflow' : 'step' });\n }\n return out;\n }\n\n /**\n * What workflows the LIVE fleet announces it can execute — the deployment-wide registry a picker\n * (\"call this existing workflow\") needs, and the one question this engine's own registry cannot\n * answer. {@link workflowBody} answers only for this process, and a missing body is ambiguous: it\n * means \"not registered here\", but equally \"registered via {@link registerRemote} against another\n * SDK\" or \"a group resolved by convention against a worker\". An inferred answer would therefore\n * differ per replica. This one does not: every pod folds the same published announcements.\n *\n * Scoped like every other poll surface — an engine WITH a `namespace` sees only workers in it, and\n * an operator (namespace unset) sees the whole deployment (\"ver tudo = ausência de namespace\"). A\n * descriptor that states no namespace is `default`, matching how a single-tenant fleet publishes.\n *\n * Cost: one advertisement scan per CALL, on demand. Nothing is added to the poll loop and nothing\n * is retained — no pod holds a table of the fleet's registrations. Empty when no transport can\n * introspect the advertisement keyspace (a pure in-process transport advertises nothing).\n *\n * Workflows only, and deliberately: see the \"steps are out of scope\" note in `handshake/announced`.\n */\n async announcedWorkflows(): Promise<AnnouncedWorkflow[]> {\n return (await this.workflowDirectory()).workflows;\n }\n\n /**\n * {@link announcedWorkflows}, plus the thing a list of workflows can never say: why it is the\n * length it is. See {@link WorkflowDirectory} for the three states an empty array used to collapse\n * into one — \"nobody asked\", \"nothing is live\", and the partition mismatch that reads exactly like\n * the second from the caller's side.\n *\n * Two live reads, both on demand and neither retained: the descriptor advertisement (what workers\n * SAY they serve) and the heartbeat keyspace (what is demonstrably consuming a queue right now).\n * The second is why a worker on an SDK too old to publish a descriptor appears here at all — it\n * beats and never describes itself, and reading only descriptors reported such a fleet as empty\n * while `resolveRemoteByConvention`, a few lines away in this same class, was routing calls to it\n * off those very keys. Two answers out of one Redis, disagreeing. Now they agree, and the entry\n * says which of the two kinds of evidence it rests on rather than flattening them together.\n */\n async workflowDirectory(): Promise<WorkflowDirectory> {\n return buildWorkflowDirectory({\n descriptors: await this.pool.readAllWorkerDescriptors(),\n heartbeats: await this.pool.readAllWorkerHeartbeats(),\n namespace: this.namespace,\n supported: this.pool.introspectsFleet,\n sanitize: sanitizeQueueToken,\n });\n }\n\n /**\n * The routing groups of every in-flight run's still-`pending` remote step — the queues where work is\n * dispatched and awaiting a worker. Folded into {@link workerHealth} so a step waiting on a group\n * that is NEITHER a registration NOR heartbeating (the exact shape of a run stuck on an offline\n * tenant pool) still reports its backlog: without this the health scan can't \"see\" that queue, and\n * the dashboard shows the run as running instead of no-worker. Only the BullMQ transport introspects\n * health, so on any other transport this is harmless (the groups just resolve to no `groupHealth`).\n *\n * Cost: one `listRuns` over the non-terminal runs plus a checkpoint read each — a diagnostic-path\n * scan, not a hot path. Scoped to `running`/`suspended`/`blocked` (a `pending` run has dispatched no\n * step yet) and deduped to distinct groups.\n */\n private async inflightStepGroups(): Promise<string[]> {\n const inflight = await this.store.listRuns({ statuses: ['running', 'suspended', 'blocked'] });\n const groups = new Set<string>();\n for (const run of inflight) {\n for (const cp of await this.store.listCheckpoints(run.id)) {\n if (cp.kind === 'remote' && cp.status === 'pending' && cp.workerGroup) {\n groups.add(cp.workerGroup);\n }\n }\n }\n return [...groups];\n }\n\n /**\n * Persist a streamed local-step lifecycle event from a remote workflow worker (see\n * {@link WorkflowStepEvent}). A Python `@workflow` runs its `ctx.step`s inline over one turn that\n * can last minutes; the worker streams each step's start/finish so the engine checkpoints it LIVE —\n * a step shows `running` the moment its body begins, then resolves to `completed`/`failed` with its\n * real wall-clock window and sub-process events — instead of every step appearing at once when the\n * turn ends. The turn's final `recordStep` command re-persists the same (runId, seq) checkpoint\n * idempotently, so this is purely additive observability and never changes the run's outcome.\n */\n private async persistStepEvent(event: WorkflowStepEvent): Promise<void> {\n const startedAt = new Date(event.startedAt);\n if (event.phase === 'running') {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n status: 'running',\n events: event.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt: startedAt, // placeholder until the step settles\n parallelGroup: event.parallelGroup,\n }),\n );\n this.emit({\n type: 'step.started',\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n });\n return;\n }\n const failed = event.phase === 'failed';\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n status: failed ? 'failed' : 'completed',\n output: failed ? undefined : event.output,\n error: failed ? event.error : undefined,\n events: event.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt: event.finishedAt != null ? new Date(event.finishedAt) : new Date(),\n parallelGroup: event.parallelGroup,\n }),\n );\n this.emit({\n type: failed ? 'step.failed' : 'step.completed',\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n output: failed ? undefined : event.output,\n error: failed ? event.error : undefined,\n });\n }\n\n /**\n * Announce a local step's body has begun and (when `trackStepStart`) checkpoint it as `running`,\n * so it's visible in flight rather than appearing only on completion. The checkpoint is a\n * placeholder overwritten by {@link completeStep}/{@link failStep}; it never short-circuits replay\n * (only `completed` does), so a crash mid-body just re-runs the step. The `step.started` event\n * fires regardless — the live SSE view sees the start even with persistence off.\n */\n private async startStep(step: StepRecord): Promise<void> {\n if (this.trackStepStart) {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'running',\n input: step.input,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: step.startedAt, // placeholder until the body settles\n }),\n );\n }\n this.emit({\n type: 'step.started',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n });\n }\n\n /** Checkpoint a finished step and announce it — the two things that must always happen together. */\n private async completeStep(step: StepRecord & { output: unknown }): Promise<void> {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'completed',\n input: step.input,\n output: step.output,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: new Date(),\n }),\n );\n this.emit({\n type: 'step.completed',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n output: step.output,\n queueMs: step.startedAt.getTime() - step.enqueuedAt.getTime(),\n durationMs: Date.now() - step.startedAt.getTime(),\n });\n }\n\n /** Checkpoint a step that failed terminally, so the failure point is visible (not just the run). */\n private async failStep(step: StepRecord & { error: StepError }): Promise<void> {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'failed',\n input: step.input,\n error: step.error,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: new Date(),\n }),\n );\n this.emit({\n type: 'step.failed',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n error: step.error,\n queueMs: step.startedAt.getTime() - step.enqueuedAt.getTime(),\n durationMs: Date.now() - step.startedAt.getTime(),\n });\n }\n\n /** Admission persists the wait atomically; never overwrite a cancellation after it returns. */\n private async singletonWaitResult(run: WorkflowRun): Promise<RunResult> {\n const current = await this.store.getRun(run.id);\n await this.store.releaseRunLock(run.id);\n if (!current) throw new Error(`run ${run.id} was deleted during singleton admission`);\n if (current.status === 'suspended') {\n this.emit({\n type: 'run.suspended',\n runId: current.id,\n workflow: current.workflow,\n namespace: current.namespace,\n });\n }\n return {\n runId: current.id,\n status: current.status,\n output: current.output,\n error: current.error,\n };\n }\n\n private async execute(run: WorkflowRun, fn: WorkflowFn): Promise<RunResult> {\n // Synchronous fast path (`??` short-circuits) for registered runs — no extra await, so execution\n // timing for the common case is unchanged; only an unregistered (inherited-remote) run awaits.\n const registered =\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n (await this.findInheritedRegistration(run)) ??\n (await this.resolveRemoteByConvention(run));\n // Hold the lease for the WHOLE execution — whatever path got us here (leased sweep, a signal, a\n // remote result, a dashboard action). The leased sweeps already own it; the event-driven paths\n // don't, so acquire it here. If another instance owns it, don't double-run. While we run, renew\n // the lease periodically so a long run keeps it (a crashed worker's lease still expires and is\n // reclaimed by periodic recovery).\n const lockNow = this.clock();\n if (run.lockedBy !== this.instanceId || (run.lockedUntil ?? 0) <= lockNow) {\n if (\n !(await this.store.tryLockRun(run.id, this.instanceId, lockNow + this.leaseMs, lockNow))\n ) {\n return { runId: run.id, status: run.status };\n }\n }\n const renew = setInterval(\n () => {\n void this.store\n .renewRunLock(run.id, this.instanceId, this.clock() + this.leaseMs)\n .catch(() => undefined);\n },\n Math.max(50, Math.floor(this.leaseMs / 2)),\n );\n renew.unref?.();\n try {\n // A remote (e.g. Python) workflow is advanced by dispatching workflow tasks, not by running an\n // in-process body — but everything around it (lease, recovery, timers, the resume that lands us\n // here on a step result) is identical, so it branches here under the same lease.\n const result = registered?.remote\n ? await this.runRemoteExecution(run, registered)\n : await this.runExecution(run, fn, registered);\n // Notify-on-release: a singleton run that just reached a terminal state freed a slot — wake the\n // next gated waiter(s) now instead of waiting for the ~1s retry timer. Fire-and-forget so it\n // never blocks the settling run; the durable timer is still the cross-instance/crash fallback.\n if (\n registered?.singleton &&\n (result.status === 'completed' ||\n result.status === 'failed' ||\n result.status === 'cancelled' ||\n result.status === 'dead')\n ) {\n void this.singletons.wakeNext(run).catch(() => undefined);\n }\n return result;\n } finally {\n clearInterval(renew);\n }\n }\n\n /**\n * Advance a remote (cross-SDK) workflow one turn: hand its history to the executor (which dispatches\n * a workflow task to the worker and awaits its replay) and apply the decision. Mirrors\n * {@link runExecution}'s settle/suspend; the lease is held by {@link execute}. The result that lands\n * us back here (a remote step finished, a timer fired) goes through `resume` like any TS workflow.\n */\n /**\n * Apply a terminal/suspended transition once: persist the new run status, emit the matching\n * lifecycle event, and (on completion/failure) wake a waiting parent. Both the TS and remote\n * executors funnel their completed/failed/suspended outcomes through here so a status update can\n * never drift from its event or `notifyParent` call. Does NOT touch the run lock — each executor\n * keeps its own lease handling (the TS executor's `finally`, the remote path's caller).\n */\n private async settleRun(run: WorkflowRun, outcome: RunOutcome): Promise<RunResult> {\n const updatedAt = new Date();\n if (outcome.kind === 'completed') {\n // Clear any error from an earlier failed-then-retried attempt — a completed run is a success.\n await this.store.updateRun(run.id, {\n status: 'completed',\n output: outcome.output,\n error: undefined,\n updatedAt,\n });\n this.emit({\n type: 'run.completed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n output: outcome.output,\n });\n void this.notifyParent(run.id, { ok: true, value: outcome.output });\n return { runId: run.id, status: 'completed', output: outcome.output };\n }\n if (outcome.kind === 'failed') {\n await this.store.updateRun(run.id, { status: 'failed', error: outcome.error, updatedAt });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error: outcome.error,\n });\n void this.notifyParent(run.id, { ok: false, error: outcome.error.message });\n return { runId: run.id, status: 'failed', error: outcome.error };\n }\n if (outcome.kind === 'blocked') return this.parkBlocked(run, outcome.blocked);\n // This outcome was computed by a turn that started from a possibly-stale run snapshot. If the run\n // was cancelled WHILE that turn was still executing (e.g. `ctx.all`'s failFast cancelling a\n // sibling mid-turn — plain `cancel()` writes `cancelled` directly, without waiting for the target's\n // in-flight turn to notice), this now-stale \"suspended\" outcome must not resurrect it: re-check the\n // CURRENT persisted status right before writing and echo it instead of clobbering a real cancel.\n const latest = await this.store.getRun(run.id);\n if (latest?.status === 'cancelled') {\n return { runId: run.id, status: 'cancelled', error: latest.error };\n }\n await this.store.updateRun(run.id, {\n status: 'suspended',\n wakeAt: this.reconcileWakeAt(outcome.wakeAt),\n updatedAt,\n });\n this.emit({\n type: 'run.suspended',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n return { runId: run.id, status: 'suspended' };\n }\n\n /**\n * A wakeAt to persist on a suspend: the natural timer if the turn produced one (a `ctx.sleep`, a\n * remote-step deadline), else the {@link reconcileMs} fallback so an event-waiting run (child/signal/\n * timeout-less remote step) can't be orphaned forever if its wake is lost. `undefined` only when the\n * fallback is disabled (`reconcileMs: 0`). See {@link WorkflowEngineDeps.reconcileMs}.\n */\n private reconcileWakeAt(wakeAt: number | undefined): number | undefined {\n if (wakeAt != null) return wakeAt;\n return this.reconcileMs != null ? this.clock() + this.reconcileMs : undefined;\n }\n\n private async runRemoteExecution(\n run: WorkflowRun,\n registered: RegisteredWorkflow,\n ): Promise<RunResult> {\n // Compensating cancel in flight for a remote workflow: its steps execute in the worker, so there\n // are no TS-side compensations to replay here — finalize to cancelled. Re-broadcast so a live worker\n // mid-turn aborts cooperatively; on recovery (the broadcast was lost to a crash) this still settles\n // the run deterministically instead of resurrecting it by re-advancing.\n if (run.status === 'cancelling') {\n const error = { message: 'cancelled' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n this.notifyCancelled(run.id);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId: run.id, from: this.instanceId })\n .catch(() => undefined);\n }\n await this.store.releaseRunLock(run.id);\n return { runId: run.id, status: 'cancelled', error };\n }\n const remote = registered.remote as NonNullable<RegisteredWorkflow['remote']>;\n if (run.status === 'pending') {\n await this.store.updateRun(run.id, { status: 'running', updatedAt: new Date() });\n run.status = 'running';\n this.emit({\n type: 'run.started',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n }\n if (registered.singleton && !(await this.singletons.admit(run, registered.singleton))) {\n return this.singletonWaitResult(run);\n }\n\n // Capability/protocol routing guard for the remote workflow turn (handshake design §7.5): if\n // descriptors are published on its group but none is capability-capable + protocol-compatible, park\n // `blocked` (never dispatch into a queue nobody consumes). No descriptors → skip (legacy, §7.7). The\n // routing token mirrors the executor's own `tenantGroup(sanitizeQueueToken(group), …)` dispatch\n // target — see RemoteWorkflowExecutor. Settled inline here (this path releases its own lease), unlike\n // the step guard which parks via the run-execution catch.\n const wfPlan = await this.planRoute(\n tenantGroup(sanitizeQueueToken(remote.group), undefined),\n registered.requires,\n );\n if (wfPlan?.status === 'blocked') return this.parkBlocked(run, wfPlan);\n\n const history = await this.remoteHistory(run.id);\n\n // DISPATCH-AND-SUSPEND (broker-backed executors): SUSPEND-then-ENQUEUE. The engine generates the\n // turn's `taskId`, records it on the run as the awaited marker, and RELEASES the lease — all BEFORE\n // enqueuing the turn — so a fast worker's decision (delivered over `onDecision`, applied durably by\n // `completeRemoteDecision` on WHATEVER instance consumes it) can NEVER arrive ahead of its marker,\n // nor contend with a still-held lease, and be dropped. (The original dispatch-then-mark order lost a\n // sub-millisecond cached-replay decision that round-tripped the in-cluster broker before the marker\n // write to the remote store committed — the multi-instance decision-drop's deeper race.) Liveness is\n // the suspended turn's heartbeat-rearmed window (`remoteAdvanceSilenceMs` → `wakeAt`): if no\n // decision/heartbeat lands before it lapses (including a dispatch that throws below), the timer\n // poller re-drives by re-marking + re-enqueuing a fresh turn.\n if (remote.executor.dispatch) {\n const taskId = `${run.id}:wf:${globalThis.crypto.randomUUID().slice(0, 8)}`;\n const silenceMs = this.remoteAdvanceSilenceMs;\n const wakeAt = silenceMs != null ? this.clock() + silenceMs : undefined;\n // MARK FIRST: record the awaited turn before it is enqueued. No resurrection risk — unlike the old\n // mark-AFTER-dispatch order, nothing rewrites `status` past this point, so a parent-cancel that\n // writes a terminal status during the enqueue below simply wins (its decision is later dropped by\n // `completeRemoteDecision`'s terminal-status check).\n await this.store.updateRun(run.id, {\n status: 'suspended',\n awaitingDecisionTaskId: taskId,\n wakeAt,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.suspended',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n // RELEASE BEFORE ENQUEUE: the decision must be able to BOTH match the marker AND acquire the lease\n // the instant it arrives — even a few ms after the enqueue. Holding the lease through the enqueue\n // would drop a fast decision at lock contention. Idempotent vs. `execute`'s own finally release.\n await this.store.releaseRunLock(run.id);\n // THEN enqueue. A failed/lost dispatch leaves the run suspended-awaiting with `wakeAt` set, so the\n // timer poller re-drives it — no lost run.\n await remote.executor.dispatch(run, history, taskId);\n return { runId: run.id, status: 'suspended' };\n }\n\n // INLINE advance (in-process group-served executors): the decision is produced in-process, so await\n // it under the lease. Single-instance by nature; the dispatch path above is the multi-instance one.\n const advanceExecutor = remote.executor.advance;\n if (!advanceExecutor) {\n throw new Error(\n `workflow ${run.workflow}@${run.workflowVersion}: executor implements neither advance nor dispatch`,\n );\n }\n let decision: WorkflowDecision;\n try {\n // When `remoteAdvanceSilenceMs` is configured, wrap the advance in a heartbeat-rearmed deadline\n // keyed by `run.id`: a worker replaying this turn beats (a run-scoped Heartbeat) to keep it alive,\n // and only a genuinely-silent worker trips RemoteWorkflowTimeout → recovery re-drive. Unset = the\n // prior unbounded await. INVARIANT: `advance()` is created and passed to awaitWithLivenessDeadline\n // SYNCHRONOUSLY (no await between), so the `heartbeatResets` entry is registered before the event\n // loop can deliver any beat — an early beat is never lost. If the executor ALSO carries its own\n // `timeoutMs`, the shorter of the two deadlines wins (both raise the same RemoteWorkflowTimeout,\n // handled identically by the catch below).\n const silenceMs = this.remoteAdvanceSilenceMs;\n const advance = advanceExecutor.call(remote.executor, run, history);\n decision =\n silenceMs != null\n ? await this.awaitWithLivenessDeadline(\n run.id,\n advance,\n silenceMs,\n () => new RemoteWorkflowTimeout(run.id, silenceMs),\n )\n : await advance;\n } catch (err) {\n // A RemoteWorkflowTimeout is NOT a failure: the advance only timed out (the decision was likely\n // dropped, while the work may have actually completed). Failing the run here would be wrong — and\n // would notify the parent of a false failure. Instead RELEASE the lease and leave the run in its\n // current `running` state so `recoverIncomplete` re-acquires the now-free lease and re-drives it;\n // the re-driven turn replays completed steps from history and, if the work was done, returns the same\n // `completed` decision → settles → notifies the parent. Opt-in: only reachable when the executor\n // was constructed with a `timeoutMs` (absent = prior unbounded await, unchanged).\n //\n // FIXED-TIMEOUT HAZARD: a bare RemoteWorkflowExecutor `timeoutMs` that fires while a worker is\n // LEGITIMATELY still executing a not-yet-checkpointed step re-drives → DUPLICATE side effects, so\n // that knob is only safe set GENEROUSLY (> the longest legitimate single turn). The robust fix is\n // the heartbeat-rearmed deadline above (`remoteAdvanceSilenceMs`): the worker beats while it works,\n // so only a genuinely-silent (dead) worker trips the timeout — no re-drive of a live turn.\n //\n // Lease lifecycle: `execute` clears its renew interval in its `finally` once this returns, so the\n // lease (released just below) stays free. `releaseRunLock` is idempotent, and `renewRunLock` is a\n // no-op once `lockedBy` is cleared, so a renew tick racing the release cannot re-acquire it.\n if (err instanceof RemoteWorkflowTimeout) {\n await this.store.releaseRunLock(run.id);\n // The suspended path returned early above; run is always `running` here — left for recovery to re-drive.\n return { runId: run.id, status: 'running' as const };\n }\n const error = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n // terminal failure: lease expires naturally — no recovery re-drive will race it\n await this.store.updateRun(run.id, { status: 'failed', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n return { runId: run.id, status: 'failed', error };\n }\n\n return this.applyDecision(run, decision);\n }\n\n /**\n * Apply a remote workflow turn's {@link WorkflowDecision}: persist the local steps it ran, then\n * settle (completed/failed/cancelled) or dispatch its blocking ops and suspend (continue). Shared by\n * the INLINE-advance path ({@link runRemoteExecution}, under the held lease) and the durable\n * DISPATCH path ({@link completeRemoteDecision}, which holds the lease itself). Idempotent transitions\n * — the caller has already ensured this is the decision for the currently-awaited turn.\n */\n private async applyDecision(run: WorkflowRun, decision: WorkflowDecision): Promise<RunResult> {\n if (decision.status === 'completed') {\n // Persist the local steps THIS turn ran before marking the run done. A workflow that runs\n // straight to completion in a single turn (every step inline, never suspending — e.g. a Python\n // @workflow whose body is a sequence of ctx.step calls) emits ALL its recordStep commands on\n // this terminal turn; without applying them the run shows `completed` with zero recorded steps.\n // Only this turn's NEW steps are present (prior turns' steps replay as `found`, emitting no\n // command), so there's no duplication.\n await this.applyCommands(run, decision.commands);\n return this.settleRun(run, { kind: 'completed', output: decision.output });\n }\n if (decision.status === 'failed') {\n // Same as completed: persist the steps this turn ran — including the failed one (the worker\n // records a failed-step command before raising) — so the dashboard shows WHERE it failed.\n await this.applyCommands(run, decision.commands);\n return this.settleRun(run, {\n kind: 'failed',\n error: decision.error ?? { message: 'workflow failed' },\n });\n }\n\n if (decision.status === 'cancelled') {\n // The worker bailed at an op boundary because the run was cancelled mid-turn — `cancel` already\n // set status=cancelled, cascaded to children and emitted the lifecycle event. Persist the steps\n // that DID run this turn (partial progress / where it stopped) and reassert `cancelled`\n // (idempotent with `cancel`'s write; preserves the existing error). The point is to NOT resurrect\n // the run to `suspended` or flip it to `failed` — both of which a normal turn result would do.\n await this.applyCommands(run, decision.commands);\n await this.store.updateRun(run.id, { status: 'cancelled', updatedAt: new Date() });\n return { runId: run.id, status: 'cancelled' };\n }\n\n // continue: persist any local steps the replay ran, dispatch the blocking ops, then suspend. When\n // those resolve (a result lands, a timer fires) `resume` brings us back for the next turn.\n //\n // Guard: re-read the run BEFORE writing `suspended` — a parent-cancel cascade may have written\n // `cancelled` to the store WHILE the executor was replaying this turn (the advance() awaited above\n // runs outside the store transaction). Overwriting `cancelled` → `suspended` would let recovery\n // re-drive the run forever. If the store already shows a terminal/cancelled state, bail without\n // touching it — identical to the guard in `completeRemoteResult` for remote step results.\n const fresh = await this.store.getRun(run.id);\n if (\n fresh &&\n (fresh.status === 'cancelled' || fresh.status === 'completed' || fresh.status === 'dead')\n ) {\n return { runId: run.id, status: fresh.status, output: fresh.output, error: fresh.error };\n }\n const wakeAt = await this.applyCommands(run, decision.commands, true);\n const suspended = await this.settleRun(run, { kind: 'suspended', wakeAt });\n // This turn may have been computed from a history older than the store's, in which case it just\n // parked on ops that are already settled — see {@link redriveIfTurnSawStaleHistory}.\n await this.redriveIfTurnSawStaleHistory(run.id, decision.commands);\n return suspended;\n }\n\n /**\n * Re-drive a run whose turn was computed from a history OLDER than the store's.\n *\n * A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The\n * canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's\n * lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns\n * silently, so that call's wake is spent with nothing to show for it, and the decision then parks\n * the run on a `call` that is already complete. Nothing would ever wake it again — only the\n * `reconcileMs` orphan sweep, minutes later.\n *\n * The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A\n * turn with an up-to-date history never does that, because a settled op is in its history and the\n * replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and\n * cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.\n *\n * Scheduled off the current stack so it runs after the caller released the run lease.\n */\n private async redriveIfTurnSawStaleHistory(\n runId: string,\n commands: WorkflowCommand[],\n ): Promise<void> {\n const blocking = commands.filter(\n (cmd) => cmd.kind === 'call' || cmd.kind === 'startChild' || cmd.kind === 'waitSignal',\n );\n if (blocking.length === 0) return;\n for (const cmd of blocking) {\n const checkpoint = await this.store.getCheckpoint(runId, cmd.seq);\n if (checkpoint && checkpoint.status !== 'pending') {\n setTimeout(() => {\n void this.resumeImplicit(runId).catch(() => undefined);\n }, 0).unref?.();\n return;\n }\n }\n }\n\n /**\n * A polyglot workflow's re-emitted `call` whose checkpoint already exists: decide whether the step\n * is still out for delivery, or whether its dispatch was LOST and has to be re-driven. Returns the\n * lease deadline to park the run on (so the next decision lands exactly when it's due), or\n * `undefined` when there is nothing to wait for.\n *\n * WHY THIS EXISTS. A worker process killed mid-step (OOM, exit 137 — a pod's memory ceiling, not a\n * bug in anyone's code) takes its in-flight job with it: BullMQ's stalled-check eventually fails the\n * job, and for a consumer that can't bridge a terminal job failure back into a `StepResult` (any\n * non-TS SDK) NOTHING settles the checkpoint. It stays `pending` — \"out for delivery\" — and the\n * `applyCommands` idempotency guard, which exists so a `ctx.gather_calls` fan-out doesn't\n * double-dispatch its still-in-flight siblings on every partial resume, skips it on every later turn.\n * The run then wakes on the reconcile sweep, dispatches a turn, has the call re-emitted, skips it\n * again, and sleeps. Forever. Observed in the wild on a six-run `gather_calls` fan-out: `pending`,\n * `attempts = 1`, `wakeAt` NULL, over an hour, no retry.\n *\n * THE POLICY (mirrors {@link callRemote}'s `ctx.step` self-heal, which this path silently did not\n * share — so `remoteRedispatchMs` simply did not apply to a fan-out):\n * - a SETTLED checkpoint always wins: a step that completed just before the crash is never re-run;\n * - `remoteRedispatchMs` unset (the default) keeps the by-design \"re-suspend, never re-dispatch\";\n * - otherwise the pending checkpoint carries a LEASE in `wakeAt` — a result or a step heartbeat\n * ({@link rearmStepLease}) renews it, so a live worker still holding the step is never\n * double-dispatched — and only a LAPSED lease re-dispatches, bounded by `remoteRedispatchMax`;\n * - past the bound the step is failed `remote_step_lost` and the failure enters the run's history,\n * so the workflow's own error path surfaces it instead of the engine looping.\n */\n private async redriveLostCall(run: WorkflowRun, cp: StepCheckpoint): Promise<number | undefined> {\n // Settled (or a non-remote seq): the checkpoint is the truth, nothing to re-drive.\n if (cp.kind !== 'remote' || cp.status !== 'pending') return undefined;\n if (this.remoteRedispatchMs == null) return undefined;\n // First sight of this pending step under the self-heal: stamp its lease (clock-space, persisted,\n // stable across replays and crashes) and park the run on it.\n if (cp.wakeAt == null) {\n const lease = this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint({ ...cp, wakeAt: lease });\n return this.stepLeaseWakeAt(lease);\n }\n if (this.clock() < cp.wakeAt) return this.stepLeaseWakeAt(cp.wakeAt);\n // The lease lapsed with no result and no heartbeat: the dispatch is presumed lost.\n if (cp.attempts >= this.remoteRedispatchMax) {\n const error = {\n message: `remote step \"${cp.name}\" lost — no result after ${cp.attempts} dispatch(es)`,\n code: 'remote_step_lost',\n retryable: false,\n };\n const now = new Date();\n // Settling it `failed` puts the failure in the run's history (see {@link remoteHistory}), where\n // the worker's replay raises it. The caller's `redriveIfTurnSawStaleHistory` sees a blocking op\n // that is no longer pending and re-drives the run, so that next turn happens immediately.\n await this.store.saveCheckpoint({\n ...cp,\n status: 'failed',\n error,\n wakeAt: undefined,\n finishedAt: now,\n events: [...(cp.events ?? []), lostStepEvent(this.clock(), cp.attempts, 'lost')],\n });\n this.emit({\n type: 'step.failed',\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n kind: 'remote',\n error,\n });\n return undefined;\n }\n const attempts = cp.attempts + 1;\n const lease = this.clock() + this.remoteRedispatchMs;\n const at = new Date();\n await this.store.saveCheckpoint({\n ...cp,\n attempts,\n wakeAt: lease,\n // The re-dispatch restarts the step's wall-clock window; the old one measured a worker that died.\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n // Observability: the step's own trail says WHY it ran again — a lost worker, not a failure retry.\n events: [...(cp.events ?? []), lostStepEvent(this.clock(), attempts, 'redispatched')],\n });\n await this.dispatchRemoteTask({\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n stepId: cp.stepId ?? stepId(run.id, cp.seq),\n group: cp.workerGroup ?? sanitizeQueueToken(cp.name),\n input: cp.input,\n attempt: attempts,\n });\n this.emit({\n type: 'step.started',\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n kind: 'remote',\n redispatched: true,\n });\n return this.stepLeaseWakeAt(lease);\n }\n\n /**\n * The run `wakeAt` a step lease should park on: the lease itself, but never LATER than the\n * `reconcileMs` safety net would have woken the run anyway. A long lease (a fan-out step that\n * legitimately runs for half an hour) must not stretch the orphan sweep's cadence for this run —\n * an early wake just re-parks on the un-lapsed lease, which is cheap and convergent.\n */\n private stepLeaseWakeAt(lease: number): number {\n const reconcile = this.reconcileMs;\n return reconcile == null ? lease : Math.min(lease, this.clock() + reconcile);\n }\n\n /** Earliest clock time a step's lease is worth LOOKING at again (`stepId` → clock ms) — the read\n * throttle for {@link rearmStepLease}, the step-scoped sibling of {@link decisionDeadlineRearms}. */\n private readonly stepLeaseRearms = new Map<string, number>();\n\n /**\n * A step-scoped heartbeat for a durably-suspended remote step: push its LEASE forward so a worker\n * that is still working on it is never presumed dead and double-dispatched. The durable counterpart\n * of {@link callRemoteInMemory}'s in-memory `heartbeatResets` rearm (which only exists on the\n * instance that dispatched a `timeoutMs` step), and the step-scoped sibling of\n * {@link rearmDecisionDeadline}. No-op unless the lost-dispatch self-heal is on — without\n * `remoteRedispatchMs` nothing ever re-dispatches, so there is no lease to defend.\n *\n * THROTTLED BY THE LEASE ITSELF, not a fixed interval: a renewal buys at most ONE window, so it is\n * only WORTH a write once the window is half spent. Beats arrive every couple of seconds from a hot\n * worker loop — and a `gather_calls` fan-out multiplies that by its in-flight steps — so an\n * unthrottled rearm is a per-beat SELECT + UPDATE storm (plus a `getRun` + `updateRun` whenever the\n * run is parked exactly on this step's lease). The `cp.wakeAt >= renewed` guard it replaces never\n * short-circuited anything, because `renewed` advances with the clock. So:\n * - a beat that finds more than half the window still on the clock writes nothing, and records the\n * half-spent mark so subsequent beats skip even the `getCheckpoint` READ until then;\n * - a beat at or past the mark renews, leaving a full half-window of headroom — the lease can never\n * lapse under a worker whose beats are anywhere near their normal cadence.\n *\n * That bounds the cost at ONE read + ONE write per half `remoteRedispatchMs` per in-flight step,\n * independent of beat frequency (with a 30-minute window: two writes an hour). The in-memory mark is\n * a pure optimisation — cold on a fresh instance, or on the one that didn't dispatch the step — and\n * the durable half-spent check below re-derives the same answer from the checkpoint, so nothing\n * depends on it surviving. Cleared wholesale past 1024 entries: a rare extra read, never a leak.\n */\n private async rearmStepLease(runId: string, seq: number): Promise<void> {\n if (this.remoteRedispatchMs == null) return;\n const id = stepId(runId, seq);\n const now = this.clock();\n const lookAgainAt = this.stepLeaseRearms.get(id);\n if (lookAgainAt !== undefined && now < lookAgainAt) return;\n // EVERY store call below is swallowed, reads AND writes: this runs inside the transport's beat\n // handler, which delivers beats serially and does not catch — a throwing rearm would take the whole\n // beat loop down (and on `bullmq`, where the subscriber does `void handler(...)`, surface as an\n // unhandled rejection that can kill the process). A lost beat is harmless by the same headroom\n // argument that justifies the throttle: the lease still has at least half its window left, and the\n // half-spent mark is only advanced AFTER a successful write, so the very next beat retries.\n try {\n const cp = await this.store.getCheckpoint(runId, seq);\n if (!cp || cp.kind !== 'remote' || cp.status !== 'pending') {\n // Settled (or gone): stop tracking it, so a long-lived worker's stale beats don't keep the entry.\n this.stepLeaseRearms.delete(id);\n return;\n }\n const halfWindow = Math.ceil(this.remoteRedispatchMs / 2);\n // More than half the window left: nothing to buy, and nothing to look at until it is half spent.\n if (cp.wakeAt != null && cp.wakeAt > now + halfWindow) {\n this.stepLeaseRearms.set(id, cp.wakeAt - halfWindow);\n return;\n }\n const renewed = now + this.remoteRedispatchMs;\n const previous = cp.wakeAt;\n await this.store.saveCheckpoint({ ...cp, wakeAt: renewed });\n if (this.stepLeaseRearms.size > 1024) this.stepLeaseRearms.clear();\n this.stepLeaseRearms.set(id, renewed - halfWindow);\n // If the run is parked EXACTLY on this step's old lease, carry its wake forward too — otherwise a\n // beating worker costs one wasted turn per renewal window. Only on an exact match: any other\n // `wakeAt` belongs to some other timer (a sleep, a sibling's shorter lease) and moving it would\n // delay that instead.\n if (previous == null) return;\n const run = await this.store.getRun(runId);\n if (run?.status === 'suspended' && run.wakeAt === previous) {\n await this.store.updateRun(runId, { wakeAt: renewed, updatedAt: new Date() });\n }\n } catch {\n // Best-effort liveness: a store blip costs one skipped renewal, never the beat loop. The mark was\n // not advanced unless the lease write itself already committed, so nothing is silently left stale.\n }\n }\n\n /** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */\n private async remoteHistory(runId: string): Promise<HistoryEvent[]> {\n const checkpoints = await this.store.listCheckpoints(runId);\n const kindOf: Record<StepKind, HistoryEvent['kind']> = {\n remote: 'call',\n local: 'step',\n sleep: 'timer',\n signal: 'signal',\n };\n const events: HistoryEvent[] = [];\n for (const cp of checkpoints) {\n if (cp.status === 'completed' || cp.status === 'failed') {\n // A child run resolves THROUGH the signal machinery (a `child:<id>` waiter notified on the\n // child's terminal state), so its checkpoint is kind `signal` with a `signal:child:` name and\n // a Completion payload. Surface it as a `child` event with the value/error unwrapped.\n if (cp.kind === 'signal' && cp.name.startsWith('signal:child:')) {\n const completion = cp.output as Completion<unknown> | undefined;\n events.push({\n seq: cp.seq,\n kind: 'child',\n output: completion?.ok ? completion.value : undefined,\n error:\n completion && completion.ok === false ? { message: completion.error } : undefined,\n });\n continue;\n }\n events.push({\n seq: cp.seq,\n kind: kindOf[cp.kind] ?? 'step',\n // A signal checkpoint's name is the internal `signal:<token>`, not the workflow-level signal\n // name the replay used — omit it so the replay matches on seq + kind (its determinism anchor).\n name: cp.kind === 'signal' ? undefined : cp.name,\n output: cp.status === 'completed' ? cp.output : undefined,\n error: cp.status === 'failed' ? cp.error : undefined,\n });\n } else if (cp.kind === 'sleep' && cp.wakeAt != null && cp.wakeAt <= this.clock()) {\n // a still-`pending` sleep whose deadline has passed reads as a resolved timer on replay.\n events.push({ seq: cp.seq, kind: 'timer', name: cp.name });\n }\n }\n return events.sort((a, b) => a.seq - b.seq);\n }\n\n /** Apply a turn's commands: persist recorded local steps, dispatch remote calls, schedule timers.\n * Returns the earliest timer deadline to suspend on (or undefined — suspended on a result).\n *\n * `redriveLost` is set only by the `continue` path: a turn that PARKS on its blocking ops is the\n * one that may find a re-emitted `call` whose dispatch was lost and needs re-driving (see\n * {@link redriveLostCall}). A terminal turn (completed/failed/cancelled) applies its commands only\n * to record what already ran, and must never dispatch anything new. */\n private async applyCommands(\n run: WorkflowRun,\n commands: WorkflowCommand[],\n redriveLost = false,\n ): Promise<number | undefined> {\n let wakeAt: number | undefined;\n for (const cmd of commands) {\n const at = new Date();\n const id = stepId(run.id, cmd.seq);\n if (cmd.kind === 'recordStep') {\n // Prefer the step's real wall-clock window + sub-process events (carried by the command, and\n // already streamed live via persistStepEvent) so the checkpoint shows a true duration and its\n // p-process trail — not a 0ms placeholder. Fall back to apply-time for older workers.\n const startedAt = cmd.startedAt != null ? new Date(cmd.startedAt) : at;\n const finishedAt = cmd.finishedAt != null ? new Date(cmd.finishedAt) : at;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'local',\n status: cmd.error ? 'failed' : 'completed',\n output: cmd.output,\n error: cmd.error,\n events: cmd.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt,\n // Carry the worker's `parallelGroup` (a Python `ctx.gather` tags every step in the fan with\n // the same group) onto the checkpoint, so the dashboard can render the steps as one parallel\n // group instead of a sequential list. Additive: undefined for ordinary sequential steps.\n parallelGroup: cmd.parallelGroup,\n }),\n );\n this.emit({\n type: cmd.error ? 'step.failed' : 'step.completed',\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'local',\n output: cmd.output,\n error: cmd.error,\n });\n } else if (cmd.kind === 'call') {\n // Idempotency (load-bearing for `ctx.gather_calls`): a fan-out re-emits its still-pending\n // `call` commands on every PARTIAL resume (a sibling settled, but not all). Without this guard\n // each re-emit would re-persist + re-dispatch an already-in-flight (or already-completed) step,\n // double-dispatching the worker and resetting attempts. So if a checkpoint for (run.id, seq)\n // already exists — pending OR terminal — skip the save + dispatch entirely; its result lands\n // independently via completeRemoteResult (keyed by seq, so concurrent calls never clobber).\n // Mirrors the `startChild` `getRun(childId)` guard below.\n //\n // What that guard must NOT do is treat \"a checkpoint exists\" as \"somebody is still going to\n // deliver it\". A dispatched job can be LOST — the worker was OOM-killed mid-step, so the job\n // died with the process and no result will ever come — and the checkpoint still reads\n // `pending`. Skipping such a command forever is how a fan-out orphans its run (see\n // {@link redriveLostCall}, which owns that decision; a settled checkpoint always wins).\n const existing = await this.store.getCheckpoint(run.id, cmd.seq);\n if (existing) {\n const leaseAt = redriveLost ? await this.redriveLostCall(run, existing) : undefined;\n if (leaseAt != null) wakeAt = wakeAt == null ? leaseAt : Math.min(wakeAt, leaseAt);\n continue;\n }\n // The dispatched step's LEASE: when the lost-dispatch self-heal is on (`remoteRedispatchMs`),\n // stamp the deadline by which a result (or a step heartbeat renewing it) must have landed, and\n // suspend the run ON it — so the re-drive lands when it's due instead of waiting for the\n // reconcile sweep. Unset (default) leaves `wakeAt` NULL exactly as before.\n const lease =\n this.remoteRedispatchMs == null ? undefined : this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'remote',\n status: 'pending',\n input: cmd.input,\n attempts: 1,\n wakeAt: lease,\n // `cmd.group` is the routing declaration the worker's replay emitted (cross-SDK, or a\n // group-served TS body) — treated as an isolation partition on top of the step's own\n // name, mirroring the StepDef formula below (identical expression everywhere).\n workerGroup: tenantGroup(sanitizeQueueToken(cmd.name), cmd.group),\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n // A `ctx.gather_calls([...])` fan-out stamps every dispatched `call` in the fan with the\n // same group, so the dashboard renders the dispatched steps as one parallel fan (parity\n // with the gathered `recordStep`/`startChild` tags). Undefined for a lone sequential `ctx.step`.\n parallelGroup: cmd.parallelGroup,\n }),\n );\n await this.pool.dispatch(\n {\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n stepId: id,\n group: tenantGroup(sanitizeQueueToken(cmd.name), cmd.group),\n input: cmd.input,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt: 1,\n },\n undefined,\n );\n this.emit({\n type: 'step.started',\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'remote',\n });\n if (lease != null) {\n const leaseWake = this.stepLeaseWakeAt(lease);\n wakeAt = wakeAt == null ? leaseWake : Math.min(wakeAt, leaseWake);\n }\n } else if (cmd.kind === 'sleep') {\n const deadline = this.clock() + cmd.ms;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: `sleep:${cmd.seq}`,\n kind: 'sleep',\n status: 'pending',\n attempts: 1,\n wakeAt: deadline,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n }),\n );\n wakeAt = wakeAt == null ? deadline : Math.min(wakeAt, deadline);\n } else if (cmd.kind === 'waitSignal') {\n // Park on a signal: register a waiter at this seq so engine.signal(token) lands the resolving\n // `signal` checkpoint here and resumes the run. The token is the signal name, so an external\n // engine.signal(name, payload) delivers it. If the signal was already delivered (buffered\n // before the workflow reached this point — e.g. signalWithStart), resolve it now and re-drive\n // on a macrotask, AFTER this turn suspends and frees the run lock (a re-entrant resume bails).\n //\n // NOTE: `WorkflowCommand` has no `waitEvent` kind — a polyglot (remote-executor) workflow has\n // no way to issue `ctx.waitForEvent(name, { match })` today; only in-process TS workflows\n // (`workflow-ctx.ts`) can. So buffered EVENTS (`bufferEvent`/`listBufferedEvents`/\n // `removeBufferedEvent`) are reachable only from `engine.publishEvent` and the in-process\n // `waitForEvent`/reconcile paths — never from this remote command loop. Extending the\n // polyglot protocol with an event-wait command is future work, not something to invent here.\n const deliverBuffered = async (payload: unknown): Promise<void> => {\n await this.store.saveCheckpoint(\n instantCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: `signal:${cmd.signal}`,\n kind: 'signal',\n output: payload,\n }),\n );\n setTimeout(() => void this.resumeImplicit(run.id).catch(() => undefined), 0);\n };\n const buffered = await this.store.takeBufferedSignal(cmd.signal);\n if (buffered) {\n await deliverBuffered(buffered.payload);\n } else {\n // Same reorder as the in-process ctx.waitForSignal (see there for why registering\n // UNCONDITIONALLY before even the first check is unsafe — it would expose a \"this turn is\n // about to self-resolve\" waiter row to a concurrent signal for a token a polyglot entity\n // loop reuses, which could steal it and misdeliver): check first, and only on a miss\n // register, then re-check once more before suspending — closing the lost-wake window where\n // a signal races in between the miss above and the registration below (see the interleaving\n // proof at engine.signal).\n await this.store.putSignalWaiter({ token: cmd.signal, runId: run.id, seq: cmd.seq });\n const lateBuffered = await this.store.takeBufferedSignal(cmd.signal);\n if (lateBuffered) {\n // Resolved it ourselves — remove OUR OWN row via the exact match (not\n // takeSignalWaiter(cmd.signal), which deletes ANY row for this token and could steal a\n // different run's waiter that has since claimed the same token).\n await this.store.removeSignalWaiter({ token: cmd.signal, runId: run.id, seq: cmd.seq });\n await deliverBuffered(lateBuffered.payload);\n }\n }\n } else if (cmd.kind === 'startChild') {\n // Start a child run and await it (the worker's ctx.start_child suspends until the child's\n // result is in history). Mirror the in-process `ctx.child`: register a `child:<id>` waiter at\n // this seq — the child notifies it on its terminal state (engine.notifyParent) — then start the\n // child once, deferred so a fast child can't reentrantly resume this still-suspending parent,\n // and id-idempotent so replay/recovery never double-starts it.\n const childId = `${run.id}.child.${cmd.seq}`;\n await this.store.putSignalWaiter({\n token: `child:${childId}`,\n runId: run.id,\n seq: cmd.seq,\n // A `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` in the fan with the same\n // group. Thread it onto the waiter so the child's terminal `signal:child:<id>` checkpoint\n // (written by engine.signal when the child notifies the parent) carries the group and the\n // dashboard renders the fan as one parallel group. Undefined for a lone (non-fan) child.\n parallelGroup: cmd.parallelGroup,\n });\n if (!(await this.store.getRun(childId))) {\n // Inherit the parent run's namespace (see ctxHostFor.startChild) so a remote workflow's\n // child stays on the parent's tenant/partition regardless of which engine executes it.\n this.startChildDeferred(cmd.workflow, cmd.input, childId, { namespace: run.namespace });\n }\n } else {\n throw new Error(\n `remote workflow command '${(cmd as { kind: string }).kind}' is not supported yet`,\n );\n }\n }\n return wakeAt;\n }\n\n /**\n * Undo the registered saga compensations in reverse and settle the run `cancelled`. Shared by EVERY\n * exit path of a run with a compensating cancel in flight — whether the resumed replay returned,\n * suspended, hit continue-as-new, or threw — so a cancel is never lost just because the body didn't\n * stop at a suspension point.\n *\n * A dispatched compensation still in flight (or backing off a retry) needs the run to keep waiting:\n * unlike the failure path (which is fine going `suspended` — a resumable state no different from an\n * ordinary in-flight `ctx.step`), THIS run must stay `cancelling` — `engine.cancel`'s idempotent\n * re-check, `waitForRun`'s non-terminal treatment, and crash recovery (`recoverIncomplete` only\n * re-drives `running`/`cancelling` runs — a `cancelling` one with a free lease, whatever it's\n * internally waiting on) all key off that status. So on a pending unwind this returns WITHOUT\n * touching `status` (already `cancelling`, untouched since `engine.cancel` set it) — the in-memory\n * cancel flag stays too, re-derived from the status on any later re-drive regardless.\n */\n private async compensateAndCancel(\n run: WorkflowRun,\n compensations: Compensation[],\n replay?: Map<number, StepCheckpoint>,\n ): Promise<RunResult> {\n const pending = await this.unwindCompensations(run, compensations, replay);\n if (pending) return { runId: run.id, status: 'cancelling' };\n this.cancelRequested.delete(run.id);\n const error = { message: 'cancelled' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n return { runId: run.id, status: 'cancelled', error };\n }\n\n /**\n * The run body, lease held + renewed by {@link execute}, wrapped in the registered\n * {@link runDurableExecution} wrappers so an observability scope covers ONE WHOLE TURN.\n *\n * The wrap goes here — around the entire turn — rather than tightly around the `fn(ctx, input)`\n * call, because the store writes that bracket the body (the `pending` → `running` transition, the\n * step checkpoints, the terminal `settleRun` update) are exactly the queries an operator wants\n * correlated to the turn that issued them. Narrowing the wrap to the body would leave them\n * uncorrelated for the sake of a purity that buys nothing.\n *\n * Only the TS path is wrapped. {@link runRemoteExecution} does not execute a body at all — it\n * dispatches a workflow task and awaits the worker's decision — so a scope opened there would\n * describe a dispatch, not an execution, and would mislead anyone reading the trace.\n */\n private runExecution(\n run: WorkflowRun,\n fn: WorkflowFn,\n registered: RegisteredWorkflow | undefined,\n ): Promise<RunResult> {\n return runDurableExecution(\n {\n unit: 'workflow',\n runId: run.id,\n workflow: run.workflow,\n name: undefined,\n seq: undefined,\n attempt: undefined,\n },\n () => this.runExecutionTurn(run, fn, registered),\n );\n }\n\n private async runExecutionTurn(\n run: WorkflowRun,\n fn: WorkflowFn,\n registered: RegisteredWorkflow | undefined,\n ): Promise<RunResult> {\n // A run persisted as `cancelling` is a compensating cancel in flight — possibly re-driven by\n // recovery after a crash that lost the in-memory cancel flag. Re-derive the intent from the status\n // so the replay below reaches the WorkflowSuspended + cancelRequested branch and compensates →\n // cancelled (this is what makes a compensating cancel durable across a crash).\n if (run.status === 'cancelling') this.cancelRequested.add(run.id);\n // First execution of an enqueued run: mark it running and announce the start, BEFORE the singleton\n // gate. A resumed run is already past `pending`, so this fires exactly once.\n if (run.status === 'pending') {\n await this.store.updateRun(run.id, { status: 'running', updatedAt: new Date() });\n run.status = 'running';\n this.emit({\n type: 'run.started',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n }\n // Singleton admission gate: if this run shares its key with `limit` older in-flight runs, wait\n // (suspend on a short timer) until a slot frees instead of running now. Re-checked on each resume.\n // A `cancelling` run skips the gate — it is tearing down, not competing for a slot, and suspending\n // it here would clobber the `cancelling` status.\n if (\n run.status !== 'cancelling' &&\n registered?.singleton &&\n !(await this.singletons.admit(run, registered.singleton))\n ) {\n return this.singletonWaitResult(run);\n }\n // Saga compensations registered by completed steps; run in reverse if the run later fails.\n const compensations: Compensation[] = [];\n // Load this run's checkpoints ONCE and key them by seq, so replaying the completed prefix reads\n // from memory instead of one `getCheckpoint` SELECT per primitive (the O(N²) replay-reads fix).\n // Read once at execution start: a checkpoint written AFTER this snapshot (the signal/timer/child\n // this resume wakes on, or one written later in this same execution) is absent from the map, and\n // the ctx falls back to the live store for any absent seq — so replay semantics are unchanged.\n const snapshot = await this.store.listCheckpoints(run.id);\n const replay = new Map<number, StepCheckpoint>();\n for (const cp of snapshot) replay.set(cp.seq, cp);\n let suspendedOnFan: FanJoin | undefined;\n const ctx = createWorkflowCtx(\n this.ctxHostFor(replay, run.namespace),\n run.id,\n compensations,\n run.workflow,\n registered?.searchAttributesSchema,\n );\n // Every settle below is `return await`ed, never a bare `return this.settleRun(...)`: inside\n // `try … finally` a bare return runs the `finally` — which RELEASES THE LEASE — as soon as the\n // return expression is evaluated, while the settle's own writes are still in flight. The run then\n // sits unlocked but still reading `running`, which is exactly the shape `recoverIncomplete` takes\n // for a crashed turn: it re-enqueued the run and a second execution replayed it alongside the one\n // a fast step result had legitimately resumed. The lease must outlive the state it protects.\n try {\n // The ambient-context wrap is what lets class-first statics (`MyWorkflow.execute()`) find\n // this ctx from anywhere on the body's async path — first run and every replay alike.\n const output = await runInWorkflowCtx(ctx, () => fn(ctx, run.input));\n // A compensating cancel may have been requested while this turn ran (or re-derived from a\n // `cancelling` status on recovery): undo + settle cancelled rather than completing, so the cancel\n // is never lost when the body returns without first hitting a suspension point.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n return await this.settleRun(run, { kind: 'completed', output });\n } catch (err) {\n if (err instanceof ContinueAsNew) {\n // A cancel in flight wins over continue-as-new: undo + cancel instead of spawning the next run.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n // Hand off to a fresh execution with a clean history: complete this run, then start the next\n // (`<id>~N`) with the new input. Deferred + idempotent by the continuation id, so a crash\n // mid-handoff re-derives the same next run instead of forking.\n await this.store.updateRun(run.id, {\n status: 'completed',\n output: undefined,\n error: undefined,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.completed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n void this.notifyParent(run.id, { ok: true, value: undefined });\n const nextId = nextContinuationId(run.id);\n queueMicrotask(\n () => void this.start(run.workflow, err.input, nextId).catch(() => undefined),\n );\n return { runId: run.id, status: 'completed' };\n }\n if (err instanceof WorkflowBlocked) {\n // No live worker can run the next dispatch (capability/protocol gap) — park the run `blocked`\n // (design §7.5/§7.6) with the structured diagnostics, instead of writing a `pending` checkpoint\n // + dispatching into a queue nobody consumes. The blocked-recovery poll re-drives it when a\n // capable+compatible worker appears. A compensating cancel in flight still wins.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n return await this.settleRun(run, { kind: 'blocked', blocked: err.plan });\n }\n if (err instanceof WorkflowSuspended) {\n // A compensating cancel resumed this run to reach here: undo + cancel instead of re-suspending.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n const suspended = await this.settleRun(run, { kind: 'suspended', wakeAt: err.wakeAt });\n suspendedOnFan = err.fan;\n return suspended;\n }\n // A cancel in flight that surfaced as a thrown error still settles cancelled (not failed) — the\n // saga undo runs either way; this just keeps the terminal status faithful to the cancel request.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n const error = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n // Saga: undo completed steps in reverse — local ones in-process, dispatched ones as durable\n // remote-step dispatches (see `unwindCompensations`) — each made VISIBLE as a `compensate:<step>`\n // step event/checkpoint so a stranded undo is never silently swallowed; a failing one is still\n // skipped so it can't mask the original failure or strand the rest (compensations should be\n // idempotent). A dispatched undo still in flight (or backing off a retry) SUSPENDS the run\n // exactly like an ordinary `ctx.step` dispatch — the next re-drive (the worker's result landing,\n // or the retry backoff elapsing) resumes `unwindCompensations` right where it left off.\n const pending = await this.unwindCompensations(run, compensations, replay);\n if (pending) return await this.settleRun(run, { kind: 'suspended', wakeAt: pending.wakeAt });\n return await this.settleRun(run, { kind: 'failed', error });\n } finally {\n // Release the recovery lease once the run reaches a terminal/suspended state, so the\n // next instance (or the timer poller) can pick it up promptly.\n await this.store.releaseRunLock(run.id);\n if (suspendedOnFan) {\n void this.redriveSettledChildren(run.id, suspendedOnFan).catch(() => undefined);\n }\n }\n }\n\n /**\n * Undo every registered saga compensation in strict reverse order — the shared unwind both the\n * run-failure path (`runExecution`'s catch) and the compensating-cancel path\n * (`compensateAndCancel`) drive. Every entry, LOCAL or DISPATCHED, gets a NEGATIVE checkpoint seq\n * `-(k + 1)` for its position `k` (0, 1, 2… walking the stack in reverse) — reserved space that can\n * never collide with a body position (those start at 0), so a saga's undo trail composes onto the\n * run's ordinary checkpoint history with no store-schema change, and shows up in run detail exactly\n * like any other step. Deterministic because `compensations` is rebuilt identically on every replay\n * (see `workflow-ctx.ts`), so the same comp always lands on the same negative seq across a crash +\n * re-drive — the crash-safety this whole scheme rests on.\n *\n * A LOCAL entry runs in-process (`runCompensation`), which checkpoints its own outcome — completed,\n * or failed once `compensationRetries` are exhausted — so a crash mid-unwind SKIPS an\n * already-resolved one on the next pass instead of re-running it (and re-spending its retry budget)\n * from attempt 1. A DISPATCHED entry is an ordinary remote-step dispatch under the hood\n * (`dispatchCompensation`): when it needs the run to WAIT — freshly dispatched, still in flight, or\n * backing off a durable retry — this function returns that wait signal immediately (skipping every\n * comp after it in this pass); the CALLER decides how to represent \"still unwinding\" (see\n * `compensateAndCancel`'s doc comment for why that differs between the two callers). Either way, the\n * run resumes later exactly like any other dispatched step: `completeRemoteResult` completes the\n * negative-seq checkpoint and re-drives, the body replays and deterministically re-throws the same\n * exit it took before (the original failure, or the suspension `compensateAndCancel` resumed from),\n * this function runs again, the now-resolved comp is skipped, and the unwind continues from there.\n *\n * Returns `undefined` once every compensation has resolved — the caller then finalizes the run\n * (`failed` with the ORIGINAL body error, never masked by a comp outcome; or `cancelled`).\n */\n private async unwindCompensations(\n run: WorkflowRun,\n compensations: Compensation[],\n replay?: Map<number, StepCheckpoint>,\n ): Promise<UnwindPending | undefined> {\n for (let i = compensations.length - 1; i >= 0; i -= 1) {\n const comp = compensations[i];\n if (!comp) continue;\n const seq = -(compensations.length - i);\n if ('fn' in comp) {\n const existing = replay?.get(seq) ?? (await this.store.getCheckpoint(run.id, seq));\n if (existing) continue; // already resolved (completed or exhausted-failed) in an earlier pass\n await this.runCompensation(run, comp, seq, replay);\n continue;\n }\n const pending = await this.dispatchCompensation(run, comp, seq, replay);\n if (pending) return pending;\n }\n return undefined;\n }\n\n /**\n * Run one LOCAL saga compensation, retried up to `compensationRetries`, emitting a\n * `compensate:<step>` step event for its outcome so a stranded undo is visible. Never throws — a\n * permanently-failing compensation is skipped so it can't mask the original failure. Checkpoints\n * its outcome at `seq` (a negative unwind position reserved by {@link unwindCompensations}) so a\n * crash mid-unwind skips an already-resolved undo on a later pass instead of re-running it (and\n * re-spending its retry budget) from attempt 1 — the checkpoint is durability/visibility only; the\n * runtime retry-in-process-back-to-back semantics of `comp.fn()` are unchanged.\n */\n private async runCompensation(\n run: WorkflowRun,\n comp: Extract<Compensation, { fn: () => Promise<void> }>,\n seq: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<void> {\n const name = `compensate:${comp.name}`;\n const enqueuedAt = new Date();\n for (let attempt = 1; attempt <= this.compensationRetries; attempt += 1) {\n const startedAt = new Date();\n try {\n await comp.fn();\n this.emit({\n type: 'step.completed',\n runId: run.id,\n workflow: run.workflow,\n name,\n kind: 'local',\n durationMs: Date.now() - startedAt.getTime(),\n });\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'local',\n status: 'completed',\n attempts: attempt,\n enqueuedAt,\n startedAt,\n finishedAt: new Date(),\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n return;\n } catch (err) {\n if (attempt >= this.compensationRetries) {\n const error = { message: err instanceof Error ? err.message : String(err) };\n this.emit({\n type: 'step.failed',\n runId: run.id,\n workflow: run.workflow,\n name,\n kind: 'local',\n error,\n durationMs: Date.now() - startedAt.getTime(),\n });\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'local',\n status: 'failed',\n attempts: attempt,\n error,\n enqueuedAt,\n startedAt,\n finishedAt: new Date(),\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n }\n }\n }\n }\n\n /**\n * Resolve (or advance) ONE dispatched saga compensation at its reserved negative `seq` — the undo\n * handler is an ordinary remote `@Step`, so this mirrors `callRemote`'s pending/failed/absent\n * branches (engine.ts's `callRemote`), minus the queue/admission and in-memory-`timeoutMs` paths\n * (V1: dispatch direct by name, always durable). Returns the wait signal when the run must pause for\n * this compensation (freshly dispatched, still in flight, or backing off before a durable retry);\n * `undefined` once it's resolved — completed (crash-safe skip), or retries exhausted/non-retryable\n * (already visible: `completeRemoteResult` emitted `step.failed` for `compensate:<name>` when that\n * checkpoint landed — never re-emitted here, and never allowed to block the rest of the unwind or\n * mask the run's original failure).\n */\n private async dispatchCompensation(\n run: WorkflowRun,\n comp: Extract<Compensation, { dispatch: unknown }>,\n seq: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<UnwindPending | undefined> {\n const { def, args } = comp.dispatch;\n const name = `compensate:${comp.name}`;\n const existing = replay?.get(seq) ?? (await this.store.getCheckpoint(run.id, seq));\n if (existing?.status === 'completed') return undefined;\n if (existing?.status === 'pending') return {}; // dispatched, awaiting the worker's result\n if (existing?.status === 'failed') {\n const maxAttempts = Math.max(1, def.retries ?? 1);\n const retryable = existing.error?.retryable !== false;\n if (!retryable || existing.attempts >= maxAttempts) return undefined;\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + backoffDelay(existing.attempts, def);\n const withWakeAt = { ...existing, wakeAt };\n await this.store.saveCheckpoint(withWakeAt);\n replay?.set(seq, withWakeAt);\n return { wakeAt };\n }\n if (this.clock() < existing.wakeAt) return { wakeAt: existing.wakeAt };\n await this.dispatchCompensationAttempt(\n run,\n seq,\n name,\n def,\n args,\n existing.attempts + 1,\n replay,\n );\n return {};\n }\n // Absent: first dispatch.\n await this.dispatchCompensationAttempt(run, seq, name, def, args, 1, replay);\n return {};\n }\n\n /**\n * Dispatch (or re-dispatch, on a durable retry) one compensation's undo handler — mirrors\n * `callRemote`'s dispatch block (persist the `pending` checkpoint BEFORE handing off to the\n * transport, so a fast result always finds it to complete). Two DIFFERENT names are in play: the\n * checkpoint's `name` is `compensate:<originalStepName>` (what makes this undo show up on the run's\n * timeline, and what `completeRemoteResult` emits `step.completed`/`step.failed` under); the WIRE\n * task's `name` is the undo handler's OWN routing name (`def.name`) — a worker dispatches to the\n * `@Step` it registered, not to this saga-visibility label.\n */\n private async dispatchCompensationAttempt(\n run: WorkflowRun,\n seq: number,\n name: string,\n def: StepDef<StepUndo<unknown, unknown>, unknown>,\n args: StepUndo<unknown, unknown>,\n attempt: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<void> {\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // The undo belongs to the tenant that ran the step it undoes — route it off the RUN, never off\n // the executing engine (see {@link stepGroup}).\n const group = stepGroup(def, run.namespace);\n const enqueuedAt = new Date();\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'remote',\n status: 'pending',\n input: args,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt: enqueuedAt,\n finishedAt: enqueuedAt,\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n await this.pool.dispatch({\n runId: run.id,\n seq,\n name: def.name,\n stepId: cp.stepId,\n group,\n input: args,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt,\n });\n this.emit({ type: 'step.started', runId: run.id, seq, name, kind: 'remote' });\n }\n\n /** The seam handed to {@link createWorkflowCtx}: the authoring API reaches durability + lifecycle\n * (checkpointing, dispatch, child start) through this, so the ctx primitives live in their own\n * module and the engine stays the orchestrator. */\n private ctxHostFor(replay?: Map<number, StepCheckpoint>, parentNamespace?: string): CtxHost {\n return {\n store: this.store,\n replay,\n clock: this.clock,\n webhookUrl: this.webhookUrl,\n startStep: (s) => this.startStep(s),\n completeStep: (s) => this.completeStep(s),\n failStep: (s) => this.failStep(s),\n // Route the dispatch by the RUN's tenant (same reason as `startChild` below): the executing\n // engine may be an operator driving every namespace, so the token must come from the run, not\n // from this engine. See {@link stepGroup}.\n callRemote: (runId, seq, step, input, queue, transport, admission) =>\n this.callRemote(runId, seq, step, input, queue, transport, replay, admission, {\n namespace: parentNamespace,\n }),\n // Defer so a fast child can't reentrantly resume a still-running parent. Stamp the child with\n // the PARENT run's namespace (not this engine's) so a child belongs to the tenant/partition of\n // the run it was spawned from — even when an operator (namespace: undefined, drives every\n // namespace) is the one executing the parent. Otherwise an operator recovery-resuming a\n // `davi-local` pipeline would stamp its `processing` child `default` and it would leak off the\n // tenant's worker pool onto the shared/dev workers.\n startChild: (workflow, input, id, priority, version) => {\n this.startChildDeferred(workflow, input, id, {\n priority,\n namespace: parentNamespace,\n // Absent unless the body pinned one (`ctx.child(ref, input, { version })`) — an omitted\n // pin must stay omitted, so the child keeps resolving `latest` exactly as before.\n version,\n });\n },\n // Deferred for the same reentrancy reason as `startChild` above. `cancel()` is already\n // idempotent on a terminal/cancelled run (returns its existing status without side effects), so\n // no extra guard is needed here for the failFast replay case (re-issuing the same cancel calls).\n cancelChild: (childId) => {\n queueMicrotask(() => void this.cancel(childId).catch(() => undefined));\n },\n // Shallow-merge into the run's searchAttributes (the ctx primitive makes this exactly-once).\n upsertSearchAttributes: async (runId, attrs) => {\n const run = await this.store.getRun(runId);\n await this.store.updateRun(runId, {\n searchAttributes: { ...(run?.searchAttributes ?? {}), ...attrs },\n updatedAt: new Date(),\n });\n },\n signalEntity: (name, key, op, arg, reply) => {\n queueMicrotask(\n () => void this.entities.dispatch(name, key, op, arg, reply).catch(() => undefined),\n );\n },\n interceptStep: (invocation, body) => this.interceptStep(invocation, body),\n };\n }\n\n /**\n * Resume a run paused at a {@link WorkflowCtx.breakpoint} (e.g. the dashboard \"continue\" button).\n * Finds the run's pending breakpoint checkpoint and signals it. Returns null if the run isn't\n * paused at a breakpoint.\n */\n async continue(runId: string): Promise<RunResult | null> {\n const checkpoints = await this.store.listCheckpoints(runId);\n const bp = checkpoints.find(isBreakpoint);\n if (!bp) return null;\n return this.signal(breakpointToken(runId, bp.seq), undefined);\n }\n\n /**\n * Read the latest value a run published for `key` via {@link WorkflowCtx.setEvent} — a\n * side-effect-free query of a live (or finished) run's state. Returns `undefined` if the run\n * never published that key. The suspend-model counterpart of a Temporal query.\n */\n async getEvent<TValue = unknown>(runId: string, key: string): Promise<TValue | undefined> {\n const name = `event:${key}`;\n // Targeted read: the highest-seq checkpoint for this name is the most recent value (a re-published\n // key overwrites at a higher seq), matching the old \"last in seq order wins\" scan. Falls back to a\n // full listCheckpoints scan (last match in seq-ascending order wins) for a store that omits it.\n if (this.store.getLatestCheckpointByName) {\n const latest = await this.store.getLatestCheckpointByName(runId, name);\n return latest?.output as TValue | undefined;\n }\n // listCheckpoints is ordered by seq ascending, so the last match is the most recent value.\n let latest: TValue | undefined;\n for (const cp of await this.store.listCheckpoints(runId))\n if (cp.name === name) latest = cp.output as TValue;\n return latest;\n }\n\n /**\n * Register a validator gating `engine.update(runId, name, …)` for runs of `workflow`. The\n * validator runs BEFORE the update is delivered, so a rejection leaves the run untouched. One\n * validator per (workflow, update name); registering again replaces it.\n */\n registerUpdateValidator<TArg>(\n workflow: string,\n name: string,\n validate: UpdateValidator<TArg>,\n ): void {\n this.updateValidators.set(`${workflow}:${name}`, validate as UpdateValidator);\n }\n\n /**\n * Deliver a validated update to the run waiting at `ctx.onUpdate(name)`. Runs the registered\n * validator (if any) first: on rejection returns `{ accepted: false, reason }` without disturbing\n * the run; otherwise delivers `arg` and resumes, returning `{ accepted: true, run }` (`run` is null\n * if nothing was waiting — a too-early or duplicate update).\n */\n async update(runId: string, name: string, arg: unknown): Promise<UpdateResult> {\n const run = await this.store.getRun(runId);\n if (!run) return { accepted: false, reason: `run ${runId} not found` };\n const validate = this.updateValidators.get(`${run.workflow}:${name}`);\n if (validate) {\n try {\n const reason = await validate(arg);\n if (typeof reason === 'string' && reason.length > 0) return { accepted: false, reason };\n } catch (err) {\n return { accepted: false, reason: err instanceof Error ? err.message : String(err) };\n }\n }\n const result = await this.signal(`update:${runId}:${name}`, arg);\n return { accepted: true, run: result };\n }\n\n /**\n * Plan a dispatch to `token` for a handler requiring `requires` (handshake design §7.5). Returns:\n * - `undefined` — NO live descriptors published on this token: the guard does not engage, so a\n * pre-handshake fleet (or an in-process transport that advertises none) keeps flowing exactly as\n * before (design §7.7);\n * - a `routable` plan — ≥1 live worker is capability-capable AND protocol-compatible (dispatch);\n * - a `blocked` plan — descriptors exist but none can run it (park the run, never dispatch into it).\n */\n private async planRoute(\n token: string,\n requires: string[] | undefined,\n ): Promise<DispatchPlan | undefined> {\n const descriptors = await this.pool.readWorkerDescriptors(token);\n if (descriptors.length === 0) return undefined; // legacy / no-descriptor path — skip the guard\n return planDispatch(requires ?? [], descriptors, this.cpDescriptor, token);\n }\n\n /** Throw {@link WorkflowBlocked} when no live worker can run a dispatch to `token` — so the caller's\n * run-execution catch parks the run `blocked` (with the plan) instead of persisting a `pending`\n * checkpoint + dispatching into a queue nobody consumes (design §7.5). A no-op when the guard does\n * not engage (no descriptors) or a capable+compatible worker exists. */\n private async ensureRoutable(token: string, requires: string[] | undefined): Promise<void> {\n const plan = await this.planRoute(token, requires);\n if (plan?.status === 'blocked') throw new WorkflowBlocked(plan);\n }\n\n /**\n * Park a run `blocked` (handshake design §7.5/§7.6): no live worker on its next-dispatch group is\n * capability-capable + protocol-compatible. Persists the `blocked` status with a human reason + the\n * machine `code` + a `wakeAt` so the blocked-recovery poll re-drives it, emits the LOUD structured\n * `capability.unavailable`/`protocol.incompatible` diagnostics (both descriptors + the precise delta),\n * and releases the run lease so any instance can re-drive it. Re-checks the persisted status first so\n * a concurrent cancel/complete is never clobbered. `releaseRunLock` is idempotent, so a caller whose\n * own `finally` also releases (the run-execution path) is safe.\n */\n private async parkBlocked(run: WorkflowRun, blocked: BlockedDispatch): Promise<RunResult> {\n const current = await this.store.getRun(run.id);\n if (current && (current.status === 'cancelled' || current.status === 'completed')) {\n await this.store.releaseRunLock(run.id);\n return {\n runId: run.id,\n status: current.status,\n output: current.output,\n error: current.error,\n };\n }\n const error: StepError = { message: blocked.reason, code: blocked.code, retryable: true };\n await this.store.updateRun(run.id, {\n status: 'blocked',\n error,\n wakeAt: this.clock() + this.blockedPollMs,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.blocked',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n requires: blocked.requires,\n diagnostics: blocked.diagnostics,\n });\n await this.store.releaseRunLock(run.id);\n return { runId: run.id, status: 'blocked', error };\n }\n\n /** Runs parked `blocked` whose recovery poll is due (`wakeAt <= nowMs`), namespace-scoped like\n * {@link resumeDueTimers}. Re-driving one re-checks the live fleet: it dispatches if a\n * capable+compatible worker has appeared, else re-parks with a fresh `wakeAt` (design §7.5). */\n private async dueBlockedRuns(nowMs: number): Promise<WorkflowRun[]> {\n const blocked = await this.store.listRuns({ statuses: ['blocked'] });\n return blocked.filter(\n (r) =>\n (this.namespace === undefined ||\n r.namespace === undefined ||\n r.namespace === this.namespace) &&\n r.wakeAt !== undefined &&\n r.wakeAt <= nowMs,\n );\n }\n\n private async callRemote<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n queue?: string,\n transport?: string,\n replay?: Map<number, StepCheckpoint>,\n admission?: { priority?: number | undefined; fairnessKey?: string | undefined },\n routing?: { namespace?: string | undefined },\n ): Promise<TOutput> {\n const group = stepGroup(step, routing?.namespace);\n // Read the prefix from the per-execution snapshot (avoids the O(N²) replay SELECTs); a seq absent\n // from the snapshot — not yet dispatched, or written after the snapshot — falls back to the store.\n let existing = replay?.get(seq) ?? (await this.store.getCheckpoint(runId, seq));\n // A `pending` step in the SNAPSHOT may already have its result: the snapshot is taken when this\n // execution starts, and the result can land any time after. Every branch below that sees\n // `pending` either suspends on it or WRITES the checkpoint back (`{ ...existing, wakeAt }` stamping\n // the lost-dispatch lease, or a re-dispatch) — written from a stale row, that overwrites the landed\n // `completed` result with `pending` and parks the run on a lease an hour out. So a pending step is\n // re-read from the store before anything acts on it (one read, only at a suspension point).\n if (existing?.status === 'pending' && replay?.has(seq)) {\n existing = (await this.store.getCheckpoint(runId, seq)) ?? existing;\n }\n if (existing && existing.name !== step.name) {\n throw new NonDeterminismError(runId, seq, step.name, existing.name);\n }\n if (existing?.status === 'completed') return existing.output as TOutput;\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // A step with a liveness `timeoutMs` keeps the in-memory await + heartbeat path (re-dispatch a\n // presumed-dead worker). Without one, the call SUSPENDS DURABLY: dispatch, persist a `pending`\n // checkpoint, and let the result resume the run on whichever instance receives it — so a worker\n // pod can scale down or crash mid-step without losing the run or re-running completed work.\n if (step.timeoutMs) return this.callRemoteInMemory(runId, seq, step, input, transport, group);\n if (existing?.status === 'pending') {\n // Dispatched; normally we just keep waiting for the result to resume the run. But a LOST dispatch\n // (worker crashed with no result, or the transport dropped the job) would hang here forever — a\n // reconcile re-drive replays straight back to this guard. Opt-in self-heal: once the step has been\n // pending longer than `remoteRedispatchMs`, re-dispatch the same stepId (the idempotent step\n // re-runs, its result resumes the run), bounded by `remoteRedispatchMax` so a never-settling step\n // fails instead of looping. Unset (default) keeps the by-design \"re-suspend, never re-dispatch\".\n if (this.remoteRedispatchMs == null) throw new WorkflowSuspended();\n // Stamp a redispatch deadline (clock-space, persisted) the first time we see this pending step,\n // stable across replays and crashes — mirrors the failed-retry backoff below. The run's wakeAt\n // becomes this deadline, so a reconcile re-drive lands exactly when it's due to re-dispatch.\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint({ ...existing, wakeAt });\n throw new WorkflowSuspended(wakeAt);\n }\n if (this.clock() < existing.wakeAt) throw new WorkflowSuspended(existing.wakeAt);\n // Past the deadline with no result — the dispatch is presumed lost. Re-dispatch (bounded by\n // `remoteRedispatchMax` so a step that never settles fails the run instead of looping forever).\n if (existing.attempts >= this.remoteRedispatchMax) {\n throw new RemoteStepError({\n message: `remote step \"${step.name}\" lost — no result after ${existing.attempts} re-dispatch(es)`,\n code: 'remote_step_lost',\n });\n }\n const reAttempt = existing.attempts + 1;\n const nextDeadline = this.clock() + this.remoteRedispatchMs;\n const reEnqueuedAt = new Date();\n await this.store.saveCheckpoint({\n ...existing,\n attempts: reAttempt,\n wakeAt: nextDeadline,\n enqueuedAt: reEnqueuedAt,\n startedAt: reEnqueuedAt,\n finishedAt: reEnqueuedAt,\n // Same observable marker the polyglot `call` path stamps (see redriveLostCall): the step's own\n // trail distinguishes a lost-dispatch re-drive from a failure retry.\n events: [\n ...(existing.events ?? []),\n lostStepEvent(this.clock(), reAttempt, 'redispatched'),\n ],\n });\n await this.dispatchRemoteTask({\n runId,\n seq,\n name: step.name,\n stepId: existing.stepId ?? stepId(runId, seq),\n group: existing.workerGroup ?? group,\n input: existing.input,\n priority: admission?.priority,\n attempt: reAttempt,\n transport,\n });\n this.emit({\n type: 'step.started',\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n redispatched: true,\n });\n throw new WorkflowSuspended(nextDeadline);\n }\n\n // Durable retry: a failed attempt re-dispatches up to `retries`, spacing attempts by `backoff` —\n // unless the worker marked the error non-retryable (a deterministic verdict like a declined card).\n // The retry deadline is stamped on the failed checkpoint as `wakeAt` (clock-space, persisted) the\n // first time we see it, so it's stable across replays and survives a crash.\n let attempt = 1;\n if (existing?.status === 'failed') {\n const maxAttempts = Math.max(1, step.retries ?? 1);\n const retryable = existing.error?.retryable !== false;\n if (!retryable || existing.attempts >= maxAttempts) throw new RemoteStepError(existing.error);\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + backoffDelay(existing.attempts, step);\n await this.store.saveCheckpoint({ ...existing, wakeAt });\n throw new WorkflowSuspended(wakeAt);\n }\n if (this.clock() < existing.wakeAt) throw new WorkflowSuspended(existing.wakeAt);\n attempt = existing.attempts + 1;\n }\n\n // Capability/protocol routing guard (handshake design §7.5): BEFORE consuming an admission slot or\n // writing a `pending` checkpoint, ensure a live worker on this step's group is capability-capable\n // AND protocol-compatible. If descriptors are published on the group but none qualifies, throw\n // `WorkflowBlocked` — the run-execution catch parks the run `blocked` (with a `wakeAt` for the\n // recovery poll) so it neither dispatches into a queue nobody consumes nor leaves a `pending` row a\n // later re-drive mistakes for \"already dispatched\". No descriptors published → guard skipped, the\n // legacy fleet keeps flowing (design §7.7).\n await this.ensureRoutable(group, step.requires);\n\n const id = stepId(runId, seq);\n // Flow control: a queued call that can't be admitted (concurrency/rate) does NOT dispatch — the\n // run re-suspends with the queue's retry time and the timer poller re-tries admission later, so\n // the limit is durable. The admitted slot is released when the result lands (completeRemoteResult).\n if (queue && this.admission.handles(queue)) {\n // Admission carries the per-call priority + fairness key (default the runId so each run is its\n // own fairness bucket), and the stepId as a STABLE waiter id so the backend tracks one waiter\n // across this call's durable retries. Ordering lives in the backend (in-process by default, or\n // global) — this is the dispatch/admission layer, not the positional replay path.\n const decision = await this.admission.tryAdmit(queue, {\n priority: admission?.priority,\n key: admission?.fairnessKey ?? runId,\n waiterId: id,\n });\n if (!decision.ok) {\n // Remember this run as blocked on `queue` so a freed-slot signal can wake it early.\n const waiters = this.queueWaiters.get(queue) ?? new Set<string>();\n waiters.add(runId);\n this.queueWaiters.set(queue, waiters);\n throw new WorkflowSuspended(decision.retryAt);\n }\n this.queueWaiters.get(queue)?.delete(runId);\n this.stepQueue.set(id, queue);\n }\n\n const enqueuedAt = new Date();\n // Persist the pending checkpoint BEFORE dispatching, so a fast result always finds it to complete.\n await this.store.saveCheckpoint({\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n stepId: id,\n status: 'pending',\n input,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt: enqueuedAt, // placeholders until the worker result lands\n finishedAt: enqueuedAt,\n });\n await this.dispatchRemoteTask({\n runId,\n seq,\n name: step.name,\n stepId: id,\n group,\n input,\n priority: admission?.priority,\n attempt,\n transport,\n });\n this.emit({ type: 'step.started', runId, seq, name: step.name, kind: 'remote' });\n throw new WorkflowSuspended();\n }\n\n /** Enqueue a remote step task to its worker group via the transport pool. Shared by the initial\n * dispatch, the opt-in self-heal re-dispatch (see `remoteRedispatchMs`), and the explicit\n * {@link redispatchPending}. Carries the current trace/context so a re-dispatch is traceable. */\n private dispatchRemoteTask(task: {\n runId: string;\n seq: number;\n name: string;\n stepId: string;\n group: string;\n input: unknown;\n attempt: number;\n priority?: number | undefined;\n transport?: string | undefined;\n }): Promise<void> {\n return this.pool.dispatch(\n {\n runId: task.runId,\n seq: task.seq,\n name: task.name,\n stepId: task.stepId,\n group: task.group,\n input: task.input,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n priority: task.priority,\n attempt: task.attempt,\n },\n task.transport,\n );\n }\n\n /**\n * Complete a durable remote step from its worker result and resume the run — runs on whichever\n * instance receives the result (the dispatching one may be gone), so the run is crash/scale-safe.\n * A no-op if the checkpoint isn't `pending` (a duplicate or late delivery).\n */\n private async completeRemoteResult(result: StepResult): Promise<void> {\n const cp = await this.store.getCheckpoint(result.runId, result.seq);\n if (!cp || cp.status !== 'pending') return;\n // A result settling this step frees its flow-control slot (no-op if it wasn't queued). Done\n // before the cancelled-run early-return below, so a cancellation can't leak the slot. Released\n // fire-and-forget: the slot/notify is best-effort (a global backend self-heals via lease), and\n // not awaiting keeps it off the result-processing critical path (no ordering shift).\n void this.releaseQueueSlot(cp.stepId).catch(() => undefined);\n // Drop a late result for a run that was cancelled/finished meanwhile — don't complete the step\n // or resume (the run is already terminal). This is the engine side of cooperative cancellation.\n const run = await this.store.getRun(result.runId);\n if (run && (run.status === 'cancelled' || run.status === 'completed')) return;\n const finishedAt = new Date();\n const startedAt = result.startedAt ? new Date(result.startedAt) : cp.startedAt;\n await this.store.saveCheckpoint({\n ...cp,\n status: result.status,\n output: result.status === 'completed' ? result.output : cp.output,\n error: result.error,\n events: result.events ?? cp.events,\n startedAt,\n finishedAt,\n });\n this.emit({\n type: result.status === 'completed' ? 'step.completed' : 'step.failed',\n runId: result.runId,\n seq: result.seq,\n name: cp.name,\n kind: cp.kind,\n output: result.output,\n error: result.error,\n queueMs: startedAt.getTime() - cp.enqueuedAt.getTime(),\n durationMs: finishedAt.getTime() - startedAt.getTime(),\n });\n await this.resumeImplicit(result.runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * Apply a remote workflow-turn {@link WorkflowDecision} durably — runs on WHATEVER instance receives\n * it over the broker (the dispatching one may be gone, or a point-to-point broker handed it to a\n * non-dispatcher). The durable, multi-instance-safe twin of {@link completeRemoteResult} for the\n * workflow TURN: look the run up by `decision.runId`, verify the decision matches the run's\n * CURRENTLY-awaited turn (`awaitingDecisionTaskId`) — so a stale / duplicate / foreign / re-driven\n * decision is dropped (applied AT MOST ONCE) — lease it, clear the marker, and apply the decision.\n */\n private async completeRemoteDecision(decision: WorkflowDecision): Promise<void> {\n // Cheap pre-checks before contending for the lease: only the run currently awaiting THIS taskId\n // (and not already terminal) is a candidate. A re-driven turn has a different taskId, so a late\n // decision for the prior turn is dropped here.\n const run = await this.store.getRun(decision.runId);\n if (!run || run.awaitingDecisionTaskId !== decision.taskId) return;\n if (run.status === 'cancelled' || run.status === 'completed' || run.status === 'dead') return;\n if (\n this.namespace !== undefined &&\n run.namespace !== undefined &&\n run.namespace !== this.namespace\n ) {\n return;\n }\n const nowMs = this.clock();\n // Lease so exactly one instance applies it — serialized with a concurrent timer re-drive of the\n // same run. If the lease is held (a re-drive in flight), drop: the re-driven turn produces a fresh\n // decision. The common single-decision path is uncontended, so this acquires immediately.\n if (\n !(await this.store.tryLockRun(decision.runId, this.instanceId, nowMs + this.leaseMs, nowMs))\n ) {\n return;\n }\n const renew = setInterval(\n () => {\n void this.store\n .renewRunLock(decision.runId, this.instanceId, this.clock() + this.leaseMs)\n .catch(() => undefined);\n },\n Math.max(50, Math.floor(this.leaseMs / 2)),\n );\n renew.unref?.();\n try {\n // Re-read under the lease and re-check the marker — it may have changed (a re-drive applied\n // first, or another decision raced in) between the unlocked pre-check and acquiring the lease.\n const fresh = await this.store.getRun(decision.runId);\n if (!fresh || fresh.awaitingDecisionTaskId !== decision.taskId) return;\n if (fresh.status === 'cancelled' || fresh.status === 'completed' || fresh.status === 'dead') {\n return;\n }\n // Clear the awaited-turn marker and the re-drive deadline: this turn is now being applied exactly\n // once. `applyDecision` resets `wakeAt` itself when it suspends on the turn's blocking ops.\n await this.store.updateRun(decision.runId, {\n awaitingDecisionTaskId: undefined,\n wakeAt: undefined,\n updatedAt: new Date(),\n });\n fresh.awaitingDecisionTaskId = undefined;\n await this.applyDecision(fresh, decision);\n } finally {\n clearInterval(renew);\n await this.store.releaseRunLock(decision.runId);\n }\n }\n\n /** Earliest clock time a suspended turn's deadline is worth LOOKING at again (`runId` → clock ms) —\n * the read throttle for {@link rearmDecisionDeadline}, the run-scoped sibling of\n * {@link stepLeaseRearms}. */\n private readonly decisionDeadlineRearms = new Map<string, number>();\n\n /**\n * A run-scoped heartbeat for a run suspended awaiting a workflow-turn decision (the dispatch path):\n * push its durable re-drive deadline (`wakeAt`) forward so a still-working worker's turn is not\n * re-dispatched. The durable counterpart of an inline turn's in-memory `heartbeatResets` rearm.\n *\n * THROTTLED exactly as {@link rearmStepLease} is, and for the same reason: a long workflow turn's\n * worker beats every couple of seconds, and each beat otherwise cost a `getRun` + `updateRun`.\n * The window here is `remoteAdvanceSilenceMs`, and a renewal buys at most one of them — so it is\n * only worth a write once the window is half spent, which leaves a full half-window of headroom\n * before the timer poller would re-drive the turn. The in-memory mark is a pure optimisation: a\n * cold (or different) instance re-derives the same answer from the run's own `wakeAt`.\n */\n private async rearmDecisionDeadline(runId: string): Promise<void> {\n const silenceMs = this.remoteAdvanceSilenceMs;\n if (silenceMs == null) return;\n const now = this.clock();\n const lookAgainAt = this.decisionDeadlineRearms.get(runId);\n if (lookAgainAt !== undefined && now < lookAgainAt) return;\n // Read AND write swallowed, for the same reason {@link rearmStepLease} swallows its own: the\n // transport's beat loop is serial and uncaught, so a throwing rearm takes it (or the process) down,\n // while a skipped beat costs nothing while half the window remains — and the mark is only advanced\n // after the write commits, so the next beat retries.\n try {\n const run = await this.store.getRun(runId);\n if (!run || run.status !== 'suspended' || run.awaitingDecisionTaskId === undefined) {\n // Not awaiting a turn any more (settled, or re-driven under a fresh taskId): stop tracking it.\n this.decisionDeadlineRearms.delete(runId);\n return;\n }\n const halfWindow = Math.ceil(silenceMs / 2);\n // More than half the window left: nothing to buy, and nothing to look at until it is half spent.\n if (run.wakeAt != null && run.wakeAt > now + halfWindow) {\n this.decisionDeadlineRearms.set(runId, run.wakeAt - halfWindow);\n return;\n }\n const renewed = now + silenceMs;\n await this.store.updateRun(runId, { wakeAt: renewed, updatedAt: new Date() });\n if (this.decisionDeadlineRearms.size > 1024) this.decisionDeadlineRearms.clear();\n this.decisionDeadlineRearms.set(runId, renewed - halfWindow);\n } catch {\n // Best-effort liveness: a store blip costs one skipped renewal, never the beat loop.\n }\n }\n\n /**\n * A slot freed on `queue` (a fleet-wide signal): resume this instance's runs blocked on it so they\n * re-contend now instead of at their retry tick. Snapshot-and-clear — a run still blocked after the\n * retry re-registers itself, and one that's gone (cancelled/admitted) is dropped. Best-effort.\n */\n private wakeQueueWaiters(queue: string): void {\n const waiters = this.queueWaiters.get(queue);\n if (!waiters || waiters.size === 0) return;\n const runIds = [...waiters];\n waiters.clear();\n for (const runId of runIds) void this.resumeImplicit(runId).catch(() => undefined);\n }\n\n /** Release the flow-control slot a dispatched step held (if any), by its stepId. */\n private async releaseQueueSlot(id: string): Promise<void> {\n const queue = this.stepQueue.get(id);\n if (queue === undefined) return;\n this.stepQueue.delete(id);\n await this.admission.release(queue, id);\n }\n\n /** In-memory await path for a remote step with a liveness `timeoutMs` (re-dispatch on timeout). */\n private async callRemoteInMemory<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n transport?: string,\n /** The run-tenant-aware routing token, computed by {@link callRemote} (see {@link stepGroup}). */\n group = stepGroup(step, undefined),\n ): Promise<TOutput> {\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // Capability/protocol routing guard (handshake design §7.5), same as the durable `callRemote` path:\n // BEFORE the first dispatch, ensure a live worker on this step's group is capability-capable AND\n // protocol-compatible. If descriptors are published on the group but none qualifies, throw\n // `WorkflowBlocked` — the run-execution catch parks the run `blocked` instead of dispatching into a\n // queue nobody consumes (this `timeoutMs` path would otherwise burn its liveness window + retries\n // waiting on a worker that can't run it). No descriptors published → guard skipped (legacy, §7.7).\n await this.ensureRoutable(group, step.requires);\n // A bare `@Step()` (no `input`/`output` schemas attached) skips validation.\n const validInput = step.input ? step.input.parse(input) : input;\n const id = stepId(runId, seq);\n const enqueuedAt = new Date();\n this.emit({ type: 'step.started', runId, seq, name: step.name, kind: 'remote' });\n // Retry policy differs from an in-process step on purpose: the internal in-process primitives\n // (`ctx.task`'s dispatch, `ctx.now`/`ctx.sideEffect`) retry any non-fatal throw (the work is in-process),\n // but a dispatched `ctx.step` only re-dispatches on a liveness TIMEOUT (presumed-dead worker). A\n // worker that *reported* an error returned a deterministic verdict, so we surface it to the\n // workflow instead of hammering the worker. Timeout retries need a window to detect death, so\n // they're gated on `timeoutMs` being set.\n const maxAttempts = step.timeoutMs ? Math.max(1, step.retries ?? 1) : 1;\n\n for (let attempt = 1; ; attempt += 1) {\n const resultPromise = new Promise<RemoteResolution>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n });\n await this.pool.dispatch(\n {\n runId,\n seq,\n name: step.name,\n stepId: id,\n group,\n input: validInput,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt,\n },\n transport,\n );\n try {\n const resolution = step.timeoutMs\n ? await this.awaitWithHeartbeat(id, resultPromise, step.timeoutMs)\n : await resultPromise;\n const output = step.output\n ? (step.output.parse(resolution.output) as TOutput)\n : (resolution.output as TOutput);\n // The worker reports when it actually picked the task up; fall back to dispatch time if a\n // transport doesn't carry it (queue-wait then reads as zero rather than going negative).\n const startedAt = resolution.startedAt ? new Date(resolution.startedAt) : enqueuedAt;\n await this.completeStep({\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n input: validInput,\n output,\n events: resolution.events,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt,\n });\n return output;\n } catch (err) {\n this.pending.delete(id);\n if (err instanceof RemoteStepTimeout && attempt < maxAttempts) continue;\n throw err;\n }\n }\n }\n\n /**\n * Await `resultPromise`, but reject with `onTimeout()` if neither it settles nor a heartbeat for `id`\n * arrives within `timeoutMs`. Each heartbeat (delivered via `transport.onHeartbeat`, looked up in\n * `heartbeatResets` by `id`) REARMS the window, so a worker that keeps beating stays alive past\n * `timeoutMs`. Shared by the remote-STEP liveness (keyed by stepId) and the remote-WORKFLOW advance\n * liveness (keyed by runId); the caller supplies the timeout error and any extra cleanup via `onTimeout`.\n */\n private awaitWithLivenessDeadline<T>(\n id: string,\n resultPromise: Promise<T>,\n timeoutMs: number,\n onTimeout: () => Error,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout>;\n const cleanup = () => {\n clearTimeout(timer);\n this.heartbeatResets.delete(id);\n };\n const arm = () => {\n timer = setTimeout(() => {\n cleanup();\n reject(onTimeout());\n }, timeoutMs);\n (timer as { unref?: () => void }).unref?.();\n };\n this.heartbeatResets.set(id, () => {\n clearTimeout(timer);\n arm();\n });\n arm();\n resultPromise.then(\n (value) => {\n cleanup();\n resolve(value);\n },\n (err) => {\n cleanup();\n reject(err);\n },\n );\n });\n }\n\n /** Remote-STEP liveness: await a worker result, timing out (with the step's pending-map cleanup) to\n * `RemoteStepTimeout` if it neither lands nor beats within `timeoutMs`. See {@link awaitWithLivenessDeadline}. */\n private awaitWithHeartbeat(\n id: string,\n resultPromise: Promise<RemoteResolution>,\n timeoutMs: number,\n ): Promise<RemoteResolution> {\n return this.awaitWithLivenessDeadline(id, resultPromise, timeoutMs, () => {\n this.pending.delete(id);\n return new RemoteStepTimeout(id, timeoutMs);\n });\n }\n}\n\n/** Raised inside the workflow when a remote worker reports a step failure. */\nexport class RemoteStepError extends Error {\n readonly stepError?: StepError | undefined;\n constructor(stepError?: StepError) {\n super(stepError?.message ?? 'remote step failed');\n this.name = 'RemoteStepError';\n this.stepError = stepError;\n }\n}\n\n/** Checkpoint names that record a parent→child edge: an awaited child, a folded group of them, a spawn. */\nconst CHILD_EDGE_PREFIXES = ['signal:child:', FOLDED_PREFIX, 'spawn:'];\n\n/** The child run ids a parent's {@link CHILD_EDGE_PREFIXES} checkpoints point at. */\nfunction childIdsOf(checkpoints: StepCheckpoint[]): string[] {\n const ids: string[] = [];\n for (const cp of checkpoints) {\n if (cp.name.startsWith('signal:child:')) ids.push(cp.name.slice('signal:child:'.length));\n if (cp.name.startsWith(FOLDED_PREFIX)) ids.push(...foldedChildIds(cp));\n if (cp.name.startsWith('spawn:') && typeof cp.output === 'string') ids.push(cp.output);\n }\n return ids;\n}\n","import type { RunFacetRow, RunStatus } from './interfaces';\n\n/**\n * The origin a facet cell is filed under. An origin that is absent, null, or blank is all the same\n * thing to an operator — a run no package claims — so they collapse to `null` here. Without this the\n * \"unknown\" chip would count only one of those spellings while `origin IS NULL` paging returned\n * another, and the chip's number would not match the page it opens.\n */\nexport function facetOrigin(origin: string | null | undefined): string | null {\n return origin?.trim() ? origin : null;\n}\n\n/**\n * Fold `(status, origin)` counts into one cell per pair, normalising origins via {@link facetOrigin}.\n * Store adapters group in SQL and pipe their rows through this, so every adapter — and the in-memory\n * store the tests run against — agrees on what lands in the unattributed bucket instead of each\n * collapsing blanks its own way.\n */\nexport function mergeRunFacetRows(\n rows: readonly { status: RunStatus; origin: string | null | undefined; count: number }[],\n): RunFacetRow[] {\n const cells = new Map<string, RunFacetRow>();\n for (const row of rows) {\n const origin = facetOrigin(row.origin);\n const key = JSON.stringify([row.status, origin]);\n const cell = cells.get(key);\n if (cell) cell.count += row.count;\n else cells.set(key, { status: row.status, origin, count: row.count });\n }\n return [...cells.values()];\n}\n","import type {\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n WorkflowRun,\n} from './interfaces';\nimport { facetOrigin } from './run-facets';\n\n/** Rows a value picker gets when the caller names no bound — enough to fill a dropdown several times\n * over, small enough that an axis with unbounded cardinality (tags) can't return a listing. */\nexport const RUN_VALUE_FACET_LIMIT = 100;\n\n/** Runs read when an axis has to be counted in-process (see {@link RunValueFacetOptions.scan}). */\nexport const RUN_VALUE_FACET_SCAN = 5000;\n\n/**\n * Tag prefixes the ENGINE mints one of PER KEY — `singleton:<key>` is stamped on every run of a\n * singleton workflow so the admission gate can find its siblings.\n *\n * A picker ranks these last. They are machine bookkeeping with cardinality that grows with the data,\n * and on a real deployment they crowd out everything an operator would actually choose: measured on\n * a 12k-run control plane, 82 of the top 100 tags were `singleton:*`, pushing genuine tags like\n * `type:mvr` to the edge of the list and past it.\n *\n * Ranked, not REMOVED: a singleton tag is still a legitimate thing to filter by (a run row's tag chip\n * sets exactly that), so it stays offered — just after the tags a human wrote. `version:undeclared`\n * is engine-minted too but is a single fixed value, so it competes fairly and is not listed here.\n */\nexport const ENGINE_MINTED_TAG_PREFIXES = ['singleton:', 'concurrency:'] as const;\n\n/** Is this a tag the engine mints one of per key? See {@link ENGINE_MINTED_TAG_PREFIXES}. */\nexport function isEngineMintedTag(value: string | null): boolean {\n return value !== null && ENGINE_MINTED_TAG_PREFIXES.some((prefix) => value.startsWith(prefix));\n}\n\n/**\n * Is this axis a plain column on the runs table, and so countable with a `GROUP BY` over the whole\n * matching set?\n *\n * The other three are not: the value isn't in a column of the row being counted. A run's tags live\n * inside ONE json array column, and its search attributes in a side table. Neither has a form that\n * is the same across sqlite/MySQL/Postgres — each engine expands a JSON array its own way — so an\n * adapter either writes that dialect SQL (the MikroORM one does, and answers those axes exactly) or\n * counts them in-process over a bounded scan ({@link runValueFacetsFromRuns}), where the counts\n * describe that window rather than the whole store. This function is what the second kind uses.\n */\nexport function axisIsRunColumn(\n axis: RunValueAxis,\n): axis is { field: 'workflow' | 'status' | 'origin' | 'namespace' } {\n return (\n axis.field === 'workflow' ||\n axis.field === 'status' ||\n axis.field === 'origin' ||\n axis.field === 'namespace'\n );\n}\n\n/** The values one run contributes to an axis — several for `tag` (a run carries a set), one for the\n * column axes, and none when the run has nothing on that axis (an absent search-attribute key). */\nfunction valuesOf(run: WorkflowRun, axis: RunValueAxis): Array<string | null> {\n switch (axis.field) {\n case 'workflow':\n return [run.workflow];\n case 'status':\n return [run.status];\n case 'origin':\n return [facetOrigin(run.origin)];\n case 'namespace':\n return run.namespace === undefined ? [] : [run.namespace];\n case 'tag':\n return run.tags ?? [];\n case 'attributeKey':\n return Object.keys(run.searchAttributes ?? {});\n case 'attributeValue': {\n const value = run.searchAttributes?.[axis.key];\n return value === undefined ? [] : [String(value)];\n }\n }\n}\n\n/**\n * Fold, order, search and bound raw `(value, count)` rows into the answer callers see: highest count\n * first, ties broken alphabetically so a picker's order is stable between polls (and therefore\n * pageable), the unattributed bucket (`null`) last, and one `limit`-sized page from `offset`.\n *\n * Every store pipes its `GROUP BY` through this — the same role {@link mergeRunFacetRows} plays for\n * status/origin counts — so a picker lists the same values in the same order whichever adapter is\n * underneath, rather than each SQL dialect's default ordering leaking into the UI.\n */\nexport function mergeRunValueFacetRows(\n rows: readonly { value: string | null | undefined; count: number }[],\n opts?: RunValueFacetOptions,\n): RunValueFacetRow[] {\n const counts = new Map<string | null, number>();\n for (const row of rows) {\n const value = row.value ?? null;\n counts.set(value, (counts.get(value) ?? 0) + Number(row.count));\n }\n const needle = opts?.search?.trim().toLowerCase();\n const merged = [...counts]\n .map(([value, count]) => ({ value, count }))\n .filter((row) => row.count > 0)\n // Applied here rather than by the caller so every store searches identically — and before the\n // bound, so a match outside the top slice is still reachable, which is the whole point of a\n // search box on a list that was cut to fit.\n .filter((row) => !needle || row.value?.toLowerCase().includes(needle))\n .sort((a, b) => {\n // Engine-minted per-key tags rank after everything else, however common they are — see\n // ENGINE_MINTED_TAG_PREFIXES for what they otherwise do to a picker.\n const engineA = isEngineMintedTag(a.value);\n const engineB = isEngineMintedTag(b.value);\n if (engineA !== engineB) return engineA ? 1 : -1;\n if (b.count !== a.count) return b.count - a.count;\n if (a.value === null) return 1;\n if (b.value === null) return -1;\n return a.value.localeCompare(b.value);\n });\n const offset = opts?.offset ?? 0;\n return merged.slice(offset, offset + (opts?.limit ?? RUN_VALUE_FACET_LIMIT));\n}\n\n/**\n * Count an axis's distinct values across runs already narrowed by the caller's predicates — the\n * in-process path, used by the in-memory store for every axis and by a SQL store for the axes it\n * cannot group in the database (see {@link axisIsRunColumn}). `runs` must be ordered newest-first\n * and already bounded to {@link RunValueFacetOptions.scan}, since that window is what the counts\n * then describe.\n */\nexport function runValueFacetsFromRuns(\n runs: readonly WorkflowRun[],\n axis: RunValueAxis,\n opts?: RunValueFacetOptions,\n): RunValueFacetRow[] {\n const rows: { value: string | null; count: number }[] = [];\n for (const run of runs) {\n for (const value of valuesOf(run, axis)) rows.push({ value, count: 1 });\n }\n return mergeRunValueFacetRows(rows, opts);\n}\n","import type {\n EngineEvent,\n GroupHealth,\n RunFacetQuery,\n RunFacetRow,\n RunQuery,\n RunResult,\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n RunWaiting,\n StepCheckpoint,\n WorkflowRun,\n} from './interfaces';\n\n/** A run as returned by the gateway's list — the durable run plus an optional {@link RunWaiting}\n * descriptor the control plane resolves (what a suspended run is parked on), so the dashboard can\n * name the wait in a list row without fetching each run's timeline. Additive: `waiting` is absent\n * on a non-parked run and on gateways/versions that don't compute it. */\nexport type RunListItem = WorkflowRun & { waiting?: RunWaiting | undefined };\n\n/** Which durable topology a gateway speaks for — surfaced in the dashboard so an operator can tell a\n * control plane from a tenant at a glance (the store-backed gateway is the operator; the proxy is a\n * tenant). Cheap, synchronous, local knowledge — no round-trip. */\nexport interface DurableTopology {\n role: 'control-plane' | 'tenant';\n /** The tenant's isolation partition name; set only when `role` is 'tenant'. */\n tenant?: string;\n}\n\n/** A run + its timeline + child ids — the detail view. Single source of truth: the dashboard server\n * re-exports this instead of re-declaring it, and the dashboard client derives its wire mirror from\n * it via {@link WireDates} instead of hand-mirroring field by field. */\nexport interface RunDetail {\n run: WorkflowRun;\n /** Steps in execution order (local + remote). */\n timeline: StepCheckpoint[];\n /** Ids of runs this run spawned (parent→children tree). */\n children: string[];\n}\n\n/**\n * Maps every `Date` (and `Date | undefined`) field of `T` to its ISO-string wire form — the shape a\n * JSON response actually carries once dates cross the wire (`JSON.stringify` already does this\n * coercion; this just types it). Homomorphic: each field keeps its own optional modifier, so a\n * required `Date` becomes a required `string` and an optional one stays optional. Lets a consumer\n * derive its own wire-facing client type from a core server type (e.g. the dashboard's SPA `WorkflowRun`/\n * `StepCheckpoint`/`RunDetail`) instead of hand-mirroring it field by field and drifting.\n */\nexport type WireDates<T> = {\n [K in keyof T]: T[K] extends Date\n ? string\n : T[K] extends Date | undefined\n ? string | undefined\n : T[K];\n};\n\n/**\n * The bounded read/control/stream surface a consumer (e.g. a controller) needs, satisfied by BOTH\n * topologies: the control plane binds a store-backed impl (reuses `DashboardService`); a tenant binds\n * a `ProxyRunGateway` that round-trips over the transport. Deliberately smaller than the full dashboard\n * (no metrics/bulk/update/signal) — those stay control-plane-only. `workerHealth` IS on the port: the\n * operator answers it scoped to the requester's own groups, so a tenant's Workers panel works too.\n *\n * Declared as an **abstract class** rather than an interface so it doubles as its own NestJS DI token\n * (the idiomatic inject-by-type pattern): providers bind `{ provide: RunGateway, useClass/useFactory }`\n * and consumers inject `constructor(private readonly gateway: RunGateway)` with no string/symbol token.\n * `StoreRunGateway`/`ProxyRunGateway` `implements RunGateway`; abstract methods carry no body, so the\n * emitted runtime class is an empty, non-instantiable shell used only as the token.\n */\nexport abstract class RunGateway {\n /** This deployment's durable role (control plane vs tenant) — synchronous local metadata. */\n abstract topology(): DurableTopology;\n abstract getRunDetail(runId: string): Promise<RunDetail | null>;\n /** List runs, each optionally carrying a {@link RunWaiting} descriptor (what a suspended run is\n * parked on). The store-backed gateway resolves `waiting`; a proxy relays whatever the control\n * plane sent. */\n abstract listRuns(query: RunQuery): Promise<RunListItem[]>;\n /**\n * Counts of the runs matching `query`, grouped by `(status, origin)` — what a console's status and\n * origin chips display. Separate from {@link listRuns} precisely so the list can be PAGINATED: the\n * page bounds what is rendered, these counts stay whole-set exact. Zero-count cells are absent.\n */\n abstract runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;\n /**\n * The distinct values of one filter axis over the runs matching `query`, with counts — what fills a\n * console's tenant/tag/attribute pickers. On the port (not control-plane-only) because the pickers\n * belong to the same panel as {@link listRuns}: a tenant that can list its runs has to be able to\n * see what it may filter them by, or its console offers a blank dropdown.\n *\n * Returns `[]` when the underlying store does not implement the enumeration — an empty picker with\n * free-text entry still standing, not an error.\n */\n abstract runValueFacets(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]>;\n /**\n * Bulk-resolve {@link RunWaiting} for an arbitrary set of run ids — for a consumer with its OWN\n * filtered/paginated run listing (so it isn't just `listRuns` under another name) that needs to know\n * which of ITS runs are parked on a breakpoint (or any other event wait) without re-deriving the bulk\n * waiter scan itself or reaching for raw SQL against `durable_step_checkpoints`. A `Record` (not a\n * `Map`) because `ProxyRunGateway` serialises the reply over the transport as plain JSON. Entries are\n * present ONLY for runs currently waiting — an unknown id, a non-suspended id, and a suspended id\n * parked on something non-event (a bare `ctx.sleep`, an in-flight step) are simply absent, same as a\n * `listRuns` row with no `waiting`.\n */\n abstract waitingFor(runIds: string[]): Promise<Record<string, RunWaiting>>;\n /** Per-group worker health (queue backlog + live worker heartbeats). On the control plane this is\n * every group; over a tenant proxy the operator scopes it to the tenant's own groups. */\n abstract workerHealth(): Promise<GroupHealth[]>;\n abstract cancel(runId: string, opts?: { compensate?: boolean }): Promise<RunResult | null>;\n abstract retry(runId: string): Promise<RunResult | null>;\n abstract continue(runId: string): Promise<RunResult | null>;\n /** Re-dispatch every remote step of a run stuck `pending` — the operator recovery for a LOST step\n * dispatch (crashed worker / dropped job) that no automatic path re-drives. Returns the run's status\n * plus how many steps were re-dispatched, or null if the run is unknown. */\n abstract redispatchPending(runId: string): Promise<(RunResult & { redispatched: number }) | null>;\n abstract retryWithInput(runId: string, input: unknown): Promise<{ runId: string } | null>;\n /** Live lifecycle events for one run; returns an unsubscribe fn. Framework-agnostic (no rxjs). */\n abstract subscribe(runId: string, onEvent: (event: EngineEvent) => void): () => void;\n}\n","import type {\n ChildWait,\n RetentionPolicy,\n RunFacetQuery,\n RunFacetRow,\n RunQuery,\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n ScheduleQuery,\n ScheduleRecord,\n SignalWaiter,\n StateStore,\n StepCheckpoint,\n WorkflowRun,\n} from './interfaces';\n\n/**\n * Transforms a payload value as it crosses the store boundary — e.g. encrypt-at-rest, compress, or\n * redact PII. `decode` must be the exact inverse of `encode`. Both are synchronous (use a local\n * cipher / codec); wrap an async KMS yourself if you need one.\n */\nexport interface PayloadCodec {\n encode(value: unknown): unknown;\n decode(value: unknown): unknown;\n}\n\n/**\n * A `StateStore` decorator that runs run/step **payloads** (input + output) through a\n * {@link PayloadCodec} — encoded on write, decoded on read — so they're never stored in the clear.\n * Adapter-agnostic: wrap any store. Searchable metadata (id, status, workflow, tags, timestamps) and\n * the structured `error` are left untouched so the dashboard, queries, and recovery still work.\n *\n * ```ts\n * const store = new CodecStateStore(new TypeOrmStateStore(ds), aesCodec);\n * ```\n */\nexport class CodecStateStore implements StateStore {\n /** Atomic claims touch only searchable metadata and bypass payload encoding. */\n readonly tryAdmitSingleton?: (\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ) => Promise<boolean>;\n\n /**\n * Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches\n * (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store\n * actually aggregates, so `store.runFacets?.()` still reports absence through the wrapper instead\n * of resolving to a silently wrong empty result.\n */\n readonly runFacets?: (query: RunFacetQuery) => Promise<RunFacetRow[]>;\n\n /**\n * Forwarded verbatim, and safe to: the axes a value facet enumerates are searchable metadata\n * (workflow, status, origin, namespace, tags, search attributes), none of which the codec encodes.\n * Bound the same conditional way as {@link runFacets} so absence is reported, not faked.\n */\n readonly runValueFacets?: (\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ) => Promise<RunValueFacetRow[]>;\n\n /** Forwarded verbatim (deletes touch no payload). Bound only when the inner store has it, so the\n * engine's per-run fallback still kicks in through the wrapper. */\n readonly deleteRuns?: (runIds: string[]) => Promise<void>;\n\n /** Forwarded verbatim — retention selects by status/updatedAt/scope, never by payload. Bound only\n * when the inner store prunes, so the retention poller still sees (and warns about) its absence. */\n readonly pruneTerminalRuns?: (\n policy: RetentionPolicy,\n nowMs: number,\n limit: number,\n ) => Promise<number>;\n\n /** Forwarded verbatim — a count reads no payload. Bound only when the inner store counts, so the\n * engine's facet/listing fallback still applies through the wrapper. */\n readonly countRuns?: (query: Omit<RunQuery, 'limit' | 'offset'>) => Promise<number>;\n /** The placeholder checkpoints are encoded like any other checkpoint. */\n readonly registerChildWaits?: (entries: ChildWait[]) => Promise<void>;\n /** The folded checkpoint carries the children's outputs, so it is encoded. */\n readonly compactCheckpoints?: (\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ) => Promise<void>;\n /** Forwarded verbatim — a waiter carries no payload. */\n readonly listSignalWaitersByRun?: (runIds: string[]) => Promise<SignalWaiter[]>;\n /** Forwarded verbatim — a waiter carries no payload. */\n readonly hasSignalWaiter?: (runId: string, tokenPrefix: string) => Promise<boolean>;\n\n /** Schedules persist their run `input` inside `spec` — encoded like any other payload. Bound only\n * when the inner store persists schedules, so `engine.schedules` reports absence faithfully. */\n readonly saveSchedule?: (record: ScheduleRecord) => Promise<void>;\n readonly getSchedule?: (id: string) => Promise<ScheduleRecord | null>;\n readonly updateSchedule?: (\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ) => Promise<boolean>;\n readonly deleteSchedule?: (id: string) => Promise<boolean>;\n readonly listSchedules?: (query: ScheduleQuery) => Promise<ScheduleRecord[]>;\n\n constructor(\n private readonly inner: StateStore,\n private readonly codec: PayloadCodec,\n ) {\n if (inner.tryAdmitSingleton) this.tryAdmitSingleton = inner.tryAdmitSingleton.bind(inner);\n const deleteRuns = inner.deleteRuns;\n if (deleteRuns) this.deleteRuns = (ids) => deleteRuns.call(inner, ids);\n const prune = inner.pruneTerminalRuns;\n if (prune)\n this.pruneTerminalRuns = (policy, now, limit) => prune.call(inner, policy, now, limit);\n const count = inner.countRuns;\n if (count) this.countRuns = (query) => count.call(inner, query);\n const registerChildWaits = inner.registerChildWaits;\n if (registerChildWaits)\n this.registerChildWaits = (entries) =>\n registerChildWaits.call(\n inner,\n entries.map((e) => ({ waiter: e.waiter, checkpoint: this.encCp(e.checkpoint) })),\n );\n const compact = inner.compactCheckpoints;\n if (compact)\n this.compactCheckpoints = (runId, fromSeq, toSeq, into) =>\n compact.call(inner, runId, fromSeq, toSeq, this.encCp(into));\n const byRun = inner.listSignalWaitersByRun;\n if (byRun) this.listSignalWaitersByRun = (runIds) => byRun.call(inner, runIds);\n const hasWaiter = inner.hasSignalWaiter;\n if (hasWaiter)\n this.hasSignalWaiter = (runId, tokenPrefix) => hasWaiter.call(inner, runId, tokenPrefix);\n\n const { saveSchedule, getSchedule, updateSchedule, deleteSchedule, listSchedules } = inner;\n if (saveSchedule && getSchedule && updateSchedule && deleteSchedule && listSchedules) {\n this.saveSchedule = (r) => saveSchedule.call(inner, this.encSchedule(r));\n this.getSchedule = async (id) => this.decSchedule(await getSchedule.call(inner, id));\n this.updateSchedule = (id, patch, expected) =>\n updateSchedule.call(\n inner,\n id,\n patch.spec ? { ...patch, spec: this.encSpec(patch.spec) } : patch,\n expected,\n );\n this.deleteSchedule = (id) => deleteSchedule.call(inner, id);\n this.listSchedules = async (q) =>\n (await listSchedules.call(inner, q)).map((r) => this.decSchedule(r) as ScheduleRecord);\n }\n const facets = inner.runFacets;\n if (facets) this.runFacets = (query) => facets.call(inner, query);\n const valueFacets = inner.runValueFacets;\n if (valueFacets) {\n this.runValueFacets = (axis, query, opts) => valueFacets.call(inner, axis, query, opts);\n }\n }\n\n private enc(v: unknown): unknown {\n return v === undefined ? undefined : this.codec.encode(v);\n }\n private dec(v: unknown): unknown {\n return v === undefined ? undefined : this.codec.decode(v);\n }\n\n private encRun(run: WorkflowRun): WorkflowRun {\n return { ...run, input: this.enc(run.input), output: this.enc(run.output) };\n }\n private decRun<T extends WorkflowRun | null>(run: T): T {\n return (run && { ...run, input: this.dec(run.input), output: this.dec(run.output) }) as T;\n }\n private encCp(cp: StepCheckpoint): StepCheckpoint {\n return { ...cp, input: this.enc(cp.input), output: this.enc(cp.output) };\n }\n private decCp<T extends StepCheckpoint | null>(cp: T): T {\n return (cp && { ...cp, input: this.dec(cp.input), output: this.dec(cp.output) }) as T;\n }\n\n private encSpec(spec: Record<string, unknown>): Record<string, unknown> {\n return 'input' in spec ? { ...spec, input: this.enc(spec.input) } : spec;\n }\n private encSchedule(r: ScheduleRecord): ScheduleRecord {\n return { ...r, spec: this.encSpec(r.spec) };\n }\n private decSchedule(r: ScheduleRecord | null): ScheduleRecord | null {\n if (!r || !('input' in r.spec)) return r;\n return { ...r, spec: { ...r.spec, input: this.dec(r.spec.input) } };\n }\n\n ensureSchema(): Promise<void> {\n return this.inner.ensureSchema?.() ?? Promise.resolve();\n }\n\n createRun(run: WorkflowRun): Promise<void> {\n return this.inner.createRun(this.encRun(run));\n }\n updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const next = { ...patch };\n if ('input' in patch) next.input = this.enc(patch.input);\n if ('output' in patch) next.output = this.enc(patch.output);\n return this.inner.updateRun(runId, next);\n }\n async getRun(runId: string): Promise<WorkflowRun | null> {\n return this.decRun(await this.inner.getRun(runId));\n }\n deleteRun(runId: string): Promise<void> {\n return this.inner.deleteRun(runId);\n }\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n return this.decCp(await this.inner.getCheckpoint(runId, seq));\n }\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n return this.inner.saveCheckpoint(this.encCp(checkpoint));\n }\n transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n if (!this.inner.transaction) {\n throw new Error('the wrapped store does not support transactions');\n }\n // Encode the checkpoint inside the tx, so payloads stay encoded at rest like the normal path.\n return this.inner.transaction((tx) =>\n work({ raw: tx.raw, saveCheckpoint: (cp) => tx.saveCheckpoint(this.encCp(cp)) }),\n );\n }\n async listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listIncompleteRuns(namespace)).map((r) => this.decRun(r));\n }\n async listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listPendingRuns(limit, namespace)).map((r) => this.decRun(r));\n }\n async listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listDueTimers(nowMs, namespace)).map((r) => this.decRun(r));\n }\n tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean> {\n return this.inner.tryLockRun(runId, owner, leaseUntilMs, nowMs);\n }\n releaseRunLock(runId: string): Promise<void> {\n return this.inner.releaseRunLock(runId);\n }\n renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n return this.inner.renewRunLock(runId, owner, leaseUntilMs);\n }\n putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n return this.inner.putSignalWaiter(waiter);\n }\n takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n return this.inner.takeSignalWaiter(token);\n }\n listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n return this.inner.listSignalWaiters(prefix);\n }\n removeSignalWaiter(waiter: SignalWaiter): Promise<void> {\n return this.inner.removeSignalWaiter(waiter);\n }\n bufferSignal(token: string, payload: unknown): Promise<void> {\n return this.inner.bufferSignal(token, this.enc(payload));\n }\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const buffered = await this.inner.takeBufferedSignal(token);\n return buffered && { payload: this.dec(buffered.payload) };\n }\n bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void> {\n return this.inner.bufferEvent({ ...input, payload: this.enc(input.payload) });\n }\n async listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>> {\n const events = await this.inner.listBufferedEvents(name, limit);\n return events.map((e) => ({ ...e, payload: this.dec(e.payload) }));\n }\n removeBufferedEvent(id: string): Promise<boolean> {\n return this.inner.removeBufferedEvent(id);\n }\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n return (await this.inner.listRuns(query)).map((r) => this.decRun(r));\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n return (await this.inner.listCheckpoints(runId)).map((c) => this.decCp(c));\n }\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n // Forward the targeted read when the inner store implements it; otherwise fall back to the\n // (always-present) listCheckpoints scan so wrapping a legacy custom store keeps working.\n if (this.inner.getLatestCheckpointByName) {\n const cp = await this.inner.getLatestCheckpointByName(runId, name);\n return cp ? this.decCp(cp) : undefined;\n }\n let latest: StepCheckpoint | undefined;\n for (const cp of await this.inner.listCheckpoints(runId)) if (cp.name === name) latest = cp;\n return latest ? this.decCp(latest) : undefined;\n }\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n const matches = this.inner.listCheckpointsByNamePrefix\n ? await this.inner.listCheckpointsByNamePrefix(runId, prefixes)\n : (await this.inner.listCheckpoints(runId)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n return matches.map((c) => this.decCp(c));\n }\n}\n","import type { EngineEvent } from './interfaces';\n\nexport interface MetricsSnapshot {\n runs: { started: number; completed: number; failed: number; suspended: number };\n steps: { started: number; completed: number; failed: number };\n /** Per-workflow run counters, keyed by workflow name. */\n byWorkflow: Record<string, { started: number; completed: number; failed: number }>;\n /** Sum + count of recorded step durations (ms), for an average. */\n stepDuration: { sumMs: number; count: number };\n}\n\nexport interface MetricsCollector {\n snapshot(): MetricsSnapshot;\n /** Prometheus text exposition of the counters — serve this from a `/metrics` endpoint. */\n prometheus(): string;\n /** Unsubscribe from the engine. */\n stop(): void;\n}\n\ntype Subscribable = { subscribe(listener: (event: EngineEvent) => void): () => void };\n\n/**\n * Subscribe to an engine's lifecycle events and accumulate Prometheus-style counters (runs + steps by\n * outcome, per-workflow run counts, step-duration sum/count). Dependency-free — call `.prometheus()`\n * from your metrics endpoint, or `.snapshot()` for the raw numbers. Counters are per process; scrape\n * each instance.\n */\nexport function collectMetrics(engine: Subscribable): MetricsCollector {\n const m: MetricsSnapshot = {\n runs: { started: 0, completed: 0, failed: 0, suspended: 0 },\n steps: { started: 0, completed: 0, failed: 0 },\n byWorkflow: {},\n stepDuration: { sumMs: 0, count: 0 },\n };\n const wf = (name?: string) => {\n const k = name ?? 'unknown';\n let entry = m.byWorkflow[k];\n if (!entry) {\n entry = { started: 0, completed: 0, failed: 0 };\n m.byWorkflow[k] = entry;\n }\n return entry;\n };\n\n const stop = engine.subscribe((e) => {\n switch (e.type) {\n case 'run.started':\n m.runs.started += 1;\n wf(e.workflow).started += 1;\n break;\n case 'run.completed':\n m.runs.completed += 1;\n wf(e.workflow).completed += 1;\n break;\n case 'run.failed':\n m.runs.failed += 1;\n wf(e.workflow).failed += 1;\n break;\n case 'run.suspended':\n m.runs.suspended += 1;\n break;\n case 'step.started':\n m.steps.started += 1;\n break;\n case 'step.completed':\n m.steps.completed += 1;\n if (e.durationMs != null) {\n m.stepDuration.sumMs += e.durationMs;\n m.stepDuration.count += 1;\n }\n break;\n case 'step.failed':\n m.steps.failed += 1;\n break;\n }\n });\n\n return {\n snapshot: () => structuredClone(m),\n stop,\n prometheus: () => {\n const lines: string[] = [];\n lines.push('# TYPE durable_runs_total counter');\n for (const [k, v] of Object.entries(m.runs))\n lines.push(`durable_runs_total{event=\"${k}\"} ${v}`);\n lines.push('# TYPE durable_steps_total counter');\n for (const [k, v] of Object.entries(m.steps))\n lines.push(`durable_steps_total{event=\"${k}\"} ${v}`);\n lines.push('# TYPE durable_runs_by_workflow_total counter');\n for (const [name, v] of Object.entries(m.byWorkflow))\n for (const [event, n] of Object.entries(v))\n lines.push(`durable_runs_by_workflow_total{workflow=\"${name}\",event=\"${event}\"} ${n}`);\n lines.push('# TYPE durable_step_duration_ms_sum counter');\n lines.push(`durable_step_duration_ms_sum ${m.stepDuration.sumMs}`);\n lines.push('# TYPE durable_step_duration_count counter');\n lines.push(`durable_step_duration_count ${m.stepDuration.count}`);\n return `${lines.join('\\n')}\\n`;\n },\n };\n}\n","import type {\n AttributeFilter,\n AttributeOp,\n RunQuery,\n ScalarAttributeFilter,\n WorkflowRun,\n} from './interfaces';\nimport type { SearchAttributes } from './interfaces';\n\n/** Compare one attribute value against a predicate. Range ops need both sides comparable; `in` is an\n * OR over its operand set, so an empty set matches nothing. */\nfunction compare(actual: unknown, filter: AttributeFilter): boolean {\n if (filter.op === 'in') return filter.values.some((v) => actual === v);\n const expected = filter.value;\n switch (filter.op) {\n case 'eq':\n return actual === expected;\n case 'ne':\n return actual !== expected;\n case 'gt':\n return actual != null && actual > expected;\n case 'gte':\n return actual != null && actual >= expected;\n case 'lt':\n return actual != null && actual < expected;\n case 'lte':\n return actual != null && actual <= expected;\n }\n}\n\n/**\n * Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`\n * on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined\n * filters match everything. Shared by every store so typed/range queries behave identically across\n * adapters (applied in-process after the coarse workflow/status/tag filters).\n */\nexport function matchesAttributes(\n attributes: SearchAttributes | undefined,\n filters: AttributeFilter[] | undefined,\n): boolean {\n if (!filters?.length) return true;\n if (!attributes) return false;\n return filters.every((f) => f.key in attributes && compare(attributes[f.key], f));\n}\n\n/**\n * Apply a query's attribute predicates then its `offset`/`limit`, in-process — for store adapters\n * that can't express typed/range predicates in SQL. Pass rows already coarse-filtered (workflow /\n * status / tag) and sorted newest-first; this filters by `attributes` and paginates. Only call it\n * when `query.attributes` is set (otherwise let the DB do `LIMIT`/`OFFSET`).\n */\nexport function applyAttributeQuery(rows: WorkflowRun[], query: RunQuery): WorkflowRun[] {\n const filtered = rows.filter((r) => matchesAttributes(r.searchAttributes, query.attributes));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? filtered.length;\n return filtered.slice(offset, offset + limit);\n}\n\n/**\n * One normalized row of the `durable_run_attributes` side-table: a single (key → value) pair of a\n * run's search attributes, split into typed columns so SQL can index/range-scan it. Exactly one of\n * `strValue`/`numValue` is set per row (booleans normalize to a string `\"true\"`/`\"false\"` so `eq`/`ne`\n * still match). NULL for the column that doesn't apply, which keeps `(key, numValue)` /\n * `(key, strValue)` indexes selective.\n */\nexport interface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\n/**\n * Explode a run's search attributes into normalized side-table rows (one per key). Used by SQL stores\n * to maintain `durable_run_attributes` on every create/update and by the in-memory store's index, so\n * attribute predicates can be pushed DOWN into a join/EXISTS instead of scanned in-process. Numbers go\n * to `numValue`; strings to `strValue`; booleans to `strValue` as `\"true\"`/`\"false\"` (matching how the\n * in-process `compare` treats `eq`/`ne` on booleans). Returns `[]` for a run with no attributes.\n */\nexport function normalizeAttributeRows(\n runId: string,\n attributes: SearchAttributes | undefined,\n): RunAttributeRow[] {\n if (!attributes) return [];\n const out: RunAttributeRow[] = [];\n for (const [key, value] of Object.entries(attributes)) {\n if (typeof value === 'number') {\n out.push({ runId, key, strValue: null, numValue: value });\n } else if (typeof value === 'boolean') {\n out.push({ runId, key, strValue: value ? 'true' : 'false', numValue: null });\n } else {\n out.push({ runId, key, strValue: value, numValue: null });\n }\n }\n return out;\n}\n\n/**\n * SQL comparison operator for a single-operand {@link AttributeOp} (used to build pushdown\n * predicates). `in` is absent by construction: it compares against a SET, which a store emits as an\n * OR of equalities over {@link attributePredicateOperands} rather than as one comparator.\n */\nexport function sqlComparator(op: Exclude<AttributeOp, 'in'>): string {\n switch (op) {\n case 'eq':\n return '=';\n case 'ne':\n return '<>';\n case 'gt':\n return '>';\n case 'gte':\n return '>=';\n case 'lt':\n return '<';\n case 'lte':\n return '<=';\n }\n}\n\n/**\n * Which side-table column an attribute filter compares against: numeric operands (and range ops on\n * numbers) hit `numValue`; everything else hits `strValue` (booleans are stored as `\"true\"`/`\"false\"`).\n * Keeping this in core means every SQL adapter pushes predicates down identically.\n */\nexport function attributeColumnFor(filter: ScalarAttributeFilter): 'numValue' | 'strValue' {\n return typeof filter.value === 'number' ? 'numValue' : 'strValue';\n}\n\n/** The literal a side-table predicate compares against (booleans → `\"true\"`/`\"false\"` strings). */\nexport function attributeOperand(filter: ScalarAttributeFilter): string | number {\n if (typeof filter.value === 'boolean') return filter.value ? 'true' : 'false';\n return filter.value;\n}\n\n/** One comparison a side-table predicate makes: which typed column, with which operator, against\n * which literal. */\nexport interface AttributePredicateOperand {\n column: 'numValue' | 'strValue';\n comparator: string;\n operand: string | number;\n}\n\n/**\n * The comparisons one {@link AttributeFilter} makes, for a store to OR together inside its\n * `EXISTS`/join on the normalized attribute side-table. A scalar op yields exactly ONE comparison\n * (the same column/operator/literal {@link attributeColumnFor} and {@link attributeOperand} give);\n * `in` yields one per member, each an equality, since its operands may be of mixed types and so land\n * in different typed columns.\n *\n * An EMPTY list is a real answer, not a missing one: `in` over no values can match no run. A caller\n * that ORs an empty list must emit a false predicate rather than dropping the filter, or the query\n * silently widens to every run.\n */\nexport function attributePredicateOperands(filter: AttributeFilter): AttributePredicateOperand[] {\n if (filter.op === 'in') {\n return filter.values.map((value) => {\n const scalar = { key: filter.key, op: 'eq', value } as ScalarAttributeFilter;\n return {\n column: attributeColumnFor(scalar),\n comparator: '=',\n operand: attributeOperand(scalar),\n };\n });\n }\n return [\n {\n column: attributeColumnFor(filter),\n comparator: sqlComparator(filter.op),\n operand: attributeOperand(filter),\n },\n ];\n}\n","import type { InferSearchAttributes, SearchAttributes, SearchAttributesSchema } from './interfaces';\n\n/**\n * Read a run's `searchAttributes` through a {@link SearchAttributesSchema}, typed to the schema's\n * inferred output. **Safe-parse semantics, deliberately lenient** — unlike\n * `ctx.upsertSearchAttributes` (which is strict: an invalid merge throws), a failed validation here\n * returns `{}` rather than throwing. This is intentional: `run.searchAttributes` may predate the\n * schema (an older deploy wrote it under a looser or absent schema, or a run started before this\n * workflow ever declared one), and a dashboard/read path crashing on old history is worse than it\n * quietly reporting no typed attributes for that run. Write-time enforcement is what keeps NEW writes\n * conformant; this is the read-side counterpart for consuming them.\n *\n * The schema's `validate` must be synchronous (matching the write-side constraint in\n * `ctx.upsertSearchAttributes`) — one returning a `Promise` throws with a clear error rather than\n * being silently awaited or silently treated as a failure.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * import { readSearchAttributes } from '@dudousxd/nestjs-durable-core';\n *\n * const orderAttrs = z.object({ tier: z.enum(['free', 'pro']), amount: z.number() });\n *\n * const run = await store.getRun(runId);\n * const attrs = readSearchAttributes(orderAttrs, run ?? {}); // { tier: 'pro', amount: 42 } | {}\n * ```\n */\nexport function readSearchAttributes<S extends SearchAttributesSchema>(\n schema: S,\n // `| null` because ORM store entities (MikroORM/TypeORM/Prisma) type the JSON column as\n // nullable — the entity row is the argument every real consumer passes.\n run: { searchAttributes?: SearchAttributes | null | undefined },\n): InferSearchAttributes<S> {\n const result = schema['~standard'].validate(run.searchAttributes ?? {});\n if (result instanceof Promise) {\n throw new Error(\n \"readSearchAttributes: schema validation must be synchronous (the searchAttributes schema's \" +\n '`~standard.validate` returned a Promise) — async Standard Schema validators are not supported.',\n );\n }\n if (result.issues) {\n // Lenient by design (see doc comment) — old/foreign runs shouldn't crash a read path. The `{}`\n // is cast, not `Partial<InferSearchAttributes<S>>`, to keep the common case (destructuring known\n // keys straight off the result) ergonomic; callers reading untrusted history should still treat\n // every field as possibly absent.\n return {} as InferSearchAttributes<S>;\n }\n return result.value as InferSearchAttributes<S>;\n}\n","/**\n * Dependency-injection tokens. Adapters bind their implementations to these so `core` and\n * `@dudousxd/nestjs-durable` depend only on the interfaces in `./interfaces`.\n *\n * These use `Symbol.for(key)` (the global symbol registry), NOT `Symbol(key)`, so the token is the\n * SAME instance no matter how many times `core` is evaluated in a process. A consumer can hold more\n * than one physical copy of `core` at runtime — pnpm peer-dependency multiplexing installs a\n * separate virtual copy per distinct peer set, and the dual ESM/CJS build can be loaded once as\n * `import` (`index.js`) and once as `require` (`index.cjs`). A plain `Symbol()` would mint a\n * DISTINCT token per copy, so `DurableModule` (provider) and `DashboardService` / a store adapter\n * (injector) could resolve different symbols → Nest can't satisfy the dependency\n * (`STATE_STORE is not available in the DurableApiModule context`). A registered symbol collapses\n * them to one. Mirrors the `CONTEXT_ACCESSOR` token in `@dudousxd/nestjs-durable`'s `tokens.ts`.\n */\n\n/**\n * @deprecated Use {@link STATE_STORE_CANONICAL} (`@dudousxd/nestjs-durable:state-store`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const STATE_STORE = Symbol.for('nestjs-durable:STATE_STORE');\n/**\n * @deprecated Use {@link TRANSPORT_CANONICAL} (`@dudousxd/nestjs-durable:transport`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const TRANSPORT = Symbol.for('nestjs-durable:TRANSPORT');\n/**\n * @deprecated Use {@link DURABLE_OPTIONS_CANONICAL} (`@dudousxd/nestjs-durable:options`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const DURABLE_OPTIONS = Symbol.for('nestjs-durable:DURABLE_OPTIONS');\n\n/**\n * Canonical, cross-lib-discoverable aliases of the durable DI tokens, following the ecosystem\n * capability naming `@dudousxd/nestjs-durable:<name>` (identical to `capability('durable', <name>)`).\n * `DurableModule` binds these alongside the legacy tokens (dual-bind), so an external library can\n * resolve durable's store/transport/options by the canonical name without importing durable\n * internals. Bare `Symbol.for` (same cross-copy-stability rationale as the legacy tokens above)\n * keeps `core` free of any `@dudousxd/nestjs-diagnostics` runtime dependency.\n */\nexport const STATE_STORE_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:state-store');\nexport const TRANSPORT_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:transport');\nexport const DURABLE_OPTIONS_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:options');\n","import { parseDuration } from '../duration';\nimport {\n type ChildWait,\n type RetentionPolicy,\n type RunFacetQuery,\n type RunFacetRow,\n type RunQuery,\n type RunValueAxis,\n type RunValueFacetOptions,\n type RunValueFacetRow,\n type ScheduleQuery,\n type ScheduleRecord,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n TERMINAL_RUN_STATUSES,\n type WorkflowRun,\n} from '../interfaces';\nimport type { AttributeFilter } from '../interfaces';\nimport { mergeRunFacetRows } from '../run-facets';\nimport { RUN_VALUE_FACET_SCAN, runValueFacetsFromRuns } from '../run-value-facets';\nimport {\n type RunAttributeRow,\n attributePredicateOperands,\n normalizeAttributeRows,\n} from '../search-attributes';\nimport {\n SINGLETON_ADMITTED_TAG,\n singletonAdmissionDenialPatch,\n singletonAdmissionTags,\n} from '../singleton-admission';\n\n/**\n * A non-durable, in-process `StateStore` for tests and local development.\n * The shipped `@dudousxd/nestjs-durable-store` package re-exports an equivalent.\n */\nexport class InMemoryStateStore implements StateStore {\n private readonly runs = new Map<string, WorkflowRun>();\n private readonly checkpoints = new Map<string, StepCheckpoint>();\n private readonly signalWaiters = new Map<string, SignalWaiter>();\n\n /**\n * Normalized search-attribute side-table, the in-memory analog of the SQL stores'\n * `durable_run_attributes`: `key -> (runId -> row)`. Maintained on every create/update so an\n * attribute query can be pushed DOWN to a key-indexed candidate set instead of scanning every run\n * and comparing in-process. Mirrors {@link normalizeAttributeRows} so behavior matches the SQL path.\n */\n private readonly attributeIndex = new Map<string, Map<string, RunAttributeRow>>();\n /** Test/observability hook: how many candidate runs the last attribute query's index produced. */\n lastAttributeCandidates = 0;\n /**\n * Test/observability hook: how many checkpoint rows the LAST checkpoint read materialized (the rows\n * actually returned to the caller). `listCheckpoints` returns all rows for the run; the targeted\n * {@link getLatestCheckpointByName} / {@link listCheckpointsByNamePrefix} return only the matches —\n * so this lets the benchmark contrast \"fetch N, scan in JS\" against \"fetch the k that match\".\n */\n lastCheckpointRowsRead = 0;\n\n private key(runId: string, seq: number): string {\n return `${runId}:${seq}`;\n }\n\n /** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */\n private reindexAttributes(runId: string, attributes: WorkflowRun['searchAttributes']): void {\n for (const byRun of this.attributeIndex.values()) byRun.delete(runId);\n for (const row of normalizeAttributeRows(runId, attributes)) {\n let byRun = this.attributeIndex.get(row.key);\n if (!byRun) {\n byRun = new Map();\n this.attributeIndex.set(row.key, byRun);\n }\n byRun.set(runId, row);\n }\n }\n\n async tryAdmitSingleton(\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ): Promise<boolean> {\n // No await between snapshot and claim: JavaScript's synchronous turn is the critical section.\n const runs = [...this.runs.values()];\n const tags = singletonAdmissionTags(runs, runId, tag, workflow, limit);\n if (!tags) {\n const patch = singletonAdmissionDenialPatch(runs, runId, tag, workflow, retryWakeAt);\n const candidate = this.runs.get(runId);\n if (patch && candidate) this.runs.set(runId, { ...candidate, ...patch });\n return false;\n }\n const run = this.runs.get(runId);\n if (!run) return false;\n this.runs.set(runId, { ...run, tags });\n return true;\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n // Normalize undefined namespace to 'default', matching the SQL stores' column DEFAULT 'default'\n // (interfaces.ts: \"the store persists it as 'default'\"). This ensures legacy runs (created without\n // a namespace, e.g. in tests that bypass the engine) are reachable via a namespace='default' filter.\n this.runs.set(run.id, { ...run, namespace: run.namespace ?? 'default' });\n this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void> {\n const patch =\n inputPatch.status && TERMINAL_RUN_STATUSES.includes(inputPatch.status)\n ? {\n ...inputPatch,\n tags: ('tags' in inputPatch ? inputPatch.tags : this.runs.get(runId)?.tags)?.filter(\n (tag) => tag !== SINGLETON_ADMITTED_TAG,\n ),\n }\n : inputPatch;\n const existing = this.runs.get(runId);\n if (!existing) throw new Error(`run ${runId} not found`);\n const next = { ...existing, ...patch };\n this.runs.set(runId, next);\n if ('searchAttributes' in patch) this.reindexAttributes(runId, next.searchAttributes);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const run = this.runs.get(runId);\n return run ? { ...run } : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n this.runs.delete(runId);\n for (const [key, cp] of this.checkpoints) {\n if (cp.runId === runId) this.checkpoints.delete(key);\n }\n for (const [token, waiter] of this.signalWaiters) {\n if (waiter.runId === runId) this.signalWaiters.delete(token);\n }\n // Drop the run's normalized attribute rows (reindex with no attributes clears them).\n this.reindexAttributes(runId, undefined);\n }\n\n async deleteRuns(runIds: string[]): Promise<void> {\n for (const runId of runIds) await this.deleteRun(runId);\n }\n\n async pruneTerminalRuns(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number> {\n // Only terminal statuses are ever eligible — a policy naming a live status would race the engine.\n const statuses = policy.statuses.filter((s) => TERMINAL_RUN_STATUSES.includes(s));\n if (statuses.length === 0 || limit <= 0) return 0;\n if (policy.maxAge == null && policy.maxCount == null) return 0;\n const inScope = this.matching({ ...(policy.scope ?? {}), statuses });\n const ids = new Set<string>();\n if (policy.maxAge != null) {\n const cutoff = nowMs - parseDuration(policy.maxAge);\n const expired = inScope\n .filter((r) => r.updatedAt.getTime() < cutoff)\n .sort((a, b) => a.updatedAt.getTime() - b.updatedAt.getTime()) // oldest first\n .slice(0, limit);\n for (const r of expired) ids.add(r.id);\n }\n if (policy.maxCount != null && ids.size < limit) {\n // Everything past the newest `maxCount` runs of the (scoped) status set.\n const byRecency = [...inScope].sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime() || b.id.localeCompare(a.id),\n );\n for (const r of byRecency.slice(policy.maxCount)) {\n if (ids.size >= limit) break;\n ids.add(r.id);\n }\n }\n const doomed = [...ids].slice(0, limit);\n await this.deleteRuns(doomed);\n return doomed.length;\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const cp = this.checkpoints.get(this.key(runId, seq));\n return cp ? { ...cp } : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n this.checkpoints.set(this.key(checkpoint.runId, checkpoint.seq), { ...checkpoint });\n }\n\n async listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) =>\n (r.status === 'running' || r.status === 'cancelling') &&\n (namespace === undefined || r.namespace === namespace),\n )\n .map((r) => ({ ...r }));\n }\n\n async listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) => r.status === 'pending' && (namespace === undefined || r.namespace === namespace),\n )\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id))\n .slice(0, limit)\n .map((r) => ({ ...r }));\n }\n\n async listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) =>\n r.status === 'suspended' &&\n r.wakeAt !== undefined &&\n r.wakeAt <= nowMs &&\n (namespace === undefined || r.namespace === namespace),\n )\n .map((r) => ({ ...r }));\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const run = this.runs.get(runId);\n if (!run) return false;\n if (run.lockedUntil !== undefined && run.lockedUntil > nowMs) return false;\n run.lockedBy = owner;\n run.lockedUntil = leaseUntilMs;\n return true;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const run = this.runs.get(runId);\n if (run) {\n run.lockedBy = undefined;\n run.lockedUntil = undefined;\n }\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const run = this.runs.get(runId);\n if (!run || run.lockedBy !== owner) return false;\n run.lockedUntil = leaseUntilMs;\n return true;\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n this.signalWaiters.set(waiter.token, { ...waiter });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const waiter = this.signalWaiters.get(token);\n if (!waiter) return null;\n this.signalWaiters.delete(token);\n return { ...waiter };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n return [...this.signalWaiters.values()]\n .filter((w) => w.token.startsWith(prefix))\n .map((w) => ({ ...w }));\n }\n\n async registerChildWaits(entries: ChildWait[]): Promise<void> {\n for (const { waiter } of entries) this.signalWaiters.set(waiter.token, { ...waiter });\n for (const { checkpoint } of entries) await this.saveCheckpoint(checkpoint);\n }\n\n async compactCheckpoints(\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ): Promise<void> {\n for (let seq = fromSeq; seq <= toSeq; seq += 1) this.checkpoints.delete(this.key(runId, seq));\n this.checkpoints.set(this.key(runId, into.seq), { ...into, runId });\n }\n\n async listSignalWaitersByRun(runIds: string[]): Promise<SignalWaiter[]> {\n const ids = new Set(runIds);\n return [...this.signalWaiters.values()].filter((w) => ids.has(w.runId)).map((w) => ({ ...w }));\n }\n\n async hasSignalWaiter(runId: string, tokenPrefix: string): Promise<boolean> {\n for (const w of this.signalWaiters.values()) {\n if (w.runId === runId && w.token.startsWith(tokenPrefix)) return true;\n }\n return false;\n }\n\n async removeSignalWaiter(waiter: SignalWaiter): Promise<void> {\n // Keyed by token only (one row per token) — only delete if the CURRENT row still matches this\n // exact (runId, seq); a later putSignalWaiter for the same token may have already replaced it\n // with a different run's row, which must be left alone.\n const current = this.signalWaiters.get(waiter.token);\n if (current && current.runId === waiter.runId && current.seq === waiter.seq) {\n this.signalWaiters.delete(waiter.token);\n }\n }\n\n // No real DB transaction (there's no DB) — run the work and save the checkpoint. Exactly-once\n // across a crash needs a SQL store; this keeps `ctx.transaction` usable in tests / local dev.\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return work({ raw: this, saveCheckpoint: (cp) => this.saveCheckpoint(cp) });\n }\n\n private readonly bufferedSignals = new Map<string, unknown[]>();\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const queue = this.bufferedSignals.get(token) ?? [];\n queue.push(payload);\n this.bufferedSignals.set(token, queue);\n }\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const queue = this.bufferedSignals.get(token);\n if (!queue || queue.length === 0) return null;\n const payload = queue.shift();\n if (queue.length === 0) this.bufferedSignals.delete(token);\n return { payload };\n }\n\n /** `id -> row`, so {@link removeBufferedEvent} can delete an exact row regardless of iteration\n * order — mirrors the SQL stores' PK-by-id delete. */\n private readonly bufferedEvents = new Map<\n string,\n { name: string; payload: unknown; publishedAt: number }\n >();\n async bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void> {\n this.bufferedEvents.set(input.id, {\n name: input.name,\n payload: input.payload,\n publishedAt: input.publishedAt,\n });\n }\n async listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>> {\n return [...this.bufferedEvents.entries()]\n .filter(([, e]) => e.name === name)\n .sort((a, b) => a[1].publishedAt - b[1].publishedAt) // oldest first\n .slice(0, limit)\n .map(([id, e]) => ({ id, payload: e.payload, publishedAt: e.publishedAt }));\n }\n async removeBufferedEvent(id: string): Promise<boolean> {\n return this.bufferedEvents.delete(id);\n }\n\n /**\n * Candidate run ids satisfying ONE attribute predicate, served from {@link attributeIndex} — the\n * pushdown step. Numeric predicates scan only `numValue` rows under the key; string/boolean ones\n * scan `strValue` rows. This is the in-memory analog of the SQL EXISTS on `durable_run_attributes`.\n */\n private candidatesForFilter(f: AttributeFilter): Set<string> {\n const byRun = this.attributeIndex.get(f.key);\n const out = new Set<string>();\n if (!byRun) return out;\n // One comparison per operand — a scalar op has exactly one, `in` has one per member — ORed, the\n // same shape the SQL stores emit inside their EXISTS. An `in` over no values compares nothing and\n // so matches nothing, which is why this ORs a possibly-empty list instead of skipping the filter.\n const comparisons = attributePredicateOperands(f);\n for (const row of byRun.values()) {\n const matched = comparisons.some(({ column, comparator, operand }) => {\n const actual = column === 'numValue' ? row.numValue : row.strValue;\n if (actual == null) return false;\n switch (comparator) {\n case '=':\n return actual === operand;\n case '<>':\n return actual !== operand;\n case '>':\n return actual > operand;\n case '>=':\n return actual >= operand;\n case '<':\n return actual < operand;\n default:\n return actual <= operand;\n }\n });\n if (matched) out.add(row.runId);\n }\n return out;\n }\n\n /** Every run satisfying `query`'s predicates, unsorted and unpaged — the shared body of\n * {@link listRuns} (which then sorts + pages it) and {@link runFacets} (which groups it). */\n private matching(query: RunQuery): WorkflowRun[] {\n let runs = [...this.runs.values()];\n if (query.workflow) runs = runs.filter((r) => r.workflow === query.workflow);\n if (query.workflows) runs = runs.filter((r) => query.workflows?.includes(r.workflow));\n if (query.status) runs = runs.filter((r) => r.status === query.status);\n if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));\n if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag as string));\n // ANY of the tags, against a run that carries a SET of them — see `RunQuery.tags`.\n if (query.tags) runs = runs.filter((r) => r.tags?.some((t) => query.tags?.includes(t)));\n if (query.namespace !== undefined) runs = runs.filter((r) => r.namespace === query.namespace);\n if (query.namespaces) {\n runs = runs.filter(\n (r) => r.namespace !== undefined && query.namespaces?.includes(r.namespace),\n );\n }\n // Exact match on a value; `null` selects the runs carrying NO origin — see `RunQuery.origin`.\n if (query.origin === null) runs = runs.filter((r) => r.origin == null);\n else if (query.origin !== undefined) runs = runs.filter((r) => r.origin === query.origin);\n // `null` is a member like any other here, so a set can ask for named origins AND the\n // unattributed bucket in one predicate.\n if (query.origins) {\n runs = runs.filter((r) => query.origins?.includes(r.origin ?? null));\n }\n if (query.attributes?.length) {\n // Pushdown: intersect per-predicate candidate sets from the key-indexed side-table, so we only\n // ever materialize the runs that already satisfy EVERY attribute filter (no full per-run scan).\n let candidates: Set<string> | null = null;\n for (const f of query.attributes) {\n const next = this.candidatesForFilter(f);\n if (candidates == null) {\n candidates = next;\n } else {\n const prev: Set<string> = candidates;\n candidates = new Set([...prev].filter((id) => next.has(id)));\n }\n if (candidates.size === 0) break;\n }\n const ids = candidates ?? new Set<string>();\n this.lastAttributeCandidates = ids.size;\n runs = runs.filter((r) => ids.has(r.id));\n }\n return runs;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const runs = this.matching(query);\n // Newest first (matches the store adapters' `createdAt DESC`) — recent runs on top in the dashboard.\n runs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n const offset = query.offset ?? 0;\n const limit = query.limit ?? runs.length;\n return runs.slice(offset, offset + limit).map((r) => ({ ...r }));\n }\n\n async countRuns(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number> {\n return this.matching(query).length;\n }\n\n async runFacets(query: RunFacetQuery): Promise<RunFacetRow[]> {\n return mergeRunFacetRows(\n this.matching(query).map((run) => ({ status: run.status, origin: run.origin, count: 1 })),\n );\n }\n\n /** Counted over the newest `scan` matching runs for EVERY axis, not just `tag`: this store holds\n * its runs in a Map with no index to group by, so the bound that the SQL stores need only for tags\n * is the honest one to apply here throughout. */\n async runValueFacets(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]> {\n const runs = await this.listRuns({ ...query, limit: opts?.scan ?? RUN_VALUE_FACET_SCAN });\n return runValueFacetsFromRuns(runs, axis, opts);\n }\n\n private readonly schedules = new Map<string, ScheduleRecord>();\n\n async saveSchedule(record: ScheduleRecord): Promise<void> {\n this.schedules.set(record.id, structuredClone(record));\n }\n\n async getSchedule(id: string): Promise<ScheduleRecord | null> {\n const record = this.schedules.get(id);\n return record ? structuredClone(record) : null;\n }\n\n async updateSchedule(\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ): Promise<boolean> {\n const record = this.schedules.get(id);\n if (!record) return false;\n if (expectedNextFireAt !== undefined && record.nextFireAt !== expectedNextFireAt) return false;\n this.schedules.set(id, { ...record, ...structuredClone(patch) });\n return true;\n }\n\n async deleteSchedule(id: string): Promise<boolean> {\n return this.schedules.delete(id);\n }\n\n async listSchedules(query: ScheduleQuery): Promise<ScheduleRecord[]> {\n const rows = [...this.schedules.values()]\n .filter((s) => query.namespace === undefined || s.namespace === query.namespace)\n .filter((s) => query.workflow === undefined || s.workflow === query.workflow)\n .filter((s) => query.tag === undefined || (s.tags ?? []).includes(query.tag))\n .filter((s) => query.paused === undefined || s.paused === query.paused)\n .filter(\n (s) =>\n query.dueBy === undefined ||\n (!s.paused && s.nextFireAt !== null && s.nextFireAt <= query.dueBy),\n )\n .sort(\n (a, b) =>\n (a.nextFireAt ?? Number.POSITIVE_INFINITY) - (b.nextFireAt ?? Number.POSITIVE_INFINITY) ||\n a.id.localeCompare(b.id),\n );\n const offset = query.offset ?? 0;\n return rows\n .slice(offset, query.limit != null ? offset + query.limit : undefined)\n .map((s) => structuredClone(s));\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = [...this.checkpoints.values()]\n .filter((cp) => cp.runId === runId)\n .sort((a, b) => a.seq - b.seq)\n .map((cp) => ({ ...cp }));\n this.lastCheckpointRowsRead = rows.length;\n return rows;\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n let latest: StepCheckpoint | undefined;\n for (const cp of this.checkpoints.values()) {\n if (cp.runId !== runId || cp.name !== name) continue;\n if (!latest || cp.seq > latest.seq) latest = cp;\n }\n this.lastCheckpointRowsRead = latest ? 1 : 0;\n return latest ? { ...latest } : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n const rows = [...this.checkpoints.values()]\n .filter((cp) => cp.runId === runId && prefixes.some((p) => cp.name.startsWith(p)))\n .sort((a, b) => a.seq - b.seq)\n .map((cp) => ({ ...cp }));\n this.lastCheckpointRowsRead = rows.length;\n return rows;\n }\n}\n","import type {\n ControlMessage,\n ControlPlane,\n Heartbeat,\n RemoteTask,\n StepResult,\n Transport,\n WorkflowStepEvent,\n} from '../interfaces';\nimport { type StepHandler, runStepHandler } from '../protocol';\n\n/**\n * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered\n * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,\n * and control messages broadcast locally. Pass the same instance as both `transport` and\n * `controlPlane`.\n */\nexport class InMemoryTransport implements Transport, ControlPlane {\n private readonly handlers = new Map<string, StepHandler>();\n private resultHandler?: (result: StepResult) => Promise<void>;\n private heartbeatHandler?: (beat: Heartbeat) => Promise<void>;\n private stepEventHandler?: (event: WorkflowStepEvent) => Promise<void>;\n private readonly controlHandlers = new Set<(msg: ControlMessage) => void>();\n\n /** Register a fake worker handler for a step name. */\n handle(name: string, fn: StepHandler): void {\n this.handlers.set(name, fn);\n }\n\n async dispatch(task: RemoteTask): Promise<void> {\n if (!this.resultHandler) throw new Error('no result handler registered');\n const result = await runStepHandler(task, this.handlers.get(task.name));\n // Deliver the result ASYNCHRONOUSLY, not inline: a durable `ctx.call` suspends the run right\n // after dispatch, so the result must land AFTER that unwinds (else the resume re-enters\n // mid-suspend). Real brokers are async; this mirrors them.\n setImmediate(() => void this.resultHandler?.(result));\n }\n\n onResult(handler: (result: StepResult) => Promise<void>): void {\n this.resultHandler = handler;\n }\n\n onHeartbeat(handler: (beat: Heartbeat) => Promise<void>): void {\n // In-process step handlers run synchronously (no step liveness to track), but a test can drive a\n // RUN-scoped beat via `emitHeartbeat` to exercise the engine's heartbeat-rearmed advance deadline.\n this.heartbeatHandler = handler;\n }\n\n /** Test hook: deliver a liveness heartbeat to the engine, as a real broker would on its channel. */\n async emitHeartbeat(beat: Heartbeat): Promise<void> {\n await this.heartbeatHandler?.(beat);\n }\n\n /** Workflow step lifecycle: deliver to the engine's handler (async, mirroring a real broker). */\n async dispatchStepEvent(event: WorkflowStepEvent): Promise<void> {\n await this.stepEventHandler?.(event);\n }\n\n onStepEvent(handler: (event: WorkflowStepEvent) => Promise<void>): void {\n this.stepEventHandler = handler;\n }\n\n // Control plane: broadcast to every registered handler (including the publisher's own — the\n // engine dedupes by `from`), mirroring how a real broker echoes a publish to all subscribers.\n async publishControl(msg: ControlMessage): Promise<void> {\n for (const handler of this.controlHandlers) handler(msg);\n }\n\n onControl(handler: (msg: ControlMessage) => void): void {\n this.controlHandlers.add(handler);\n }\n}\n"],"mappings":"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","names":["QueueController","inFlight","windowStart","windowCount","waiters","Map","waiterSeq","keyServed","servedTick","config","clock","ordered","fairness","order","tryAdmit","item","now","rl","rateLimit","periodMs","limit","ok","retryAt","usingOrder","priority","waiterId","full","concurrency","register","retryMs","size","isNext","delete","key","set","release","existing","get","seq","self","undefined","Number","POSITIVE_INFINITY","best","w","values","better","a","b","sa","servedOf","sb","InMemoryAdmissionBackend","controllers","Map","clock","register","config","set","name","QueueController","handles","queue","has","tryAdmit","item","controller","get","ok","release","_slotId","AsyncLocalStorage","STORAGE_KEY","Symbol","for","globalRef","globalThis","AsyncLocalStorage","storage","runInWorkflowCtx","ctx","fn","run","currentWorkflowCtx","getStore","STEP_SCOPE_KEY","stepScopeRef","stepScopeStorage","runInStepScope","owner","step","currentStepScope","runOutsideWorkflowCtx","exit","AsyncLocalStorage","STORAGE_KEY","Symbol","for","globalRef","globalThis","AsyncLocalStorage","storage","runInStepLogger","logger","fn","run","currentStep","getStore","log","level","message","data","debug","info","warn","error","sub","name","status","subEvent","e","noopSubProcessHandle","phase","skip","fail","subProcess","body","opts","Promise","resolve","CONTROL_FLOW_SIGNAL","Symbol","for","isWorkflowControlFlowSignal","error","FatalError","Error","code","message","name","ConcurrencyLimitError","workflow","key","limit","active","SingletonQueueFullError","maxQueueDepth","SignalTimeoutError","token","timeoutMs","RemoteStepTimeout","stepId","RemoteWorkflowTimeout","taskId","NonDeterminismError","runId","seq","expected","recorded","NestedWorkflowCallError","primitive","step","GatherError","failures","total","ids","map","f","id","join","denom","length","WorkflowSuspended","wakeAt","fan","CONTROL_FLOW_SIGNAL","ContinueAsNew","input","WORKFLOW_NAME_KEY","Symbol","for","workflowName","ref","name","Error","BINDINGS_KEY","Symbol","for","globalRef","globalThis","WeakMap","bindings","bindWorkflowClass","ctor","client","set","clientOf","get","Error","workflowName","DurableWorkflow","start","input","opts","cls","ctx","currentWorkflowCtx","runId","startChild","id","status","crypto","randomUUID","execute","child","waitForRun","FatalError","settled","timeoutMs","until","output","detail","error","message","code","UNIT_MS","ms","s","sec","second","seconds","m","min","minute","minutes","h","hr","hour","hours","d","day","days","w","week","weeks","parseDuration","duration","match","trim","Error","value","Number","unit","toLowerCase","factor","undefined","backoffDelay","attempt","options","base","backoffMs","raw","backoff","capped","backoffMaxMs","Math","min","jitter","round","random","wrappers","useDurableExecution","wrapper","push","i","indexOf","splice","clearDurableExecutionWrappers","length","hasDurableExecutionWrappers","runDurableExecution","execution","body","outcome","inner","value","ok","error","chain","reduceRight","next","undefined","Error","withDuration","start","now","data","base","durationMs","createStepLogger","events","currentSub","push","level","message","at","subId","id","undefined","subEvent","e","status","phase","name","group","subProcess","body","opts","globalThis","crypto","randomUUID","prevSub","terminal","emit","handle","skip","reason","fail","result","err","Error","String","debug","m","d","info","warn","error","sub","stepId","runId","seq","breakpointToken","runStepHandler","task","handler","base","startedAt","Date","now","status","error","message","name","retryable","events","withEvents","result","length","logger","createStepLogger","output","runDurableExecution","unit","workflow","undefined","attempt","runOutsideWorkflowCtx","runInStepLogger","input","err","e","Error","String","code","REDISPATCHED_STEP_EVENT","LOST_STEP_EVENT","lostStepEvent","at","attempts","outcome","level","name","message","nonEmptyEvents","events","length","undefined","stepCheckpoint","p","runId","seq","kind","stepId","status","input","output","error","workerGroup","wakeAt","parallelGroup","enqueuedAt","startedAt","finishedAt","instantCheckpoint","Date","isFailedCompletion","payload","c","ok","unwrapCompletion","label","FatalError","error","value","DEFAULT_CONCURRENCY_STATUSES","concurrencyTag","key","resolveConcurrency","override","config","input","undefined","limit","countStatuses","countRuns","store","query","runFacets","status","statuses","origin","cells","reduce","sum","c","count","rest","filter","includes","listRuns","length","assertConcurrency","workflow","quota","active","tag","ConcurrencyLimitError","ENTITY_WORKFLOW","entityRunId","name","key","Entities","configs","Map","host","register","ctx","input","run","config","set","dispatch","op","arg","reply","runId","signalWithStart","token","payload","signal","getState","getEvent","get","FatalError","state","initialState","i","msg","waitForSignal","out","localStep","handler","handlers","result","setEvent","accToken","target","EventAccumulators","host","register","ctx","input","debounce","batch","route","config","payload","workflow","mode","windowMs","maxSize","signalWithStart","token","last","waitForSignal","timeoutMs","e","SignalTimeoutError","startChild","continueAsNew","events","deadline","now","length","remaining","push","enc","s","Buffer","from","toString","dec","EVENT_BUFFER_SCAN_LIMIT","EVENT_TOKEN_PREFIX","eventPrefix","name","isEventToken","token","startsWith","eventToken","match","runId","seq","JSON","stringify","eventNameOf","split","eventMatchOf","parse","eventMatches","payload","keys","Object","length","p","every","k","allChildId","runId","firstSeq","index","wave","allBase","allGroup","mode","allWait","base","waiterPrefix","checkpointPrefix","fanJoin","waits","FOLDED_PREFIX","allFoldedName","foldedChildIds","checkpoint","name","slice","length","from","values","output","map","_","j","undefined","allWaves","size","concurrency","Number","isInteger","Error","waveSize","maxWaves","Math","floor","ENGINE_CHILD_ID","parentRunIdOf","exec","GROUP","REST","fanOfWaiter","waiter","group","parallelGroup","token","startsWith","rest","failFast","CURRENT_PROTOCOL_VERSION","LEGACY_V1_PROTOCOL","version","range","LEGACY_V1_CAPABILITIES","Object","freeze","isLegacyDescriptor","raw","protocol","undefined","normalizeDescriptor","instanceId","runtime","sdk","name","capabilities","workflows","steps","registrations","partition","namespace","startedAt","canonicalizeRegistrations","regs","canonical","map","r","group","requires","Set","sort","origin","byJson","Map","entry","set","JSON","stringify","keys","k","get","canonicalizeForHash","d","xs","fnv1a64Hex","input","OFFSET","PRIME","MASK","hash","i","length","BigInt","charCodeAt","toString","padStart","descriptorHash","descriptor","heartbeatStatus","opts","ts","Date","now","status","describeWorker","a","b","localeCompare","announcementsOf","raw","d","normalizeDescriptor","identity","instanceId","runtime","announcements","registrations","map","reg","covered","Set","a","name","workflows","has","push","announcementKey","version","undefined","stated","values","filter","v","sort","aggregateAnnouncements","descriptors","byKey","Map","descriptor","announcement","key","bucket","get","set","out","groups","group","origins","origin","requiresByJson","requires","canonical","JSON","stringify","x","y","join","localeCompare","disagreements","length","axis","r","first","evidence","runtimes","instances","b","observedAnnouncements","heartbeats","byToken","beat","add","entries","coveredTokens","announced","sanitize","tokens","entry","step","steps","token","partition","DEFAULT_PARTITION","partitionOfToken","token","at","lastIndexOf","slice","buildWorkflowDirectory","input","descriptors","heartbeats","namespace","supported","sanitize","workflows","otherPartitions","detail","mine","undefined","ownDescriptors","filter","d","ownBeats","foreign","Map","beat","group","partition","push","seen","get","groups","add","instances","instanceId","set","Set","declared","aggregateAnnouncements","observed","observedAnnouncements","coveredTokens","sort","a","b","key","localeCompare","entries","map","describeDirectory","summarize","names","limit","length","join","here","elsewhere","p","w","evidence","declaredNote","rangesOverlap","a","b","Math","max","min","difference","bset","Set","filter","x","has","sort","intersection","negotiate","localRaw","remoteRaw","opts","local","normalizeDescriptor","remote","localRange","protocol","range","remoteRange","shared","capabilities","missingOnRemote","missingOnLocal","outcome","negotiatedProtocol","reason","code","message","detail","required","missingRequired","length","join","parts","push","requiredCapabilities","handler","list","Array","isArray","requires","Set","canRoute","worker","required","length","advertised","normalizeDescriptor","capabilities","every","cap","has","missingCapabilities","filter","capableWorkers","workers","w","resolveRouting","capable","map","status","suffix","join","reason","controlPlaneDescriptor","opts","version","CURRENT_PROTOCOL_VERSION","instanceId","runtime","sdk","name","String","protocol","range","capabilities","workflows","steps","partition","undefined","namespace","startedAt","WorkflowBlocked","Error","plan","reason","planDispatch","requires","liveDescriptors","cp","token","required","requiredCapabilities","workers","map","normalizeDescriptor","capable","filter","w","canRoute","compatible","negotiate","outcome","length","status","workerRanges","code","join","diagnostics","liveWorkers","controlPlaneRange","controlPlane","advertised","Set","flatMap","missingCapabilities","cap","has","TERMINAL_RUN_STATUSES","isNonEmptyRunScope","scope","workflow","undefined","workflows","tag","tags","namespace","namespaces","attributes","length","tenantGroup","baseGroup","tenant","undefined","sanitizeQueueToken","name","replace","RemoteWorkflowExecutor","transport","name","partition","_opts","dispatch","run","history","taskId","pendingSignals","dispatchWorkflowTask","Error","task","runId","id","workflow","workflowVersion","input","group","tenantGroup","sanitizeQueueToken","priority","attempt","WEBHOOK_PREFIX","CHILD_PREFIX","BREAKPOINT_PREFIX","EVENT_PREFIX","EVENT_TOKEN_PREFIX","classifyWaiterToken","token","startsWith","on","name","slice","length","eventNameOf","resolveRunWaiting","run","waiterByRun","status","undefined","waiter","get","id","RUN_ID_BATCH","listSignalWaitersOfRuns","store","runIds","unique","Set","listSignalWaitersByRun","ids","listSignalWaiters","filter","w","has","runId","out","at","push","indexWaitersByRun","waiters","byRun","Map","set","createRequire","isIndexable","value","unwrapDefault","module_","Reflect","get","undefined","inner","v4Entry","parse","expr","options","call","v5Entry","parser","resolveCronParse","resolved","nodeRequire","createRequire","url","defaultSleep","ms","Promise","r","setTimeout","scheduledRunId","key","everyMs","nowMs","Math","floor","cronParser","loadCronParser","undefined","Error","prevCronFireMs","expr","timezone","parse","resolveCronParse","currentDate","Date","tz","prev","toDate","getTime","nextCronFireMs","afterMs","next","scheduleRunIdAt","s","cron","scheduleRunIdsAt","current","backfill","maxCatchup","ids","bucket","oldest","max","b","push","prior","cursor","i","before","reverse","runSchedules","engine","schedules","opts","random","sleep","paused","overlap","prevBucket","getRun","status","jitter","runId","start","workflow","input","ScheduleAlreadyExistsError","Error","scheduleId","name","ScheduleNotFoundError","DEFAULT_NAMESPACE","ON_TIME_GRACE_MS","TICK_BATCH","ScheduleClient","store","host","options","now","clock","Date","supported","s","saveSchedule","getSchedule","updateSchedule","deleteSchedule","listSchedules","requireStore","r","call","id","patch","expected","q","create","opts","write","upsert","get","record","describe","list","query","map","delete","pause","note","mustGet","spec","undefined","paused","updatedAt","resume","window","nextWindowAfter","nextFireAt","jitterFor","state","trigger","runId","start","workflow","specOf","input","startOptions","tick","nowMs","started","round","due","dueBy","namespace","limit","fire","push","length","latest","next","latestWindowAtOrBefore","error","lastError","errorMessage","jitter","jitterMs","onTime","fired","skipMissed","catchup","beforeWindow","overlapping","getRun","nextState","lastFireAt","lastRunId","fires","stripUndefined","overlap","prev","TERMINAL_RUN_STATUSES","includes","status","existing","toSpec","workflowName","tags","createdAt","cron","every","everyMs","parseDuration","v","timezone","searchAttributes","priority","concurrency","atMs","prevCronFireMs","Math","floor","afterMs","nextCronFireMs","max","h","ch","charCodeAt","imul","o","Object","fromEntries","entries","filter","message","String","SINGLETON_ADMITTED_TAG","SINGLETON_ACTIVE_STATUSES","singletonAdmissionTags","runs","runId","tag","workflow","limit","Number","isInteger","Error","active","filter","run","includes","status","tags","candidate","find","id","holders","remaining","length","waiters","sort","a","b","createdAt","getTime","localeCompare","slice","some","clearTerminalSingletonAdmission","patch","getRun","TERMINAL_RUN_STATUSES","singletonAdmissionDenialPatch","retryWakeAt","undefined","wakeAt","updatedAt","Date","SINGLETON_RETRY_MS","SINGLETON_RETRY_JITTER_MS","SingletonGate","deps","tag","cfg","input","store","tryAdmitSingleton","Error","key","retryWakeAt","clock","Math","floor","random","assertCapacity","workflow","maxQueueDepth","cap","limit","queued","listRuns","statuses","SINGLETON_ACTIVE_STATUSES","length","SingletonQueueFullError","admit","run","admitted","id","tags","includes","SINGLETON_ADMITTED_TAG","wakeNext","settled","configFor","find","t","startsWith","gated","sort","a","b","createdAt","getTime","localeCompare","next","slice","updateRun","wakeAt","updatedAt","Date","catch","undefined","dispatch","TransportPool","transports","size","length","primary","first","Error","transport","bind","onResult","onHeartbeat","onStepEvent","onDecision","dispatch","task","preferId","lastErr","id","ordered","err","groupHealth","group","reports","push","undefined","depth","reduce","sum","r","liveWorkers","flatMap","onStartRun","handler","readWorkerDescriptors","descriptors","readAllWorkerDescriptors","byInstance","Map","descriptor","has","instanceId","set","values","readAllWorkerHeartbeats","seen","beat","key","introspectsFleet","some","listWorkerGroups","groups","Set","g","add","transportWithLiveGroup","includes","pref","filter","t","DURABLE_STEP_NAME","Symbol","for","DURABLE_STEP_CONFIG","isStepConfig","value","stepNameOf","ref","undefined","stamped","stepConfigOf","FAN_CHUNK","FOLD_MIN_FAN","normalizeChildOptions","options","childId","formatIssuePath","path","length","map","segment","String","key","join","resolveStepPolicy","config","opts","policy","retries","undefined","backoff","backoffMs","backoffMaxMs","jitter","timeoutMs","requires","Position","seq","next","rewind","peek","createWorkflowCtx","host","runId","compensations","workflow","searchAttributesSchema","store","replay","pos","scopeOwner","readCheckpoint","hit","get","getCheckpoint","writeCheckpoint","cp","saveCheckpoint","set","localStep","name","fn","current","existing","NonDeterminismError","status","compensate","push","output","maxAttempts","Math","max","startedAt","Date","startStep","kind","attempts","enqueuedAt","attempt","events","invocation","stepName","body","logger","createStepLogger","clock","runInStepScope","runInStepLogger","interceptStep","completeStep","err","FatalError","failStep","error","message","Error","stack","wait","backoffDelay","Promise","resolve","setTimeout","transaction","tx","raw","instantCheckpoint","suspendUntil","wakeAt","now","WorkflowSuspended","at","sleep","duration","parseDuration","sleepUntil","when","getTime","continueAsNew","input","ContinueAsNew","consumeBuffered","token","buffered","takeBufferedSignal","payload","value","consumeBufferedEvent","match","candidates","listBufferedEvents","EVENT_BUFFER_SCAN_LIMIT","candidate","eventMatches","removeBufferedEvent","id","removeSignalWaiter","stampDeadline","deadlineSeq","label","recorded","deadline","waitForSignal","putSignalWaiter","lateBuffered","waitSeq","waited","catch","SignalTimeoutError","waitForEvent","eventToken","bufferedHit","task","dispatch","unwrapCompletion","child","priority","version","getRun","startChild","workflowName","fanJoin","waiterPrefix","checkpointPrefix","all","inputs","mode","waves","allWaves","concurrency","positions","firstSeq","group","allGroup","waveOf","i","floor","waveSize","allChildId","checkpoints","folded","readFan","allWait","allFoldedName","waveCount","ceil","waveItems","k","_","from","slice","c","ok","j","cancelChild","GatherError","index","compactCheckpoints","items","first","last","values","into","parallelGroup","delete","sent","some","settled","every","active","unsettled","maxWaves","toRegister","toEnsure","chunk","entries","waiter","checkpoint","registerChildWaits","outputs","failures","prefixes","expand","startsWith","FOLDED_PREFIX","fold","Array","isArray","forEach","missing","filter","listCheckpointsByNamePrefix","bySeq","Map","e","callEntity","op","arg","reply","signalEntity","breakpoint","breakpointToken","patched","marker","onUpdate","setEvent","webhook","takeSignalWaiter","url","webhookUrl","sideEffect","upsertSearchAttributes","attrs","run","merged","searchAttributes","result","validate","issues","offendingKeys","Set","issue","details","resolveCompensateDef","stepNameOf","stepConfigOf","step","handlerOrName","def","callRemote","queue","transport","fairnessKey","then","args","nestedStep","scope","currentStepScope","owner","guard","primitive","NestedWorkflowCallError","guardedWebhook","mergeTags","staticTags","runTags","length","undefined","Set","BREAKPOINT","isBreakpoint","cp","status","name","startsWith","VERSION_UNDECLARED_TAG","versionKey","version","stepGroup","step","runNamespace","tenantGroup","sanitizeQueueToken","partition","nextContinuationId","runId","m","match","Number","isNewerVersion","a","b","na","nb","isNaN","localeCompare","numeric","NamespaceMismatch","Error","WorkflowEngine","store","pool","controlPlane","clock","instanceId","namespace","leaseMs","maxRecoveryAttempts","remoteAdvanceSilenceMs","reconcileMs","eventBufferTtlMs","remoteRedispatchMs","remoteRedispatchMax","blockedPollMs","cpDescriptor","webhookUrl","traceparent","context","rehydrate","compensationRetries","trackStepStart","runDispatcher","singletons","schedules","workflows","Map","latest","eventTriggers","entities","accumulators","pending","heartbeatResets","listeners","interceptors","cancelListeners","enqueuedListeners","deadListeners","updateValidators","cancelRequested","admission","queueWaiters","stepQueue","inflight","draining","deps","TransportPool","transports","transport","id","Date","now","InMemoryAdmissionBackend","onFreed","queue","wakeQueueWaiters","globalThis","crypto","randomUUID","Math","max","controlPlaneDescriptor","_carrier","fn","dispatch","queueMicrotask","runOne","catch","SingletonGate","configFor","run","get","workflow","workflowVersion","singleton","ScheduleClient","start","input","opts","getRun","bind","result","waiter","stepId","delete","resolve","output","startedAt","events","reject","RemoteStepError","error","completeRemoteResult","beat","reset","rearmDecisionDeadline","rearmStepLease","seq","event","persistStepEvent","decision","completeRemoteDecision","onStartRun","message","tenant","tags","searchAttributes","onControl","msg","from","kind","deliver","at","notifyCancelled","EventAccumulators","Entities","registerEntity","config","register","signalEntity","key","op","arg","signal","getEntityState","getState","onEnqueued","listener","add","group","executor","registered","concurrency","executionTimeoutMs","executionTimeout","parseDuration","validateInput","searchAttributesSchema","onEvent","eventBatch","requires","origin","hasBody","remote","set","current","subscribers","workflowBody","reg","registeredVersions","versions","values","filter","w","map","join","registerRemote","rest","RemoteWorkflowExecutor","primary","registerQueue","subscribe","use","interceptor","push","i","indexOf","splice","interceptStep","invocation","body","carrier","chain","reduceRight","next","onCancel","onDead","notifyDead","emit","full","publishControl","workflowName","pinned","ancestor","findRemoteAncestor","synthesizeRemoteChild","conventionRun","createdAt","updatedAt","resolveRemoteByConvention","askFleetForVersion","prior","quota","resolveConcurrency","assertConcurrency","stampedTags","tag","concurrencyTag","versionDeclared","SINGLETON_ADMITTED_TAG","assertCapacity","priority","createRun","resume","resumeRun","resumeImplicit","allowFailed","releaseRunLock","includes","updateRun","findInheritedRegistration","track","execute","liveTransport","transportWithLiveGroup","declared","declaredVersion","readWorkerDescriptors","descriptors","announced","aggregateAnnouncements","only","childRunId","visited","has","parentRunId","findParentRunId","parent","parentReg","token","waiters","listSignalWaiters","find","p","done","then","drain","timeoutMs","size","timer","Promise","t","setTimeout","unref","race","allSettled","sweepTimeouts","deadline","listRuns","getTime","code","type","cancelChildren","recoverIncomplete","nowMs","results","listed","listIncompleteRuns","acquired","tryLockRun","dispatched","inFlightRemoteStep","wakeAt","reconcileWakeAt","settled","countRecovery","checkpoints","listCheckpoints","attempts","recoveryAttempts","resumeDueTimers","due","listDueTimers","blocked","dueBlockedRuns","waiterByRun","indexWaitersByRun","listSignalWaitersOfRuns","resumeLeased","reconcileSignalWaiter","isEventToken","reconcileBufferedEvent","buffered","takeBufferedSignal","removeSignalWaiter","deliverSignal","payload","eventNameOf","eventMatchOf","candidates","listBufferedEvents","EVENT_BUFFER_SCAN_LIMIT","candidate","publishedAt","removeBufferedEvent","eventMatches","err","requeue","_seen","seen","resurrecting","isFailureCompletion","v","ok","saveCheckpoint","retryable","childId","slice","parked","successAt","findIndex","success","bufferSignal","bufferedSuccess","putSignalWaiter","parallelGroup","child","redispatchPending","redispatched","reAttempt","reEnqueuedAt","enqueuedAt","finishedAt","dispatchRemoteTask","workerGroup","attempt","retryWithInput","newRunId","runPending","listPendingRuns","waitForRun","TERMINAL","isSettled","until","awaitingDecisionTaskId","toResult","off","poller","clearInterval","finish","clearTimeout","fail","check","interval","setInterval","ev","runs","onLocked","console","publishEvent","touched","eventPrefix","eventId","batch","route","buffer","bufferedId","bufferEvent","lateWaiters","lateWaiter","takeSignalWaiter","instantCheckpoint","fanStillWaiting","hasSignalWaiter","fan","fanOfWaiter","failFast","isFailedCompletion","waiterPrefix","redriveSettledChildren","wait","waits","listCheckpointsByNamePrefix","checkpointPrefix","every","reclaimed","signalWithStart","completeTask","value","failTask","notifyParent","completion","lastIndexOf","startChildDeferred","String","cancel","TERMINAL_RUN_STATUSES","compensate","wakeNext","cancelWhere","r","deleteRun","deleted","getRunChildren","purgeRuns","scope","isNonEmptyRunScope","batchSize","cancelLive","withChildren","children","statuses","previous","limit","fingerprint","known","ids","collectSubtrees","doomed","deleteRunIds","purgeNamespace","rootIds","prefixes","CHILD_EDGE_PREFIXES","childrenOf","awaitedChildIds","cps","some","childIdsOf","ordered","visit","deleteRuns","childIds","childCheckpoints","knownGroups","extra","groups","def","workerHealth","listWorkerGroups","inflightStepGroups","workflowTokens","out","health","groupHealth","baseToken","announcedWorkflows","workflowDirectory","buildWorkflowDirectory","readAllWorkerDescriptors","heartbeats","readAllWorkerHeartbeats","supported","introspectsFleet","sanitize","phase","stepCheckpoint","failed","startStep","completeStep","queueMs","durationMs","failStep","singletonWaitResult","lockNow","lockedBy","lockedUntil","renew","renewRunLock","floor","runRemoteExecution","runExecution","settleRun","outcome","parkBlocked","admit","wfPlan","planRoute","history","remoteHistory","taskId","silenceMs","advanceExecutor","advance","call","awaitWithLivenessDeadline","RemoteWorkflowTimeout","stack","applyDecision","applyCommands","commands","fresh","suspended","redriveIfTurnSawStaleHistory","blocking","cmd","checkpoint","getCheckpoint","redriveLostCall","lease","stepLeaseWakeAt","lostStepEvent","reconcile","min","stepLeaseRearms","lookAgainAt","halfWindow","ceil","renewed","clear","kindOf","local","sleep","sort","redriveLost","existing","leaseAt","leaseWake","ms","deliverBuffered","lateBuffered","compensateAndCancel","compensations","replay","unwindCompensations","runDurableExecution","unit","runExecutionTurn","snapshot","suspendedOnFan","ctx","createWorkflowCtx","ctxHostFor","runInWorkflowCtx","ContinueAsNew","nextId","WorkflowBlocked","plan","WorkflowSuspended","comp","runCompensation","dispatchCompensation","args","maxAttempts","retries","backoffDelay","withWakeAt","dispatchCompensationAttempt","parentNamespace","s","callRemote","startChild","cancelChild","upsertSearchAttributes","attrs","reply","continue","bp","breakpointToken","getEvent","getLatestCheckpointByName","registerUpdateValidator","validate","update","accepted","reason","planDispatch","ensureRoutable","diagnostics","routing","NonDeterminismError","callRemoteInMemory","nextDeadline","handles","tryAdmit","fairnessKey","waiterId","retryAt","task","releaseQueueSlot","decisionDeadlineRearms","runIds","release","validInput","parse","resultPromise","resolution","awaitWithHeartbeat","RemoteStepTimeout","onTimeout","cleanup","arm","stepError","FOLDED_PREFIX","foldedChildIds","facetOrigin","origin","trim","mergeRunFacetRows","rows","cells","Map","row","key","JSON","stringify","status","cell","get","count","set","values","RUN_VALUE_FACET_LIMIT","RUN_VALUE_FACET_SCAN","ENGINE_MINTED_TAG_PREFIXES","isEngineMintedTag","value","some","prefix","startsWith","axisIsRunColumn","axis","field","valuesOf","run","workflow","status","facetOrigin","origin","namespace","undefined","tags","Object","keys","searchAttributes","key","String","mergeRunValueFacetRows","rows","opts","counts","Map","row","set","get","Number","count","needle","search","trim","toLowerCase","merged","map","filter","includes","sort","a","b","engineA","engineB","localeCompare","offset","slice","limit","runValueFacetsFromRuns","runs","push","RunGateway","CodecStateStore","tryAdmitSingleton","runFacets","runValueFacets","deleteRuns","pruneTerminalRuns","countRuns","registerChildWaits","compactCheckpoints","listSignalWaitersByRun","hasSignalWaiter","saveSchedule","getSchedule","updateSchedule","deleteSchedule","listSchedules","inner","codec","bind","ids","call","prune","policy","now","limit","count","query","entries","map","e","waiter","checkpoint","encCp","compact","runId","fromSeq","toSeq","into","byRun","runIds","hasWaiter","tokenPrefix","r","encSchedule","id","decSchedule","patch","expected","spec","encSpec","q","facets","valueFacets","axis","opts","enc","v","undefined","encode","dec","decode","encRun","run","input","output","decRun","cp","decCp","ensureSchema","Promise","resolve","createRun","updateRun","next","getRun","deleteRun","getCheckpoint","seq","saveCheckpoint","transaction","work","Error","tx","raw","listIncompleteRuns","namespace","listPendingRuns","listDueTimers","nowMs","tryLockRun","owner","leaseUntilMs","releaseRunLock","renewRunLock","putSignalWaiter","takeSignalWaiter","token","listSignalWaiters","prefix","removeSignalWaiter","bufferSignal","payload","takeBufferedSignal","buffered","bufferEvent","listBufferedEvents","name","events","removeBufferedEvent","listRuns","listCheckpoints","c","getLatestCheckpointByName","latest","listCheckpointsByNamePrefix","prefixes","matches","filter","some","p","startsWith","collectMetrics","engine","m","runs","started","completed","failed","suspended","steps","byWorkflow","stepDuration","sumMs","count","wf","name","k","entry","stop","subscribe","e","type","workflow","durationMs","snapshot","structuredClone","prometheus","lines","push","v","Object","entries","event","n","join","compare","actual","filter","op","values","some","v","expected","value","matchesAttributes","attributes","filters","length","every","f","key","applyAttributeQuery","rows","query","filtered","r","searchAttributes","offset","limit","slice","normalizeAttributeRows","runId","out","Object","entries","push","strValue","numValue","sqlComparator","attributeColumnFor","attributeOperand","attributePredicateOperands","map","scalar","column","comparator","operand","readSearchAttributes","schema","run","result","validate","searchAttributes","Promise","Error","issues","value","STATE_STORE","Symbol","for","TRANSPORT","DURABLE_OPTIONS","STATE_STORE_CANONICAL","TRANSPORT_CANONICAL","DURABLE_OPTIONS_CANONICAL","InMemoryStateStore","runs","Map","checkpoints","signalWaiters","attributeIndex","lastAttributeCandidates","lastCheckpointRowsRead","key","runId","seq","reindexAttributes","attributes","byRun","values","delete","row","normalizeAttributeRows","get","set","tryAdmitSingleton","tag","workflow","limit","retryWakeAt","tags","singletonAdmissionTags","patch","singletonAdmissionDenialPatch","candidate","run","createRun","id","namespace","searchAttributes","updateRun","inputPatch","status","TERMINAL_RUN_STATUSES","includes","filter","SINGLETON_ADMITTED_TAG","existing","Error","next","getRun","deleteRun","cp","token","waiter","undefined","deleteRuns","runIds","pruneTerminalRuns","policy","nowMs","statuses","s","length","maxAge","maxCount","inScope","matching","scope","ids","Set","cutoff","parseDuration","expired","r","updatedAt","getTime","sort","a","b","slice","add","size","byRecency","localeCompare","doomed","getCheckpoint","saveCheckpoint","checkpoint","listIncompleteRuns","map","listPendingRuns","createdAt","listDueTimers","wakeAt","tryLockRun","owner","leaseUntilMs","lockedUntil","lockedBy","releaseRunLock","renewRunLock","putSignalWaiter","takeSignalWaiter","listSignalWaiters","prefix","w","startsWith","registerChildWaits","entries","compactCheckpoints","fromSeq","toSeq","into","listSignalWaitersByRun","has","hasSignalWaiter","tokenPrefix","removeSignalWaiter","current","transaction","work","raw","bufferedSignals","bufferSignal","payload","queue","push","takeBufferedSignal","shift","bufferedEvents","bufferEvent","input","name","publishedAt","listBufferedEvents","e","removeBufferedEvent","candidatesForFilter","f","out","comparisons","attributePredicateOperands","matched","some","column","comparator","operand","actual","numValue","strValue","query","workflows","t","namespaces","origin","origins","candidates","prev","listRuns","offset","countRuns","runFacets","mergeRunFacetRows","count","runValueFacets","axis","opts","scan","RUN_VALUE_FACET_SCAN","runValueFacetsFromRuns","schedules","saveSchedule","record","structuredClone","getSchedule","updateSchedule","expectedNextFireAt","nextFireAt","deleteSchedule","listSchedules","rows","paused","dueBy","Number","POSITIVE_INFINITY","listCheckpoints","getLatestCheckpointByName","latest","listCheckpointsByNamePrefix","prefixes","p","InMemoryTransport","handlers","Map","resultHandler","heartbeatHandler","stepEventHandler","controlHandlers","Set","handle","name","fn","set","dispatch","task","Error","result","runStepHandler","get","setImmediate","onResult","handler","onHeartbeat","emitHeartbeat","beat","dispatchStepEvent","event","onStepEvent","publishControl","msg","onControl","add"]}
|
|
1
|
+
{"version":3,"sources":["../src/queue.ts","../src/admission.ts","../src/ambient-ctx.ts","../src/ambient-step.ts","../src/control-flow-signal.ts","../src/errors.ts","../src/workflow-ref.ts","../src/durable-workflow.ts","../src/duration.ts","../src/backoff.ts","../src/execution-hooks.ts","../src/step-logger.ts","../src/protocol.ts","../src/checkpoints.ts","../src/completion.ts","../src/concurrency.ts","../src/entities.ts","../src/event-accumulators.ts","../src/events.ts","../src/fan-join.ts","../src/handshake/descriptor.ts","../src/handshake/announced.ts","../src/handshake/directory.ts","../src/handshake/negotiate.ts","../src/handshake/routing.ts","../src/handshake/dispatch-routing.ts","../src/interfaces.ts","../src/tenant-group.ts","../src/remote-workflow-executor.ts","../src/run-waiting.ts","../src/scheduler.ts","../src/cron-compat.ts","../src/schedules.ts","../src/singleton-admission.ts","../src/singleton-gate.ts","../src/transport-pool.ts","../src/step-name-symbol.ts","../src/workflow-ctx.ts","../src/engine.ts","../src/run-facets.ts","../src/run-value-facets.ts","../src/run-gateway.ts","../src/codec-state-store.ts","../src/metrics.ts","../src/search-attributes.ts","../src/search-attributes-schema.ts","../src/tokens.ts","../src/testing/in-memory-state-store.ts","../src/testing/in-memory-transport.ts"],"sourcesContent":["/**\n * Flow control for dispatched steps. A queue caps how much work `ctx.step(step, input, { queue })`\n * admits at once — a concurrency limit and/or a fixed-window rate limit. When a call can't be\n * admitted it doesn't dispatch: the run re-suspends with a near-future wake time, and the timer\n * poller re-tries admission later — so flow control is durable (survives crashes) without holding\n * the run in memory.\n *\n * Accounting is per engine instance (the DBOS `workerConcurrency` tier): correct for the common\n * single-orchestrator deployment. Global, cross-instance limits would need a durable counter in the\n * store — a deliberate follow-up, not built here.\n *\n * Beyond raw caps, the controller can admit contended slots by PRIORITY and by per-KEY FAIRNESS\n * (round-robin), so a single noisy key/tenant can't monopolize the concurrency budget. This is the\n * DISPATCH/admission layer — it never touches workflow replay (engine positional logic). Default\n * behaviour is unchanged FIFO when neither priority nor fairness is configured/passed.\n *\n * Design (vs Temporal/Inngest/DBOS): Temporal task queues are FIFO with separate priority levels;\n * Inngest concurrency keys + throttle give per-key fairness; DBOS queues are FIFO with a\n * `workerConcurrency` cap. We fold both knobs into the same in-process admission gate: an optional\n * per-call `priority` (higher first) and an optional queue-level `fairness: 'key'` (round-robin by\n * the per-call `key`). Because blocked calls re-suspend durably and retry independently (there is no\n * resident FIFO list to reorder), the controller remembers the set of WAITERS that asked-and-were-\n * blocked, and on a later retry only admits the one that is rightful-next under the policy.\n */\nexport interface QueueConfig {\n /** Queue name, referenced by `ctx.step(step, input, { queue: name })`. */\n name: string;\n /** Max steps in flight at once for this queue (this instance). Omit for unlimited. */\n concurrency?: number;\n /** Fixed-window rate limit: at most `limit` admissions per `periodMs`. Omit for unlimited. */\n rateLimit?: { limit: number; periodMs: number };\n /** Delay (ms) before a concurrency-blocked call re-checks for a free slot. Default 1000. */\n retryMs?: number;\n /**\n * Fairness policy for a contended concurrency slot. `'key'` round-robins across distinct per-call\n * keys (the least-recently-served key wins the next slot), so one key can't monopolize the budget.\n * Omit (or `'fifo'`) for plain first-come ordering. Priority always wins over fairness; fairness\n * only breaks ties within the same priority.\n */\n fairness?: 'fifo' | 'key';\n /**\n * Arrival-order tiebreak among otherwise-equal waiters (same priority, same fairness rank).\n * `'fifo'` (default) admits the earliest arrival; `'lifo'` admits the most recent (a stack). Orthogonal\n * to `priority` and `fairness` — those still win first; this only breaks their ties.\n */\n order?: 'fifo' | 'lifo';\n}\n\n/**\n * Per-call admission hints. All optional — omitting them keeps the legacy FIFO behaviour.\n * - `priority`: higher is admitted first (default 0).\n * - `key`: the fairness bucket (e.g. a tenant id) for `fairness: 'key'`.\n * - `waiterId`: a stable id for THIS call across its retries (the engine passes the stepId), so the\n * controller can track it as one waiter instead of counting each retry as a new contender.\n */\nexport interface AdmissionItem {\n priority?: number | undefined;\n key?: string | undefined;\n waiterId?: string | undefined;\n}\n\n/** Admission decision: either admitted, or blocked until `retryAt` (epoch ms). */\nexport type Admission = { ok: true } | { ok: false; retryAt: number };\n\n/** A call that asked for a slot and was blocked — remembered so the controller can order admission. */\ninterface Waiter {\n priority: number;\n key?: string | undefined;\n /** Monotonic registration order — FIFO tiebreak within equal priority/fairness. */\n seq: number;\n}\n\n/** In-process admission controller for one {@link QueueConfig}. */\nexport class QueueController {\n private inFlight = 0;\n private windowStart = 0;\n private windowCount = 0;\n /** Registered waiters by id (only used when priority/fairness ordering is in play). */\n private readonly waiters = new Map<string, Waiter>();\n /** Monotonic counter stamping each newly-seen waiter for a stable FIFO tiebreak. */\n private waiterSeq = 0;\n /** Per-key \"last served\" order for round-robin fairness — higher = more recently served. */\n private readonly keyServed = new Map<string, number>();\n private servedTick = 0;\n\n constructor(\n readonly config: QueueConfig,\n private readonly clock: () => number,\n ) {}\n\n /** Whether this controller does any priority/fairness ordering (else it's a plain FIFO gate). */\n private get ordered(): boolean {\n return this.config.fairness === 'key' || this.config.order === 'lifo';\n }\n\n /**\n * Try to admit one unit of work. On `ok`, the caller has taken a concurrency slot and must call\n * {@link release} when the step settles. On block, `retryAt` is when admission may next succeed.\n *\n * `item` carries optional priority/fairness hints; omitting it is the legacy FIFO path. When\n * ordering is configured (or a priority is given), a blocked call REGISTERS as a waiter and is only\n * admitted on a later retry once it is the rightful next under (priority desc, fairness, FIFO).\n */\n tryAdmit(item?: AdmissionItem): Admission {\n const now = this.clock();\n const rl = this.config.rateLimit;\n // Rate limit is a hard global window — checked first and unaffected by priority/fairness.\n if (rl) {\n if (now - this.windowStart >= rl.periodMs) {\n this.windowStart = now;\n this.windowCount = 0;\n }\n if (this.windowCount >= rl.limit)\n return { ok: false, retryAt: this.windowStart + rl.periodMs };\n }\n\n const usingOrder = this.ordered || item?.priority != null || item?.waiterId != null;\n const waiterId = item?.waiterId;\n\n // Concurrency gate.\n const full = this.config.concurrency != null && this.inFlight >= this.config.concurrency;\n if (full) {\n // No slot at all → block (and register as a waiter so a later retry can be ordered).\n if (usingOrder && waiterId != null) this.register(waiterId, item);\n return { ok: false, retryAt: now + (this.config.retryMs ?? 1000) };\n }\n\n // A slot is free. Without ordering, admit immediately (legacy FIFO). With ordering, only admit if\n // THIS call is the rightful next among all registered waiters — otherwise keep it waiting so the\n // freed slot can go to a higher-priority / under-served key on its retry.\n if (usingOrder && this.waiters.size > 0) {\n if (waiterId != null) this.register(waiterId, item);\n if (!this.isNext(waiterId, item)) {\n return { ok: false, retryAt: now + (this.config.retryMs ?? 1000) };\n }\n }\n\n // Admit: consume the slot, the rate-window tick, and clear this waiter.\n if (rl) this.windowCount += 1;\n this.inFlight += 1;\n if (waiterId != null) this.waiters.delete(waiterId);\n if (item?.key != null) this.keyServed.set(item.key, ++this.servedTick);\n return { ok: true };\n }\n\n /** Release a concurrency slot taken by a successful {@link tryAdmit}. */\n release(): void {\n if (this.inFlight > 0) this.inFlight -= 1;\n }\n\n /** Track (or refresh) a blocked call as a waiter; its FIFO seq is stamped only on first sight. */\n private register(waiterId: string, item?: AdmissionItem): void {\n const existing = this.waiters.get(waiterId);\n if (existing) {\n existing.priority = item?.priority ?? 0;\n existing.key = item?.key;\n return;\n }\n this.waiters.set(waiterId, {\n priority: item?.priority ?? 0,\n key: item?.key,\n seq: this.waiterSeq++,\n });\n }\n\n /**\n * Is the calling item the best candidate among all registered waiters? Ordering, best first:\n * 1. higher `priority`;\n * 2. fairness: with `fairness: 'key'`, the least-recently-served key wins (round-robin);\n * 3. earliest registration (FIFO) — stable tiebreak.\n * A bare item (no waiterId) is compared on its hints directly.\n */\n private isNext(waiterId: string | undefined, item?: AdmissionItem): boolean {\n const self: Waiter =\n (waiterId != null ? this.waiters.get(waiterId) : undefined) ??\n ({ priority: item?.priority ?? 0, key: item?.key, seq: Number.POSITIVE_INFINITY } as Waiter);\n let best = self;\n for (const w of this.waiters.values()) {\n if (this.better(w, best)) best = w;\n }\n return best === self;\n }\n\n /** Strict \"a should be admitted before b\" comparison under the active policy. */\n private better(a: Waiter, b: Waiter): boolean {\n if (a.priority !== b.priority) return a.priority > b.priority;\n if (this.config.fairness === 'key') {\n const sa = this.servedOf(a.key);\n const sb = this.servedOf(b.key);\n if (sa !== sb) return sa < sb; // least-recently-served key first\n }\n return this.config.order === 'lifo' ? a.seq > b.seq : a.seq < b.seq; // arrival tiebreak\n }\n\n /** Last-served tick for a key (0 = never served, so an unseen key is admitted before a busy one). */\n private servedOf(key?: string): number {\n if (key == null) return 0;\n return this.keyServed.get(key) ?? 0;\n }\n}\n","import { type Admission, type AdmissionItem, type QueueConfig, QueueController } from './queue';\n\n/**\n * Pluggable backend for the step flow-control gate (`ctx.step(step, input, { queue })`). The\n * engine asks it whether a queued call may be admitted now (concurrency / rate / ordering) and tells\n * it when an admitted slot is released.\n *\n * The default {@link InMemoryAdmissionBackend} keeps per-instance counts — correct for a single\n * orchestrator. Swap in a store/Redis-backed backend to make the caps and ordering GLOBAL across\n * engine replicas (so `concurrency: 5` means 5 in-flight across the whole fleet, not 5 per pod).\n *\n * `tryAdmit`/`release` are async so a global backend can do its atomic round-trip; the in-memory one\n * resolves synchronously. An UNREGISTERED queue name is treated as ungated (admits immediately) — the\n * engine only tracks/releases a slot for a registered queue.\n */\nexport interface AdmissionBackend {\n /** Register (or replace) a queue's config. Called from `engine.registerQueue`. */\n register(config: QueueConfig): void;\n /** Whether `queue` is registered (gated). The engine only tracks/releases a slot for a gated queue. */\n handles(queue: string): boolean;\n /** May a call on `queue` take a slot now? On `ok`, the caller holds a slot until {@link release}. */\n tryAdmit(queue: string, item: AdmissionItem): Promise<Admission>;\n /**\n * Release the slot granted by {@link tryAdmit} for `queue`. `slotId` is the admitted item's\n * `waiterId` (the engine's stepId), so a lease-based backend can drop the exact slot; an in-process\n * counter ignores it.\n */\n release(queue: string, slotId: string): Promise<void>;\n /**\n * Optional: subscribe to \"a slot just freed on `queue`\" events (e.g. a fleet-wide pub/sub). The\n * engine uses it to wake its admission-blocked runs early instead of waiting for their retry tick.\n * A backend without it falls back to retry-tick polling. Fired best-effort across the fleet.\n */\n onFreed?(handler: (queue: string) => void): void;\n}\n\n/**\n * Default admission backend: one in-process {@link QueueController} per registered queue. Caps and\n * waiter ordering are per engine instance (see {@link QueueConfig}). Preserves the exact pre-backend\n * behaviour — the engine used to hold these controllers directly.\n */\nexport class InMemoryAdmissionBackend implements AdmissionBackend {\n private readonly controllers = new Map<string, QueueController>();\n\n constructor(private readonly clock: () => number) {}\n\n register(config: QueueConfig): void {\n this.controllers.set(config.name, new QueueController(config, this.clock));\n }\n\n handles(queue: string): boolean {\n return this.controllers.has(queue);\n }\n\n async tryAdmit(queue: string, item: AdmissionItem): Promise<Admission> {\n const controller = this.controllers.get(queue);\n // Unregistered queue → ungated (mirrors the old `this.queues.get(queue)` truthiness check).\n if (!controller) return { ok: true };\n return controller.tryAdmit(item);\n }\n\n async release(queue: string, _slotId: string): Promise<void> {\n this.controllers.get(queue)?.release();\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { WorkflowCtx } from './interfaces';\n\n/**\n * The ambient workflow context: an `AsyncLocalStorage` the engine (and the thin worker runtime)\n * installs around every execution of a workflow body, so code running ON the body's async path can\n * discover the live {@link WorkflowCtx} without threading it through — the mechanism behind the\n * class-first `MyWorkflow.start()` / `MyWorkflow.execute()` statics (see `durable-workflow.ts`).\n *\n * One storage per PROCESS, not per copy of this package: stashed on `globalThis` under a\n * `Symbol.for` key, so a dependency tree carrying duplicate copies of core still shares the same\n * ambient context (the same duplicate-copy trap the DI tokens guard against — see `tokens.ts`).\n */\nconst STORAGE_KEY = Symbol.for('nestjs-durable:ambient-workflow-ctx');\n\ntype GlobalWithStorage = typeof globalThis & {\n [STORAGE_KEY]?: AsyncLocalStorage<WorkflowCtx>;\n};\n\nconst globalRef = globalThis as GlobalWithStorage;\nif (!globalRef[STORAGE_KEY]) {\n globalRef[STORAGE_KEY] = new AsyncLocalStorage<WorkflowCtx>();\n}\nconst storage: AsyncLocalStorage<WorkflowCtx> = globalRef[STORAGE_KEY];\n\n/**\n * Run `fn` with `ctx` as the ambient workflow context. Engine-internal: wraps every execution of a\n * workflow body (first run and every replay), so ambient reads inside the body see the SAME ctx the\n * body received.\n */\nexport function runInWorkflowCtx<T>(ctx: WorkflowCtx, fn: () => T): T {\n return storage.run(ctx, fn);\n}\n\n/**\n * The {@link WorkflowCtx} of the workflow body currently executing on this async path — or\n * `undefined` outside one. Note a `@Step` HANDLER runs on a worker, off the body's path: it has no\n * ambient workflow context (by design — a handler is not the workflow body).\n */\nexport function currentWorkflowCtx(): WorkflowCtx | undefined {\n return storage.getStore();\n}\n\n/**\n * The ambient STEP scope: which workflow ctx's checkpointed step body (if any) is executing on this\n * async path. The engine installs it around every in-body step execution (`ctx.localStep`,\n * `ctx.transaction`, and everything built on them) so the ctx primitives can refuse to run from\n * inside a step body — see {@link NestedWorkflowCallError}. `owner` is the identity of the ctx whose\n * step is running, so a DIFFERENT run's body executed inline from a step (e.g. a step that signals a\n * run which resumes on this async path) is never mistaken for a nested call.\n *\n * Shared per process under a `Symbol.for` key, for the same duplicate-copy reason as the ctx storage.\n */\nexport interface StepScope {\n readonly owner: object;\n readonly step: string;\n}\n\nconst STEP_SCOPE_KEY = Symbol.for('nestjs-durable:ambient-step-scope');\ntype GlobalWithStepScope = typeof globalThis & {\n [STEP_SCOPE_KEY]?: AsyncLocalStorage<StepScope>;\n};\nconst stepScopeRef = globalThis as GlobalWithStepScope;\nif (!stepScopeRef[STEP_SCOPE_KEY]) {\n stepScopeRef[STEP_SCOPE_KEY] = new AsyncLocalStorage<StepScope>();\n}\nconst stepScopeStorage: AsyncLocalStorage<StepScope> = stepScopeRef[STEP_SCOPE_KEY];\n\n/** Run `fn` as the body of step `step` of the ctx identified by `owner`. Engine-internal. */\nexport function runInStepScope<T>(owner: object, step: string, fn: () => T): T {\n return stepScopeStorage.run({ owner, step }, fn);\n}\n\n/** The step body currently executing on this async path, or `undefined` outside one. */\nexport function currentStepScope(): StepScope | undefined {\n return stepScopeStorage.getStore();\n}\n\n/**\n * Run `fn` with NO ambient workflow ctx and no step scope — for a dispatched `@Step` handler. A\n * handler is not the workflow body (on a remote worker it never sees one), but an in-process\n * transport invokes it on the body's async path, where the parent's ctx would otherwise leak in and\n * turn a handler's `MyWorkflow.start()` into a journal-corrupting `ctx.startChild` of a parent that\n * is already suspended. Clearing it makes in-process and remote handlers behave identically.\n */\nexport function runOutsideWorkflowCtx<T>(fn: () => T): T {\n return storage.exit(() => stepScopeStorage.exit(fn));\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport type { StepLogger, SubProcessHandle } from './interfaces';\n\n/**\n * The ambient step logger: an `AsyncLocalStorage` the engine installs around every execution of a\n * step body — local (`ctx.step`) and remote (`runStepHandler`) alike — so code running DEEP inside\n * a step can record events without the {@link StepLogger} being threaded through every signature\n * on the way down. The TypeScript twin of the Python SDK's context-local `current_step()`.\n *\n * This is what makes observability symmetric across the two SDKs: in Python a nested helper emits\n * without receiving anything, whereas in TypeScript the logger only ever arrived as the step body's\n * second argument. A generic utility a few layers below the handler (a batch inserter, an HTTP\n * client) can now emit progress without its callers being edited.\n *\n * One storage per PROCESS, not per copy of this package: stashed on `globalThis` under a\n * `Symbol.for` key, so a dependency tree carrying duplicate copies of core still shares the same\n * ambient logger (the same duplicate-copy trap `ambient-ctx.ts` and the DI tokens guard against).\n */\nconst STORAGE_KEY = Symbol.for('nestjs-durable:ambient-step-logger');\n\ntype GlobalWithStorage = typeof globalThis & {\n [STORAGE_KEY]?: AsyncLocalStorage<StepLogger>;\n};\n\nconst globalRef = globalThis as GlobalWithStorage;\nif (!globalRef[STORAGE_KEY]) {\n globalRef[STORAGE_KEY] = new AsyncLocalStorage<StepLogger>();\n}\nconst storage: AsyncLocalStorage<StepLogger> = globalRef[STORAGE_KEY];\n\n/**\n * Run `fn` with `logger` as the ambient step logger. Engine-internal: wraps every execution of a\n * step body, binding the SAME logger instance the body receives as its second argument — never a\n * second one, so an event emitted ambiently and one emitted through the argument land in the same\n * `StepEvent[]` and are checkpointed together.\n *\n * Because it is an `AsyncLocalStorage`, concurrent step invocations (the worker runs steps under\n * adaptive concurrency) each see their own logger — they never leak into one another.\n */\nexport function runInStepLogger<T>(logger: StepLogger, fn: () => T): T {\n return storage.run(logger, fn);\n}\n\n/**\n * The {@link StepLogger} of the step body currently executing on this async path — or `undefined`\n * outside one. Reading it is the escape hatch for code that cannot take a logger parameter:\n *\n * ```ts\n * currentStep()?.subEvent({ id, name: 'insert', phase: `${rows} rows` });\n * ```\n */\nexport function currentStep(): StepLogger | undefined {\n return storage.getStore();\n}\n\n/**\n * Record a log line on the current step, taking the level as a value. No-op outside a step. The\n * literal twin of the Python SDK's module-level `log(level, message, data)` — keep reaching for it\n * when the level is computed (mapping a foreign log level, re-emitting a captured record); for a\n * level known at the call site the per-level shortcuts below read better.\n *\n * The no-op contract is what lets a generic utility be instrumented without an `if` at the call\n * site, and keeps it usable in a unit test with no durable run around it.\n */\nexport function log(\n level: 'debug' | 'info' | 'warn' | 'error',\n message: string,\n data?: unknown,\n): void {\n currentStep()?.[level](message, data);\n}\n\n// The per-level shortcuts, mirroring the same four methods on a `StepLogger` instance so ambient\n// code reads exactly like code that was handed the logger — `info('...')` vs `log.info('...')`.\n// They are the idiomatic TypeScript form; `log(level, ...)` above is the Python-symmetric one.\n// Both are kept: neither subsumes the other (one takes the level as data, the other as a name).\n\n/** Record a `debug` line on the current step. No-op outside a step. */\nexport function debug(message: string, data?: unknown): void {\n currentStep()?.debug(message, data);\n}\n\n/** Record an `info` line on the current step. No-op outside a step. */\nexport function info(message: string, data?: unknown): void {\n currentStep()?.info(message, data);\n}\n\n/** Record a `warn` line on the current step. No-op outside a step. */\nexport function warn(message: string, data?: unknown): void {\n currentStep()?.warn(message, data);\n}\n\n/** Record an `error` line on the current step. No-op outside a step — note this only RECORDS a line;\n * it never fails the step (that is what throwing from the body does). */\nexport function error(message: string, data?: unknown): void {\n currentStep()?.error(message, data);\n}\n\n/** Record a sub-step / sub-process outcome on the current step. No-op outside a step. */\nexport function sub(\n name: string,\n status: 'ok' | 'failed' | 'skipped',\n message?: string,\n data?: unknown,\n): void {\n currentStep()?.sub(name, status, message, data);\n}\n\n/** Record a sub-process event (phase or terminal outcome) on the current step. No-op outside a step. */\nexport function subEvent(e: {\n id: string;\n name: string;\n group?: string | undefined;\n phase?: string | undefined;\n status?: 'ok' | 'failed' | 'skipped' | undefined;\n message?: string | undefined;\n data?: unknown;\n}): void {\n currentStep()?.subEvent(e);\n}\n\n// Outside a step there is nothing to emit to, but `subProcess`'s body still has to run and still\n// receives a handle — so the same business code takes the same path whether or not it is durable.\nconst noopSubProcessHandle: SubProcessHandle = {\n phase: () => noopSubProcessHandle,\n skip: () => {},\n fail: () => {},\n};\n\n/**\n * Run `body` as a timed sub-process of the current step (see {@link StepLogger.subProcess}).\n * Outside a step the body still RUNS — and still gets a handle — but nothing is emitted; only the\n * observability disappears, never the work. Mirrors the Python SDK's `sub_process`.\n */\nexport function subProcess<T>(\n name: string,\n body: (sp: SubProcessHandle) => Promise<T> | T,\n opts?: { group?: string; id?: string },\n): Promise<T> {\n const logger = currentStep();\n if (!logger) return Promise.resolve(body(noopSubProcessHandle));\n return logger.subProcess(name, body, opts);\n}\n","/**\n * Cross-package, cross-runtime marker for engine CONTROL-FLOW signals — {@link WorkflowSuspended}\n * and {@link ContinueAsNew} (this package), plus the thin worker's {@link\n * import('@dudousxd/durable-worker').Suspend} (`@dudousxd/durable-worker`, the BullMQ\n * route-by-handler runtime). These are thrown by `WorkflowCtx`/`WorkflowContext` ops to unwind the\n * current turn — never real failures — so a workflow's `catch` block MUST rethrow them untouched.\n * Running a failure/cleanup path on a control-flow signal corrupts the run: it emits extra\n * `recordStep` commands into history that a subsequent replay didn't produce the first time,\n * surfacing as a `NonDeterminismError`/`NondeterminismError` on resume.\n *\n * `Symbol.for` (the GLOBAL registry), NOT a plain `Symbol()` — so a duplicate copy of this module\n * (pnpm peer-dependency multiplexing, a dual ESM/CJS load, or the SEPARATE `@dudousxd/durable-worker`\n * package declaring the same `Symbol.for` key locally) still collapses onto the SAME symbol. Same\n * rationale as `DURABLE_STEP_NAME` in `./step-name-symbol.ts`.\n *\n * Deliberately checked as a stamped property, NOT `instanceof` — `instanceof` only recognizes a\n * signal thrown by the SAME class the checking code imported, which fails across the in-process\n * engine (`@dudousxd/nestjs-durable-core`'s `WorkflowSuspended`/`ContinueAsNew`) and the thin worker\n * (`@dudousxd/durable-worker`'s `Suspend`) — two different classes for what is, from a workflow\n * author's catch block, the same \"this isn't a real error, let it through\" event.\n *\n * NOT designed to survive a serialization boundary (e.g. JSON over the wire) — these signals are\n * always thrown and caught in-process within a single replay turn, never (de)serialized, so a\n * stamped-but-not-cloneable property is sufficient.\n */\nexport const CONTROL_FLOW_SIGNAL = Symbol.for('aviary:durable:control-flow');\n\n/**\n * True for any engine control-flow signal (currently: {@link WorkflowSuspended}, {@link\n * ContinueAsNew}, and the thin worker's `Suspend`) — regardless of which runtime or module instance\n * threw it. Workflow `catch` blocks MUST rethrow these untouched; running a failure/cleanup path on\n * one corrupts the run's history (extra commands recorded during what replay will later see as a\n * suspend, not a failure) and the resumed replay dies with a non-determinism error.\n *\n * Deliberately NOT control-flow (do not add to this predicate):\n * - `Cancelled` (worker) / a cancelled run — a TERMINAL outcome the consumer may legitimately want\n * to observe and react to (e.g. release a lock), not a mid-turn unwind to rethrow untouched.\n * - `StepFailed` (worker) / an awaited step rejection reaching the engine — a REAL failure a\n * workflow's `catch` is meant to compensate for; misclassifying it as control-flow would swallow\n * genuine errors instead of protecting them.\n *\n * @example\n * ```ts\n * try {\n * await ctx.step('chargeCard', input);\n * } catch (error) {\n * if (isWorkflowControlFlowSignal(error)) throw error; // suspend/continue-as-new: rethrow as-is\n * await ctx.step('refund', input); // a REAL failure — safe to run cleanup here\n * throw error;\n * }\n * ```\n */\nexport function isWorkflowControlFlowSignal(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n (error as { [CONTROL_FLOW_SIGNAL]?: unknown })[CONTROL_FLOW_SIGNAL] === true\n );\n}\n","import { CONTROL_FLOW_SIGNAL, type isWorkflowControlFlowSignal } from './control-flow-signal';\n\n/**\n * Thrown inside a step to signal an unrecoverable failure: the engine will NOT retry it,\n * regardless of the step's `retries` setting, and fails the run immediately. Use it for\n * business errors that retrying cannot fix (e.g. a declined card, invalid input).\n */\nexport class FatalError extends Error {\n readonly code?: string | undefined;\n constructor(message: string, code?: string) {\n super(message);\n this.name = 'FatalError';\n this.code = code;\n }\n}\n\n/**\n * Thrown by `start` when a run would exceed its concurrency quota: `active` runs sharing the quota\n * `key` are already in flight (in the quota's counted statuses) and the `limit` is `limit`. Nothing\n * was created — the start is rejected up front, so the caller can shed load or answer \"try again in a\n * moment\" (e.g. map it to HTTP 429). See `StartOptions.concurrency` / `ConcurrencyConfig`.\n */\nexport class ConcurrencyLimitError extends Error {\n readonly workflow: string;\n readonly key: string;\n readonly limit: number;\n readonly active: number;\n constructor(workflow: string, key: string, limit: number, active: number) {\n super(\n `concurrency limit reached for key \"${key}\" (${active}/${limit} in flight); ${workflow} was not started — retry later`,\n );\n this.name = 'ConcurrencyLimitError';\n this.workflow = workflow;\n this.key = key;\n this.limit = limit;\n this.active = active;\n }\n}\n\n/**\n * Thrown by `start` when a singleton workflow's wait queue is full: the count of in-flight + gated\n * runs sharing the key already equals `limit + maxQueueDepth`, so admitting another would let the\n * same-key backlog grow unbounded. Back-pressure — the caller should retry later or shed load. Only\n * raised when {@link SingletonConfig.maxQueueDepth} is set (omit it for the old unbounded behavior).\n */\nexport class SingletonQueueFullError extends Error {\n readonly workflow: string;\n readonly key: string;\n readonly maxQueueDepth: number;\n constructor(workflow: string, key: string, maxQueueDepth: number) {\n super(\n `singleton queue for ${workflow} key \"${key}\" is full (maxQueueDepth=${maxQueueDepth}); retry later`,\n );\n this.name = 'SingletonQueueFullError';\n this.workflow = workflow;\n this.key = key;\n this.maxQueueDepth = maxQueueDepth;\n }\n}\n\n/**\n * Internal control signal thrown to suspend a run (e.g. on a durable sleep). Not an error the\n * user should throw or catch; the engine uses it to stop execution and persist `wakeAt`.\n */\nexport class SignalTimeoutError extends Error {\n readonly token: string;\n readonly timeoutMs: number;\n constructor(token: string, timeoutMs: number) {\n super(`timed out after ${timeoutMs}ms waiting for signal \"${token}\"`);\n this.name = 'SignalTimeoutError';\n this.token = token;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown when a remote step produces no result and no heartbeat within its `timeoutMs` window —\n * i.e. the worker is presumed dead. Subject to the step's `retries` (it's retryable), so the engine\n * re-dispatches before giving up.\n */\nexport class RemoteStepTimeout extends Error {\n readonly stepId: string;\n readonly timeoutMs: number;\n constructor(stepId: string, timeoutMs: number) {\n super(`remote step ${stepId} produced no result/heartbeat within ${timeoutMs}ms`);\n this.name = 'RemoteStepTimeout';\n this.stepId = stepId;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown by a remote {@link WorkflowExecutor} (e.g. {@link RemoteWorkflowExecutor}) when an `advance`\n * does not produce its decision within the configured `timeoutMs` — i.e. the worker is presumed gone\n * (the decision was dropped by a stall/redelivery or an instance restart spanning the in-memory waiter\n * map). Crucially this is NOT a run failure: the work may have actually completed and only the decision\n * was lost. The engine treats it as RECOVERABLE — it releases the run lease and leaves the run\n * `running` so `recoverIncomplete` re-drives it deterministically (replaying completed steps from\n * history). Distinct from a real executor error, which still fails the run.\n *\n * OPT-IN: only thrown when the executor was constructed with a `timeoutMs`. Absent a timeout, the\n * engine awaits the decision with its prior (unbounded) behavior — so existing users see no change.\n *\n * Known hazard: a timeout that fires while a worker is LEGITIMATELY still executing a not-yet-\n * checkpointed step will re-drive and re-run that in-flight step → DUPLICATE side effects. Therefore\n * the timeout is only safe when set GENEROUSLY (longer than the longest legitimate single turn). The\n * robust fix — a liveness/heartbeat-rearmed deadline so only a genuinely-dead worker re-drives — is the\n * documented follow-up (see the Track A diagnosis doc, \"Part B\").\n */\nexport class RemoteWorkflowTimeout extends Error {\n readonly taskId: string;\n readonly timeoutMs: number;\n constructor(taskId: string, timeoutMs: number) {\n super(\n `remote workflow task ${taskId} produced no decision within ${timeoutMs}ms — presumed dropped; re-driving via recovery`,\n );\n this.name = 'RemoteWorkflowTimeout';\n this.taskId = taskId;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Thrown on resume when the workflow code no longer matches the recorded history: the step at a\n * logical position has a different name/kind than the checkpoint saved there. This means the\n * workflow definition changed (a step was added/removed/reordered) under an in-flight run without a\n * new `@Workflow` version — continuing would replay the wrong checkpoint into the wrong step and\n * silently corrupt the run, so the engine fails loudly instead. Register a new workflow version for\n * breaking changes (old runs finish on the version they started on).\n */\nexport class NonDeterminismError extends Error {\n readonly runId: string;\n readonly seq: number;\n constructor(runId: string, seq: number, expected: string, recorded: string) {\n super(\n `non-determinism at ${runId}#${seq}: code expects \"${expected}\" but history recorded ` +\n `\"${recorded}\". The workflow changed under an in-flight run — register a new @Workflow version.`,\n );\n this.name = 'NonDeterminismError';\n this.runId = runId;\n this.seq = seq;\n }\n}\n\n/**\n * Thrown AT THE CALL SITE when a workflow-ctx primitive (`ctx.startChild`, `ctx.child`, `ctx.step`,\n * `ctx.sleep`, `ctx.sideEffect`, … — or a `MyWorkflow.start()`/`.execute()` static, which route to\n * them through the ambient ctx) is called from INSIDE the body of a checkpointed step\n * (`ctx.localStep`, `ctx.transaction`, `ctx.sideEffect`, `ctx.now`, `ctx.task`'s dispatch).\n *\n * A step body runs once and is replayed from its checkpoint WITHOUT re-running, so a primitive it\n * called claims a journal position on the first run that no replay ever claims again: every later\n * position shifts and the run dies on its next replay with a `NonDeterminismError` far from the\n * cause. Failing here instead names the real mistake. Move the call out of the step body (into the\n * workflow body), or — from a dispatched `@Step` handler — start a top-level run.\n *\n * A `FatalError` (code `nested_workflow_call`): the step is not retried, the run fails.\n */\nexport class NestedWorkflowCallError extends FatalError {\n readonly runId: string;\n readonly primitive: string;\n readonly step: string;\n constructor(runId: string, primitive: string, step: string) {\n super(\n `ctx.${primitive}() was called inside the body of step \"${step}\" (run ${runId}). Workflow primitives (child/startChild/step/sleep/signals/sideEffect/…, and MyWorkflow.start()/.execute() via the ambient ctx) must be called from the workflow body, never from inside a step body: the step's checkpoint replays without re-running it, so the nested call would shift every later journal position and corrupt the run on replay. Move the call out of the step.`,\n 'nested_workflow_call',\n );\n this.name = 'NestedWorkflowCallError';\n this.runId = runId;\n this.primitive = primitive;\n this.step = step;\n }\n}\n\n/**\n * Thrown by `ctx.all` when one or more parallel child workflows fail. Carries the per-item failures\n * (input index, child run id, error message) and presents an aggregate message summarizing the count\n * and the failing ids — the wait-all/fail-fast counterpart to a single child's FatalError. Mirrors\n * the Python SDK's `GatherFailed`.\n */\nexport class GatherError extends Error {\n readonly failures: { index: number; id: string; error: string }[];\n constructor(failures: { index: number; id: string; error: string }[], total?: number) {\n const ids = failures.map((f) => f.id).join(', ');\n const denom = total ?? failures.length;\n super(`ctx.all: ${failures.length} of ${denom} child(ren) failed: ${ids}`);\n this.name = 'GatherError';\n this.failures = failures;\n }\n}\n\nexport class WorkflowSuspended extends Error {\n /** Epoch ms to auto-resume (durable sleep), or undefined when waiting on an external signal. */\n readonly wakeAt?: number | undefined;\n /** Set when awaited children are what the run is waiting on — see {@link FanJoin}. */\n readonly fan?: FanJoin | undefined;\n /** Marks this as a control-flow signal — see {@link isWorkflowControlFlowSignal}. */\n readonly [CONTROL_FLOW_SIGNAL] = true;\n constructor(wakeAt?: number, fan?: FanJoin) {\n super('workflow suspended');\n this.name = 'WorkflowSuspended';\n this.wakeAt = wakeAt;\n this.fan = fan;\n }\n}\n\n/**\n * What a run suspended on when it awaits children (`ctx.all`, `ctx.child`). For each group of\n * children, every waiter token starts with `waiterPrefix` and every `signal:child:` checkpoint name\n * with `checkpointPrefix`, so the engine can tell whether the group has settled without knowing the\n * children's ids.\n */\nexport interface FanJoin {\n waits: FanWait[];\n}\n\nexport interface FanWait {\n waiterPrefix: string;\n checkpointPrefix: string;\n}\n\n/**\n * Thrown by `ctx.continueAsNew(input)` to end the current run and hand off to a fresh execution of\n * the same workflow with a clean history — for long-running / looping workflows that would otherwise\n * accumulate unbounded checkpoints. The engine completes this run and starts the next one.\n */\nexport class ContinueAsNew extends Error {\n /** Marks this as a control-flow signal — see {@link isWorkflowControlFlowSignal}. */\n readonly [CONTROL_FLOW_SIGNAL] = true;\n constructor(readonly input: unknown) {\n super('workflow continued as new');\n this.name = 'ContinueAsNew';\n }\n}\n","/**\n * A **workflow reference** is how one workflow names another to call it: either a registered workflow\n * **name** (a string — the only option across runtimes, e.g. a Python workflow) or, for a same-runtime\n * TypeScript workflow, its **class**. The class carries the input/output types through the call, so\n * `ctx.child(ShippingWorkflow, input)` type-checks the input and returns a typed result — while a\n * string stays available for the cross-runtime case.\n */\n\n/**\n * The symbol the `@Workflow` decorator stamps a workflow's registered name onto, so a class ref can\n * be resolved back to its name. A global-registry symbol (`Symbol.for`) so it survives duplicate\n * copies of this package in a dependency tree.\n */\nexport const WORKFLOW_NAME_KEY: unique symbol = Symbol.for('nestjs-durable:workflow-name');\n\n/** Structural shape of a `@Workflow` class — its `run(ctx, input)` carries the input/output types. */\nexport type WorkflowClass<TInput = unknown, TOutput = unknown> = abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: TInput): Promise<TOutput> | TOutput;\n};\n\n/** A workflow reference: a registered name (cross-runtime) or a workflow class (typed, same-runtime). */\nexport type WorkflowRef<TInput = unknown, TOutput = unknown> =\n | string\n | WorkflowClass<TInput, TOutput>;\n\n/** The input type a workflow class's `run` accepts. */\nexport type WorkflowInputOf<C> = C extends abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: infer I): unknown;\n}\n ? I\n : unknown;\n\n/** The output type a workflow class's `run` resolves to (Promise unwrapped). */\nexport type WorkflowOutputOf<C> = C extends abstract new (\n ...args: never[]\n) => {\n run(ctx: never, input: never): infer R;\n}\n ? Awaited<R>\n : unknown;\n\n/**\n * Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a\n * `@Workflow` class is resolved via the name the decorator stamped on it. Throws if a class was\n * never decorated (so it carries no registered name).\n */\nexport function workflowName(ref: WorkflowRef): string {\n if (typeof ref === 'string') return ref;\n const name = (ref as { [WORKFLOW_NAME_KEY]?: string })[WORKFLOW_NAME_KEY];\n if (!name) {\n throw new Error(\n `workflow class ${ref.name} has no registered name — is it decorated with @Workflow({ name })?`,\n );\n }\n return name;\n}\n","import { currentWorkflowCtx } from './ambient-ctx';\nimport type { StartOptions } from './engine';\nimport { FatalError } from './errors';\nimport type { RunResult } from './interfaces';\nimport {\n type WorkflowClass,\n type WorkflowInputOf,\n type WorkflowOutputOf,\n workflowName,\n} from './workflow-ref';\n\n/**\n * What the class-first statics need from whoever registered the workflow class: the engine, or a\n * store-less start facade (a tenant's `DurableStartClient`). `waitForRun` is optional — a facade\n * without a store cannot wait, so `execute` outside a workflow throws a clear error there.\n */\nexport interface WorkflowStartClient {\n start(workflow: string, input: unknown, runId: string, opts?: StartOptions): Promise<RunResult>;\n waitForRun?(\n runId: string,\n opts?: { timeoutMs?: number; until?: 'settled' | 'terminal' },\n ): Promise<RunResult>;\n}\n\n/**\n * Per-process class → start-client bindings, written by the registrar at boot. On `globalThis`\n * under a `Symbol.for` key for the same duplicate-copy reason as the ambient context: every copy of\n * core in the tree must read the same map. A WeakMap so a torn-down module doesn't pin its classes.\n */\nconst BINDINGS_KEY = Symbol.for('nestjs-durable:workflow-class-bindings');\n\ntype GlobalWithBindings = typeof globalThis & {\n // biome-ignore lint/complexity/noBannedTypes: keyed by class constructors\n [BINDINGS_KEY]?: WeakMap<Function, WorkflowStartClient>;\n};\n\nconst globalRef = globalThis as GlobalWithBindings;\nif (!globalRef[BINDINGS_KEY]) {\n globalRef[BINDINGS_KEY] = new WeakMap();\n}\nconst bindings = globalRef[BINDINGS_KEY];\n\n/**\n * Bind a `@Workflow` class to the client that can start it — called by the registrar for every\n * discovered workflow at boot. This is what lets `MyWorkflow.start()` resolve THE engine that\n * registered it, with no global engine singleton (two engines in one process each bind their own\n * classes).\n */\n// biome-ignore lint/complexity/noBannedTypes: keyed by class constructors\nexport function bindWorkflowClass(ctor: Function, client: WorkflowStartClient): void {\n bindings.set(ctor, client);\n}\n\nfunction clientOf(ctor: WorkflowClass): WorkflowStartClient {\n const client = bindings.get(ctor);\n if (!client) {\n throw new Error(\n `${workflowName(ctor)} is not bound to a durable engine — the class-first statics only work after the module that registers this workflow has booted (or, in a store-less tenant worker, use the injected WorkflowService/engine facade instead).`,\n );\n }\n return client;\n}\n\n/**\n * Optional base class giving a `@Workflow` a **class-first API** — start it from anywhere without\n * injecting the engine or `WorkflowService`:\n *\n * ```ts\n * @Workflow({ name: 'checkout', version: '1' })\n * export class CheckoutWorkflow extends DurableWorkflow {\n * async run(ctx: WorkflowCtx, order: Order) { ... }\n * }\n *\n * const { runId } = await CheckoutWorkflow.start(order); // fire-and-forget, typed input\n * const result = await CheckoutWorkflow.execute(order); // run-and-await, typed output\n * ```\n *\n * Each method means the same thing everywhere; only the mechanism adapts to where you call it:\n *\n * - {@link DurableWorkflow.start | `start`} — **fire-and-forget**. Outside a workflow it is exactly\n * `engine.start` (enqueue, return `{ runId, status }` immediately). Inside a workflow body it\n * becomes `ctx.startChild` — checkpointed, replay-safe, parent-linked — same contract.\n * - {@link DurableWorkflow.execute | `execute`} — **run-and-await the typed output**. Inside a\n * workflow it is `ctx.child` (the parent suspends with zero compute and resumes with the result).\n * Outside it starts the run and waits until it settles terminally, resolving the output or\n * throwing `FatalError` when the run failed/cancelled/dead.\n *\n * Inside-ness is detected via the ambient workflow context the engine installs around every body\n * execution (see `ambient-ctx.ts`). A `@Step` handler runs on a worker, off the body's path — the\n * statics there start a TOP-LEVEL run, which is correct: a handler is not the workflow body.\n */\nexport class DurableWorkflow {\n /**\n * Fire-and-forget start — `engine.start` outside a workflow, `ctx.startChild` (parent-linked)\n * inside one. `opts.id` pins the run id (outside) / child id (inside) for idempotent starts.\n */\n static async start<C extends WorkflowClass>(\n this: C,\n input: WorkflowInputOf<C>,\n opts?: { id?: string } & StartOptions,\n ): Promise<RunResult> {\n // biome-ignore lint/complexity/noThisInStatic: the polymorphic `this` IS the subclass being started — the class name would break every subclass\n // biome-ignore lint/complexity/noUselessThisAlias: aliased ONCE on purpose so the noThisInStatic suppression lives in one place, not on every `this` use below\n const cls = this;\n const ctx = currentWorkflowCtx();\n if (ctx) {\n const runId = await ctx.startChild(cls, input, opts?.id);\n return { runId, status: 'pending' };\n }\n const runId = opts?.id ?? globalThis.crypto.randomUUID();\n return clientOf(cls).start(workflowName(cls), input, runId, opts);\n }\n\n /**\n * Run-and-await the typed output — `ctx.child` inside a workflow (suspends the parent, zero\n * compute); outside, starts the run and waits until it settles terminally. Throws `FatalError`\n * when the run does not complete. `opts.timeoutMs` bounds the OUTSIDE wait only (inside, a\n * suspended parent costs nothing — bound the child itself with `executionTimeout` instead).\n */\n static async execute<C extends WorkflowClass>(\n this: C,\n input: WorkflowInputOf<C>,\n opts?: { id?: string; timeoutMs?: number } & StartOptions,\n ): Promise<WorkflowOutputOf<C>> {\n // biome-ignore lint/complexity/noThisInStatic: the polymorphic `this` IS the subclass being run — the class name would break every subclass\n // biome-ignore lint/complexity/noUselessThisAlias: aliased ONCE on purpose so the noThisInStatic suppression lives in one place, not on every `this` use below\n const cls = this;\n const ctx = currentWorkflowCtx();\n if (ctx) return ctx.child(cls, input, opts?.id);\n const client = clientOf(cls);\n if (!client.waitForRun) {\n throw new FatalError(\n `${workflowName(cls)}.execute() outside a workflow needs a store-backed engine to await the result — this class is bound to a store-less start facade (tenant worker). Use ${workflowName(cls)}.start() and observe the run instead.`,\n 'execute_unsupported',\n );\n }\n const runId = opts?.id ?? globalThis.crypto.randomUUID();\n await client.start(workflowName(cls), input, runId, opts);\n const settled = await client.waitForRun(runId, {\n ...(opts?.timeoutMs != null ? { timeoutMs: opts.timeoutMs } : {}),\n until: 'terminal',\n });\n if (settled.status === 'completed') return settled.output as WorkflowOutputOf<C>;\n const detail = settled.error ? `: ${settled.error.message}` : '';\n throw new FatalError(\n `${workflowName(cls)} run ${runId} settled ${settled.status}${detail}`,\n settled.error?.code ?? 'execute_failed',\n );\n }\n}\n","const UNIT_MS: Record<string, number> = {\n ms: 1,\n s: 1_000,\n sec: 1_000,\n second: 1_000,\n seconds: 1_000,\n m: 60_000,\n min: 60_000,\n minute: 60_000,\n minutes: 60_000,\n h: 3_600_000,\n hr: 3_600_000,\n hour: 3_600_000,\n hours: 3_600_000,\n d: 86_400_000,\n day: 86_400_000,\n days: 86_400_000,\n w: 604_800_000,\n week: 604_800_000,\n weeks: 604_800_000,\n};\n\n/**\n * Parse a human duration to milliseconds. Accepts a number (already ms) or a string like\n * `'500ms'`, `'30s'`, `'15m'`, `'2h'`, `'7d'`, `'7 days'`.\n */\nexport function parseDuration(duration: string | number): number {\n if (typeof duration === 'number') return duration;\n const match = duration.trim().match(/^(\\d+(?:\\.\\d+)?)\\s*([a-z]+)$/i);\n if (!match) throw new Error(`invalid duration: ${duration}`);\n const value = Number(match[1]);\n const unit = (match[2] ?? '').toLowerCase();\n const factor = UNIT_MS[unit];\n if (factor === undefined) throw new Error(`unknown duration unit: ${unit}`);\n return value * factor;\n}\n","import type { StepOptions } from './interfaces';\n\n/** Delay in ms before the next retry attempt, per a step's `StepOptions` backoff config. Shared by\n * the local-step retry loop and the durable remote-step retry, so they stay consistent. */\nexport function backoffDelay(attempt: number, options?: StepOptions): number {\n const base = options?.backoffMs ?? 0;\n if (base <= 0) return 0;\n const raw = options?.backoff === 'exp' ? base * 2 ** (attempt - 1) : base;\n const capped = options?.backoffMaxMs ? Math.min(raw, options.backoffMaxMs) : raw;\n return options?.jitter ? Math.round(capped * (0.5 + Math.random() * 0.5)) : capped;\n}\n","/**\n * Wrappers around the **real execution** of a unit of durable work — a workflow turn, or a step\n * handler body. Distinct from {@link StepInterceptor} (`engine.use`), which only sees the in-process\n * `localStep` primitives (`ctx.now`, `ctx.sideEffect`, `ctx.task`'s dispatch step, saga\n * compensations): a user's `ctx.step` is ALWAYS dispatched, so its handler runs inside a transport\n * callback or a worker process where no engine is in scope at all.\n *\n * That is exactly why this registry is process-level rather than per-engine. `runStepHandler` is a\n * free function every transport shares, and a thin worker (`DurableModule` with a `connection` and\n * no `store`) holds no `WorkflowEngine` to hang a hook off. A per-engine registry could not reach\n * either, so the seam that covers every deployment shape has to sit above the engine.\n *\n * The intended consumer is an observability bridge (Telescope, OTel, a logger) that needs to\n * establish an ambient scope — an AsyncLocalStorage batch, a span — that the executing code records\n * into. It is deliberately NOT a transform point: see {@link runDurableExecution}.\n */\n\n/** The unit of durable work a wrapper is being invoked around. */\nexport interface DurableExecution {\n /** `'workflow'` = one turn of a run's body; `'step'` = one step handler body. */\n readonly unit: 'workflow' | 'step';\n readonly runId: string;\n /** The workflow name. Present on a turn; a dispatched step task does not carry it on the wire. */\n readonly workflow: string | undefined;\n /** The step name, for `unit: 'step'`. Undefined for a turn. */\n readonly name: string | undefined;\n /** The step's logical position within the run, for `unit: 'step'`. */\n readonly seq: number | undefined;\n /** 1-based dispatch attempt, when the task carries one. */\n readonly attempt: number | undefined;\n}\n\n/**\n * Wraps one unit of durable work. Call `next()` to run the body (or the next wrapper). Whatever the\n * wrapper returns or throws is discarded — see {@link runDurableExecution} for why.\n */\nexport type DurableExecutionWrapper = (\n execution: DurableExecution,\n next: () => Promise<unknown>,\n) => Promise<unknown>;\n\n/** First registered is outermost, matching `engine.use`'s onion order. */\nconst wrappers: DurableExecutionWrapper[] = [];\n\n/**\n * Register a {@link DurableExecutionWrapper}. Returns an unregister function.\n *\n * Registering is the ONLY cost an unused hook imposes: with an empty registry\n * {@link runDurableExecution} returns the body's own promise without allocating a chain, so a host\n * that wires no observability pays nothing at all on the execution path.\n */\nexport function useDurableExecution(wrapper: DurableExecutionWrapper): () => void {\n wrappers.push(wrapper);\n return () => {\n const i = wrappers.indexOf(wrapper);\n if (i >= 0) wrappers.splice(i, 1);\n };\n}\n\n/** Drop every registered wrapper. For tests that must not leak a wrapper into the next file. */\nexport function clearDurableExecutionWrappers(): void {\n wrappers.length = 0;\n}\n\n/** Whether any wrapper is registered — lets a hot path skip building an execution descriptor. */\nexport function hasDurableExecutionWrappers(): boolean {\n return wrappers.length > 0;\n}\n\n/**\n * Run `body` inside every registered wrapper and settle with **the body's own outcome**.\n *\n * The wrappers' return values and throws are deliberately ignored. An observer that misbehaves —\n * returns early without calling `next()` is the one case we cannot paper over, but one that throws\n * *after* the body settled, or swallows the body's error and returns normally, is common enough in\n * telemetry code — must not be able to change what the workflow saw. A wrapper that turned a failed\n * step into a completed one would corrupt the run's history and its checkpoints, which is a far\n * worse failure than a missing trace. This is the same reasoning the bullmq/schedule Telescope\n * watchers apply when they re-throw the host's error rather than swallowing it, pushed down into\n * the seam so every wrapper gets it for free instead of having to remember.\n *\n * The one unrecoverable case is a wrapper that never calls `next()`: the body did not run, so there\n * is no outcome to return and we throw rather than invent one.\n */\nexport async function runDurableExecution<T>(\n execution: DurableExecution,\n body: () => Promise<T>,\n): Promise<T> {\n if (wrappers.length === 0) return body();\n\n let outcome: { ok: true; value: T } | { ok: false; error: unknown } | undefined;\n const inner = async (): Promise<unknown> => {\n try {\n const value = await body();\n outcome = { ok: true, value };\n return value;\n } catch (error) {\n outcome = { ok: false, error };\n throw error;\n }\n };\n const chain = wrappers.reduceRight<() => Promise<unknown>>(\n (next, wrapper) => () => wrapper(execution, next),\n inner,\n );\n\n try {\n await chain();\n } catch (error) {\n // Only a throw from BEFORE the body ran can surface here — anything else is a wrapper's own\n // failure layered on top of a body that already settled, and the body wins below.\n if (outcome === undefined) throw error;\n }\n if (outcome === undefined) {\n throw new Error(\n 'a durable execution wrapper returned without calling next() — the unit of work never ran',\n );\n }\n if (outcome.ok) return outcome.value;\n throw outcome.error;\n}\n","import type { StepEvent, StepLogger, SubProcessHandle } from './interfaces';\n\n/** Attach the elapsed `durationMs` (from `start`) to `data`, unless the caller already set one. */\nfunction withDuration(start: number, now: () => number, data?: unknown): Record<string, unknown> {\n if (data && typeof data === 'object' && 'durationMs' in data) {\n return data as Record<string, unknown>;\n }\n const base = data && typeof data === 'object' ? (data as Record<string, unknown>) : {};\n return { ...base, durationMs: now() - start };\n}\n\n/**\n * A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the\n * local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records\n * the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's\n * `StepContext`.\n */\nexport function createStepLogger(events: StepEvent[], now: () => number): StepLogger {\n // The sub-process a `subProcess(...)` body is currently inside; debug/info/warn/error emitted while\n // inside get tagged with its id, so the dashboard groups that log trail under the sub-process.\n let currentSub: { id: string } | undefined;\n const push = (level: StepEvent['level'], message: string, data?: unknown) =>\n events.push({\n at: now(),\n level,\n message,\n ...(currentSub ? { subId: currentSub.id } : {}),\n ...(data === undefined ? {} : { data }),\n });\n const subEvent: StepLogger['subEvent'] = (e) =>\n events.push({\n at: now(),\n level: e.status === 'failed' ? 'error' : e.status === 'skipped' ? 'warn' : 'info',\n message: e.message ?? e.phase ?? e.name,\n subId: e.id,\n name: e.name,\n ...(e.group === undefined ? {} : { group: e.group }),\n ...(e.phase === undefined ? {} : { phase: e.phase }),\n ...(e.status === undefined ? {} : { status: e.status }),\n ...(e.data === undefined ? {} : { data: e.data }),\n });\n const subProcess: StepLogger['subProcess'] = async (name, body, opts) => {\n const id = opts?.id ?? globalThis.crypto.randomUUID();\n const group = opts?.group;\n const start = now();\n const prevSub = currentSub;\n currentSub = { id };\n let terminal = false;\n const emit = (status: 'ok' | 'failed' | 'skipped', message?: string, data?: unknown) => {\n if (terminal) return;\n terminal = true;\n subEvent({ id, name, group, status, message, data: withDuration(start, now, data) });\n };\n const handle: SubProcessHandle = {\n phase: (phase, data) => {\n if (!terminal) subEvent({ id, name, group, phase, data });\n return handle;\n },\n skip: (reason, data) => emit('skipped', reason, data),\n fail: (reason, data) => emit('failed', reason, data),\n };\n try {\n const result = await body(handle);\n emit('ok'); // no-op if the body already called skip()/fail()\n return result;\n } catch (err) {\n emit('failed', err instanceof Error ? err.message : String(err));\n throw err;\n } finally {\n currentSub = prevSub;\n }\n };\n return {\n debug: (m, d) => push('debug', m, d),\n info: (m, d) => push('info', m, d),\n warn: (m, d) => push('warn', m, d),\n error: (m, d) => push('error', m, d),\n sub: (name, status, message, data) =>\n events.push({\n at: now(),\n level: status === 'failed' ? 'error' : status === 'skipped' ? 'warn' : 'info',\n message: message ?? name,\n name,\n status,\n ...(data === undefined ? {} : { data }),\n }),\n subEvent,\n subProcess,\n };\n}\n","import { runOutsideWorkflowCtx } from './ambient-ctx';\nimport { runInStepLogger } from './ambient-step';\nimport { runDurableExecution } from './execution-hooks';\nimport type { RemoteTask, StepEvent, StepLogger, StepResult } from './interfaces';\nimport { createStepLogger } from './step-logger';\n\n/** Canonical step id — the stable identity of a step within a run, used for dedupe and\n * correlation. The format is part of the cross-language wire contract (Python builds the same). */\nexport function stepId(runId: string, seq: number): string {\n return `${runId}:${seq}`;\n}\n\n/** Deterministic signal token a breakpoint suspends on — derived from its logical position. Shared\n * so `ctx.breakpoint` (which records it) and `engine.continue` (which signals it) agree. */\nexport const breakpointToken = (runId: string, seq: number): string => `bp:${runId}:${seq}`;\n\n/** A remote-worker step body. The optional `log` records sub-process outcomes and debug/error\n * lines that ride back on the result — the TypeScript twin of the Python SDK's `StepContext`. */\nexport type StepHandler = (input: unknown, log: StepLogger) => Promise<unknown> | unknown;\n\n/**\n * Run `handler` for `task` and produce the wire-format {@link StepResult}. Pure (no transport,\n * no I/O beyond the handler), so every transport — and any language port — can share the exact\n * same completed / failed / no-handler contract instead of re-deriving it.\n */\nexport async function runStepHandler(\n task: RemoteTask,\n handler: StepHandler | undefined,\n): Promise<StepResult> {\n // Stamp the worker's pickup time so the engine can report queue-wait (startedAt − enqueuedAt).\n // This is the one place every transport funnels through, so timing comes for free everywhere.\n const base = { runId: task.runId, seq: task.seq, stepId: task.stepId, startedAt: Date.now() };\n if (!handler) {\n return {\n ...base,\n status: 'failed',\n error: { message: `no handler for ${task.name}`, retryable: false },\n };\n }\n const events: StepEvent[] = [];\n const withEvents = (result: StepResult): StepResult =>\n events.length > 0 ? { ...result, events } : result;\n try {\n // The SAME logger goes to the handler's second argument and into the ambient storage, so a\n // helper buried under the handler emits into this step's `events` without being handed one.\n const logger = createStepLogger(events, Date.now);\n // The registered execution wrappers go OUTSIDE the handler and INSIDE this try/catch, so an\n // observability scope opened here (a Telescope batch, an OTel span) is ambient while the handler\n // body runs — a query it issues or an exception it throws is recorded inside the scope, which is\n // the whole point. Wrapping the `runStepHandler` call from a transport instead would put the\n // scope around the result-building too, and wrapping after the fact would put it around nothing.\n const output = await runDurableExecution(\n {\n unit: 'step',\n runId: task.runId,\n workflow: undefined, // a dispatched step task does not carry its workflow name on the wire\n name: task.name,\n seq: task.seq,\n attempt: task.attempt,\n },\n // Outside any ambient workflow ctx: an in-process transport runs the handler on the parent\n // body's async path, but a handler is not the body (see `runOutsideWorkflowCtx`).\n async () =>\n runOutsideWorkflowCtx(() => runInStepLogger(logger, () => handler(task.input, logger))),\n );\n return withEvents({ ...base, status: 'completed', output });\n } catch (err) {\n // Carry `code`/`retryable` off the thrown error if present, so the engine's durable retry can\n // honour a worker's \"don't retry this\" verdict (e.g. a declined card).\n const e = err as { message?: string; code?: string; retryable?: boolean };\n return withEvents({\n ...base,\n status: 'failed',\n error: {\n message: err instanceof Error ? err.message : String(err),\n ...(typeof e?.code === 'string' ? { code: e.code } : {}),\n ...(typeof e?.retryable === 'boolean' ? { retryable: e.retryable } : {}),\n },\n });\n }\n}\n","import type { StepCheckpoint, StepError, StepEvent, StepKind } from './interfaces';\nimport { stepId } from './protocol';\n\n/**\n * The step-event names the lost-dispatch self-heal stamps on a checkpoint's trail, so an operator (and\n * the dashboard, which renders a step's events under it) can tell a re-drive apart from an ordinary\n * failure retry WITHOUT a schema change: `step.redispatched` = the dispatched job was presumed lost\n * (its lease lapsed with no result and no heartbeat) and the step was re-enqueued; `step.lost` = the\n * re-drive bound (`remoteRedispatchMax`) ran out and the step was failed `remote_step_lost`.\n */\nexport const REDISPATCHED_STEP_EVENT = 'step.redispatched';\nexport const LOST_STEP_EVENT = 'step.lost';\n\n/**\n * A `warn` step event recording a lost-dispatch re-drive (or the give-up at its bound). `attempts` is\n * the dispatch count AFTER the transition, so the trail reads as the attempt an operator sees on the\n * checkpoint.\n */\nexport function lostStepEvent(\n at: number,\n attempts: number,\n outcome: 'redispatched' | 'lost',\n): StepEvent {\n return {\n at,\n level: 'warn',\n name: outcome === 'lost' ? LOST_STEP_EVENT : REDISPATCHED_STEP_EVENT,\n message:\n outcome === 'lost'\n ? `dispatch lost and the re-drive bound is spent after ${attempts} dispatch(es) — failing the step`\n : `re-dispatched after a lost dispatch (attempt ${attempts}): the step's lease lapsed with no result and no heartbeat`,\n };\n}\n\n/** Drop an empty events array to `undefined` (the repeated `events?.length ? events : undefined`). */\nfunction nonEmptyEvents(events: StepEvent[] | undefined): StepEvent[] | undefined {\n return events && events.length > 0 ? events : undefined;\n}\n\n/**\n * Build a *phased* step checkpoint — one with distinct enqueue/run/finish timestamps (a local step\n * that is running/completed/failed, or a pending remote/sleep step). Computes the deterministic\n * `stepId` and normalizes empty event arrays, so the engine's running/completed/failed/pending\n * checkpoint literals are constructed in exactly one place instead of ~8.\n *\n * For instantaneous checkpoints (sleep timers, markers, delivered signals) use {@link instantCheckpoint}.\n */\nexport function stepCheckpoint(p: {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n status: StepCheckpoint['status'];\n attempts: number;\n enqueuedAt: Date;\n startedAt: Date;\n finishedAt: Date;\n input?: unknown;\n output?: unknown;\n error?: StepError | undefined;\n events?: StepEvent[] | undefined;\n workerGroup?: string | undefined;\n wakeAt?: number | undefined;\n parallelGroup?: string | undefined;\n}): StepCheckpoint {\n return {\n runId: p.runId,\n seq: p.seq,\n name: p.name,\n kind: p.kind,\n stepId: stepId(p.runId, p.seq),\n status: p.status,\n input: p.input,\n output: p.output,\n error: p.error,\n events: nonEmptyEvents(p.events),\n attempts: p.attempts,\n workerGroup: p.workerGroup,\n wakeAt: p.wakeAt,\n parallelGroup: p.parallelGroup,\n enqueuedAt: p.enqueuedAt,\n startedAt: p.startedAt,\n finishedAt: p.finishedAt,\n };\n}\n\n/**\n * Build an *instantaneous* checkpoint — one with no distinct enqueue/run/finish phases (a durable\n * sleep timer, a breakpoint marker, a delivered signal, a published `setEvent` value, a `patched`\n * marker). All three timestamps collapse to now and `attempts` is 1. Collapses what was five\n * near-identical 10-field `saveCheckpoint({...})` literals into one builder.\n */\nexport function instantCheckpoint(p: {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n status?: StepCheckpoint['status'];\n output?: unknown;\n wakeAt?: number;\n parallelGroup?: string | undefined;\n}): StepCheckpoint {\n const at = new Date();\n return {\n runId: p.runId,\n seq: p.seq,\n name: p.name,\n kind: p.kind,\n stepId: stepId(p.runId, p.seq),\n status: p.status ?? 'completed',\n output: p.output,\n wakeAt: p.wakeAt,\n parallelGroup: p.parallelGroup,\n attempts: 1,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n };\n}\n","import { FatalError } from './errors';\n\n/**\n * The payload an external `ctx.task` / child run delivers back on its completion signal: either a\n * value or a failure. One typed envelope so `task` and `child` share the same unwrap (instead of\n * sniffing ad-hoc `__error` keys).\n */\nexport type Completion<T> = { ok: true; value: T } | { ok: false; error: string };\n\n/** Whether a signal payload is a failed `Completion`. */\nexport function isFailedCompletion(payload: unknown): boolean {\n const c = payload as Completion<unknown> | null;\n return !!c && typeof c === 'object' && 'ok' in c && c.ok === false;\n}\n\n/** Read a `Completion` from a signal payload: return the value, or throw a FatalError if it failed. */\nexport function unwrapCompletion<T>(payload: unknown, label: string): T {\n const c = payload as Completion<T> | null;\n if (c && typeof c === 'object' && 'ok' in c && c.ok === false) {\n throw new FatalError(`${label} failed: ${c.error}`);\n }\n return (c as { value: T } | null)?.value as T;\n}\n","import { ConcurrencyLimitError } from './errors';\nimport type { RunQuery, RunStatus, StateStore } from './interfaces';\n\n/**\n * A start-time concurrency quota for ONE start: at most `limit` runs sharing `key` may be in flight\n * (in `countStatuses`) at once; a start that would exceed it is rejected with\n * {@link ConcurrencyLimitError} before any run is created.\n *\n * The key is global — not per workflow — so different workflows started with the same key share the\n * quota (e.g. `tenant:acme` capping every kind of run a tenant can have executing). Passed per start\n * as `StartOptions.concurrency`, or derived from the input by a workflow's {@link ConcurrencyConfig}.\n */\nexport interface ConcurrencyQuota {\n /** The quota bucket, e.g. `tenant:acme`. Stamped on the run as the tag `concurrency:<key>`. */\n key: string;\n /** Max runs of this key in flight at once. `limit <= 0` rejects every start. */\n limit: number;\n /**\n * Which statuses occupy a slot. Default: every non-terminal status\n * ({@link DEFAULT_CONCURRENCY_STATUSES}). Narrow it to e.g. `['pending', 'running']` so runs parked\n * on a human (`suspended`) stop counting against the quota.\n */\n countStatuses?: RunStatus[] | undefined;\n}\n\n/**\n * A workflow's standing concurrency quota, declared at registration (`register(..., { concurrency })`\n * / `@Workflow({ concurrency })`): the key is derived from each start's input, and the limit may be a\n * function of the key (per-tenant plans). A `StartOptions.concurrency` on one start overrides it.\n */\nexport interface ConcurrencyConfig {\n /** Derive the quota key from the input. Return `undefined` to leave this start unlimited. */\n key: (input: unknown) => string | undefined;\n /** Max in-flight runs per key — a number, or resolved per key (e.g. from the tenant's plan). */\n limit: number | ((key: string) => number | Promise<number>);\n /** Which statuses occupy a slot. See {@link ConcurrencyQuota.countStatuses}. */\n countStatuses?: RunStatus[] | undefined;\n}\n\n/** Every non-terminal status: what \"in flight\" means when a quota doesn't narrow it. */\nexport const DEFAULT_CONCURRENCY_STATUSES: readonly RunStatus[] = [\n 'pending',\n 'running',\n 'suspended',\n 'cancelling',\n 'blocked',\n];\n\n/** The tag a quota-bearing run carries, so its siblings can be counted by one tag+status query. */\nexport function concurrencyTag(key: string): string {\n return `concurrency:${key}`;\n}\n\n/** Resolve the quota that applies to one start: the per-start override, else the workflow's config. */\nexport async function resolveConcurrency(\n override: ConcurrencyQuota | undefined,\n config: ConcurrencyConfig | undefined,\n input: unknown,\n): Promise<ConcurrencyQuota | undefined> {\n if (override) return override;\n if (!config) return undefined;\n const key = config.key(input);\n if (key === undefined) return undefined;\n const limit = typeof config.limit === 'function' ? await config.limit(key) : config.limit;\n return { key, limit, countStatuses: config.countStatuses };\n}\n\n/** Count the runs matching `query` as cheaply as the store allows (count → facets → listing). */\nexport async function countRuns(\n store: StateStore,\n query: Omit<RunQuery, 'limit' | 'offset'>,\n): Promise<number> {\n if (store.countRuns) return store.countRuns(query);\n if (store.runFacets && !query.status && !query.statuses && query.origin === undefined) {\n const cells = await store.runFacets(query);\n return cells.reduce((sum, c) => sum + c.count, 0);\n }\n if (store.runFacets && query.statuses && !query.status && query.origin === undefined) {\n const { statuses, ...rest } = query;\n const cells = await store.runFacets(rest);\n return cells.filter((c) => statuses.includes(c.status)).reduce((sum, c) => sum + c.count, 0);\n }\n return (await store.listRuns(query)).length;\n}\n\n/**\n * Reject a start that would exceed `quota`: counts the in-flight runs carrying the quota's tag and\n * throws {@link ConcurrencyLimitError} once they reach the limit.\n *\n * A SOFT cap under a race: the count and the run's creation are separate statements, so N starts\n * racing on the last free slot can each see it free (the same guarantee a hand-rolled\n * `SELECT count(*)` gate gives). It is exact whenever starts for a key are not simultaneous, and the\n * overshoot is bounded by the number of truly concurrent starts. Use `singleton` when you need a\n * strict, queueing per-key limit instead of a rejecting one.\n */\nexport async function assertConcurrency(\n store: StateStore,\n workflow: string,\n quota: ConcurrencyQuota,\n): Promise<void> {\n const active =\n quota.limit <= 0\n ? 0\n : await countRuns(store, {\n tag: concurrencyTag(quota.key),\n statuses: [...(quota.countStatuses ?? DEFAULT_CONCURRENCY_STATUSES)],\n });\n if (quota.limit <= 0 || active >= quota.limit) {\n throw new ConcurrencyLimitError(workflow, quota.key, quota.limit, active);\n }\n}\n","import { FatalError } from './errors';\nimport type { InternalWorkflowCtx } from './workflow-ctx';\n\n/** One operation on a durable entity: mutate `state` in place and/or return a result. */\nexport type EntityHandler<S = unknown> = (state: S, arg: unknown) => unknown | Promise<unknown>;\n\n/** A durable keyed entity (a virtual object): per-key serialized handlers over durable state. */\nexport interface EntityConfig<S = unknown> {\n /** Build the initial state for a fresh key. */\n initialState: () => S;\n /** Operation handlers, keyed by op name. Each runs serially per key, exactly once. */\n handlers: Record<string, EntityHandler<S>>;\n}\n\n/** The slice of the engine the entity subsystem needs (so it stays a standalone module). */\nexport interface EntityHost {\n register(\n name: string,\n version: string,\n fn: (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>,\n ): void;\n signalWithStart(\n workflow: string,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n ): Promise<{ runId: string }>;\n getEvent<T>(runId: string, key: string): Promise<T | undefined>;\n signal(token: string, payload: unknown): Promise<unknown>;\n}\n\nconst ENTITY_WORKFLOW = '__entity';\nconst entityRunId = (name: string, key: string): string => `entity:${name}:${key}`;\n\n/**\n * Durable keyed **entities** (virtual objects): a keyed actor whose handlers run **serialized per\n * key** over **durable state**, exactly once. Each key is one long-lived run (`entity:<name>:<key>`)\n * processing ops in order. Drive it with `signal` (fire) or `ctx.callEntity` (call + await result),\n * read state with `getState`. Registers its built-in runner on construction.\n */\nexport class Entities {\n private readonly configs = new Map<string, EntityConfig>();\n\n constructor(private readonly host: EntityHost) {\n host.register(ENTITY_WORKFLOW, '1', (ctx, input) => this.run(ctx, input));\n }\n\n register<S>(name: string, config: EntityConfig<S>): void {\n this.configs.set(name, config as EntityConfig);\n }\n\n /** Deliver an op to an entity's runner, starting it on first contact. `reply` (a signal token)\n * receives the handler's result, for `ctx.callEntity`. */\n dispatch(\n name: string,\n key: string,\n op: string,\n arg: unknown,\n reply?: string,\n ): Promise<{ runId: string }> {\n const runId = entityRunId(name, key);\n return this.host.signalWithStart(ENTITY_WORKFLOW, { name, key }, runId, {\n token: runId,\n payload: { op, arg, reply },\n });\n }\n\n async signal(name: string, key: string, op: string, arg?: unknown): Promise<void> {\n await this.dispatch(name, key, op, arg);\n }\n\n getState<S = unknown>(name: string, key: string): Promise<S | undefined> {\n return this.host.getEvent<S>(entityRunId(name, key), 'state');\n }\n\n /** The built-in runner: one long-lived run per key, processing ops serially over state. */\n private async run(ctx: InternalWorkflowCtx, input: unknown): Promise<unknown> {\n const { name, key } = input as { name: string; key: string };\n const config = this.configs.get(name);\n if (!config) throw new FatalError(`entity \"${name}\" is not registered`);\n const token = entityRunId(name, key);\n let state = config.initialState();\n for (let i = 0; ; i += 1) {\n const msg = (await ctx.waitForSignal(token)) as { op: string; arg: unknown; reply?: string };\n // Run the handler and snapshot the (possibly mutated) state in ONE checkpoint, so replay\n // restores the state from the checkpoint instead of re-running the handler. `ctx.step` is now\n // ALWAYS dispatched (see WorkflowCtx.step) — this in-process capture uses the internal\n // `localStep` primitive instead (same checkpointed-once-then-replayed semantics).\n const out = await ctx.localStep(`op:${i}`, async () => {\n const handler = config.handlers[msg.op];\n if (!handler) throw new FatalError(`entity \"${name}\" has no handler for op \"${msg.op}\"`);\n const result = await handler(state, msg.arg);\n return { result, state };\n });\n state = out.state; // carry state forward (and restore it from the checkpoint on replay)\n await ctx.setEvent('state', state); // publish for getState\n if (msg.reply) {\n await ctx.localStep(`reply:${i}`, async () => {\n await this.host.signal((msg as { reply: string }).reply, out.result);\n });\n }\n }\n }\n}\n","import { SignalTimeoutError } from './errors';\nimport type { WorkflowCtx } from './interfaces';\n\n/** How `onEvent` triggers are coalesced into fewer runs (see `@Workflow({ debounce | batch })`). */\nexport type EventBatchConfig =\n | { mode: 'debounce'; windowMs: number }\n | { mode: 'batch'; maxSize: number; windowMs: number };\n\n/** The slice of the engine the accumulators need (so they stay a standalone module). */\nexport interface AccumulatorHost {\n register(\n name: string,\n version: string,\n fn: (ctx: WorkflowCtx, input: unknown) => Promise<unknown>,\n ): void;\n signalWithStart(\n workflow: string,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n ): Promise<{ runId: string }>;\n}\n\nconst accToken = (target: string): string => `__evtacc__:${target}`;\n\n/**\n * Built-in workflows that coalesce `onEvent` triggers. Each is a long-lived per-target accumulator\n * fed by `signalWithStart`: it collects payloads then starts the target once, and `continueAsNew`s to\n * re-arm for the next burst. Signal buffering keeps the re-arm race-free. Registers its runners on\n * construction.\n */\nexport class EventAccumulators {\n constructor(private readonly host: AccumulatorHost) {\n host.register('__evt_debounce', '1', (ctx, input) => this.debounce(ctx, input));\n host.register('__evt_batch', '1', (ctx, input) => this.batch(ctx, input));\n }\n\n /** Route an `onEvent` payload into its target's debounce/batch accumulator. */\n route(target: string, config: EventBatchConfig, payload: unknown): Promise<{ runId: string }> {\n const [workflow, input] =\n config.mode === 'debounce'\n ? (['__evt_debounce', { target, windowMs: config.windowMs }] as const)\n : ([\n '__evt_batch',\n { target, maxSize: config.maxSize, windowMs: config.windowMs },\n ] as const);\n return this.host.signalWithStart(workflow, input, accToken(target), {\n token: accToken(target),\n payload,\n });\n }\n\n /** Fire the target with the LAST payload once events have been quiet for `windowMs`. */\n private async debounce(ctx: WorkflowCtx, input: unknown): Promise<unknown> {\n const { target, windowMs } = input as { target: string; windowMs: number };\n const token = accToken(target);\n let last = await ctx.waitForSignal(token); // park for the first event of a burst\n for (;;) {\n try {\n last = await ctx.waitForSignal(token, { timeoutMs: windowMs }); // extend on each event\n } catch (e) {\n if (e instanceof SignalTimeoutError) break; // quiet for `windowMs` → fire\n throw e; // WorkflowSuspended / ContinueAsNew etc. must propagate\n }\n }\n await ctx.startChild(target, last);\n return ctx.continueAsNew(input); // re-arm\n }\n\n /** Fire the target with all payloads (`{ events }`) once `maxSize` or `windowMs` from the first. */\n private async batch(ctx: WorkflowCtx, input: unknown): Promise<unknown> {\n const { target, maxSize, windowMs } = input as {\n target: string;\n maxSize: number;\n windowMs: number;\n };\n const token = accToken(target);\n const events: unknown[] = [await ctx.waitForSignal(token)]; // park for the first\n const deadline = (await ctx.now()) + windowMs;\n while (events.length < maxSize) {\n const remaining = deadline - (await ctx.now());\n if (remaining <= 0) break;\n try {\n events.push(await ctx.waitForSignal(token, { timeoutMs: remaining }));\n } catch (e) {\n if (e instanceof SignalTimeoutError) break; // window elapsed → fire what we have\n throw e; // WorkflowSuspended / ContinueAsNew etc. must propagate\n }\n }\n await ctx.startChild(target, { events });\n return ctx.continueAsNew(input); // re-arm\n }\n}\n","// Named events: pub/sub on top of the signal-waiter table. A `ctx.waitForEvent(name, { match })`\n// registers a signal waiter whose token encodes the event name + match criteria (base64 so they\n// never contain the `:` delimiter); `engine.publishEvent(name, payload)` lists the waiters for that\n// name by token prefix, checks each one's match against the payload, and signals the ones that pass.\n// No schema change beyond a `listSignalWaiters(prefix)` store method.\n\nconst enc = (s: string): string => Buffer.from(s, 'utf8').toString('base64');\nconst dec = (s: string): string => Buffer.from(s, 'base64').toString('utf8');\n\n/**\n * How many candidates a buffered-event scan considers (`listBufferedEvents(name, limit)`) before\n * giving up. An event's buffer is keyed by `name` only (see {@link eventMatches}'s match-based\n * consumption), so a hot name with many distinct payloads sitting unclaimed could in principle\n * accumulate an unbounded backlog; this caps the per-scan cost regardless. Shared by the workflow-ctx\n * consumer and the engine's reconcile sweep so both see the same window.\n */\nexport const EVENT_BUFFER_SCAN_LIMIT = 50;\n\n/** The literal prefix EVERY event-waiter token starts with, regardless of `name` — `eventPrefix(name)`\n * always begins with this; exported so a caller that only needs to CLASSIFY a token (not fan out a\n * specific name) doesn't have to re-derive or duplicate the literal (see run-waiting.ts's own copy,\n * kept in sync with this one, and engine.ts's reconcile sweep). */\nexport const EVENT_TOKEN_PREFIX = 'event:';\n\n/** Token prefix for every waiter on `name` — used by `listSignalWaiters` to fan an event out. */\nexport function eventPrefix(name: string): string {\n return `${EVENT_TOKEN_PREFIX}${enc(name)}:`;\n}\n\n/** Whether `token` is an event-waiter token (vs. a plain signal / child / webhook / breakpoint one). */\nexport function isEventToken(token: string): boolean {\n return token.startsWith(EVENT_TOKEN_PREFIX);\n}\n\n/** Build the unique waiter token for one `waitForEvent` call (name + match + run position). */\nexport function eventToken(\n name: string,\n match: Record<string, unknown> | undefined,\n runId: string,\n seq: number,\n): string {\n return `${eventPrefix(name)}${enc(JSON.stringify(match ?? {}))}:${runId}#${seq}`;\n}\n\n/** The event name embedded in an event waiter token (the 2nd `:`-segment is the base64 name), so a\n * dashboard can show \"waiting on event `<name>`\" instead of the opaque token. */\nexport function eventNameOf(token: string): string {\n try {\n return dec(token.split(':')[1] ?? '');\n } catch {\n return token;\n }\n}\n\n/** The match criteria embedded in an event waiter token (the 3rd `:`-segment is the base64 match). */\nexport function eventMatchOf(token: string): Record<string, unknown> {\n try {\n return JSON.parse(dec(token.split(':')[2] ?? '')) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/** Whether `payload` satisfies a waiter's `match`: every match key deep-equals the payload's value. */\nexport function eventMatches(payload: unknown, match: Record<string, unknown>): boolean {\n const keys = Object.keys(match);\n if (keys.length === 0) return true; // no criteria → matches any payload of this name\n if (!payload || typeof payload !== 'object') return false;\n const p = payload as Record<string, unknown>;\n return keys.every((k) => JSON.stringify(p[k]) === JSON.stringify(match[k]));\n}\n","import type { FanJoin, FanWait } from './errors';\nimport type { SignalWaiter } from './interfaces';\n\n/**\n * Naming shared by `ctx.all` (which mints the ids) and the engine's join barrier (which reads them\n * back off a settling child's waiter). The child id and group are replay anchors: changing either\n * shape strands every run suspended on a fan.\n *\n * An unbounded fan names its children `<runId>.all.<firstSeq>.<i>`. A fan with a `concurrency` limit\n * dispatches in waves and puts the wave in the id, `<runId>.all.<firstSeq>.w<k>.<i>`, so the barrier\n * can wait on one wave at a time.\n */\nexport function allChildId(runId: string, firstSeq: number, index: number, wave?: number): string {\n return `${allBase(runId, firstSeq, wave)}${index}`;\n}\n\n/** The fan's `parallelGroup`. A failFast fan is marked so the barrier wakes it on the first failure. */\nexport function allGroup(firstSeq: number, mode: 'waitAll' | 'failFast'): string {\n return mode === 'failFast' ? `all:${firstSeq}:failFast` : `all:${firstSeq}`;\n}\n\n/** The waiter and checkpoint name prefixes shared by a fan's children, or one wave's. */\nexport function allWait(runId: string, firstSeq: number, wave?: number): FanWait {\n const base = allBase(runId, firstSeq, wave);\n return { waiterPrefix: `child:${base}`, checkpointPrefix: `signal:child:${base}` };\n}\n\nexport function fanJoin(waits: FanWait[]): FanJoin {\n return { waits };\n}\n\n/**\n * A settled group of children (a fan, or one wave of it) folded into a single checkpoint:\n * `fan:<child id base>`, at the first child's seq. `values` are the children's outputs in input\n * order, starting at input index `from`.\n */\nexport const FOLDED_PREFIX = 'fan:';\n\nexport interface FoldedChildren {\n from: number;\n values: unknown[];\n}\n\nexport function allFoldedName(runId: string, firstSeq: number, wave?: number): string {\n return `${FOLDED_PREFIX}${allBase(runId, firstSeq, wave)}`;\n}\n\n/** The child run ids a folded checkpoint stands for. */\nexport function foldedChildIds(checkpoint: { name: string; output?: unknown }): string[] {\n const base = checkpoint.name.slice(FOLDED_PREFIX.length);\n const { from, values } = checkpoint.output as FoldedChildren;\n return values.map((_, j) => `${base}${from + j}`);\n}\n\nfunction allBase(runId: string, firstSeq: number, wave?: number): string {\n return wave === undefined ? `${runId}.all.${firstSeq}.` : `${runId}.all.${firstSeq}.w${wave}.`;\n}\n\n/**\n * How a fan of `size` children is dispatched under a `concurrency` limit: waves of `waveSize`, at\n * most `maxWaves` of them unsettled at once, so no more than `concurrency` children run together.\n * Half-size waves let the next wave start while the slowest children of the previous one finish.\n * Undefined when the limit does not bind, which keeps the unbounded fan's ids.\n */\nexport function allWaves(\n size: number,\n concurrency: number | undefined,\n): { waveSize: number; maxWaves: number } | undefined {\n if (concurrency === undefined || concurrency >= size) return undefined;\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new Error(`ctx.all: concurrency must be a positive integer, got ${concurrency}`);\n }\n // Two half-size waves in flight: an odd limit runs one child under it, rather than leaving a whole\n // wave's worth of the window idle.\n if (concurrency === 1) return { waveSize: 1, maxWaves: 1 };\n return { waveSize: Math.floor(concurrency / 2), maxWaves: 2 };\n}\n\nconst ENGINE_CHILD_ID = /^(.+)\\.(?:all\\.\\d+\\.(?:w\\d+\\.)?\\d+|child\\.\\d+)$/;\n\n/**\n * The parent of a child run whose id the engine minted: a `ctx.all` child\n * (`<parent>.all.<seq>.<i>`, or `.w<k>.<i>` under a `concurrency` limit) or a `ctx.child` /\n * `ctx.startChild` child without an explicit id (`<parent>.child.<seq>`). Undefined for any other\n * run, including a child started with a caller-chosen id.\n */\nexport function parentRunIdOf(runId: string): string | undefined {\n return ENGINE_CHILD_ID.exec(runId)?.[1];\n}\n\nconst GROUP = /^all:(\\d+)(:failFast)?$/;\nconst REST = /^(?:w(\\d+)\\.)?\\d+$/;\n\n/**\n * The `ctx.all` fan (or, for a fan with a `concurrency` limit, the wave) a waiter belongs to, or\n * undefined for any other waiter (a lone `ctx.child`, a signal, a remote `gather_children`).\n * Requires the token and the group to agree, so a waiter that merely looks similar never holds back\n * a wake.\n */\nexport function fanOfWaiter(\n waiter: SignalWaiter,\n): { waiterPrefix: string; failFast: boolean } | undefined {\n const group = waiter.parallelGroup ? GROUP.exec(waiter.parallelGroup) : null;\n if (!group) return undefined;\n const base = `child:${waiter.runId}.all.${group[1]}.`;\n if (!waiter.token.startsWith(base)) return undefined;\n const rest = REST.exec(waiter.token.slice(base.length));\n if (!rest) return undefined;\n const waiterPrefix = rest[1] === undefined ? base : `${base}w${rest[1]}.`;\n return { waiterPrefix, failFast: group[2] !== undefined };\n}\n","/**\n * Worker/control-plane handshake descriptor — the single source of truth for routing, compatibility\n * and observability across a store-less durable cluster (design §7.1). Pure data + a deterministic,\n * order-insensitive content hash; NO transport, NO I/O. Every field is part of the cross-language\n * wire contract — the adonis + python SDKs build the byte-identical shape (design §7.8), and the\n * golden fixtures in `<repo>/fixtures/wire/` pin the exact bytes all three SDKs must agree on.\n */\n\n/**\n * One workflow a worker ANNOUNCES it can execute — the richer form of a `workflows` name.\n *\n * The rule is \"announce only what you can run\": a process publishes a registration for a workflow\n * whose body it holds and whose queue it consumes. It never publishes one for a workflow it merely\n * knows how to *route to* (an engine's `registerRemote`), because that claim says nothing about a\n * live executor existing — which is precisely the ambiguity an aggregate registry has to remove.\n *\n * Every field but `name` is optional because the SDKs hold different amounts of this. A worker that\n * knows only names (the Python `@worker.workflow(\"x\")` form, or any pre-registrations SDK) publishes\n * bare `workflows` names instead and is still a first-class announcer — see {@link WorkerDescriptor.registrations}.\n * A reader must therefore treat an absent field as \"not stated\", never as a value: the aggregate in\n * `./announced` never invents a version, a group or an origin that nobody announced.\n */\nexport interface WorkflowRegistration {\n /** Registered workflow name — the `workflow` a {@link WorkflowTask} carries. */\n name: string;\n /** Registered version, when the announcer knows one. Absent = unversioned announcement. */\n version?: string;\n /** The routing token this workflow's turns are dispatched to (the queue this worker consumes for\n * it). Absent = the announcer did not say; a reader must NOT assume the by-convention token. */\n group?: string;\n /** Capabilities a worker must advertise to run it (design §7.5), as the announcer declares them. */\n requires?: string[];\n /** The package that DECLARED the workflow (see `WorkflowRun.origin`). Absent = unknown; nothing\n * ever substitutes a default, because a wrong origin is worse than no origin. */\n origin?: string;\n}\n\n/**\n * A worker's (or control-plane's) advertised identity, wire-protocol support, feature capabilities\n * and registered handlers. Published on startup + on change (design §7.2) and consumed by\n * {@link negotiate} (compat) and the capability-aware router (design §7.5). Exactly the §7.1 shape.\n */\nexport interface WorkerDescriptor {\n /** Stable id for this process in the fleet (mirrors aviary's per-instance heartbeat key). */\n instanceId: string;\n /** Execution runtime — a `python` worker and a `node` control-plane interoperate over the wire. */\n runtime: 'node' | 'python';\n /** Which SDK + version produced this descriptor. Observability only; never gates dispatch. */\n sdk: { name: string; version: string };\n /**\n * Wire-protocol majors this side speaks. `version` is its preferred/current major; `range` is the\n * inclusive `[min, max]` band it can negotiate down/up to. Overlap of two ranges is what makes two\n * sides compatible (design §7.4); `version` is informational.\n */\n protocol: { version: number; range: [number, number] };\n /** Named features advertised: `'saga'`, `'signals'`, `'search-attr-v2'`, `'priority'`, … A modern\n * worker MAY advertise `[]` (no named features); an ABSENT field means \"legacy v1\" — see\n * {@link normalizeDescriptor}. Order-insensitive: treated as a set. */\n capabilities: string[];\n /** Registered workflow handler names → routing targets. Order-insensitive (a set). */\n workflows: string[];\n /** Registered step handler names → routing targets. Order-insensitive (a set). */\n steps: string[];\n /**\n * The richer, per-workflow ANNOUNCEMENT of what this instance can execute (name + version + group\n * + requires + origin). OPTIONAL and purely additive: an SDK that has only names keeps publishing\n * {@link workflows} and is aggregated all the same, just unversioned. An SDK that publishes this\n * SHOULD also list the same names in {@link workflows}, so a reader that predates this field still\n * sees the workflow at all.\n *\n * It rides the descriptor rather than a registry of its own so it inherits the whole liveness\n * story for free: the descriptor key is written with the heartbeat's TTL and refreshed by the same\n * beat, so an announcement from a worker that has since died EXPIRES instead of offering a choice\n * that fails at run time.\n */\n registrations?: WorkflowRegistration[];\n /** Optional routing partition (queue/group sharding). */\n partition?: string;\n /** Optional tenant namespace this instance serves. */\n namespace?: string;\n /** Process start time (epoch ms) — a restart changes it, so it participates in the content hash. */\n startedAt: number;\n}\n\n/**\n * The current wire-protocol major. The whole protocol as it exists today is defined as **v1**; the\n * handshake exists so a future **v2 breaking change** is detectable rather than silently corrupting\n * (design §7.7).\n */\nexport const CURRENT_PROTOCOL_VERSION = 1;\n\n/**\n * The protocol band assumed for a descriptor that omits `protocol` entirely — an existing aviary\n * worker that predates the handshake. Absence = **legacy v1 baseline, assume compatible** (§7.7).\n */\nexport const LEGACY_V1_PROTOCOL: WorkerDescriptor['protocol'] = { version: 1, range: [1, 1] };\n\n/**\n * The feature set a legacy (pre-handshake) worker is assumed to advertise when its `capabilities`\n * field is ABSENT. These are the durable primitives aviary has shipped since v1, so a legacy worker\n * can still be routed work that `requires` them (design §7.5/§7.7).\n *\n * CROSS-SDK CONTRACT — this list is the canonical \"what a v1 worker can do\" baseline and MUST stay\n * byte-identical across the adonis + nestjs + python SDKs. It is the ACTUAL aviary durable v1\n * execution surface (each name maps to a shipped primitive: saga/compensation, signals,\n * search-attributes, priority/fairness, entities, child-workflows, singleton gating, cron schedules,\n * continue-as-new, queries, cooperative cancellation). `search-attr-v2` is a MODERN capability layered\n * on top and is deliberately NOT in the v1 baseline — a v1 worker only guarantees the v1\n * `search-attributes` surface.\n */\nexport const LEGACY_V1_CAPABILITIES: readonly string[] = Object.freeze([\n 'saga',\n 'signals',\n 'search-attributes',\n 'priority',\n 'entities',\n 'child-workflows',\n 'singleton',\n 'schedules',\n 'continue-as-new',\n 'queries',\n 'cancellation',\n]);\n\n/**\n * A raw, possibly-partial descriptor as it may arrive off the wire from an older SDK: `protocol`\n * and/or `capabilities` may be missing. {@link normalizeDescriptor} fills the legacy-v1 defaults.\n */\nexport type RawWorkerDescriptor = Omit<Partial<WorkerDescriptor>, 'instanceId' | 'runtime'> & {\n instanceId: string;\n runtime: 'node' | 'python';\n};\n\n/**\n * True when a descriptor predates the handshake — it carries no `protocol` field. Such a descriptor\n * is treated as legacy v1 and assumed compatible (design §7.7).\n */\nexport function isLegacyDescriptor(raw: RawWorkerDescriptor | WorkerDescriptor): boolean {\n return (raw as Partial<WorkerDescriptor>).protocol === undefined;\n}\n\n/**\n * Fill legacy-v1 defaults so downstream logic always sees a complete {@link WorkerDescriptor}:\n * - absent `protocol` → {@link LEGACY_V1_PROTOCOL} (assume-compatible v1 baseline),\n * - absent `capabilities` → {@link LEGACY_V1_CAPABILITIES} (a modern `[]` is preserved as-is),\n * - absent `workflows`/`steps` → `[]`, absent `sdk` → an `unknown` marker, absent `startedAt` → `0`.\n *\n * The undefined-vs-`[]` distinction is deliberate: an absent field means \"legacy, doesn't advertise\n * this axis\"; an explicit empty array means \"modern SDK that genuinely advertises nothing\". The same\n * reasoning keeps `registrations` ABSENT when it was absent (rather than defaulting to `[]`): \"this\n * SDK does not announce registrations\" and \"this SDK announces none\" are different facts, and only\n * the second one licenses a reader to conclude the worker serves nothing. (No SDK publishes `[]`\n * today — {@link describeWorker} and the Python builder both OMIT the field when there is nothing to\n * announce, so a worker with no workflows keeps its pre-announcement bytes and ETag — but a reader\n * must not collapse the two cases on that basis.)\n */\nexport function normalizeDescriptor(raw: RawWorkerDescriptor | WorkerDescriptor): WorkerDescriptor {\n return {\n instanceId: raw.instanceId,\n runtime: raw.runtime,\n sdk: raw.sdk ?? { name: 'unknown', version: '0' },\n protocol: raw.protocol ?? { ...LEGACY_V1_PROTOCOL },\n capabilities: raw.capabilities ?? [...LEGACY_V1_CAPABILITIES],\n workflows: raw.workflows ?? [],\n steps: raw.steps ?? [],\n ...(raw.registrations !== undefined ? { registrations: raw.registrations } : {}),\n ...(raw.partition !== undefined ? { partition: raw.partition } : {}),\n ...(raw.namespace !== undefined ? { namespace: raw.namespace } : {}),\n startedAt: raw.startedAt ?? 0,\n };\n}\n\n/**\n * Compact, liveness lifecycle status carried on the cheap steady-state heartbeat (design §7.2).\n * Distinct from aviary's rich `WorkerStatus` object (owned by the transport layer): this is the\n * lightweight two-tier advertisement, whose job is to carry the {@link descriptorHash} ETag.\n */\nexport type WorkerLifecycle = 'up' | 'draining' | 'quiescing' | 'stopped';\n\n/**\n * The two-tier heartbeat payload (design §7.2): a cheap `{ ts, status, descriptorHash }` beaten every\n * ~10s. The `descriptorHash` is an **ETag** — the control-plane re-reads the full (expensive)\n * descriptor only when this hash changes, keeping steady-state chatter tiny.\n */\nexport interface HeartbeatStatus {\n /** Beat time, epoch ms. */\n ts: number;\n /** Compact lifecycle status. */\n status: WorkerLifecycle;\n /** ETag over the full descriptor — see {@link descriptorHash}. */\n descriptorHash: string;\n}\n\n/**\n * Canonical, order-insensitive projection of the `registrations` announcement: each entry gets a\n * FIXED key order with absent fields collapsed to `null` (so present-with-undefined and absent\n * agree), `requires` sorted + de-duplicated, and the entries themselves de-duplicated and sorted by\n * their own canonical JSON. Announcement order therefore cannot change the hash — only the announced\n * CONTENT can, which is exactly when a control plane should re-read.\n */\nfunction canonicalizeRegistrations(regs: readonly WorkflowRegistration[]): unknown[] {\n const canonical = regs.map((r) => ({\n name: r.name,\n version: r.version ?? null,\n group: r.group ?? null,\n requires: r.requires ? [...new Set(r.requires)].sort() : null,\n origin: r.origin ?? null,\n }));\n const byJson = new Map<string, unknown>();\n for (const entry of canonical) byJson.set(JSON.stringify(entry), entry);\n return [...byJson.keys()].sort().map((k) => byJson.get(k));\n}\n\n/** Canonical, order-insensitive projection of a descriptor used for hashing. The three set-valued\n * fields are sorted + de-duplicated so member order can never change the hash; scalar fields are\n * taken verbatim; optional fields collapse to `null` so present-with-undefined and absent agree.\n *\n * `registrations` is the ONE key emitted conditionally: a descriptor that does not announce them\n * hashes to BYTE-IDENTICAL bytes as before this field existed, so every already-published ETag —\n * and the pinned cross-language golden hash — is unchanged. A descriptor that DOES announce them\n * hashes differently, which is the point: changing what a worker serves must change its ETag. */\nfunction canonicalizeForHash(d: WorkerDescriptor): unknown {\n const set = (xs: string[]): string[] => [...new Set(xs)].sort();\n // Keys are emitted in a FIXED order (this literal's order) so the stringify below is stable\n // regardless of the input object's key insertion order.\n return {\n instanceId: d.instanceId,\n runtime: d.runtime,\n sdk: { name: d.sdk.name, version: d.sdk.version },\n protocol: { version: d.protocol.version, range: [d.protocol.range[0], d.protocol.range[1]] },\n capabilities: set(d.capabilities),\n workflows: set(d.workflows),\n steps: set(d.steps),\n ...(d.registrations !== undefined\n ? { registrations: canonicalizeRegistrations(d.registrations) }\n : {}),\n partition: d.partition ?? null,\n namespace: d.namespace ?? null,\n startedAt: d.startedAt,\n };\n}\n\n/**\n * Deterministic 64-bit FNV-1a hash of a string → 16-char lowercase hex. Chosen over a crypto digest\n * because it is trivially reproducible in every SDK (TS/Python/…) with no dependency, keeping the\n * ETag scheme portable for cross-language conformance (design §7.8).\n */\nfunction fnv1a64Hex(input: string): string {\n const OFFSET = 0xcbf29ce484222325n;\n const PRIME = 0x100000001b3n;\n const MASK = 0xffffffffffffffffn;\n let hash = OFFSET;\n for (let i = 0; i < input.length; i += 1) {\n hash ^= BigInt(input.charCodeAt(i) & 0xff);\n // charCodeAt can exceed a byte; fold the high byte in too so non-ASCII still contributes.\n hash ^= BigInt((input.charCodeAt(i) >> 8) & 0xff);\n hash = (hash * PRIME) & MASK;\n }\n return hash.toString(16).padStart(16, '0');\n}\n\n/**\n * Stable ETag over a descriptor's content (design §7.2). **Order-insensitive** over the set-valued\n * fields (`capabilities`/`workflows`/`steps`) — the same members in any order yield the same hash —\n * and stable across the object's key insertion order. Any change to a routing/compat-relevant field\n * (including `startedAt` on restart) changes the hash, which is what triggers a full re-read.\n *\n * Accepts a raw/partial descriptor too: it is normalized first, so a legacy descriptor hashes as its\n * v1 baseline.\n */\nexport function descriptorHash(descriptor: RawWorkerDescriptor | WorkerDescriptor): string {\n const canonical = canonicalizeForHash(normalizeDescriptor(descriptor));\n return fnv1a64Hex(JSON.stringify(canonical));\n}\n\n/**\n * Build the compact two-tier heartbeat for a descriptor, stamping the ETag (design §7.2). `ts`\n * defaults to now and `status` to `'up'`.\n */\nexport function heartbeatStatus(\n descriptor: RawWorkerDescriptor | WorkerDescriptor,\n opts: { ts?: number; status?: WorkerLifecycle } = {},\n): HeartbeatStatus {\n return {\n ts: opts.ts ?? Date.now(),\n status: opts.status ?? 'up',\n descriptorHash: descriptorHash(descriptor),\n };\n}\n\n/**\n * Build a worker's own {@link WorkerDescriptor} in the exact §7.1 shape every SDK publishes — the\n * single builder both TS advertisers use (the BullMQ transport's in-app worker and the standalone\n * `runRedisWorker`), so two processes in the same fleet cannot drift into two dialects of the same\n * wire.\n *\n * Set-valued fields are sorted here (not just in the hash projection) so the published BYTES are\n * stable across registration order too — a re-registration in a different order must not look like a\n * change to a reader diffing the raw value. `partition` and `namespace` are omitted when empty, and\n * `namespace` additionally when it is `default`, keeping a single-tenant deployment byte-identical\n * to the un-namespaced scheme. `capabilities` is the canonical v1 baseline this protocol guarantees.\n */\nexport function describeWorker(opts: {\n instanceId: string;\n runtime: 'node' | 'python';\n sdk: { name: string; version: string };\n steps: string[];\n workflows?: string[] | undefined;\n /** What this instance announces it can EXECUTE — see {@link WorkflowRegistration}. Omitted from\n * the descriptor entirely when absent or empty, so a worker with nothing to announce keeps the\n * pre-registrations bytes (and therefore the pre-registrations hash). */\n registrations?: readonly WorkflowRegistration[] | undefined;\n startedAt: number;\n partition?: string | undefined;\n namespace?: string | undefined;\n}): WorkerDescriptor {\n const version = CURRENT_PROTOCOL_VERSION;\n const registrations = [...(opts.registrations ?? [])].sort((a, b) =>\n `${a.name}@${a.version ?? ''}`.localeCompare(`${b.name}@${b.version ?? ''}`),\n );\n return {\n instanceId: opts.instanceId,\n runtime: opts.runtime,\n sdk: { name: opts.sdk.name, version: opts.sdk.version },\n protocol: { version, range: [version, version] },\n capabilities: [...LEGACY_V1_CAPABILITIES],\n workflows: [...(opts.workflows ?? [])].sort(),\n steps: [...opts.steps].sort(),\n ...(registrations.length > 0 ? { registrations } : {}),\n ...(opts.partition ? { partition: opts.partition } : {}),\n ...(opts.namespace && opts.namespace !== 'default' ? { namespace: opts.namespace } : {}),\n startedAt: opts.startedAt,\n };\n}\n","/**\n * The announced workflow registry (design §7.9) — the aggregate answer to \"what workflows exist in\n * this deployment?\", built ONLY from what live workers say about themselves.\n *\n * ## Why this is announced, not inferred\n *\n * `WorkflowEngine.workflowBody(name, version)` answers for the process that asks, and a missing body\n * is ambiguous by design: it means \"not registered here\", but equally \"registered via\n * `registerRemote` against another SDK\" or \"a group this pod resolves by convention against a live\n * worker\". A picker built on that inference would offer different options depending on which replica\n * served the request. So the registry is not derived from any engine's registry: a worker publishes\n * what it can execute ({@link WorkerDescriptor.registrations}, or bare `workflows` names), and this\n * module folds those statements together. Every entry is therefore a fact somebody asserted, and the\n * aggregate is the same on every pod because every pod reads the same published statements.\n *\n * The announcer is always the process that CONSUMES the queue, never the engine that dispatches to\n * it — including when the two share a process (the co-located in-app worker announces; the engine\n * beside it does not). One consequence is worth stating plainly rather than leaving to be\n * rediscovered: a pure operator (`store` with no `connection`) runs its bodies inline, consumes no\n * queue, and therefore announces NOTHING. Its workflows are real and startable through its own\n * `start()`, but they are not in this registry, because nothing about them is externally addressable\n * for a picker to point at.\n *\n * ## Liveness\n *\n * There is no expiry logic here because there is no state here. An announcement lives on the\n * descriptor key, which is written with the worker-heartbeat TTL and refreshed by the same beat; a\n * worker that dies stops refreshing and its key expires, taking its announcements with it. The\n * resolution of that liveness is therefore the TTL (35s against a 10s beat), so an entry can name a\n * worker that died within the last beat window — the same staleness the capability router already\n * accepts when it reads descriptors to decide whether to dispatch. A caller that needs a stronger\n * guarantee should not seek it here: dispatch to a dead worker parks the run `blocked`/`pending` on\n * its queue and the existing worker-health surface reports it. What this design DOES rule out is the\n * unbounded failure — an announcement that outlives its worker forever.\n *\n * ## Disagreement\n *\n * Two live workers can announce the same `name@version` with different groups, origins or capability\n * demands. The aggregate keeps EVERY distinct claim and reports the axes they differ on\n * ({@link AnnouncedWorkflow.disagreements}); it never merges them into one value and never picks a\n * winner, because either choice would make a caller act on a claim nobody made. Silence is not a\n * claim: a worker that announced no origin does not disagree with one that did.\n *\n * ## Steps are deliberately out of scope\n *\n * There is no equivalent registry for steps, and this is not an omission to be fixed later. A step is\n * not addressable from outside a run: it is identified by its `(runId, seq)` position in one\n * workflow's history, `ctx.step` is only callable from inside a replaying body, and no engine entry\n * point starts a step on its own. \"Call this step\" is therefore not something the engine can do, so a\n * picker offering steps would be offering an operation that does not exist. Step HANDLER names are\n * still advertised (`WorkerDescriptor.steps`) — that is a routing/capability fact used to decide\n * whether a dispatched step can be run, not an invocable catalog.\n *\n * ## The floor: a live worker that announces nothing\n *\n * An SDK old enough to predate the descriptor advertisement publishes only its TTL'd liveness\n * heartbeat — one key per routing token it consumes. Read strictly, such a fleet announces nothing\n * and this registry would be empty while work is being served. That answer is not merely unhelpful,\n * it CONTRADICTS the engine beside it: `resolveRemoteByConvention` routes a call to `X` the moment a\n * token named `X` heartbeats, so the deployment already treats liveness as sufficient to CALL a\n * workflow while claiming to know nothing when asked to LIST one. Both answers come out of the same\n * Redis.\n *\n * So the heartbeat is folded in as a second, weaker tier of evidence ({@link AnnouncedWorkflow.evidence}\n * `'observed'`): the entry exists because a live token of that name exists, which is exactly — no more\n * and no less — the condition under which convention routing would resolve it. Listing it therefore\n * cannot introduce a failure the dispatcher did not already have. What it CANNOT do is state a\n * version, an origin, a runtime, or even that the token serves a workflow rather than a step handler\n * of the same name: none of that is in a heartbeat, and every one of those stays un-stated rather than\n * being guessed. A descriptor always wins — a token an announcement already covers is never re-added\n * as an observation.\n */\n\nimport type { RawWorkerDescriptor, WorkerDescriptor, WorkflowRegistration } from './descriptor';\nimport { normalizeDescriptor } from './descriptor';\n\n/** One live worker's claim about one workflow: the registration plus who announced it. */\nexport interface WorkflowAnnouncement extends WorkflowRegistration {\n /** The announcing worker's instance id. */\n instanceId: string;\n /** The announcing worker's runtime — how a Python-served workflow is told from a Node-served one. */\n runtime: 'node' | 'python';\n}\n\n/** An axis on which the live announcers of one workflow do not agree. `values` holds every distinct\n * DECLARED value (sorted); an announcer that stated nothing on the axis contributes nothing. */\nexport interface Disagreement {\n axis: 'group' | 'origin' | 'requires';\n values: string[];\n}\n\n/**\n * How strong the fleet's claim about a workflow is. The two tiers are NOT interchangeable and a\n * caller must not read them as the same fact:\n *\n * - `'declared'` — at least one live worker published a descriptor naming this workflow. Everything\n * populated on the entry was STATED by that worker; everything absent it declined to state.\n * - `'observed'` — nobody described it. What exists is a live routing token of this name, which is\n * precisely the condition `resolveRemoteByConvention` uses to route a call, so the name IS\n * reachable. Nothing else is known: no version, no origin, no runtime, and no assurance that the\n * worker consuming that token serves a WORKFLOW there rather than a step handler of the same name.\n * An entry like this is a live queue, not a promise.\n */\nexport type AnnouncementEvidence = 'declared' | 'observed';\n\n/** One workflow the live fleet announces, folded across every worker that announced it. */\nexport interface AnnouncedWorkflow {\n /** What kind of claim this entry rests on — see {@link AnnouncementEvidence}. A caller that shows\n * a version, an origin or a runtime must check this first: an `'observed'` entry has none of\n * them, and the emptiness is a fact about the fleet, not a rendering gap. */\n evidence: AnnouncementEvidence;\n /** `name@version`, or the bare `name` when no announcer stated a version. Stable sort key. */\n key: string;\n name: string;\n /** Absent when no announcer stated one — never inferred from another announcer's version. */\n version?: string;\n /** Every distinct routing group announced (sorted). Empty = nobody stated one. On an `'observed'`\n * entry this is the token the heartbeat was published UNDER — not a claim by anybody, but the\n * queue a call would actually land on, which is the one thing an observation does establish. */\n groups: string[];\n /** Every distinct declaring package announced (sorted). Empty = nobody stated one. */\n origins: string[];\n /** Every distinct capability demand announced, each de-duplicated + sorted. Empty = nobody stated\n * one. Two entries here means two workers demand different capabilities for the same version. */\n requires: string[][];\n /** Runtimes of the live announcers (sorted, de-duplicated). EMPTY on an `'observed'` entry: a\n * heartbeat does not say what runtime wrote it, and the instance id's shape is a convention, not\n * a statement, so it is not read as one. */\n runtimes: ('node' | 'python')[];\n /** Instance ids of the live workers announcing it (sorted, de-duplicated). Its length is how many\n * workers can currently run this workflow — `1` is a single point of failure, and it is never 0\n * (an entry exists only because somebody announced it, or because somebody is beating on it). */\n instances: string[];\n /** The axes the announcers differ on, empty when they speak with one voice. A caller that must\n * pick a single target has to resolve these itself — the registry refuses to guess. */\n disagreements: Disagreement[];\n}\n\n/**\n * What one descriptor announces. `registrations` is authoritative when present; any `workflows` name\n * it does not cover is still announced as a bare, unversioned claim, so a worker that describes some\n * of its workflows richly and others by name alone is reported in full rather than in part.\n *\n * A descriptor with neither field announces nothing — including the control plane's own descriptor,\n * which is a router, not an executor.\n */\nexport function announcementsOf(\n raw: RawWorkerDescriptor | WorkerDescriptor,\n): WorkflowAnnouncement[] {\n const d = normalizeDescriptor(raw);\n const identity = { instanceId: d.instanceId, runtime: d.runtime };\n const announcements = (d.registrations ?? []).map((reg) => ({ ...reg, ...identity }));\n const covered = new Set(announcements.map((a) => a.name));\n for (const name of d.workflows) {\n if (!covered.has(name)) announcements.push({ name, ...identity });\n }\n return announcements;\n}\n\n/** `name@version`, or the bare name when unversioned — the identity two announcements are folded on. */\nfunction announcementKey(a: WorkflowRegistration): string {\n return a.version === undefined ? a.name : `${a.name}@${a.version}`;\n}\n\n/** Sorted, de-duplicated members of `values`, dropping the un-stated ones. */\nfunction stated(values: readonly (string | undefined)[]): string[] {\n return [...new Set(values.filter((v): v is string => v !== undefined))].sort();\n}\n\n/**\n * Fold every live descriptor's announcements into one entry per `name@version`, sorted by key.\n *\n * Pure: it holds nothing and caches nothing, so no pod ever carries a growing table of the fleet's\n * registrations — the caller reads the live descriptors it already knows how to read, folds them\n * here, and drops the result. The work is O(descriptors × announcements) per call, on demand.\n *\n * The same instance announcing the same workflow twice (a worker publishes its descriptor under\n * every routing token it consumes, so the same bytes arrive several times) folds to ONE announcer:\n * `instances` is a set, so it counts workers, not keys.\n */\nexport function aggregateAnnouncements(\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n): AnnouncedWorkflow[] {\n const byKey = new Map<string, WorkflowAnnouncement[]>();\n for (const descriptor of descriptors) {\n for (const announcement of announcementsOf(descriptor)) {\n const key = announcementKey(announcement);\n const bucket = byKey.get(key);\n if (bucket) bucket.push(announcement);\n else byKey.set(key, [announcement]);\n }\n }\n\n const out: AnnouncedWorkflow[] = [];\n for (const [key, announcements] of byKey) {\n const groups = stated(announcements.map((a) => a.group));\n const origins = stated(announcements.map((a) => a.origin));\n // A capability demand is a SET, so it is compared as its canonical (sorted, de-duplicated) form:\n // two workers demanding ['saga','signals'] and ['signals','saga'] agree, and must not be reported\n // as a disagreement over the same demand written two ways.\n const requiresByJson = new Map<string, string[]>();\n for (const a of announcements) {\n if (a.requires === undefined) continue;\n const canonical = [...new Set(a.requires)].sort();\n requiresByJson.set(JSON.stringify(canonical), canonical);\n }\n // Ordered by the same rendering `disagreements` uses, so the two lists read in step.\n const requires = [...requiresByJson.values()].sort((x, y) =>\n x.join(',').localeCompare(y.join(',')),\n );\n\n const disagreements: Disagreement[] = [];\n if (groups.length > 1) disagreements.push({ axis: 'group', values: groups });\n if (origins.length > 1) disagreements.push({ axis: 'origin', values: origins });\n if (requires.length > 1) {\n disagreements.push({ axis: 'requires', values: requires.map((r) => r.join(',')) });\n }\n\n const first = announcements[0];\n if (!first) continue;\n out.push({\n evidence: 'declared',\n key,\n name: first.name,\n ...(first.version !== undefined ? { version: first.version } : {}),\n groups,\n origins,\n requires,\n runtimes: [...new Set(announcements.map((a) => a.runtime))].sort(),\n instances: [...new Set(announcements.map((a) => a.instanceId))].sort(),\n disagreements,\n });\n }\n return out.sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * The part of one live worker heartbeat this registry can read: the routing token the beat was\n * published under, and which process published it. That is genuinely all a heartbeat holds — it is\n * the cheap tier of the two-tier advertisement, and its job is liveness, not description.\n *\n * Structurally satisfied by `WorkerHeartbeat` (the transport-facing shape, which also carries a beat\n * time and an execution snapshot). Declared here rather than imported so this module keeps its \"pure\n * data, no transport\" footing and `interfaces.ts` can keep importing FROM it.\n */\nexport interface HeartbeatSighting {\n /** The routing token the beat was published under (already partition-suffixed when partitioned). */\n group: string;\n /** The beating process's instance id. */\n instanceId: string;\n}\n\n/**\n * The weaker tier: one entry per live routing token that NO descriptor accounts for.\n *\n * `covered` holds every token the declared announcements already explain — both the sanitized form of\n * each announced NAME and every group any announcer stated. A token in that set is dropped, so a\n * fleet that describes itself properly gets exactly the same registry it got before this tier\n * existed, and a worker is never counted twice under two kinds of evidence.\n *\n * Everything an observation cannot know stays empty rather than being filled with a plausible guess:\n * no version (so nothing can be pinned against it), no origin, no requires, no runtime. The `name` is\n * the token itself, which equals the workflow's name for every name a queue token can round-trip —\n * `sanitizeQueueToken` rewrites `:` to `-` and that rewrite is not invertible, so a workflow named\n * `orders:fulfill` is observed as `orders-fulfill`. Stated here because a picker showing that string\n * should show what the queue is really called, not a reconstruction that might be wrong.\n */\nexport function observedAnnouncements(\n heartbeats: readonly HeartbeatSighting[],\n covered: ReadonlySet<string>,\n): AnnouncedWorkflow[] {\n const byToken = new Map<string, Set<string>>();\n for (const beat of heartbeats) {\n if (!beat.group || covered.has(beat.group)) continue;\n const instances = byToken.get(beat.group);\n if (instances) instances.add(beat.instanceId);\n else byToken.set(beat.group, new Set([beat.instanceId]));\n }\n return [...byToken.entries()]\n .map(([group, instances]) => ({\n evidence: 'observed' as const,\n key: group,\n name: group,\n groups: [group],\n origins: [],\n requires: [],\n runtimes: [],\n instances: [...instances].sort(),\n disagreements: [],\n }))\n .sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * Every routing token a live descriptor already ACCOUNTS FOR, and which therefore needs no\n * observation — for either of the two opposite reasons.\n *\n * - A token some worker announced as a WORKFLOW: already in the registry, richer than an\n * observation could ever be, and re-adding it would count one worker twice.\n * - A token some worker declared as a STEP HANDLER (`WorkerDescriptor.steps`): it must be left OUT,\n * because a step is not addressable from outside a run and offering one as callable would be\n * offering an operation the engine does not have. Route-by-handler gives every step its own queue,\n * so without this the liveness floor turns a fleet's entire step surface into fake workflows.\n *\n * That second exclusion is a DECLARED negative — the worker said \"this name is a step\" — which is\n * exactly the sort of fact an observation cannot supply for itself, and the clearest illustration of\n * what the two tiers are each worth. A worker on an SDK too old to describe itself declares neither\n * its workflows nor its steps, so every one of its tokens stays observed and indistinguishable: its\n * step queues are listed alongside its workflow queues because nothing published says which is\n * which. That is a fair report of the fleet, not a defect in the read.\n *\n * `sanitize` is injected so this module keeps no dependency on the queue layer; a declared name is\n * covered in its bare token form and, for a partitioned worker, in the suffixed form its queues\n * actually carry.\n */\nexport function coveredTokens(\n announced: readonly AnnouncedWorkflow[],\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n sanitize: (name: string) => string,\n): Set<string> {\n const tokens = new Set<string>();\n for (const entry of announced) {\n tokens.add(sanitize(entry.name));\n for (const group of entry.groups) tokens.add(group);\n }\n for (const raw of descriptors) {\n const d = normalizeDescriptor(raw);\n for (const step of d.steps) {\n const token = sanitize(step);\n tokens.add(token);\n if (d.partition) tokens.add(`${token}@${d.partition}`);\n }\n }\n return tokens;\n}\n","/**\n * The workflow directory — {@link ./announced}'s registry plus the thing an empty registry could\n * never say: WHY it is empty.\n *\n * ## The three states an empty list used to collapse\n *\n * \"What workflows can I call?\" has three honest answers, and returning `[]` for all of them is the\n * bug this module exists to fix. They are not shades of the same answer; they call for three\n * different actions from whoever asked.\n *\n * 1. **This process cannot ask.** No transport here can introspect the advertisement or liveness\n * keyspace — a pure in-process pool advertises nothing and scans nothing. Workers may well be\n * running; nobody looked. ({@link WorkflowDirectory.supported} is `false`.) The action is to\n * configure a transport, or to stop treating this pod's answer as the deployment's answer.\n * 2. **Nothing is live.** The fleet WAS asked and the fleet is empty. ({@link WorkflowDirectory.supported}\n * is `true`, `workflows` is `[]`.) The action is to start a worker.\n * 3. **Here it is.** ({@link WorkflowDirectory.supported} is `true`, `workflows` is populated.)\n *\n * There is a fourth that hides inside the second and is the most expensive to debug, because it\n * looks exactly like \"nobody is running\" from the caller's side: **a worker is live on a partition\n * this engine does not serve.** A worker started with a partition consumes `<token>@<partition>`,\n * convention resolution computes the token for THIS engine's namespace, misses, and reports absence.\n * The heartbeat keyspace is shared, so the evidence is right there — and\n * {@link WorkflowDirectory.otherPartitions} reports it instead of letting the caller conclude that\n * nothing exists.\n *\n * ## Why a sentence rides along\n *\n * Every field here is structured and a caller can branch on all of it. {@link WorkflowDirectory.detail}\n * exists anyway because the three states are only useful if the human reading the picker learns which\n * one they are in, and a UI that has to re-derive that prose from booleans will re-derive it\n * differently in each place it is shown. The sentence is written once, next to the logic that decides\n * which state it is.\n */\n\nimport type { AnnouncedWorkflow, HeartbeatSighting } from './announced';\nimport { aggregateAnnouncements, coveredTokens, observedAnnouncements } from './announced';\nimport type { RawWorkerDescriptor, WorkerDescriptor } from './descriptor';\n\n/** The namespace a descriptor or a bare routing token belongs to when it states none. Mirrors\n * `tenantGroup`'s default-is-bare rule, so a single-tenant deployment reads as `'default'`\n * everywhere rather than as a special case. */\nexport const DEFAULT_PARTITION = 'default';\n\n/** Live workers seen on a partition the asking engine does not serve — the case that otherwise reads\n * identically to \"nothing is running\". */\nexport interface PartitionSighting {\n /** The partition suffix carried by the tokens (never this engine's own). */\n partition: string;\n /** The routing tokens live on it, as published (sorted). */\n groups: string[];\n /** The instance ids beating there (sorted). */\n instances: string[];\n}\n\n/** What the live fleet can be asked, and what it answered. See the module docblock for the states. */\nexport interface WorkflowDirectory {\n /**\n * Could this process ask the fleet at all?\n *\n * `false` means no transport here can read the advertisement or liveness keyspace, so `workflows`\n * is empty because nothing was asked — NOT because nothing is running. `true` means the read\n * happened and `workflows` is the answer, including when it is empty.\n */\n supported: boolean;\n /** Everything callable in this engine's partition, declared and observed alike. */\n workflows: AnnouncedWorkflow[];\n /** Live workers on OTHER partitions (empty for an operator engine, which serves them all). */\n otherPartitions: PartitionSighting[];\n /** One sentence saying which state this is and what it implies. Written for a human. */\n detail: string;\n}\n\n/** The partition a routing token belongs to: the suffix after the LAST `@`, or {@link DEFAULT_PARTITION}\n * for a bare token. Matches how `tenantGroup` builds the token and how `workerHealth` takes it apart. */\nexport function partitionOfToken(token: string): string {\n const at = token.lastIndexOf('@');\n return at === -1 ? DEFAULT_PARTITION : token.slice(at + 1);\n}\n\n/**\n * Fold live descriptors and live heartbeats into the directory for one engine.\n *\n * `namespace` is the asking engine's, and `undefined` means an operator that serves every partition\n * (\"ver tudo = ausência de namespace\"): it filters nothing and reports no foreign partitions, because\n * none of them are foreign to it. A namespaced engine sees only its own partition's workers, and\n * everything else it can see is reported as a sighting rather than silently dropped — dropping is\n * what made a misconfigured partition indistinguishable from an empty fleet.\n *\n * Pure and holds nothing: the caller does the two live reads it already knows how to do, folds them\n * here, and drops the result.\n */\nexport function buildWorkflowDirectory(input: {\n descriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[];\n heartbeats: readonly HeartbeatSighting[];\n namespace: string | undefined;\n /** Whether ANY transport in the pool could perform the reads above. */\n supported: boolean;\n /** The queue-token form of a workflow name — injected so this module needs no queue dependency. */\n sanitize: (name: string) => string;\n}): WorkflowDirectory {\n const { descriptors, heartbeats, namespace, supported, sanitize } = input;\n if (!supported) {\n return {\n supported: false,\n workflows: [],\n otherPartitions: [],\n detail:\n 'No transport in this process can read what the fleet advertises, so nothing here was asked and this list is empty for that reason alone. Workers may well be running. A workflow can still be called by name.',\n };\n }\n\n const mine = namespace === undefined ? undefined : namespace;\n const ownDescriptors =\n mine === undefined\n ? descriptors\n : descriptors.filter((d) => (d.namespace ?? DEFAULT_PARTITION) === mine);\n const ownBeats: HeartbeatSighting[] = [];\n const foreign = new Map<string, { groups: Set<string>; instances: Set<string> }>();\n for (const beat of heartbeats) {\n if (!beat.group) continue;\n const partition = partitionOfToken(beat.group);\n if (mine === undefined || partition === mine) {\n ownBeats.push(beat);\n continue;\n }\n const seen = foreign.get(partition);\n if (seen) {\n seen.groups.add(beat.group);\n seen.instances.add(beat.instanceId);\n } else {\n foreign.set(partition, {\n groups: new Set([beat.group]),\n instances: new Set([beat.instanceId]),\n });\n }\n }\n\n const declared = aggregateAnnouncements(ownDescriptors);\n const observed = observedAnnouncements(\n ownBeats,\n coveredTokens(declared, ownDescriptors, sanitize),\n );\n const workflows = [...declared, ...observed].sort((a, b) => a.key.localeCompare(b.key));\n const otherPartitions: PartitionSighting[] = [...foreign.entries()]\n .map(([partition, seen]) => ({\n partition,\n groups: [...seen.groups].sort(),\n instances: [...seen.instances].sort(),\n }))\n .sort((a, b) => a.partition.localeCompare(b.partition));\n\n return {\n supported: true,\n workflows,\n otherPartitions,\n detail: describeDirectory(workflows, otherPartitions, mine),\n };\n}\n\n/** A few names plus a count, for prose. Route-by-handler gives every step its own queue, so one\n * partitioned worker can be beating on dozens of tokens and inlining them all makes the sentence\n * unreadable — measured at 17 on a single live worker. The complete list stays on\n * {@link PartitionSighting.groups}, where a caller that wants it can read it in full. */\nfunction summarize(names: readonly string[], limit = 3): string {\n if (names.length <= limit) return names.join(', ');\n return `${names.slice(0, limit).join(', ')} and ${names.length - limit} more`;\n}\n\n/** The one sentence a picker shows. Says which of the states the reader is in, and — when nothing is\n * callable but something IS beating elsewhere — names the partition, because that is the difference\n * between \"start a worker\" and \"the worker you started is on the wrong partition\". */\nfunction describeDirectory(\n workflows: readonly AnnouncedWorkflow[],\n otherPartitions: readonly PartitionSighting[],\n namespace: string | undefined,\n): string {\n const here = namespace === undefined ? 'this deployment' : `partition \"${namespace}\"`;\n const elsewhere =\n otherPartitions.length === 0\n ? ''\n : ` Live workers were seen on ${otherPartitions\n .map((p) => `\"${p.partition}\" (${summarize(p.groups)})`)\n .join(\n ', ',\n )}, which ${here} does not route to — a worker on the wrong partition looks exactly like no worker at all, so it is named here rather than left out.`;\n\n if (workflows.length === 0) {\n return `The fleet was asked just now and nothing is live in ${here}, so this list is empty because the deployment is empty — not because the question could not be put.${elsewhere}`;\n }\n const observed = workflows.filter((w) => w.evidence === 'observed').length;\n const declaredNote =\n observed === 0\n ? ''\n : ` ${observed} of them ${observed === 1 ? 'is' : 'are'} known only from a live queue: the worker serving ${observed === 1 ? 'it' : 'them'} publishes no description, so ${observed === 1 ? 'its' : 'their'} version, origin and runtime are genuinely unknown and a version pinned against ${observed === 1 ? 'it' : 'them'} cannot be checked.`;\n return `Every workflow a live worker in ${here} can execute, read just now. A worker that stops beating drops off this list within about half a minute.${declaredNote}${elsewhere}`;\n}\n","/**\n * Bilateral compatibility negotiation between two handshake descriptors (design §7.3/§7.4). Pure\n * logic: given a local and a remote {@link WorkerDescriptor}, compute the negotiated session (highest\n * common protocol major + capability intersection) and classify it into one of three outcomes with a\n * precise, structured reason — never a bare boolean (design §7.6).\n */\n\nimport { type RawWorkerDescriptor, type WorkerDescriptor, normalizeDescriptor } from './descriptor';\n\n/**\n * The three compatibility outcomes (design §7.4):\n * - `compatible` — protocol ranges intersect + full capability parity → dispatch freely.\n * - `degraded` — ranges intersect but a capability is missing on one side → dispatch, but route\n * capability-requiring work only to capable workers (soft warning).\n * - `incompatible` — no protocol-range overlap → do NOT dispatch; red flag with the exact reason.\n */\nexport type NegotiationOutcome = 'compatible' | 'degraded' | 'incompatible';\n\n/** Structured failure/warning payload — carries the precise delta so a diagnostics event can render\n * it on the timeline + dashboard health panel (design §7.6). Never a bare boolean. */\nexport interface NegotiationReason {\n /** Stable machine code for alerting/telescope. */\n code: 'protocol.incompatible' | 'capability.unavailable';\n /** Human-readable one-liner (dashboard/telescope copy). */\n message: string;\n /** The exact delta: which protocol ranges failed to overlap, or which capabilities are missing. */\n detail: {\n localRange?: [number, number];\n remoteRange?: [number, number];\n /** Capabilities the local side advertises that the remote lacks. */\n missingOnRemote?: string[];\n /** Capabilities the remote side advertises that the local lacks. */\n missingOnLocal?: string[];\n /** Explicitly-required capabilities not satisfied by the negotiated session. */\n missingRequired?: string[];\n };\n}\n\n/** The negotiated session + full delta between two sides. Carries both normalized descriptors so a\n * downstream diagnostics event can attach them wholesale (design §7.6). */\nexport interface NegotiationResult {\n outcome: NegotiationOutcome;\n /** Highest common protocol major, or `null` when ranges do not overlap (incompatible). */\n negotiatedProtocol: number | null;\n protocol: { localRange: [number, number]; remoteRange: [number, number] };\n capabilities: {\n /** Intersection — the capabilities the negotiated session can rely on everywhere. */\n shared: string[];\n /** Local advertises, remote lacks. */\n missingOnRemote: string[];\n /** Remote advertises, local lacks. */\n missingOnLocal: string[];\n };\n /** Present for `degraded` + `incompatible`; absent for `compatible`. */\n reason?: NegotiationReason;\n local: WorkerDescriptor;\n remote: WorkerDescriptor;\n}\n\nexport interface NegotiateOptions {\n /**\n * Capabilities the local side needs the negotiated session to provide. A required capability the\n * remote lacks degrades the session (dispatch generally, but capability-requiring runs park via\n * the router, design §7.5) — it never, on its own, makes the pair *incompatible*: only a protocol\n * range gap does that (design §7.4).\n */\n required?: string[];\n}\n\nconst rangesOverlap = (a: [number, number], b: [number, number]): boolean =>\n Math.max(a[0], b[0]) <= Math.min(a[1], b[1]);\n\nconst difference = (a: string[], b: string[]): string[] => {\n const bset = new Set(b);\n return [...new Set(a)].filter((x) => !bset.has(x)).sort();\n};\n\nconst intersection = (a: string[], b: string[]): string[] => {\n const bset = new Set(b);\n return [...new Set(a)].filter((x) => bset.has(x)).sort();\n};\n\n/**\n * Negotiate compatibility between `local` and `remote` (design §7.3/§7.4). Accepts raw/partial\n * descriptors (a missing `protocol`/`capabilities` is normalized to the legacy-v1 baseline, so a\n * legacy peer negotiates as **assume-compatible**, design §7.7).\n *\n * Outcome logic:\n * 1. no protocol-range overlap → `incompatible` (`protocol.incompatible`);\n * 2. else if a `required` capability is missing on the remote → `degraded` (`capability.unavailable`);\n * 3. else if the capability sets differ at all (either direction) → `degraded`;\n * 4. else full parity → `compatible`.\n *\n * **Bilateral-symmetric** on outcome for the parity path: `negotiate(a, b).outcome ===\n * negotiate(b, a).outcome` (the `missingOnLocal`/`missingOnRemote` delta swaps). `required` is the\n * caller's own need and intentionally asymmetric.\n */\nexport function negotiate(\n localRaw: RawWorkerDescriptor | WorkerDescriptor,\n remoteRaw: RawWorkerDescriptor | WorkerDescriptor,\n opts: NegotiateOptions = {},\n): NegotiationResult {\n const local = normalizeDescriptor(localRaw);\n const remote = normalizeDescriptor(remoteRaw);\n const localRange = local.protocol.range;\n const remoteRange = remote.protocol.range;\n\n const shared = intersection(local.capabilities, remote.capabilities);\n const missingOnRemote = difference(local.capabilities, remote.capabilities);\n const missingOnLocal = difference(remote.capabilities, local.capabilities);\n const capabilities = { shared, missingOnRemote, missingOnLocal };\n\n // (1) Protocol range gap → incompatible. This is the ONLY path that blocks dispatch outright.\n if (!rangesOverlap(localRange, remoteRange)) {\n return {\n outcome: 'incompatible',\n negotiatedProtocol: null,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'protocol.incompatible',\n message:\n `no common protocol major: local speaks [${localRange[0]}, ${localRange[1]}], ` +\n `remote speaks [${remoteRange[0]}, ${remoteRange[1]}]`,\n detail: { localRange, remoteRange },\n },\n local,\n remote,\n };\n }\n\n const negotiatedProtocol = Math.min(localRange[1], remoteRange[1]);\n\n // (2) A required capability the remote cannot provide → degraded (router parks the specific run).\n const required = opts.required ?? [];\n const missingRequired = difference(required, remote.capabilities);\n if (missingRequired.length > 0) {\n return {\n outcome: 'degraded',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'capability.unavailable',\n message: `remote is missing required capability(ies): ${missingRequired.join(', ')}`,\n detail: { missingRequired, missingOnRemote, missingOnLocal },\n },\n local,\n remote,\n };\n }\n\n // (3) Any capability asymmetry → degraded (soft; route capability-requiring work carefully).\n if (missingOnRemote.length > 0 || missingOnLocal.length > 0) {\n const parts: string[] = [];\n if (missingOnRemote.length > 0) parts.push(`remote lacks ${missingOnRemote.join(', ')}`);\n if (missingOnLocal.length > 0) parts.push(`local lacks ${missingOnLocal.join(', ')}`);\n return {\n outcome: 'degraded',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n reason: {\n code: 'capability.unavailable',\n message: `capability mismatch: ${parts.join('; ')}`,\n detail: { missingOnRemote, missingOnLocal },\n },\n local,\n remote,\n };\n }\n\n // (4) Ranges overlap + full capability parity → compatible.\n return {\n outcome: 'compatible',\n negotiatedProtocol,\n protocol: { localRange, remoteRange },\n capabilities,\n local,\n remote,\n };\n}\n","/**\n * Capability-aware routing (design §7.5). A workflow/step handler may declare\n * `requires: ['saga', 'search-attr-v2']`; the control-plane dispatches only to workers whose\n * descriptor advertises every required capability. If no live capable worker exists the run must\n * **park as `blocked`** with a precise reason (visible in the dashboard) — never a silent hang.\n *\n * Pure logic: no transport, no store. Consumers (the dispatcher/provider) feed live descriptors in.\n */\n\nimport { type RawWorkerDescriptor, type WorkerDescriptor, normalizeDescriptor } from './descriptor';\n\n/** A handler's capability demand — either a bare list, or anything carrying a `requires` array\n * (a workflow/step ref). An absent/empty list means \"runs anywhere\" (design §7.5). */\nexport type CapabilityRequirement = string[] | { requires?: string[] };\n\n/** Normalize the two accepted shapes to a de-duplicated list of required capability names. */\nexport function requiredCapabilities(handler: CapabilityRequirement): string[] {\n const list = Array.isArray(handler) ? handler : (handler.requires ?? []);\n return [...new Set(list)];\n}\n\n/**\n * Can `worker` run a handler with these requirements? True iff the worker's (normalized) descriptor\n * advertises **every** required capability. A legacy worker (no `capabilities` field) is normalized\n * to the v1 baseline first (design §7.7), so it can still run baseline-only work.\n */\nexport function canRoute(\n handler: CapabilityRequirement,\n worker: RawWorkerDescriptor | WorkerDescriptor,\n): boolean {\n const required = requiredCapabilities(handler);\n if (required.length === 0) return true;\n const advertised = new Set(normalizeDescriptor(worker).capabilities);\n return required.every((cap) => advertised.has(cap));\n}\n\n/**\n * The capabilities a handler requires that `worker` does NOT advertise — the precise routing delta.\n * Empty iff {@link canRoute} is true.\n */\nexport function missingCapabilities(\n handler: CapabilityRequirement,\n worker: RawWorkerDescriptor | WorkerDescriptor,\n): string[] {\n const advertised = new Set(normalizeDescriptor(worker).capabilities);\n return requiredCapabilities(handler).filter((cap) => !advertised.has(cap));\n}\n\n/** Filter a fleet down to the workers that can run a handler (design §7.5). */\nexport function capableWorkers<T extends RawWorkerDescriptor | WorkerDescriptor>(\n handler: CapabilityRequirement,\n workers: readonly T[],\n): T[] {\n return workers.filter((w) => canRoute(handler, w));\n}\n\n/** A run is dispatchable — at least one live worker can execute the handler. */\nexport interface RoutableResolution {\n status: 'routable';\n /** The normalized subset of the fleet that can run it. */\n workers: WorkerDescriptor[];\n requires: string[];\n}\n\n/** No live capable worker — the run parks as `blocked` with a human reason (design §7.5). */\nexport interface BlockedResolution {\n status: 'blocked';\n /** Exactly the dashboard copy: `blocked: no compatible worker (requires <caps>)`. */\n reason: string;\n requires: string[];\n}\n\nexport type RoutingResolution = RoutableResolution | BlockedResolution;\n\n/**\n * Decide whether a handler can be dispatched to the given live fleet (design §7.5). Returns\n * `routable` with the capable subset, or `blocked` with a precise reason when nobody can run it —\n * so the run parks visibly instead of hanging silently. An empty fleet always blocks.\n */\nexport function resolveRouting(\n handler: CapabilityRequirement,\n workers: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n): RoutingResolution {\n const requires = requiredCapabilities(handler);\n const capable = capableWorkers(handler, workers).map(normalizeDescriptor);\n\n if (capable.length > 0) {\n return { status: 'routable', workers: capable, requires };\n }\n\n const suffix = requires.length > 0 ? ` (requires ${requires.join(', ')})` : '';\n return {\n status: 'blocked',\n reason: `blocked: no compatible worker${suffix}`,\n requires,\n };\n}\n","/**\n * Capability- & protocol-aware dispatch planning (design §7.5/§7.6). Sits BETWEEN the pure handshake\n * (`resolveRouting`/`negotiate`, `./{routing,negotiate}`) and the engine's dispatch path: given a\n * step's/workflow's required capabilities and the LIVE worker descriptors for its routing token,\n * decide whether a live worker can actually run it — and if not, produce the LOUD, structured reason\n * the engine parks the run `blocked` with (never a silent hang into a queue nobody consumes).\n *\n * Pure logic + a small control-plane descriptor factory: no transport, no store, no I/O. The engine\n * feeds in descriptors it read off the broker and acts on the returned plan.\n */\n\nimport {\n CURRENT_PROTOCOL_VERSION,\n type RawWorkerDescriptor,\n type WorkerDescriptor,\n normalizeDescriptor,\n} from './descriptor';\nimport { negotiate } from './negotiate';\nimport { canRoute, requiredCapabilities } from './routing';\n\n/**\n * Build the control-plane's OWN handshake descriptor — the side the engine negotiates AGAINST each\n * worker (design §7.3). The CP advertises the protocol band it speaks so a worker stuck on an\n * incompatible major is detected instead of dispatched into (design §7.4). Capabilities default to\n * empty (the CP demands nothing of itself); `partition`/`namespace` scope it to a pool when set.\n *\n * The CP is not a worker, so `workflows`/`steps` are empty and `runtime` is `node`. `startedAt`\n * participates only in the descriptor hash (irrelevant for negotiation), so it defaults to `0` unless\n * a caller wants a stable identity.\n */\nexport function controlPlaneDescriptor(opts: {\n instanceId: string;\n /** SDK identity for observability (never gates dispatch). */\n sdk?: { name: string; version: string };\n /** Protocol majors the CP can negotiate. Defaults to the current single-major band `[v, v]`. */\n protocol?: { version: number; range: [number, number] };\n /** Capabilities the CP itself advertises (rarely needed; the CP is a router, not an executor). */\n capabilities?: string[];\n partition?: string | undefined;\n namespace?: string | undefined;\n startedAt?: number;\n}): WorkerDescriptor {\n const version = CURRENT_PROTOCOL_VERSION;\n return {\n instanceId: opts.instanceId,\n runtime: 'node',\n sdk: opts.sdk ?? { name: '@dudousxd/nestjs-durable-core', version: String(version) },\n protocol: opts.protocol ?? { version, range: [version, version] },\n capabilities: opts.capabilities ?? [],\n workflows: [],\n steps: [],\n ...(opts.partition !== undefined ? { partition: opts.partition } : {}),\n ...(opts.namespace !== undefined ? { namespace: opts.namespace } : {}),\n startedAt: opts.startedAt ?? 0,\n };\n}\n\n/** The structured delta a blocked-dispatch diagnostics event carries (design §7.6) — enough for the\n * telescope timeline + dashboard health panel to render exactly WHY nobody could run the work, never\n * a bare boolean. Serializable (plain data), so it rides an `EngineEvent`/control-plane message. */\nexport interface DispatchDiagnostics {\n /** Which machine code fired — a missing capability vs. an unbridgeable protocol gap. */\n code: 'capability.unavailable' | 'protocol.incompatible';\n /** The routing token the work would have been dispatched to. */\n token: string;\n /** The capabilities the handler required (de-duplicated). */\n requires: string[];\n /** How many live workers were advertising on this token at decision time. */\n liveWorkers: number;\n /** Required capabilities NOT advertised by ANY live worker (the `capability.unavailable` delta). */\n missingCapabilities?: string[];\n /** The protocol band the control-plane speaks (the `protocol.incompatible` delta). */\n controlPlaneRange?: [number, number];\n /** Protocol bands of the capable-but-incompatible workers (the `protocol.incompatible` delta). */\n workerRanges?: [number, number][];\n /** The control-plane descriptor negotiated against (attached wholesale for observability). */\n controlPlane: WorkerDescriptor;\n /** The live worker descriptors considered (attached wholesale — the full picture on the timeline). */\n workers: WorkerDescriptor[];\n}\n\n/** At least one live worker can run the handler — dispatch proceeds as today. */\nexport interface RoutableDispatch {\n status: 'routable';\n /** The normalized subset that is BOTH capable and protocol-compatible. */\n workers: WorkerDescriptor[];\n}\n\n/** No live worker can run the handler — the engine parks the run `blocked` with this reason/delta. */\nexport interface BlockedDispatch {\n status: 'blocked';\n code: 'capability.unavailable' | 'protocol.incompatible';\n /** Dashboard/telescope copy, e.g. `blocked: no compatible worker (requires saga)`. */\n reason: string;\n requires: string[];\n diagnostics: DispatchDiagnostics;\n}\n\nexport type DispatchPlan = RoutableDispatch | BlockedDispatch;\n\n/**\n * Thrown from deep in a `ctx.step` dispatch when {@link planDispatch} returns `blocked`, so the\n * engine's run-execution catch can park the run `blocked` (with the carried plan) instead of writing\n * a `pending` checkpoint + dispatching into a queue no live worker consumes. Distinct from\n * `WorkflowSuspended` — a blocked run is re-driven by the blocked-recovery poll, not a durable timer.\n */\nexport class WorkflowBlocked extends Error {\n constructor(readonly plan: BlockedDispatch) {\n super(plan.reason);\n this.name = 'WorkflowBlocked';\n }\n}\n\n/**\n * Decide whether a handler requiring `requires` can be dispatched to a token whose LIVE fleet is\n * `liveDescriptors`, negotiating each candidate against the control-plane descriptor `cp`\n * (design §7.4/§7.5).\n *\n * A worker is dispatchable iff it is BOTH capability-capable ({@link canRoute}) AND\n * protocol-compatible ({@link negotiate} outcome ≠ `incompatible`). If ≥1 such worker exists →\n * `routable`. Otherwise `blocked`, with the reason discriminated:\n * - some workers had the capability but ALL are protocol-incompatible → `protocol.incompatible`;\n * - otherwise (no live worker advertises every required capability) → `capability.unavailable`.\n *\n * Precondition (enforced by the caller): `liveDescriptors` is NON-EMPTY. An empty fleet means \"no\n * descriptors published\" — the legacy/pre-handshake path — where the guard is intentionally skipped so\n * existing workers keep flowing (design §7.7); the engine never calls this with an empty fleet.\n */\nexport function planDispatch(\n requires: string[],\n liveDescriptors: readonly (RawWorkerDescriptor | WorkerDescriptor)[],\n cp: WorkerDescriptor,\n token: string,\n): DispatchPlan {\n const required = requiredCapabilities({ requires });\n const workers = liveDescriptors.map(normalizeDescriptor);\n const capable = workers.filter((w) => canRoute({ requires }, w));\n const compatible = capable.filter((w) => negotiate(cp, w).outcome !== 'incompatible');\n\n if (compatible.length > 0) return { status: 'routable', workers: compatible };\n\n // Blocked. Which failure? Capable-but-incompatible → protocol; no capable at all → capability.\n if (capable.length > 0) {\n const workerRanges = capable.map((w) => w.protocol.range);\n return {\n status: 'blocked',\n code: 'protocol.incompatible',\n reason: `blocked: no protocol-compatible worker${\n required.length > 0 ? ` (requires ${required.join(', ')})` : ''\n }`,\n requires: required,\n diagnostics: {\n code: 'protocol.incompatible',\n token,\n requires: required,\n liveWorkers: workers.length,\n controlPlaneRange: cp.protocol.range,\n workerRanges,\n controlPlane: cp,\n workers,\n },\n };\n }\n\n // Capability gap: required caps advertised by NO live worker.\n const advertised = new Set(workers.flatMap((w) => w.capabilities));\n const missingCapabilities = required.filter((cap) => !advertised.has(cap));\n return {\n status: 'blocked',\n code: 'capability.unavailable',\n reason: `blocked: no compatible worker${\n required.length > 0 ? ` (requires ${required.join(', ')})` : ''\n }`,\n requires: required,\n diagnostics: {\n code: 'capability.unavailable',\n token,\n requires: required,\n liveWorkers: workers.length,\n missingCapabilities,\n controlPlane: cp,\n workers,\n },\n };\n}\n","import type { z } from 'zod';\nimport type { WorkerDescriptor } from './handshake/descriptor';\nimport type { DispatchDiagnostics } from './handshake/dispatch-routing';\nimport type { StandardSchemaV1 } from './standard-schema';\nimport type { StepRef } from './step-name-symbol';\nimport type { WorkflowClass, WorkflowInputOf, WorkflowOutputOf } from './workflow-ref';\n\n/**\n * Core type contracts for nestjs-durable.\n *\n * These are intentionally framework-agnostic: `@dudousxd/nestjs-durable-core` knows only\n * these interfaces, never a concrete transport, store or ORM. Adapters implement them.\n */\n\n// ---------------------------------------------------------------------------\n// Runs & checkpoints — the durable state owned by the orchestrator\n// ---------------------------------------------------------------------------\n\nexport type RunStatus =\n /** Created + enqueued by `start`, not yet picked up — a worker will lease and execute it. */\n | 'pending'\n | 'running'\n | 'suspended'\n /**\n * Compensating cancel in progress: `cancel(runId, { compensate: true })` has been requested and the\n * saga undo is running in the background. NON-TERMINAL — the run is still in-flight (counted by the\n * admission gate, re-driven by recovery if the engine crashes mid-compensation), and flips to\n * `cancelled` once compensation completes. A non-compensating cancel skips this and goes straight to\n * `cancelled`.\n */\n | 'cancelling'\n /**\n * No live worker on the run's next-dispatch group is BOTH capability-capable and protocol-compatible\n * (handshake design §7.5). NON-TERMINAL — the run wrote no `pending` checkpoint and dispatched\n * nothing; it carries a `wakeAt` so the blocked-recovery poll re-drives it to re-check the live\n * fleet, and proceeds the moment a capable+compatible worker appears. Only engaged when descriptors\n * are actually published (a legacy/pre-handshake fleet skips the guard, design §7.7).\n */\n | 'blocked'\n | 'completed'\n | 'failed'\n | 'cancelled'\n /** Dead-letter: recovery gave up after `maxRecoveryAttempts` (a poison pill). Terminal; inspect it. */\n | 'dead';\n\n/** One execution of a workflow. The unit of durability and the unit shown in the dashboard. */\nexport interface WorkflowRun {\n id: string;\n /** Registered workflow name, e.g. `checkout`. */\n workflow: string;\n /** Code version at start; old runs must resume on the version they began on. */\n workflowVersion: string;\n status: RunStatus;\n /** Serialized workflow input (the args the run was started with). */\n input: unknown;\n /** Serialized workflow output, once `completed`. */\n output?: unknown;\n /** Structured error, once `failed`. */\n error?: StepError | undefined;\n /** When `suspended` on a durable sleep: epoch ms at which the run becomes due to resume. */\n wakeAt?: number | undefined;\n /** Recovery lease owner (engine instance id) while a run is being resumed. */\n lockedBy?: string | undefined;\n /** Recovery lease expiry (epoch ms); another instance may take over once it passes. */\n lockedUntil?: number | undefined;\n /** How many times crash-recovery has picked this run up — caps poison pills (see maxRecoveryAttempts). */\n recoveryAttempts?: number | undefined;\n /** Searchable labels: the workflow's static `@Workflow({ tags })` merged with the run's start-time tags. */\n tags?: string[] | undefined;\n /** Typed, queryable run data (e.g. `{ amount: 200, tier: 'pro' }`) — see {@link RunQuery.attributes}. */\n searchAttributes?: SearchAttributes | undefined;\n /**\n * The worker-pool partition this run belongs to. Stamped at creation from the creating engine's\n * `namespace` (default `'default'`). A worker only picks up / recovers / resumes-timers-for /\n * times-out runs in its own namespace. `undefined` on a run created before this field existed; the\n * store persists it as `'default'`. Read paths (dashboard, `getRun`) are NOT namespace-scoped.\n */\n namespace?: string | undefined;\n /**\n * The npm package that DECLARED this run's workflow — e.g. `@dudousxd/nestjs-catalog-pipeline` for\n * a workflow shipped by a library, or the host app's own `package.json` `name` for one written in\n * the app. This is a CODE-PROVENANCE axis (\"which lib owns this body\"), NOT a tenancy axis — for\n * that, see {@link namespace}.\n *\n * Stamped at creation from the workflow's registration, exactly as {@link namespace} is stamped\n * from the creating engine. It is DERIVED, never caller input: `StartOptions` has no `origin`, so\n * nothing a caller passes to `start` can make a run claim another lib's name.\n *\n * `undefined` means UNKNOWN — never \"the app\". It is what you get for a run created before this\n * field existed, for a registration path that carries no origin (`registerRemote`, convention\n * routing, a synthesized remote child, or a bare `engine.register` with no `origin` option), and\n * for a workflow whose declaring package could not be resolved with confidence. A wrong origin is\n * worse than an absent one: a filter that silently drops runs looks exactly like runs that never\n * existed, so callers must render unknown as unknown and never fold it into a real package.\n */\n origin?: string | undefined;\n /**\n * Dispatch priority for a REMOTE run (one advanced by a {@link WorkflowExecutor} over a broker):\n * carried onto each {@link WorkflowTask} so an urgent child workflow can jump ahead of enqueued\n * lower-priority ones at the worker. Higher wins; absent = unprioritised. Best-effort ordering, not\n * durable state required for correctness — a transport without priority support ignores it.\n */\n priority?: number | undefined;\n /**\n * REMOTE workflow turn awaiting a decision: the `taskId` of the turn the engine dispatched to a\n * workflow worker and then SUSPENDED on. Set by the dispatch-and-suspend path; matched by\n * {@link WorkflowEngine.completeRemoteDecision} so ONLY the decision for the currently-awaited turn\n * is applied (a stale/duplicate/foreign decision is dropped), then cleared the moment it is applied.\n * This is what makes a workflow-turn decision multi-instance safe: any engine instance that receives\n * the decision looks the run up by `decision.runId` and applies it durably, instead of resolving an\n * in-memory promise that only the dispatching instance held. Absent on non-remote / not-awaiting runs.\n */\n awaitingDecisionTaskId?: string | undefined;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/**\n * WHAT an event-parked suspended run is waiting on, resolved for display — the engine keeps one\n * generic `suspended` status (it's what drives recovery/timers/queries), but to a human \"waiting on\n * signal `approve`\" reads very differently from \"waiting on webhook `stripe-cb`\". Computed by the\n * store-backed gateway from the run's signal waiters (`listSignalWaiters`, ONE bulk scan), so the\n * dashboard can NAME the wait in a list row without fetching each run's timeline. `on` is derived from\n * the waiter token's prefix (see `classifyWaiterToken`): `wh:<runId>:<seq>` ⇒ `webhook`, `child:<id>`\n * ⇒ `child`, `bp:<runId>:<seq>` ⇒ `breakpoint` (a `ctx.breakpoint` DOES register a signal waiter —\n * same machinery, `engine.continue` resumes it — so it's classified here, not left to fall through to\n * the generic `signal` case with the raw token as its ugly display name), `event:<name>:…` ⇒ `signal`\n * (name decoded), anything else ⇒ `signal` (the token IS the signal name).\n *\n * Deliberately EVENT-only (no timer/step): `wakeAt` alone can't tell a real `ctx.sleep` from the\n * reconcile-fallback `wakeAt` an event/step suspend now carries, and the store exposes no cheap bulk\n * checkpoint scan to disambiguate — so the client shows a non-event suspend with a live worker as\n * `running` (it flips off \"no worker\" the moment a worker returns) rather than guessing \"sleeping\".\n * The detail view (which has the timeline) still distinguishes sleep vs in-flight step precisely.\n */\nexport interface RunWaiting {\n on: 'signal' | 'webhook' | 'child' | 'breakpoint';\n /**\n * The token/name the run is parked on — the signal name, webhook token, or awaited child id. For a\n * breakpoint this is always the literal `'breakpoint'`: the real label (if any) lives on the pending\n * `breakpoint`/`breakpoint:<label>` checkpoint, which the detail view's timeline already shows —\n * naming it here would need an extra per-run checkpoint read, defeating the bulk waiter scan.\n */\n name: string;\n}\n\nexport type StepKind = 'local' | 'remote' | 'sleep' | 'signal';\n\n/**\n * The recorded result of a single step at a deterministic logical position (`seq`).\n * On replay, a `completed` checkpoint means the step is NOT re-executed — its `output` is\n * returned. A non-terminal checkpoint (`pending`/`running`) does not short-circuit: the step is\n * re-awaited (remote) or re-run (local).\n */\nexport interface StepCheckpoint {\n runId: string;\n /** Deterministic logical position of the step within the run. */\n seq: number;\n /** Registered step name (matches the remote handler name for remote steps). */\n name: string;\n kind: StepKind;\n /** Stable id passed to remote workers so they can dedupe a re-delivered task. */\n stepId: string;\n /**\n * `pending` = a remote step dispatched and awaiting its worker result (the run is durably\n * suspended, not held in memory); it becomes `completed`/`failed` when the result arrives.\n * `running` = a local step whose body is executing in-process right now (see `trackStepStart`);\n * it's overwritten by `completed`/`failed` when the body settles, and on a crash mid-body it\n * simply re-runs on replay (only `completed` short-circuits).\n */\n status: 'pending' | 'running' | 'completed' | 'failed';\n /** What the step was called with — the `ctx.step` (dispatched) args for a remote step (a local step has none). */\n input?: unknown;\n output?: unknown;\n error?: StepError | undefined;\n attempts: number;\n /** For remote steps: which worker group ran it. */\n workerGroup?: string | undefined;\n /** Structured events/logs the step emitted (sub-step outcomes, debug/error lines). */\n events?: StepEvent[] | undefined;\n /** For sleep steps: epoch ms the sleep elapses at. */\n wakeAt?: number | undefined;\n /**\n * Set on the running placeholder checkpoints of the children dispatched by one `ctx.all` call —\n * a shared tag (`all:<firstSeq>`) grouping the N siblings so the dashboard can render them as one\n * parallel fan-out. Optional and additive: absent on every non-`all` checkpoint. Mirrors the\n * Python SDK's `parallelGroup`.\n */\n parallelGroup?: string | undefined;\n /**\n * When the step entered the system: for a remote step, when the engine dispatched it to the\n * transport; for a local step, when it began. Queue-wait time = `startedAt − enqueuedAt`.\n */\n enqueuedAt: Date;\n /** When processing actually began: worker pickup for a remote step, execution start for a local one. */\n startedAt: Date;\n finishedAt: Date;\n}\n\n/**\n * A structured event a step (or its worker) emits while running — a log line and/or a sub-step\n * outcome. The dashboard renders these under the step, so you can see what happened inside a step\n * that the workflow treats as one unit (e.g. which of N parallel sub-processes ok/failed/skipped).\n */\nexport interface StepEvent {\n /** Epoch ms. */\n at: number;\n level: 'debug' | 'info' | 'warn' | 'error';\n message: string;\n /** Stable run identity for a sub-process. Distinct invocations of the same `name` carry distinct\n * ids, so their phases and log trails never collapse into one. Absent on events emitted by the\n * legacy `sub()` path, which keys by `name` instead. */\n subId?: string;\n /** For a sub-step/sub-process within the step: its name. */\n name?: string;\n /** Open, consumer-defined grouping label for a sub-process (e.g. a handler/lane). The dashboard\n * groups rows by it. The library never interprets it. */\n group?: string;\n /** For a sub-step: its terminal outcome (closed enum — drives colour + aggregation). */\n status?: 'ok' | 'failed' | 'skipped';\n /** Open, consumer-defined intermediate phase label for a sub-process transition. Carries no\n * terminal `status`; the library timestamps and orders it but never interprets it. */\n phase?: string;\n /** For a log line emitted *inside* a sub-process: that owning sub-process's name, so the dashboard\n * can group a step's log trail under each sub-process instead of one flat list. Set on logs (no\n * `status`); a worker stamps it from the sub-process it's running.\n * @deprecated Superseded by `subId` for run-distinct grouping; kept so existing workers/runs render. */\n process?: string;\n /** Optional structured payload. `data.durationMs` (number) overrides the derived duration. */\n data?: unknown;\n}\n\n/**\n * Handed to a local step's body (`ctx.step(name, (log) => …)`) so it can record what happened\n * inside the step — debug/info/warn/error lines and per-sub-process outcomes. The events are\n * checkpointed with the step and rendered under it in the dashboard. The remote/cross-language\n * counterpart is the worker attaching the same `StepEvent[]` to its `StepResult` (see the Python\n * SDK's `StepContext`), so observability is symmetric regardless of where the step ran.\n */\nexport interface StepLogger {\n debug(message: string, data?: unknown): void;\n info(message: string, data?: unknown): void;\n warn(message: string, data?: unknown): void;\n error(message: string, data?: unknown): void;\n /** Record a sub-step / sub-process outcome (e.g. one of N parallel p-processes). */\n sub(name: string, status: 'ok' | 'failed' | 'skipped', message?: string, data?: unknown): void;\n /** Record a sub-process event. Typically pass `phase` for an intermediate transition (carrying no\n * terminal status), or `status` for the terminal outcome — the type permits either; the engine\n * interprets which is set. `id` is the run identity (distinct per invocation); `group` is an\n * open grouping label. */\n subEvent(e: {\n id: string;\n name: string;\n group?: string | undefined;\n phase?: string | undefined;\n status?: 'ok' | 'failed' | 'skipped' | undefined;\n message?: string | undefined;\n data?: unknown;\n }): void;\n /**\n * Ergonomic sub-process lifecycle: run `body`, timing it, and record a terminal `ok` with the\n * measured `durationMs` on success — or `failed` (with the error message) if it throws, then\n * re-throw. `sp.phase(label)` records an intermediate transition; `sp.skip(reason)` a terminal\n * `skipped`. Logs emitted inside `body` are tagged to this sub-process so the dashboard groups\n * them under it. Returns whatever `body` returns. The TS twin of the Python SDK's `sub_process`.\n *\n * ```ts\n * const rows = await log.subProcess('fetch-data', async () => readEverything());\n * await log.subProcess('export-file', () => upload(rows));\n * ```\n */\n subProcess<T>(\n name: string,\n body: (sp: SubProcessHandle) => Promise<T> | T,\n opts?: { group?: string; id?: string },\n ): Promise<T>;\n}\n\n/** The handle a {@link StepLogger.subProcess} body receives to mark phases / a non-`ok` outcome. */\nexport interface SubProcessHandle {\n /** Record an intermediate phase transition (a consumer-defined label, no terminal status). */\n phase(phase: string, data?: unknown): SubProcessHandle;\n /** Record a terminal `skipped` outcome (e.g. nothing to do / validation failed). */\n skip(reason?: string, data?: unknown): void;\n /** Record a terminal `failed` outcome explicitly (the wrapper also does this if the body throws). */\n fail(reason?: string, data?: unknown): void;\n}\n\nexport interface StepError {\n message: string;\n /** Optional machine-readable code, e.g. `declined`, `timeout`. */\n code?: string | undefined;\n /** Whether the engine should treat this as retryable. */\n retryable?: boolean | undefined;\n stack?: string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// StateStore — where runs and checkpoints live (Postgres / MySQL / SQLite via ORM adapters)\n// ---------------------------------------------------------------------------\n\nexport interface StateStore {\n /**\n * Provision the tables/collections this store needs, idempotently. Called on boot when the\n * module's `autoSchema` is on. Optional: stores that need no setup (in-memory) omit it.\n */\n ensureSchema?(): Promise<void>;\n\n /**\n * Atomically read active runs sharing workflow/tag in this store's read scope, preserve durable\n * admitted holders, and claim a free slot for an eligible FIFO waiter. The claim persists the\n * reserved SINGLETON_ADMITTED_TAG in tags. Execution lease expiry never releases a slot; terminal\n * status does. Optional for general stores, required when using singleton workflows. Implement\n * with a database transaction that serializes competing claims BEFORE reading; list/update alone\n * is unsafe across engine instances. If retryWakeAt is supplied, denial must atomically suspend\n * the still-active candidate with that wakeAt while the same locks are held. Never overwrite a\n * cancelling or terminal run on denial. Return false for missing/terminal/out-of-scope runs.\n */\n tryAdmitSingleton?(\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ): Promise<boolean>;\n\n createRun(run: WorkflowRun): Promise<void>;\n updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void>;\n getRun(runId: string): Promise<WorkflowRun | null>;\n\n /**\n * Hard-delete a run and all of its rows — the run plus its checkpoints, signal waiters, and\n * normalized search-attribute rows. Unlike a cancelled run (which stays as terminal history), a\n * deleted run is GONE: it no longer appears in {@link getRun} or {@link listRuns}. This removes\n * exactly the one run — the engine's {@link WorkflowEngine.deleteRun} handles the child cascade.\n * No-op if the run doesn't exist. (Token-keyed buffered signals are transient and left alone.)\n */\n deleteRun(runId: string): Promise<void>;\n\n /**\n * Hard-delete up to `limit` terminal runs that fall OUTSIDE `policy` (oldest / over the count cap\n * first), cascading to their child rows exactly like {@link deleteRun}. Returns how many runs were\n * deleted — call again while it returns `limit` to drain a large backlog in bounded batches.\n *\n * A policy with a {@link RetentionPolicy.scope} only ever selects (and counts, for `maxCount`) runs\n * matching that scope.\n *\n * Optional: only adapters that implement a bulk prune provide it; the retention poller no-ops with a\n * warning when the configured store omits it. See {@link RetentionPolicy} for the keep/prune rule.\n */\n pruneTerminalRuns?(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number>;\n\n /**\n * Hard-delete a BATCH of runs and all of their rows in one go — exactly {@link deleteRun} applied to\n * every id (checkpoints, signal waiters, attribute rows, then the runs), but as a handful of\n * `IN (...)` statements in one transaction instead of four round-trips per run. Ids that don't exist\n * are ignored. Like {@link deleteRun} it removes exactly the listed runs; the engine's\n * `purgeRuns` walks the child edges first.\n *\n * Optional: a store that omits it still works — the engine falls back to one {@link deleteRun} per id.\n */\n deleteRuns?(runIds: string[]): Promise<void>;\n\n getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;\n /**\n * Persist a checkpoint and advance the run atomically. Durable semantics depend on this\n * being a single transaction; stores without transactions cannot give the strong guarantee.\n */\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;\n\n /** Used by recovery on boot to find runs to resume (crashed, left `running`). */\n listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]>;\n\n /** The oldest `pending` runs awaiting dispatch (FIFO, by `createdAt`), capped at `limit`. */\n listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]>;\n\n /** Suspended runs whose durable timer is due (`wakeAt <= nowMs`), ready to resume. */\n listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]>;\n\n /**\n * Atomically acquire the recovery lease on a run for `owner` until `leaseUntilMs`, but only if\n * it is currently unlocked or its lease has expired (`<= nowMs`). Returns whether it was\n * acquired — so concurrent engine instances never recover the same run twice.\n */\n tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;\n\n /** Release a run's recovery lease so another instance can pick it up (e.g. once it suspends). */\n releaseRunLock(runId: string): Promise<void>;\n\n /**\n * Extend a run's lease to `leaseUntilMs`, but ONLY if `owner` still holds it — so a live worker\n * heartbeating its long run keeps the lease, while a dead worker's lease still expires and gets\n * reclaimed. Returns false if the lease was lost (taken over or released).\n */\n renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean>;\n\n /** Record that a run is suspended waiting for an external signal `token`. */\n putSignalWaiter(waiter: SignalWaiter): Promise<void>;\n /** Atomically take (and remove) the run waiting on `token`, if any. */\n takeSignalWaiter(token: string): Promise<SignalWaiter | null>;\n /** List waiters whose `token` starts with `prefix` — used to fan out an event to its subscribers. */\n listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;\n /**\n * Whether run `runId` still has at least one waiter whose `token` starts with `tokenPrefix` (an\n * exact prefix: `%`/`_` in the prefix are literal characters, not wildcards). The `ctx.all` join\n * barrier asks this after each child settles, so it must stay O(1)-ish however many siblings are\n * still waiting — answer it with a bounded lookup, never by listing the whole group.\n *\n * Optional: a store without it keeps `ctx.all` correct, but the parent replays once per settled\n * child instead of once per fan.\n */\n hasSignalWaiter?(runId: string, tokenPrefix: string): Promise<boolean>;\n /**\n * The waiters of the given runs. Lets the engine and the dashboard read what a page of runs (or\n * one run's children) is waiting on without scanning every waiter in the store, which a wide fan\n * fills with one row per running child. Callers pass ids in bounded batches.\n *\n * Optional: without it those reads fall back to {@link listSignalWaiters} over every waiter.\n */\n listSignalWaitersByRun?(runIds: string[]): Promise<SignalWaiter[]>;\n /**\n * Register a batch of awaited children: for each entry, put `waiter` and upsert `checkpoint` (the\n * parent's `running` placeholder for that child). `ctx.all` calls it once per chunk of a fan, so a\n * wide fan costs a handful of round trips instead of two per child.\n *\n * Every entry's waiter must be durable no later than its checkpoint: the engine reads an existing\n * placeholder as proof the waiter was put, and never re-puts it. Writing both in one transaction\n * satisfies that.\n *\n * Optional: without it the engine puts each waiter, then saves each checkpoint.\n */\n registerChildWaits?(entries: ChildWait[]): Promise<void>;\n /**\n * Atomically replace run `runId`'s checkpoints with `seq` in `[fromSeq, toSeq]` by the single\n * checkpoint `into`, whose `seq` lies in that range. `ctx.all` folds a settled group of children\n * into one checkpoint this way, so every later turn of the parent loads one row instead of one per\n * child. A delete over a contiguous seq range, served by the `(runId, seq)` primary key.\n *\n * Optional: without it a settled fan keeps one checkpoint per child.\n */\n compactCheckpoints?(\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ): Promise<void>;\n\n /**\n * Delete the EXACT waiter row — `token` AND `runId` AND `seq` must all match — no-op if absent.\n * Unlike {@link takeSignalWaiter}, which deletes ANY row for `token` (fine when the caller just won\n * the race to consume it), this is for a caller removing its OWN registration after resolving the\n * wait some other way (a buffered hit, a timeout): blind `takeSignalWaiter(token)` there could steal\n * a DIFFERENT run's waiter that has since claimed the same token (`token` is the store's primary key,\n * so a later `putSignalWaiter` for the same token replaces the row). The exact-match variant only\n * ever removes the row this caller itself put there.\n */\n removeSignalWaiter(waiter: SignalWaiter): Promise<void>;\n\n /**\n * Buffer a signal whose waiter hasn't arrived yet, so the next `waitForSignal(token)` consumes it\n * instead of it being lost (FIFO per token). Makes signals reliable regardless of timing and\n * powers `signalWithStart`.\n */\n bufferSignal(token: string, payload: unknown): Promise<void>;\n /** Take the oldest buffered signal for `token` (FIFO), or null if none is buffered. */\n takeBufferedSignal(token: string): Promise<{ payload: unknown } | null>;\n\n /**\n * Buffer a published event that matched NO live waiter, so a LATER `ctx.waitForEvent(name, { match })`\n * still consumes it instead of it being silently dropped — the events analog of {@link bufferSignal}'s\n * reliability contract for signals, but MATCH-based rather than token-based: an event's buffer is keyed\n * by `name` alone (many waiters can share a name with different `match` criteria), so consumption is\n * list ({@link listBufferedEvents}) + evaluate the WAITER's own match predicate + claim\n * ({@link removeBufferedEvent}) — never a blind take, because the store has no way to know which\n * candidate a given waiter wants. `input.id` is minted by the caller (engine.publishEvent) so\n * {@link removeBufferedEvent} can later target this exact row.\n */\n bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void>;\n /**\n * Buffered events for `name`, OLDEST (`publishedAt`) first, capped at `limit`. A waiter scans these,\n * evaluates its own `eventMatches(payload, match)` locally, and claims the one it wants via\n * {@link removeBufferedEvent} — the match predicate belongs to the WAITER, never the store.\n */\n listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>>;\n /**\n * Atomically delete the buffered event `id`. Returns `true` iff a row was actually deleted, `false`\n * if it was already gone (claimed by a concurrent waiter, reclaimed by `engine.publishEvent`'s own\n * late re-check, or pruned as expired) — the arbiter under concurrency: whichever caller's delete\n * returns `true` is the one that gets to deliver the payload; every other caller backs off.\n */\n removeBufferedEvent(id: string): Promise<boolean>;\n\n /**\n * Run `work` in a SINGLE store transaction — giving it the store-native transaction handle (`raw`)\n * for the caller's own DB writes plus a `saveCheckpoint` that commits IN THE SAME transaction, so a\n * business write and the step's \"done\" checkpoint are atomic (exactly-once). Optional — only the SQL\n * adapters implement it; `ctx.transaction` errors on a store without it.\n */\n transaction?<T>(work: (tx: StoreTransaction) => Promise<T>): Promise<T>;\n\n // Persisted schedules (optional) — see {@link ScheduleRecord}. A store implements all five or none;\n // `engine.schedules` refuses to run on a store without them.\n\n /** Insert or fully replace the schedule `record.id`. */\n saveSchedule?(record: ScheduleRecord): Promise<void>;\n /** The schedule `id`, or null. */\n getSchedule?(id: string): Promise<ScheduleRecord | null>;\n /**\n * Patch the schedule `id`. With `expectedNextFireAt`, a compare-and-set: the patch applies only if\n * the stored `nextFireAt` still equals it (`null` matching `NULL`), which is how two schedulers racing\n * on the same due schedule agree on who advanced it. Returns whether a row was updated.\n */\n updateSchedule?(\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ): Promise<boolean>;\n /** Delete the schedule `id`. Returns whether it existed. Its past runs are left alone. */\n deleteSchedule?(id: string): Promise<boolean>;\n /** Schedules matching `query`, ordered by `nextFireAt` ascending (never-firing last), then `id`. */\n listSchedules?(query: ScheduleQuery): Promise<ScheduleRecord[]>;\n\n // Dashboard queries\n listRuns(query: RunQuery): Promise<WorkflowRun[]>;\n\n /**\n * How many runs match `query` — a single `COUNT(*)` over the same predicates {@link listRuns}\n * applies, without materializing a row. What the start-time concurrency quota asks on every start\n * (`tag = concurrency:<key> AND status IN (...)`), so it must stay an aggregate, not a listing.\n *\n * Optional: a store that omits it still works — the engine falls back to summing {@link runFacets}\n * cells, then to counting a {@link listRuns} result.\n */\n countRuns?(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number>;\n\n /**\n * Count the runs matching `query`, grouped by `(status, origin)` — the totals behind a console's\n * status and origin chips, in ONE aggregate instead of a full listing the caller counts in memory.\n * This is what lets a run list be paginated at all: `listRuns` can return 100 rows while the chips\n * still say how many of the 9,000 are failed.\n *\n * Cells with a zero count are simply absent. Optional: a store that omits it still works — callers\n * fall back to counting a {@link listRuns} result, which is correct but unbounded.\n */\n runFacets?(query: RunFacetQuery): Promise<RunFacetRow[]>;\n\n /**\n * The distinct values of ONE filter axis over the runs matching `query`, with counts — what a\n * console's tenant/tag/attribute pickers list instead of asking an operator to type a value blind.\n *\n * Scoped by the SAME predicates the list is under (`query`), so the options narrow as the operator\n * narrows: picking a tenant leaves the tag picker offering only tags that tenant's runs actually\n * carry, and a picker never offers a value that would return an empty list.\n *\n * Bounded by {@link RunValueFacetOptions} — read its `scan` note before trusting a `tag` count.\n *\n * Optional: a store that omits it still works — the console falls back to free-text entry for these\n * filters, which is what it had before pickers existed.\n */\n runValueFacets?(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]>;\n listCheckpoints(runId: string): Promise<StepCheckpoint[]>;\n\n /**\n * The LATEST checkpoint for `runId` whose `name` equals `name` exactly (highest `seq` wins), or\n * `undefined` if none. A targeted read that avoids fetching + deserializing every checkpoint just to\n * keep one match — the store does the filter (`WHERE name = … ORDER BY seq DESC LIMIT 1`). Preserves\n * the \"last in seq order wins\" semantics the engine relies on for `getEvent` (a re-published key\n * overwrites the prior value at a higher seq, so the highest-seq match is the current value).\n *\n * Optional: a store that omits it still works — the engine falls back to {@link listCheckpoints}\n * plus an in-JS filter that produces the identical result.\n */\n getLatestCheckpointByName?(runId: string, name: string): Promise<StepCheckpoint | undefined>;\n\n /**\n * All checkpoints for `runId` whose `name` starts with ANY of `prefixes`, ordered by `seq` ascending\n * (same order as {@link listCheckpoints}). A targeted read that avoids scanning every checkpoint just\n * to keep the prefix matches — the store does the filter (`WHERE name LIKE 'prefix%' …`). Used by the\n * run-tree to find a parent's child edges (`signal:child:` / `spawn:` checkpoints) without loading the\n * whole history. An empty `prefixes` array matches nothing.\n *\n * Optional: a store that omits it still works — the engine falls back to {@link listCheckpoints}\n * plus an in-JS prefix scan that produces the identical result.\n */\n listCheckpointsByNamePrefix?(runId: string, prefixes: string[]): Promise<StepCheckpoint[]>;\n}\n\n/**\n * A persisted schedule as the STORE sees it: a handful of queryable columns plus two JSON documents\n * the store keeps verbatim (`spec`, `state`) and never interprets. The engine's schedule client owns\n * their meaning (cron/interval math, overlap, catch-up) — so a store only has to persist rows and\n * answer \"which unpaused schedules are due by T\".\n */\nexport interface ScheduleRecord {\n /** Caller-chosen, stable id (e.g. `digest:user-42`) — also part of every run id it starts. */\n id: string;\n /** Partition: the namespace its runs are stamped with, and which schedulers fire it. */\n namespace: string;\n /** Registered workflow name the schedule starts. */\n workflow: string;\n /** A paused schedule is never due. */\n paused: boolean;\n /** Epoch ms at which it is next due (jitter included), or null when it will never fire again. */\n nextFireAt: number | null;\n /** Labels to list/filter schedules by (also stamped onto the runs it starts). */\n tags?: string[] | undefined;\n /** The schedule's definition — opaque to the store. */\n spec: Record<string, unknown>;\n /** The schedule's bookkeeping (last fire, last run id, last error…) — opaque to the store. */\n state: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Filter for {@link StateStore.listSchedules}. Every predicate is ANDed; absent = unrestricted. */\nexport interface ScheduleQuery {\n namespace?: string | undefined;\n workflow?: string | undefined;\n /** Only schedules carrying this tag. */\n tag?: string | undefined;\n paused?: boolean | undefined;\n /** Only DUE schedules: unpaused, `nextFireAt <= dueBy`. */\n dueBy?: number | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n}\n\n/** The terminal run statuses — a run in one of these is finished and will never change on its own.\n * Only these are eligible for retention pruning (a {@link RetentionPolicy} targeting a non-terminal\n * status would race the engine and delete live work). */\nexport const TERMINAL_RUN_STATUSES: readonly RunStatus[] = [\n 'completed',\n 'failed',\n 'cancelled',\n 'dead',\n];\n\n/**\n * One retention rule for hard-pruning terminal run history. Within `statuses` (terminal only), a run\n * is KEPT only if it satisfies EVERY bound you set, and pruned the moment it violates any:\n * - `maxAge` — prune runs whose `updatedAt` (≈ the time they reached terminal) is older than\n * `now - maxAge`. A number is milliseconds; a string is an `ms`-style duration parsed by\n * {@link parseDuration} (`'7d'`, `'2w'`, `'90m'` — note `'m'` is MINUTES; use `'30d'` for a month).\n * - `maxCount` — keep only the `maxCount` most-recent (by `updatedAt`) runs in the status set; prune\n * everything past that.\n *\n * Set one or both (both = the most-restrictive wins: capped at `maxCount` rows AND nothing older than\n * `maxAge`). Statuses not named by any policy are never pruned.\n */\nexport interface RetentionPolicy {\n statuses: RunStatus[];\n maxAge?: number | string;\n maxCount?: number;\n /**\n * Confine the policy to the runs matching these predicates (same semantics as the {@link RunQuery}\n * fields of the same names) — e.g. `{ namespace: 'acme' }` for one tenant, `{ tags: ['chat'] }` for\n * one kind of run, `{ workflows: ['report', 'report.branch'] }` for a workflow family. Absent = every\n * run in `statuses`. `maxCount` is then counted WITHIN the scope (\"keep acme's newest 100\").\n *\n * A scope matches runs by their own row, so a child run is only covered if it matches too (children\n * inherit their parent's `namespace`, but not its `tags`) — scope by `namespace` or by `workflows`\n * when a whole run tree must age out together.\n */\n scope?: RunScope | undefined;\n}\n\n/**\n * The run predicates a bulk operation (a scoped {@link RetentionPolicy}, `engine.purgeRuns`) is\n * confined to — the identity axes of a {@link RunQuery}: which tenant (`namespace`), which kind of\n * run (`workflow`/`tags`), which business entity (`attributes`). Status, origin and paging are left\n * out on purpose: each bulk operation owns its own status rule.\n */\nexport type RunScope = Pick<\n RunQuery,\n 'workflow' | 'workflows' | 'tag' | 'tags' | 'namespace' | 'namespaces' | 'attributes'\n>;\n\n/** True when `scope` sets at least one predicate — a bulk delete refuses an empty (match-all) scope. */\nexport function isNonEmptyRunScope(scope: RunScope | undefined): boolean {\n if (!scope) return false;\n return (\n scope.workflow !== undefined ||\n scope.workflows !== undefined ||\n scope.tag !== undefined ||\n scope.tags !== undefined ||\n scope.namespace !== undefined ||\n scope.namespaces !== undefined ||\n (scope.attributes !== undefined && scope.attributes.length > 0)\n );\n}\n\n/** Typed, queryable per-run data — exact values for `eq`/`ne`, numbers/strings for range ops. */\nexport type SearchAttributes = Record<string, string | number | boolean>;\n\n/**\n * A Standard Schema (https://standardschema.dev — implemented by zod 3.24+, valibot, arktype, …)\n * whose validated OUTPUT is search-attribute-shaped: flat `string`/`number`/`boolean` values only.\n * Declared via `@Workflow({ searchAttributes })`, this makes `ctx.upsertSearchAttributes` reject any\n * write whose merged result doesn't conform. The `Output extends SearchAttributes` bound is enforced\n * structurally at the declaration site — a schema whose inferred output has a nested object/array\n * value (e.g. `z.object({ meta: z.object({ ... }) })`) fails to satisfy this type, so it's a\n * compile-time error to declare it as a `searchAttributes` schema, not a runtime surprise.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n *\n * const orderAttrs = z.object({\n * tier: z.enum(['free', 'pro']),\n * amount: z.number(),\n * rushOrder: z.boolean().optional(),\n * });\n *\n * @Workflow({ name: 'checkout', searchAttributes: orderAttrs })\n * class CheckoutWorkflow {\n * async run(ctx: WorkflowCtx<InferSearchAttributes<typeof orderAttrs>>, input: CheckoutInput) {\n * await ctx.upsertSearchAttributes({ tier: input.tier, amount: input.total });\n * }\n * }\n * ```\n */\nexport type SearchAttributesSchema<A extends SearchAttributes = SearchAttributes> =\n StandardSchemaV1<unknown, A>;\n\n/** Infer the validated OUTPUT shape of a {@link SearchAttributesSchema} — the typed attributes a\n * workflow declares via `@Workflow({ searchAttributes })`. Feed it straight into `WorkflowCtx<A>`:\n * `WorkflowCtx<InferSearchAttributes<typeof mySchema>>`. */\nexport type InferSearchAttributes<S extends StandardSchemaV1<unknown, SearchAttributes>> =\n StandardSchemaV1.InferOutput<S>;\n\nexport type AttributeOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in';\n\n/** One value a search attribute can hold, and so one operand a predicate compares against. */\nexport type AttributeValue = string | number | boolean;\n\n/**\n * One predicate over a run's {@link SearchAttributes}; a {@link RunQuery} ANDs them all.\n *\n * The scalar ops carry a single `value`. `in` carries a SET of values matched as OR, and it needs to\n * exist as its own op because ORing inside ONE predicate is the only way to express \"tier is pro or\n * enterprise\": two `eq` predicates on the same key are ANDed like every other pair, which no run can\n * satisfy. An empty `values` matches nothing, mirroring {@link RunQuery.statuses}.\n */\nexport type AttributeFilter =\n | { key: string; op: Exclude<AttributeOp, 'in'>; value: AttributeValue; values?: never }\n | { key: string; op: 'in'; values: AttributeValue[]; value?: never };\n\n/** The single-operand members of {@link AttributeFilter} — every op except the `in` set. */\nexport type ScalarAttributeFilter = Exclude<AttributeFilter, { op: 'in' }>;\n\nexport interface RunQuery {\n workflow?: string | undefined;\n /**\n * Match any of these workflows (`workflow IN (...)`). Same shape as {@link statuses}: ORed with\n * each other, ANDed with everything else, and further narrowed by a concurrent single `workflow`.\n * Empty array = matches nothing.\n */\n workflows?: string[] | undefined;\n status?: RunStatus | undefined;\n /**\n * Match any of these statuses (a `status IN (...)` filter). ORed together, and ANDed with the other\n * predicates. Use this instead of issuing one {@link listRuns} call per status — e.g. the singleton\n * admission gate counts `running` + `suspended` in-flight runs in a single scan. If both `status` and\n * `statuses` are set, both must hold (the single `status` further narrows the set). Empty array =\n * matches nothing.\n */\n statuses?: RunStatus[] | undefined;\n /** Only runs carrying this tag (exact match against {@link WorkflowRun.tags}). */\n tag?: string | undefined;\n /**\n * Only runs carrying ANY of these tags. A run's tags are already a set, so the useful multi-value\n * question is \"in this set\", not \"has all of them\" — an operator picking `etl` and `nightly` from a\n * facet list means the union, and asking for their intersection through this field would return\n * nothing for tags that never co-occur. ANDed with a concurrent single `tag`; empty = matches nothing.\n */\n tags?: string[] | undefined;\n /**\n * Typed/range predicates over {@link WorkflowRun.searchAttributes}, ANDed together (e.g. `amount`\n * >= 200 and `tier` = 'pro'). Applied in-process after the coarse filters, so pair with\n * `workflow`/`status`/`tag` to bound the scan on large stores.\n */\n attributes?: AttributeFilter[] | undefined;\n /** Restrict to runs in this namespace (exact match), ANDed with the other predicates. */\n namespace?: string | undefined;\n /** Restrict to runs in ANY of these namespaces (`namespace IN (...)`), so a console can compare a\n * few tenants side by side. ANDed with a concurrent single `namespace`; empty = matches nothing. */\n namespaces?: string[] | undefined;\n /**\n * Restrict to runs whose workflow was declared by this package (exact match against\n * {@link WorkflowRun.origin}), ANDed with the other predicates.\n *\n * A run with NO origin (unknown — see the field) matches no `origin` VALUE at all, so a UI facet\n * built on this must keep an \"all origins\" option: filtering by any single package silently hides\n * every unattributed run, which reads to an operator as \"those runs do not exist\". `null` selects\n * exactly that absent bucket (`origin IS NULL`), so a paginated console can offer an \"unknown\"\n * facet without having to hold every run in the browser to find them.\n */\n origin?: string | null | undefined;\n /**\n * Restrict to runs from ANY of these origins. `null` is a member like any other — it selects the\n * unattributed bucket — so `['@acme/billing', null]` is \"this package's runs plus the ones nothing\n * could attribute\", which the single {@link origin} cannot express at all. ANDed with a concurrent\n * single `origin`; empty = matches nothing.\n */\n origins?: Array<string | null> | undefined;\n limit?: number | undefined;\n offset?: number | undefined;\n}\n\n/**\n * The predicates a {@link RunFacetRow} count is taken over — a {@link RunQuery} minus the axes the\n * facets THEMSELVES report (`status`/`origin`) and minus paging. Keeping them out of the type is\n * what makes the counts answerable in one query: a console narrows by tag/tenant/attribute, and the\n * one call back tells it how the matching runs split across every status and every origin at once.\n */\nexport type RunFacetQuery = Omit<RunQuery, 'status' | 'statuses' | 'origin' | 'limit' | 'offset'>;\n\n/**\n * One `(status, origin)` cell of {@link StateStore.runFacets} — a `GROUP BY` row, not a page of runs.\n * A console pivots these into its status chips and its origin chips, so both stay exact while the\n * list itself is paginated. `origin` is `null` for runs carrying none (see {@link WorkflowRun.origin});\n * that bucket is a real, countable answer here rather than the absence a value-match cannot express.\n */\nexport interface RunFacetRow {\n status: RunStatus;\n origin: string | null;\n count: number;\n}\n\n/**\n * Which axis {@link StateStore.runValueFacets} enumerates the distinct VALUES of. Every member is an\n * axis {@link RunQuery} can then filter by, which is the point: the answer to \"what can I pick here\"\n * has to be spendable as a predicate, or a console is offering choices that return nothing.\n *\n * `attributeKey` lists the search-attribute keys in use (the left-hand side of a predicate);\n * `attributeValue` lists the values recorded under ONE key (its right-hand side).\n */\nexport type RunValueAxis =\n | { field: 'workflow' | 'status' | 'origin' | 'namespace' | 'tag' | 'attributeKey' }\n | { field: 'attributeValue'; key: string };\n\n/**\n * One distinct value of a {@link RunValueAxis} and how many of the matching runs carry it — the rows\n * behind a console's value picker. `value` is `null` only where the axis itself has an absent bucket\n * (a run with no `origin`); a count is never zero, since a value with no runs produces no row.\n */\nexport interface RunValueFacetRow {\n value: string | null;\n count: number;\n}\n\n/**\n * The order {@link StateStore.runValueFacets} returns rows in, and the reason a caller can page\n * them: most runs first, ties broken alphabetically, the absent bucket (`null`) last — and tags the\n * engine mints one of per key after everything else, since they otherwise crowd out every tag a\n * human wrote (see `ENGINE_MINTED_TAG_PREFIXES`).\n *\n * Fixed, not incidental: an unordered listing cannot be paged, because page two would be taken over\n * a different arrangement of the same rows and would both repeat and skip.\n */\nexport type RunValueFacetOrder = 'engine-tags-last, count desc, value asc, null last';\n\n/**\n * How much of the store {@link StateStore.runValueFacets} may read to answer.\n *\n * `limit` bounds the ROWS RETURNED (highest count first): tag and attribute-value cardinality is\n * unbounded in principle — a run tagged `singleton:<key>` mints a new tag per key — so a picker asks\n * for the top slice rather than the whole domain, and keeps free text for everything else.\n *\n * `scan` bounds the RUNS READ, for a store that cannot group an axis in the database and has to\n * count it in memory instead. Those axes report over the newest `scan` matching runs rather than\n * over all of them — a bounded, deliberately approximate answer, where the alternative is a full\n * scan on every keystroke.\n *\n * Which axes those are is a property of the ADAPTER, not of the axis: the column axes are a `GROUP\n * BY` everywhere, and an adapter that can expand a JSON array and join its attribute side table (the\n * MikroORM one does) answers `tag` and the attribute axes exactly too, ignoring `scan` entirely.\n */\nexport interface RunValueFacetOptions {\n limit?: number | undefined;\n scan?: number | undefined;\n /**\n * How many rows to skip, for a picker that pages as it scrolls. Meaningful only because the\n * ordering is fixed (see {@link RunValueFacetRow}), so page two continues page one instead of\n * re-shuffling it.\n *\n * On an axis answered from a bounded scan rather than a `GROUP BY` (see {@link scan}), paging is\n * over that window: values outside it were never candidates on page one either.\n */\n offset?: number | undefined;\n /**\n * Narrow to values CONTAINING this text, case-insensitively — what a picker's search box sends.\n *\n * Server-side on purpose. A picker that filters an already-fetched page can only search what it\n * happened to receive, so a rare value is unfindable precisely when searching is the only way to\n * reach it: the top slice it was cut from is the reason the operator is typing.\n */\n search?: string | undefined;\n}\n\n/** The transaction handle `StateStore.transaction` hands to its work callback. */\nexport interface StoreTransaction {\n /** The store-native transaction handle (TypeORM `EntityManager`, Prisma tx client, MikroORM `EntityManager`,\n * Drizzle tx) — do your business DB writes on THIS so they commit atomically with the checkpoint. */\n readonly raw: unknown;\n /** Persist the step checkpoint inside this transaction. */\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;\n}\n\n/** Binds an external signal `token` to the suspended run/step position waiting for it. */\n/** Options for {@link WorkflowCtx.all}. */\nexport interface AllOptions {\n /** `waitAll` (default) or `failFast` — see {@link WorkflowCtx.all}. */\n mode?: 'waitAll' | 'failFast';\n /**\n * The most children running at once. Unset sends the whole fan immediately. When set, children go\n * out in waves of `floor(concurrency / 2)`, two at a time (an odd limit runs one child under it):\n * a new wave starts as soon as an earlier one settles, so one slow child does not idle the rest of\n * the window. Each settled wave costs the parent one turn.\n *\n * Part of the fan's identity: child ids carry the wave, so changing it for an in-flight run is a\n * non-deterministic change like changing `inputs`.\n */\n concurrency?: number;\n}\n\n/** One child of a fan as {@link StateStore.registerChildWaits} writes it. */\nexport interface ChildWait {\n waiter: SignalWaiter;\n checkpoint: StepCheckpoint;\n}\n\nexport interface SignalWaiter {\n token: string;\n runId: string;\n seq: number;\n /**\n * The parallel-fan group this waiter belongs to, carried from the awaiting command so the resolving\n * `signal:<token>` checkpoint (notably `signal:child:<id>` for an awaited child run) can be tagged\n * with it. A worker's `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` with the same\n * group; without threading it through the waiter, the child-await checkpoint comes out untagged and the\n * dashboard renders the fan as a sequential chain instead of one parallel group. Undefined for an\n * ordinary (non-fan) signal/child await.\n */\n parallelGroup?: string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Transport — how a remote task travels to a worker and the result returns\n// ---------------------------------------------------------------------------\n\n/**\n * A DB-less tenant worker → control plane request to start a run. Published by a worker that has\n * no direct DB access (the hosted-control-plane tenant model) onto the\n * `<effectivePrefix>-start-run` queue; the control plane consumes it and turns it into a durable\n * run (P4 of the tenants plan).\n *\n * The `tenant` identifies the namespace that owns the run (maps to the engine's `namespace`); it\n * is separate from the wire-level key prefix so a single transport can serve multiple tenants.\n */\nexport interface StartRunMessage {\n tenant: string;\n /** Registered workflow name. */\n workflow: string;\n input: unknown;\n /** Optional caller-supplied run id (idempotency key). The engine generates one if absent. */\n runId?: string | undefined;\n /** Tags to stamp on the run (merged with the workflow's static @Workflow tags). */\n tags?: string[] | undefined;\n /** Typed, queryable run data to stamp on the run (same as {@link StartOptions.searchAttributes}). */\n searchAttributes?: SearchAttributes | undefined;\n}\n\n/**\n * A tenant worker → control plane read/control request over the shared transport. Enqueued on\n * `<effectivePrefix>-run-request`; the control plane's `onRunRequest` consumer answers it, scoped to\n * `tenant`, and publishes a {@link RunReply} on `<effectivePrefix>-run-reply` correlated by `requestId`.\n */\nexport interface RunRequest {\n /** Correlation id minted by the tenant; the matching {@link RunReply} carries it back. */\n requestId: string;\n /** The requesting tenant — the operator scopes the run's namespace to this. */\n tenant: string;\n body: RunRequestKind;\n}\n\n/** The discriminated verb + args of a {@link RunRequest}. Mirrors the tenant-facing `RunGateway`. */\nexport type RunRequestKind =\n | { kind: 'getRunDetail'; runId: string }\n | { kind: 'listRuns'; query: RunQuery }\n | { kind: 'runFacets'; query: RunFacetQuery }\n | {\n kind: 'runValueFacets';\n axis: RunValueAxis;\n query: RunFacetQuery;\n opts?: RunValueFacetOptions | undefined;\n }\n // Per-group worker health — the operator answers it scoped to the requester's own groups (see\n // `RunRequestResponder`), so a tenant's Workers panel shows ITS queues, never another tenant's.\n | { kind: 'workerHealth' }\n | { kind: 'cancel'; runId: string; opts?: { compensate?: boolean } }\n | { kind: 'retry'; runId: string }\n | { kind: 'continue'; runId: string }\n | { kind: 'retryWithInput'; runId: string; input: unknown }\n | { kind: 'redispatch'; runId: string }\n // Bulk, not runId-bearing (like `listRuns`/`workerHealth`) — the operator answers it in one shot\n // and filters the result to runs the requester's tenant actually owns (see `RunRequestResponder`).\n | { kind: 'waitingFor'; runIds: string[] };\n\n/** The control plane's answer to a {@link RunRequest}, correlated by `requestId`. */\nexport interface RunReply {\n requestId: string;\n result: RunReplyResult;\n}\n\n/** Success carries the verb's payload (JSON-serialised); failure carries a re-throwable error. */\nexport type RunReplyResult =\n | { ok: true; data: unknown }\n | { ok: false; error: { message: string; code?: string } };\n\n/** A lifecycle event re-published to a single tenant's channel (`<effectivePrefix>-tenant-events-<tenant>`)\n * so a store-less tenant can live-tail ITS OWN runs. Scoped by the run's namespace at publish time. */\nexport interface TenantEvent {\n tenant: string;\n event: EngineEvent;\n}\n\n/** A unit of work dispatched to a remote worker. This is the documented wire payload. */\nexport interface RemoteTask {\n runId: string;\n seq: number;\n /** Handler name the worker registered, e.g. `payments.charge-card`. */\n name: string;\n stepId: string;\n /** Worker group expected to handle this task. */\n group: string;\n input: unknown;\n /** W3C traceparent so the worker can continue the distributed trace. */\n traceparent?: string | undefined;\n /**\n * Opaque context carrier (tenant / user / correlation ids) the worker re-exposes to the step\n * handler, for cross-process propagation alongside the {@link traceparent}. The engine treats it\n * as a pass-through object and never inspects its shape — the producer (e.g. `@dudousxd/nestjs-context`)\n * owns the keys. Absent when no `context` provider is configured.\n */\n context?: Record<string, unknown> | undefined;\n /**\n * Id of the transport this task was dispatched on (when the engine runs a pool — see\n * {@link NamedTransport}). A worker that consumes several transports replies via the matching one,\n * so failover is symmetric without the worker choosing a transport. Absent for a single transport.\n */\n transport?: string | undefined;\n /**\n * Admission priority carried through to the broker (BullMQ job `priority`) so a transport that\n * supports priority ordering lets an urgent task jump ahead of already-enqueued lower-priority\n * ones at the worker. Mirrors the per-call `priority` from `ctx.step(..., { priority })`. Higher\n * wins; absent means default/unprioritised. Transports without priority support ignore it.\n */\n priority?: number | undefined;\n attempt: number;\n}\n\nexport interface StepResult {\n runId: string;\n seq: number;\n stepId: string;\n status: 'completed' | 'failed';\n output?: unknown;\n error?: StepError | undefined;\n /** Epoch ms when the worker began processing — lets the engine report queue-wait time. */\n startedAt?: number | undefined;\n /** Structured events the worker emitted while running the step (sub-step outcomes, logs). */\n events?: StepEvent[] | undefined;\n}\n\nexport interface Heartbeat {\n runId: string;\n seq: number;\n /**\n * The in-flight step this beat keeps alive. ABSENT for a RUN-scoped (workflow-turn) heartbeat: a\n * worker replaying a long workflow turn beats for its `runId` so the engine rearms the run's\n * `advance` deadline (see `WorkflowEngineDeps.remoteAdvanceSilenceMs`). The engine then keys the\n * liveness reset by `runId` instead of `stepId`.\n */\n stepId?: string | undefined;\n group: string;\n}\n\n// ---------------------------------------------------------------------------\n// Polyglot workflows — the workflow-task / commands protocol\n//\n// A workflow authored in a non-TS SDK (e.g. Python) runs coordinator-driven: the engine stays the\n// sole owner of the durable state + recovery/timers and advances the run one TURN at a time by\n// dispatching a {@link WorkflowTask} (the run's history) to a workflow worker, which REPLAYS the\n// function locally and returns a {@link WorkflowDecision} (the commands it produced). The engine\n// applies the decision (persist checkpoints, dispatch steps, schedule timers, settle the run). The\n// worker never touches the store. See docs/plans/2026-06-15-polyglot-workflows-protocol.md.\n// ---------------------------------------------------------------------------\n\n/** engine → workflow worker: advance this run one turn by replaying the function against `history`. */\nexport interface WorkflowTask {\n /** Dedupe id for this turn (a re-delivered task must be idempotent). */\n taskId: string;\n runId: string;\n /** Registered workflow name + the version the run started on — replay must use that version. */\n workflow: string;\n workflowVersion: string;\n input: unknown;\n /** Completed durable ops so far, ordered by seq — what the worker replays its results from. */\n history: HistoryEvent[];\n /** Signals delivered to the run but not yet consumed, so `wait_signal` resolves on replay. */\n pendingSignals?: Array<{ seq: number; signal: string; payload: unknown }>;\n group: string;\n /** Id of the transport this task was dispatched on (pool failover) — see {@link NamedTransport}. */\n transport?: string;\n traceparent?: string;\n /**\n * Admission priority carried to the broker (BullMQ job `priority`) so an urgent child workflow can\n * jump ahead of already-enqueued lower-priority ones at the worker. Higher wins; absent means\n * default/unprioritised. Transports without priority support ignore it.\n */\n priority?: number | undefined;\n attempt: number;\n}\n\n/** One resolved durable op in a run's history — a superset of a completed {@link StepCheckpoint}. */\nexport interface HistoryEvent {\n seq: number;\n kind: 'step' | 'call' | 'timer' | 'signal' | 'child';\n name?: string | undefined;\n /** Resolved value: a step/call output, a child run's output, a signal payload. */\n output?: unknown;\n /** Set when the op resolved to a failure (e.g. a failed remote step the workflow may catch). */\n error?: StepError | undefined;\n}\n\n/** A decision the workflow function produced at a `seq` that was not yet in history. */\nexport type WorkflowCommand =\n /** `ctx.step(handlerOrName, input)` — dispatch a step (by typed handler reference or by name) and\n * await it. A worker's `ctx.gather_calls([...])` fan-out tags every dispatched call with the same\n * `parallelGroup` so the dashboard renders the dispatched steps as one parallel fan (parity with\n * the gathered `recordStep` / `startChild` tags). Undefined for a lone sequential `ctx.step`. */\n | {\n kind: 'call';\n seq: number;\n name: string;\n group: string;\n input: unknown;\n parallelGroup?: string;\n }\n /** `ctx.step(name, body)` — a LOCAL step the worker already ran this turn; the engine persists its\n * result so replay returns it instead of re-running (durability for side-effectful work).\n * `startedAt`/`finishedAt` (epoch ms) carry the step's real wall-clock window so the dashboard\n * shows a true duration instead of 0ms, and `events` carry the sub-process/log trail the step\n * emitted (so each handler's p-processes show under it). All optional for back-compat. */\n | {\n kind: 'recordStep';\n seq: number;\n name: string;\n output?: unknown;\n error?: StepError;\n startedAt?: number;\n finishedAt?: number;\n events?: StepEvent[];\n /** A worker's `ctx.gather([...])` tags every step in the parallel fan with the same group, so the\n * engine carries it onto the checkpoint and the dashboard renders the fan as one group. */\n parallelGroup?: string;\n }\n /** `ctx.sleep(ms)` — a durable timer of `ms` duration. The engine computes the absolute deadline\n * (now + ms) when it applies the command, so the worker never reads the clock (determinism). */\n | { kind: 'sleep'; seq: number; ms: number }\n /** `ctx.wait_signal(name)` — block until a signal `name` is delivered to the run. */\n | { kind: 'waitSignal'; seq: number; signal: string }\n /** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle. A worker's\n * `ctx.all([...])` fan-out tags every dispatched child with the same `parallelGroup` so the\n * dashboard can render the fan as one group (parity with the gathered `recordStep` tag). */\n | {\n kind: 'startChild';\n seq: number;\n workflow: string;\n input: unknown;\n parallelGroup?: string;\n };\n\n/** workflow worker → engine: the result of replaying one turn of a remote workflow. */\nexport interface WorkflowDecision {\n taskId: string;\n runId: string;\n /** `continue` = produced `commands` and is blocked on an await; otherwise the run settles.\n * `cancelled` = the worker bailed at an op boundary because the run was cancelled mid-turn. */\n status: 'continue' | 'completed' | 'failed' | 'cancelled';\n /** New durable ops the replay produced this turn (status === 'continue'), ordered by seq. */\n commands: WorkflowCommand[];\n /** Final workflow output (status === 'completed'). */\n output?: unknown;\n /** Terminal error (status === 'failed'). */\n error?: StepError;\n}\n\n/**\n * workflow worker → engine: a LOCAL step's lifecycle, streamed AS IT HAPPENS (not batched into the\n * turn's final {@link WorkflowDecision}). A Python `@workflow` runs its `ctx.step`s inline over one\n * turn that can last minutes; without this the engine learns of the steps only when the turn ends,\n * so the dashboard shows nothing mid-run. The worker emits `running` when a step's body starts and\n * `completed`/`failed` when it settles; the engine checkpoints each immediately, so a step appears\n * in-flight and then resolves live. The turn's final `recordStep` command re-persists the same\n * checkpoint idempotently (replay history), so this is purely additive observability.\n */\nexport interface WorkflowStepEvent {\n runId: string;\n seq: number;\n name: string;\n phase: 'running' | 'completed' | 'failed';\n /** Epoch ms the step body began (all phases) and settled (`completed`/`failed`). */\n startedAt: number;\n finishedAt?: number;\n /** The replayed result / failure for the settled phases. */\n output?: unknown;\n error?: StepError;\n /** Sub-process + log trail the step emitted so far (the handler's p-processes). */\n events?: StepEvent[];\n /** A worker's `ctx.gather([...])` fan tags every step's lifecycle with the same group so the\n * dashboard renders the live fan-out as one group (parity with the `recordStep` tag). */\n parallelGroup?: string | undefined;\n}\n\n/**\n * Advances a workflow run one turn. The engine has one per workflow: the default {@link InProcess}\n * one runs a registered TS function with the in-process replay machinery; a remote one dispatches a\n * {@link WorkflowTask} to a worker (Python) and awaits its {@link WorkflowDecision}. Either way the\n * engine applies the returned decision — so recovery, timers, singleton and dead-letter stay engine\n * concerns, identical for in-process and remote workflows.\n */\nexport interface WorkflowExecutor {\n /**\n * INLINE replay: advance the turn and RETURN its decision (the in-process executor runs the\n * registered TS function synchronously). The engine awaits this under the run's lease. Provide this\n * OR {@link dispatch} — exactly one. An executor with only `advance` is single-instance by nature\n * (the decision is produced in-process, not delivered over a broker).\n */\n advance?(\n run: WorkflowRun,\n history: HistoryEvent[],\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<WorkflowDecision>;\n /**\n * DISPATCH-AND-SUSPEND (broker-backed, multi-instance safe): enqueue the turn to a worker under the\n * ENGINE-SUPPLIED `taskId`, WITHOUT awaiting the decision. The engine generates `taskId`, records it\n * on the run as the awaited marker, AND releases the run's lease — all BEFORE calling this — so the\n * worker's {@link WorkflowDecision} (delivered over {@link Transport.onDecision} and applied DURABLY\n * by {@link WorkflowEngine.completeRemoteDecision}, which looks the run up by `decision.runId`) can\n * never arrive ahead of its marker or contend with a still-held lease and be dropped. This method\n * therefore ONLY enqueues — it owns no taskId generation and returns nothing. No in-memory await, so\n * the decision is never lost to a point-to-point broker handing it to a non-dispatching instance.\n * Provide this OR {@link advance} — exactly one.\n */\n dispatch?(\n run: WorkflowRun,\n history: HistoryEvent[],\n taskId: string,\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<void>;\n}\n\n/**\n * A transport in an ordered pool, identified by `id`. The engine dispatches on the first by default\n * and fails over to the next on a dispatch error; a step can pin one via `ctx.step(…, { transport })`.\n * The chosen `id` is stamped on the {@link RemoteTask} so a worker replies through the matching one.\n */\nexport interface NamedTransport {\n id: string;\n transport: Transport;\n}\n\n/**\n * Decides where a freshly-`start`ed run executes. `start` creates the run as `pending` and hands its\n * id here instead of running the body inline — so the API/caller never blocks on workflow execution.\n * The default in-process dispatcher runs it on this instance (a microtask); a broker-backed one\n * enqueues the id for a worker pool to consume (`engine.runOne(runId)`); a no-op one leaves it\n * `pending` in the store for a worker's `runPending` poll to pick up (DB-only, caller-doesn't-execute).\n */\nexport interface RunDispatcher {\n dispatch(runId: string): void | Promise<void>;\n}\n\nexport interface Transport {\n /** engine → worker */\n dispatch(task: RemoteTask): Promise<void>;\n /** worker → engine: a step finished (ok or error). */\n onResult(handler: (result: StepResult) => Promise<void>): void;\n /** worker → engine: liveness signal for an in-flight long step. */\n onHeartbeat(handler: (beat: Heartbeat) => Promise<void>): void;\n /** Release the transport's resources (broker workers, queues, connections) for a clean shutdown.\n * Optional — an in-process transport has nothing to close. Called on `onApplicationShutdown`\n * after the engine drains, so a deploy hands off instead of leaving the broker to time out. */\n close?(): Promise<void>;\n /** engine → workflow worker: dispatch a {@link WorkflowTask} (the polyglot-workflow path). Optional\n * — only transports that carry workflow tasks (BullMQ) implement it; the {@link RemoteWorkflowExecutor}\n * uses it + {@link onDecision} to advance a remote workflow over the broker. */\n dispatchWorkflowTask?(task: WorkflowTask): Promise<void>;\n /** workflow worker → engine: a replayed turn's {@link WorkflowDecision}. Pair with dispatchWorkflowTask. */\n onDecision?(handler: (decision: WorkflowDecision) => Promise<void>): void;\n /** workflow worker → engine: a LOCAL step's {@link WorkflowStepEvent}, streamed mid-turn so the\n * engine can checkpoint it live. Point-to-point (a single engine instance consumes each event and\n * persists it once — no cross-pod duplicate writes). Optional; only broker transports carry it. */\n dispatchStepEvent?(event: WorkflowStepEvent): Promise<void>;\n /** engine ← workflow worker: consume streamed {@link WorkflowStepEvent}s. Pair with dispatchStepEvent. */\n onStepEvent?(handler: (event: WorkflowStepEvent) => Promise<void>): void;\n /** Worker-health for a group: queue backlog + live worker heartbeats. Optional — only broker\n * transports (BullMQ) that can introspect the task queue and the worker-heartbeat keys implement\n * it. The engine aggregates this across its groups in {@link WorkflowEngine.workerHealth}. */\n groupHealth?(group: string): Promise<GroupHealth>;\n /** Distinct groups that currently have a live worker heartbeat — discovered from the heartbeat\n * keyspace, so a group with workers but no engine-side registration (e.g. a local-step group)\n * still surfaces. Pairs with {@link groupHealth}. */\n listWorkerGroups?(): Promise<string[]>;\n /**\n * The live handshake {@link WorkerDescriptor}s advertised for `group` (design §7.2). Optional — only\n * broker transports that carry the two-tier descriptor advertisement (BullMQ) implement it; a pure\n * in-process transport returns nothing, so the engine's routing guard stays disengaged (legacy\n * assume-compatible, design §7.7). The engine feeds these into {@link planDispatch} to decide whether\n * a run can dispatch to `group` or must park `blocked`.\n */\n readWorkerDescriptors?(group: string): Promise<WorkerDescriptor[]>;\n /**\n * Every live {@link WorkerDescriptor} in the deployment, across all groups — the read behind\n * {@link WorkflowEngine.announcedWorkflows}. Optional, same as {@link readWorkerDescriptors}: a\n * transport that cannot introspect the advertisement keyspace returns nothing and the registry is\n * simply empty.\n *\n * Deliberately NOT `listWorkerGroups()` + a read per group: a worker publishes the SAME descriptor\n * under every token it consumes, so per-group reads cost one round trip per group to re-fetch bytes\n * the caller already has. One pass over the advertisement keyspace, de-duplicated by `instanceId`,\n * answers with one scan and no per-group fan-out — and it also sees an instance whose groups the\n * caller could not have enumerated.\n */\n readAllWorkerDescriptors?(): Promise<WorkerDescriptor[]>;\n /**\n * Every live worker heartbeat in the deployment, across all groups — the LIVENESS floor under\n * {@link WorkflowEngine.workflowDirectory}. Optional, same as {@link readAllWorkerDescriptors}.\n *\n * It exists because a descriptor is the richer advertisement but not the universal one: an SDK\n * that predates the handshake beats a liveness key and publishes no descriptor at all, and reading\n * only descriptors reports such a fleet as EMPTY while it is serving work. Convention routing\n * already resolves those workers off exactly these keys, so a directory built without them\n * contradicts the dispatcher standing next to it.\n *\n * Distinct from {@link listWorkerGroups}, which answers with tokens alone: this carries the\n * instance behind each one, so the directory can say how many workers back a name and a partition\n * sighting can name who is beating there.\n */\n readAllWorkerHeartbeats?(): Promise<WorkerHeartbeat[]>;\n /**\n * DB-less tenant worker → control plane: publish a {@link StartRunMessage} requesting a new run.\n * Optional — only transports that carry the hosted-control-plane protocol (P4) implement this.\n * The message is enqueued on `<effectivePrefix>-start-run`; the control plane's\n * `onStartRun` consumer turns it into a durable run.\n */\n dispatchStartRun?(msg: StartRunMessage): Promise<void>;\n /**\n * control plane ← tenant worker: consume {@link StartRunMessage}s and start runs. Pair with\n * {@link dispatchStartRun}. Optional — only control-plane-side transports implement this.\n */\n onStartRun?(handler: (msg: StartRunMessage) => Promise<void>): void;\n /**\n * Tenant worker → control plane: publish a {@link RunRequest} (read/control) on\n * `<effectivePrefix>-run-request`. Optional — only broker transports carry it.\n */\n dispatchRunRequest?(msg: RunRequest): Promise<void>;\n /** control plane ← tenant worker: consume {@link RunRequest}s. Pair with {@link dispatchRunRequest}. */\n onRunRequest?(handler: (msg: RunRequest) => Promise<void>): void;\n /** control plane → tenant worker: publish a correlated {@link RunReply} on `<effectivePrefix>-run-reply`\n * (pub/sub; every tenant subscribes and filters by `requestId`). */\n publishRunReply?(reply: RunReply): Promise<void>;\n /** tenant worker ← control plane: consume {@link RunReply}s (filter by `requestId` client-side). */\n onRunReply?(handler: (reply: RunReply) => void): void;\n /** control plane → tenant worker: re-publish a lifecycle {@link TenantEvent} on the run's per-tenant\n * channel `<effectivePrefix>-tenant-events-<tenant>`. */\n publishTenantEvent?(evt: TenantEvent): Promise<void>;\n /** tenant worker ← control plane: subscribe to THIS tenant's event channel. Returns an unsubscribe fn. */\n onTenantEvent?(tenant: string, handler: (evt: TenantEvent) => void): () => void;\n}\n\n/** How a worker decides its concurrency, carried in {@link WorkerStatus} so a dashboard can tell a\n * fixed knob from a self-regulating one (and, for the latter, where the controller currently sits). */\nexport interface WorkerConcurrencyStatus {\n /** `fixed` = the configured `concurrency` number, never moves. `adaptive` = the controller tunes it. */\n mode: 'fixed' | 'adaptive';\n /** The concurrency ceiling in effect right now (fixed: the configured value; adaptive: the live limit). */\n limit: number;\n /** Adaptive only — the floor the controller won't go below. */\n min?: number;\n /** Adaptive only — the ceiling the controller won't exceed. */\n max?: number;\n}\n\n/** The adaptive controller's most recent limit change — the \"why did it move\" a dashboard shows so an\n * auto-tuner isn't a black box. Absent until the controller first adjusts (or for a fixed worker). */\nexport interface WorkerAdjust {\n /** Epoch ms of the adjustment. */\n at: number;\n /** Limit before this change. */\n from: number;\n /** Limit after this change. */\n to: number;\n /** Why it moved: `ram_ceiling` (hard brake), `backpressure` (errors/stall), `grow` (had headroom),\n * `shrink` (latency gradient showed queuing), `cpu_ceiling`. */\n reason: 'ram_ceiling' | 'cpu_ceiling' | 'backpressure' | 'grow' | 'shrink';\n}\n\n/** A live snapshot of a worker's execution state, carried in the worker-liveness heartbeat (so it\n * rides the existing TTL'd key — no extra round-trip) and surfaced per worker in the dashboard. Every\n * field beyond {@link concurrency}/{@link inFlight} is best-effort: a field a runtime can't measure is\n * simply omitted. The shape is shared by the TS and Python SDKs so a mixed-language group reports\n * uniformly. */\nexport interface WorkerStatus {\n /** Which SDK is running this worker — `node` (TS) or `python`. */\n runtime?: 'node' | 'python';\n /** The worker's concurrency knob and its live ceiling. */\n concurrency: WorkerConcurrencyStatus;\n /** Tasks executing right now (0..limit). With `limit`, this is the saturation a dashboard charts. */\n inFlight: number;\n /** Resident set size in bytes, if the runtime can read it. */\n rssBytes?: number;\n /** The process memory ceiling in bytes (cgroup `memory.max`, else host total), if known. */\n rssLimitBytes?: number;\n /** RSS as a percent of {@link rssLimitBytes} (0..100) — what the adaptive RAM brake watches. */\n rssPct?: number;\n /** Process CPU utilisation percent over the last control tick (0..100×cores), if measured. */\n cpuPct?: number;\n /** Completed tasks per minute over the recent window — the controller's throughput signal. */\n throughputPerMin?: number;\n /** p95 of recent task durations in ms — the latency a dashboard charts against the limit. */\n p95Ms?: number;\n /** The adaptive controller's last limit change (absent for a fixed worker or before the first move). */\n lastAdjust?: WorkerAdjust;\n}\n\n/** One worker's liveness record — a TTL'd heartbeat a worker refreshes while it's consuming. Its\n * ABSENCE (the key expired) is the signal: a worker that died or stalled stops refreshing. */\nexport interface WorkerHeartbeat {\n /** The worker group this instance serves (e.g. `pipeline`, `processing-workflows`). */\n group: string;\n /** Stable per-process id (host + pid), so N replicas of a group each show as a distinct worker. */\n instanceId: string;\n /** Epoch ms of the worker's most recent heartbeat. */\n lastBeatAt: number;\n /** The worker's live execution snapshot, when its heartbeat carries one (newer SDKs stamp a JSON\n * value; an older SDK's bare-timestamp heartbeat leaves this undefined). */\n status?: WorkerStatus;\n}\n\n/** Per-group worker-health snapshot: how much work is queued vs. how many workers are alive to do it.\n * The actionable alert state is `depth > 0 && liveWorkers.length === 0` — work piling up with no\n * consumer (exactly the failure where a worker is \"alive but not consuming\"). */\nexport interface GroupHealth {\n group: string;\n /** Outstanding jobs in the group's task queue (waiting + active + delayed + prioritized). */\n depth: number;\n /** Workers with a non-expired heartbeat for this group. */\n liveWorkers: WorkerHeartbeat[];\n /**\n * Whether this group serves a `@Workflow` body or a `@Step`/handler — route-by-handler gives each\n * its own queue, so a health list mixes both. Classified by the CONTROL PLANE from its authoritative\n * registry (`workerHealth()`): a group whose base name is a registered workflow is `'workflow'`,\n * everything else (in-process steps, remote `handle_*`) is `'step'`. `undefined` only when no\n * control-plane registry was available to classify (e.g. a transport that reports health with no\n * engine). Lets a dashboard summarise the fleet in domain terms (\"N workflows · M steps\") instead of\n * leaking the raw queue count.\n */\n kind?: 'workflow' | 'step';\n}\n\n/**\n * The **control plane** — a broadcast pub/sub across ALL engine instances (every pod), separate\n * from the {@link Transport}'s point-to-point work queues (`dispatch`/`onResult`). It carries what\n * every instance may need regardless of who runs a given run: lifecycle events (so a dashboard-only\n * pod can live-tail a run executing on a worker pod) and cancellation (so the pod actually running a\n * run learns it was cancelled elsewhere). In-process implementations broadcast locally; a\n * cross-process one (BullMQ) fans out over its broker (Redis pub/sub). Give the engine a\n * `controlPlane` to enable cross-instance events/cancellation; omit it and the engine is local-only.\n * A transport that can broadcast may implement this too and be passed as both.\n */\nexport interface ControlPlane {\n publishControl(msg: ControlMessage): Promise<void>;\n onControl(handler: (msg: ControlMessage) => void): void;\n}\n\n/** A message on the {@link ControlPlane}. `from` is the originating engine's `instanceId`, so a\n * broker that echoes a publish back to its own subscriber (e.g. Redis pub/sub) can be deduped by\n * the originator. */\nexport type ControlMessage = { from?: string } & (\n | { kind: 'event'; event: EngineEvent }\n | { kind: 'cancel'; runId: string }\n // A run was just enqueued — nudge worker instances to pick it up now instead of on the next poll.\n | { kind: 'enqueued'; runId: string }\n);\n\n// ---------------------------------------------------------------------------\n// Authoring — workflows, local steps, and typed remote steps\n// ---------------------------------------------------------------------------\n\nexport type BackoffStrategy = 'fixed' | 'exp';\n\n/**\n * Options for `ctx.child` / `ctx.startChild`. A bare string passed instead is shorthand for\n * `{ childId }`, so the existing `ctx.child(ref, input, 'my-id')` form keeps working.\n */\nexport interface ChildCallOptions {\n /** Deterministic child run id; defaults to one derived from the parent run id + call position. */\n childId?: string | undefined;\n /**\n * Pin the child to this EXACT registered version instead of the newest one — the same contract as\n * `StartOptions.version`, reached from inside a workflow body: an unregistered version fails the\n * child's start rather than quietly running a different body, and a version can only be pinned on a\n * workflow that is really registered (not on the synthesized remote/convention routes). A `ctx.child`\n * whose pinned start fails surfaces it as a failed child on the parent's waiter; a fire-and-forget\n * `ctx.startChild` buffers it until the parent joins the id.\n *\n * Replay-safe as long as you pass a CONSTANT (`{ version: '2' }`), which is the point — it names the\n * body you meant. Computing it from a live registry read at call time would make the body\n * non-deterministic, exactly like reading the clock.\n */\n version?: string | undefined;\n /**\n * Dispatch priority for a REMOTE child workflow — stamped on the child run and carried onto every\n * {@link WorkflowTask} dispatched to advance it, so an urgent child can jump ahead of enqueued\n * lower-priority ones at the worker. Higher wins; absent = unprioritised. Ignored for an in-process\n * (TS class) child, which runs in the engine and never hits a broker queue.\n */\n priority?: number | undefined;\n}\n\nexport interface StepOptions {\n /** Max attempts before the step (and run) fails. */\n retries?: number;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt). */\n backoff?: BackoffStrategy;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. */\n backoffMs?: number;\n /** Upper bound on the (exponential) backoff delay. */\n backoffMaxMs?: number;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */\n jitter?: boolean;\n /**\n * Liveness window for a dispatched step (`ctx.step`): if the worker produces no result and no\n * heartbeat within this many ms, the engine presumes it dead and fails the dispatch with a\n * `RemoteStepTimeout` (retryable — it re-dispatches per `retries`). Each heartbeat resets the\n * window. Omit to wait indefinitely.\n */\n timeoutMs?: number;\n /**\n * Capabilities a live worker MUST advertise to run this dispatched step (handshake design §7.5).\n * The control-plane routes the step only to workers whose descriptor advertises every name here;\n * if descriptors are published on the step's group but NONE is capability-capable + protocol-\n * compatible, the run parks `blocked` (never a silent hang) and the blocked-recovery poll re-drives\n * it when a capable worker appears. Absent/empty = \"runs anywhere\" (the default; backward-compatible\n * — a legacy fleet publishing no descriptors skips the guard entirely, design §7.7).\n */\n requires?: string[];\n /**\n * Saga compensation: if this step completes but the run later **fails**, the engine runs the\n * registered `compensate` callbacks in reverse order (undo what was done). Local steps only.\n * Idempotency note: a step is already deduplicated by its deterministic `stepId` (runId:seq) —\n * remote workers can use it as the idempotency key, so there's no separate key option.\n */\n compensate?: () => Promise<void>;\n}\n\n/**\n * The structural carrier a dispatched `ctx.step` call resolves to and hands the engine: `name` is\n * the routing contract (the worker registers a handler under the same name, and routing is BY that\n * name — a worker subscribes per registered handler name, not a hand-declared group). There is no\n * public factory for this anymore — a `ctx.step(ref, input)` call builds one internally from the\n * `@Step`-stamped name (see {@link StepRef}/`stepNameOf`); a `ctx.step(name, input)` call builds one\n * from the literal string. `input`/`output` are optional runtime zod schemas an authoring layer MAY\n * attach (e.g. `@Step({ input, output })`) for validation at the dispatch boundary — a bare `@Step()`\n * carries neither, and the engine skips validation when they're absent.\n */\nexport interface StepDef<TInput = unknown, TOutput = unknown> extends StepOptions {\n name: string;\n /** Optional isolation partition; routing is by `name`. Suffixes the routing token as\n * `<name>@<partition>` (via {@link tenantGroup}) — omit to route by the bare (sanitized) `name`. */\n partition?: string | undefined;\n input?: z.ZodType<TInput> | undefined;\n output?: z.ZodType<TOutput> | undefined;\n}\n\n/**\n * A durable webhook handle minted by {@link WorkflowCtx.webhook}. Hand `url` to a third party,\n * then `await wait()` — the run suspends with zero compute until the external system POSTs the\n * callback (delivered as `engine.signal(token, body)`), and resumes with the body.\n */\nexport interface DurableWebhook<TPayload = unknown> {\n /** Deterministic signal token (`wh:<runId>:<seq>`) the callback delivers on — stable across replay. */\n readonly token: string;\n /**\n * Public callback URL for `token`, built by the engine's `webhookUrl` option. Hand this to the\n * third party. `undefined` when no builder is configured (use {@link DurableWebhook.token} to\n * build your own).\n */\n readonly url?: string | undefined;\n /**\n * Suspend until the callback arrives, then resume with its payload. Waits indefinitely by default —\n * no compute consumed. Pass `{ timeoutMs }` to bound the wait: if the deadline passes first the call\n * throws a `SignalTimeoutError` (catch it in the workflow to branch) — same timeout semantics as\n * {@link WorkflowCtx.waitForSignal}. The deadline is computed once (on the first call) and persisted,\n * so a replay reuses the recorded deadline rather than recomputing it from the current clock.\n */\n wait(opts?: { timeoutMs?: number }): Promise<TPayload>;\n}\n\n/**\n * Options for a dispatched {@link WorkflowCtx.step} call. `retries`/`backoff`/`backoffMs`/\n * `backoffMaxMs`/`jitter`/`timeoutMs` are a PER-CALL override of the `@Step`-declared\n * {@link StepConfig} (see `stepConfigOf`) — the effective policy `ctx.step` builds into the dispatched\n * {@link StepDef} is `{ ...stepConfigOf(ref), ...opts }`, so a call-site value wins field-by-field. The\n * string (cross-runtime) form of `ctx.step` has no stamped `@Step` to read, so it uses these fields\n * as-is.\n */\nexport interface StepDispatchOpts {\n /** Subject the dispatch to a registered flow-control queue (concurrency / rate limit). */\n queue?: string;\n /** Admission priority within `queue`; higher is admitted first when a slot is contended\n * (default 0). No effect without a `queue`. */\n priority?: number;\n /** The fairness bucket for a queue with `fairness: 'key'` (e.g. a tenant id) — the queue\n * round-robins across distinct keys so one key can't monopolize the budget. Defaults to the run\n * id when omitted. No effect without a `queue`. */\n fairnessKey?: string;\n /** Pin the dispatch to a named transport in the pool (else the pool's first, with failover to the\n * rest). See `engine.registerQueue` / the engine's `transports` option. */\n transport?: string;\n /** Max attempts before the step (and run) fails. Overrides the `@Step`-declared value. */\n retries?: number;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt).\n * Overrides the `@Step`-declared value. */\n backoff?: BackoffStrategy;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. Overrides the\n * `@Step`-declared value. */\n backoffMs?: number;\n /** Upper bound on the (exponential) backoff delay. Overrides the `@Step`-declared value. */\n backoffMaxMs?: number;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. Overrides\n * the `@Step`-declared value. */\n jitter?: boolean;\n /** Liveness window for this dispatched step: no result/heartbeat within this many ms presumes the\n * worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per\n * `retries`). Omit to wait indefinitely. Overrides the `@Step`-declared value. */\n timeoutMs?: number;\n /** Capabilities a live worker must advertise to run this dispatch (handshake design §7.5). Overrides\n * the `@Step`-declared `requires`. Absent = inherit the def-level value (or \"runs anywhere\"). */\n requires?: string[];\n}\n\n/** What a saga undo handler receives: the compensated step's original input and its result — the\n * ONE argument a compensation `@Step` is called with, so it's self-describing on the wire (a\n * Python worker sees `{ input, output }` with no side-channel lookup needed). */\nexport interface StepUndo<TInput, TOutput> {\n input: TInput;\n output: TOutput;\n}\n\n/**\n * Derive a `ctx.step` compensation handler's expected argument from the ORIGINAL step's method\n * type, so the ref form is compile-checked against the step it undoes:\n *\n * ```ts\n * async cancelBooking(undo: UndoOf<FlightService['book']>) { ... }\n * ```\n *\n * `...rest: never[]` pins this to a single-argument method (the shape every `@Step` handler has —\n * see {@link StepRef}); `Awaited<R>` unwraps a `Promise<TOutput>` return down to `TOutput`.\n */\nexport type UndoOf<H> = H extends (input: infer I, ...rest: never[]) => infer R\n ? StepUndo<I, Awaited<R>>\n : never;\n\n/**\n * The context handed to a workflow function. Every interaction with the outside world goes\n * through it so the engine can checkpoint — the workflow body itself stays deterministic.\n *\n * Generic over `A`, the run's {@link SearchAttributes} shape — narrows {@link upsertSearchAttributes}\n * when a workflow declares a `@Workflow({ searchAttributes })` schema (pass\n * `WorkflowCtx<InferSearchAttributes<typeof mySchema>>` as the `run` method's ctx type). Defaults to\n * the untyped `SearchAttributes`, so every existing `WorkflowCtx` usage is unaffected.\n */\nexport interface WorkflowCtx<A extends SearchAttributes = SearchAttributes> {\n readonly runId: string;\n /**\n * Run a durable step — always dispatched, always engine-scheduled: the ONE step primitive (no\n * local/remote placement choice). Pass the step's method **reference** (a `@Step`-decorated\n * method, typed by its own signature — refactor-safe, autocompleted):\n *\n * ```ts\n * const r = await ctx.step(this.extraction.runExtractionPage, { page, key });\n * ```\n *\n * or its **name** for a cross-runtime handler (no JS reference to import, e.g. a Python `@step`):\n *\n * ```ts\n * const out = await ctx.step<ProcResult>('processing:proc', input);\n * ```\n *\n * Both forms dispatch identically — a step runs on whatever worker serves that name and the run\n * suspends (zero compute) until the result lands, then resumes with it (durable, replay-safe).\n *\n * `opts.compensate` registers a SAGA UNDO for this call, dispatched (durably, in reverse order\n * with every other registered undo) if the run later fails or is cancelled with\n * `{ compensate: true }`. The undo is itself a normal `@Step` — pass its reference (compile-time\n * checked: it must accept `StepUndo<TInput, TOutput>` of THIS call, see {@link UndoOf}) or its\n * name for a cross-runtime undo handler. It runs on whatever worker serves that name, called with\n * the ONE `{ input, output }` envelope — never the original handler re-invoked in-process.\n */\n step<TInput, TOutput>(\n handler: StepRef<TInput, TOutput>,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput>;\n step<TOutput = unknown, TInput = unknown>(\n name: string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput>;\n /**\n * **Exactly-once** durable step for DB work: runs `fn` and writes the step's checkpoint in ONE\n * store transaction, so the business write and the \"done\" marker commit atomically — a crash can\n * never leave the write done-but-not-checkpointed (which a plain `ctx.step` would re-run). `fn`\n * receives the store-native transaction handle (`tx` — a TypeORM/MikroORM `EntityManager`, a Prisma\n * tx client, or a Drizzle tx); do your writes on it. Needs a SQL store that supports transactions\n * (the bundled SQL adapters do); throws otherwise.\n */\n transaction<TOutput>(name: string, fn: (tx: unknown) => Promise<TOutput>): Promise<TOutput>;\n /**\n * Call a durable **entity** op and await its result — the entity (`engine.registerEntity`) runs the\n * op serialized per `key` over durable state. e.g. `await ctx.callEntity('cart', userId, 'add', item)`.\n */\n callEntity<TResult = unknown>(\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<TResult>;\n /** Send a durable entity op without awaiting a result (fire-and-forget, dispatched once). */\n signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void>;\n /**\n * Durable sleep: suspends the run for `duration` (e.g. `'30s'`, `'2h'`, `'7 days'`, or ms as a\n * number) without consuming resources, resuming automatically once the timer is due — even\n * across restarts.\n */\n sleep(duration: string | number): Promise<void>;\n /**\n * Durable sleep until an **absolute** time (a `Date` or epoch ms) — like {@link sleep} but for a\n * fixed deadline (e.g. \"resume at midnight\"). Resumes automatically once the time passes, across\n * restarts. The recorded wake time is fixed on the first run, so it's replay-stable.\n */\n sleepUntil(when: Date | number): Promise<void>;\n /**\n * End this run and **continue as a fresh execution** of the same workflow with `input` and a clean\n * history — for long-running / looping workflows that would otherwise accumulate unbounded\n * checkpoints (and slow replays). The next run gets id `<runId>~N`. Terminal: it always throws, so\n * code after it never runs. Carry forward whatever state the next iteration needs in `input`.\n */\n continueAsNew(input?: unknown): Promise<never>;\n /**\n * Suspend the run until an external `engine.signal(token, payload)` arrives (e.g. a webhook or\n * human approval), then resume with the payload. Waits indefinitely by default — no compute\n * consumed. Pass `{ timeoutMs }` to bound the wait: if the deadline passes first the call throws\n * a `SignalTimeoutError` (catch it in the workflow to branch).\n */\n waitForSignal<TPayload>(token: string, opts?: { timeoutMs?: number }): Promise<TPayload>;\n /**\n * Wait for a named **event** published via `engine.publishEvent(name, payload)`, then resume with\n * the payload. Unlike a signal (point-to-point by token), events are name-based pub/sub: pass an\n * optional `match` (a subset of the payload that must deep-equal) so a publish fans out only to the\n * runs it concerns — e.g. `ctx.waitForEvent('payment.settled', { match: { orderId } })`. `timeoutMs`\n * bounds the wait (throws `SignalTimeoutError`). No compute consumed while waiting.\n */\n waitForEvent<TPayload>(\n name: string,\n opts?: { match?: Record<string, unknown>; timeoutMs?: number },\n ): Promise<TPayload>;\n /**\n * An external task with **async completion**: run `dispatch` once (checkpointed — e.g. send to a\n * queue, kick off a non-durable worker or a foreign service like a Python process), then suspend\n * with zero compute until `engine.completeTask(runId, name, result)` (or `failTask`) reports back,\n * and resume with the result. The durable, first-class counterpart of the hand-rolled\n * \"dispatch over SQS → wait for COMPLETE_PHASE → signal\" pattern. `name` must be unique per run.\n */\n task<TResult>(\n name: string,\n dispatch: () => Promise<void>,\n options?: StepOptions,\n ): Promise<TResult>;\n /**\n * Run another registered workflow as a **tracked child** and await its result: starts it once and\n * suspends — zero compute — until the child reaches a terminal state, then resumes with the child's\n * output (or throws a FatalError if the child failed). `childId` defaults to a deterministic id\n * derived from this run and the call position, so it's stable across replay.\n *\n * Pass the child's **class** (`ctx.child(ShippingWorkflow, input)`) for a typed input + result; pass\n * a **string** name for a cross-runtime child (e.g. a Python workflow) where there's no class.\n */\n child<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n options?: string | ChildCallOptions,\n ): Promise<WorkflowOutputOf<C>>;\n child<TOutput>(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<TOutput>;\n /**\n * Start a child workflow **fire-and-forget**: dispatches it once (checkpointed, replay-safe) and\n * returns its run id immediately — the parent keeps running instead of suspending. Use it to kick\n * off side work (an audit log, a notification) you don't need to wait on, or to fan out: collect\n * the ids, then later `await ctx.child(...)` each with the same id to join (the start is idempotent\n * by id, so the child runs exactly once). Class or string ref, like {@link child}.\n */\n startChild<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n startChild(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n /**\n * Run N children of the SAME workflow **in parallel** and wait for ALL of them: dispatches one\n * child per entry in `inputs` (concurrently, each with its own durable lifecycle), suspends — zero\n * compute — until every child reaches a terminal state, then resumes with their outputs in **input\n * order**. Child ids are group-scoped and stable (`<runId>.all.<firstSeq>.<i>`), and the running\n * placeholders share a `parallelGroup` tag so the dashboard renders the fan-out as one group.\n *\n * `mode` (default `waitAll`): `waitAll` waits for all then throws an aggregate {@link GatherError}\n * if any failed; `failFast` throws as soon as a failed child is seen, and requests cancellation of\n * every sibling that hasn't completed yet (best-effort, plain cancel — no saga undo; a sibling\n * mid-step only observes it at its next checkpoint, it isn't force-killed mid-synchronous-execution,\n * so a fast sibling can still slip through and complete). Empty `inputs` returns `[]` with no side\n * effects. The wait-all / fan-out counterpart to {@link child}; parity with the Python SDK's\n * `gather_children`.\n *\n * `concurrency` caps how many children run at once (see {@link AllOptions.concurrency}).\n */\n all<C extends WorkflowClass>(\n workflow: C,\n inputs: WorkflowInputOf<C>[],\n opts?: AllOptions,\n ): Promise<WorkflowOutputOf<C>[]>;\n all<TOutput = unknown>(\n workflow: string,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<TOutput[]>;\n /**\n * Pause the run at this point until a human resumes it from the dashboard (or\n * `engine.continue(runId)`). Records a visible `pending` checkpoint so the breakpoint shows up\n * in the timeline, then suspends with zero compute — the durable equivalent of a debugger\n * breakpoint. Gate it on your own config to make breakpoints opt-in per run:\n * `if (cfg.breakAfterExtraction) await ctx.breakpoint('after-extraction')`.\n */\n breakpoint(label?: string): Promise<void>;\n /**\n * Mint a durable webhook: returns a handle with a deterministic `token` and (if the engine has a\n * `webhookUrl` builder) a public `url`. Hand the url to a third party — inside a `ctx.step` — then\n * `await handle.wait()` to suspend with zero compute until they POST the callback (the dashboard\n * turns that POST into `engine.signal(token, body)`). The first-class, replay-safe version of\n * \"expose a callback URL and wait for it\".\n */\n webhook<TPayload>(): DurableWebhook<TPayload>;\n /**\n * Publish a named, queryable value from inside the run — the latest value for `key` is readable\n * externally via `engine.getEvent(runId, key)` while the run is still in flight (progress, a\n * partial result, a status). Checkpointed and replay-safe (overwrites the previous value for the\n * same key). The read side has no effect on the run — the durable, suspend-model counterpart of a\n * Temporal query.\n */\n setEvent<TValue>(key: string, value: TValue): Promise<void>;\n /**\n * Expose a named **update point**: suspend until an external `engine.update(runId, name, arg)`\n * delivers `arg`, then resume with it. The update is run-scoped (`name` need only be unique within\n * the run) and gated by any validator registered via `engine.registerUpdateValidator` — a rejected\n * update never reaches here. Pass `{ timeoutMs }` to bound the wait (throws `SignalTimeoutError`).\n * The durable counterpart of a Temporal update handler.\n */\n onUpdate<TArg>(name: string, opts?: { timeoutMs?: number }): Promise<TArg>;\n /**\n * Guard an in-place workflow change without a new version. Wrap the changed code in\n * `if (await ctx.patched('my-change')) { …new… } else { …old… }`: a fresh run records a marker and\n * takes the new branch (`true`); a run already recorded under the old code keeps the old branch\n * (`false`), because its history has a real step where the marker would sit. The marker is\n * position-transparent for old runs (it doesn't shift their recorded steps), so guarding code is\n * replay-safe. Once every old run has drained, remove the guard (keep the new branch).\n */\n patched(id: string): Promise<boolean>;\n /**\n * Deterministic wall-clock, epoch **milliseconds** (like `Date.now()`): records the time on the\n * first run and replays the SAME value afterwards. Use this instead of `Date.now()`/`new Date()`\n * inside a workflow — a raw clock read returns a different value on every replay, which silently\n * corrupts a durable run. Returns a number so it composes in arithmetic (deadlines, elapsed);\n * for an ISO string do `new Date(await ctx.now()).toISOString()`. Every step is dispatched now\n * (see {@link step}), so a trivial timestamp capture gets this lightweight deterministic helper\n * instead of a full `@Step` + worker round-trip.\n */\n now(): Promise<number>;\n /**\n * **Deterministic capture.** Run `fn` once, checkpoint its result, and on replay return the SAME\n * value WITHOUT re-running `fn` — the durable way to bring a non-deterministic value into a workflow\n * where you control the generator: `ctx.sideEffect(() => uuidv7())`, `() => ulid()`,\n * `() => Math.random()`, a config/env read. Prefer a {@link step} for real work with side effects\n * (a DB write, an API call): `fn` here runs only once and MUST be effectively pure (it produces a\n * value; it is not re-executed on replay), like Temporal's `sideEffect`. For a plain timestamp use\n * {@link now}.\n */\n sideEffect<TValue>(fn: () => TValue | Promise<TValue>): Promise<TValue>;\n /**\n * Merge `attrs` into THIS run's {@link WorkflowRun.searchAttributes} — the indexed metadata the\n * dashboard and {@link RunQuery} filter on. Shallow merge: keys you don't pass are kept. Durable +\n * exactly-once — recorded at this position on the first run and SKIPPED on replay, so it does one\n * write, not one per turn. Use this instead of injecting the {@link StateStore} to mutate the run\n * you're executing (`@Inject(state-store)` + `store.updateRun(ctx.runId, …)` becomes\n * `ctx.upsertSearchAttributes(…)`).\n *\n * When the workflow declares a `@Workflow({ searchAttributes })` schema, the MERGED result (this\n * run's existing `searchAttributes` shallow-merged with `attrs`) is validated against it before the\n * write — an invalid merge throws, naming the workflow, the offending key(s), and the schema's\n * issues. Validation runs once, on the same first-run-only position as the write itself (skipped\n * entirely on replay, so it's never a source of nondeterminism); it must be synchronous — a schema\n * whose `validate` returns a `Promise` throws instead of being awaited. No schema declared ⇒\n * unchanged, unvalidated behavior.\n */\n upsertSearchAttributes(attrs: Partial<A>): Promise<void>;\n /**\n * Run a checkpointed step **in-process** — the escape hatch from the always-dispatched {@link step}\n * for work that must run inline in the workflow body. Like `step`, its result is a durable checkpoint\n * (returned, not re-run, on replay); unlike `step`, the body `fn` executes here rather than on a\n * worker, so it can carry an in-memory `compensate` callback for **sagas** — an undo the engine runs\n * in reverse if the run later fails (see [Sagas & compensation](/docs/reliability/sagas)). `fn`\n * receives a {@link StepLogger} for sub-process events. Prefer {@link step} for ordinary work; reach\n * for `localStep` when you need in-process execution or a compensation.\n */\n localStep<TOutput>(\n name: string,\n fn: (log: StepLogger) => Promise<TOutput>,\n options?: StepOptions,\n ): Promise<TOutput>;\n}\n\n/**\n * {@link WorkflowCtx} with ONE signature per method: the string-addressed forms of the four overloaded\n * methods (`step`, `child`, `startChild`, `all`), everything else unchanged.\n *\n * For code that drives the ctx DYNAMICALLY — an interpreter that runs a user-defined graph and only\n * ever knows workflow/step names as strings — and for test fakes. An overloaded method is awkward to\n * satisfy structurally (a fake must implement every overload, and a hand-written narrow interface\n * has to guess which overload TS will match), so depend on this instead:\n *\n * ```ts\n * type InterpreterCtx = Pick<DynamicWorkflowCtx, 'runId' | 'localStep' | 'child' | 'all' | 'sleep'>;\n * class Interpreter { constructor(private readonly ctx: InterpreterCtx) {} }\n *\n * async run(ctx: WorkflowCtx, input: Input) {\n * return new Interpreter(ctx).run(); // no cast — a WorkflowCtx IS a DynamicWorkflowCtx\n * }\n * ```\n *\n * Every `WorkflowCtx<A>` is assignable to `DynamicWorkflowCtx<A>` (guarded by\n * `dynamic-workflow-ctx.type-test.ts`), and a `Pick` of it is a plain object literal in a test.\n */\nexport interface DynamicWorkflowCtx<A extends SearchAttributes = SearchAttributes>\n extends Omit<WorkflowCtx<A>, 'step' | 'child' | 'startChild' | 'all'> {\n /** {@link WorkflowCtx.step} by step name (a cross-runtime handler, or a `@Step` by its name). */\n step<TOutput = unknown, TInput = unknown>(\n name: string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: string },\n ): Promise<TOutput>;\n /** {@link WorkflowCtx.child} by workflow name. */\n child<TOutput = unknown>(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<TOutput>;\n /** {@link WorkflowCtx.startChild} by workflow name. */\n startChild(\n workflow: string,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string>;\n /** {@link WorkflowCtx.all} by workflow name. */\n all<TOutput = unknown>(\n workflow: string,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<TOutput[]>;\n}\n\n/** Result of executing or resuming a workflow run. */\nexport interface RunResult {\n runId: string;\n status: RunStatus;\n output?: unknown;\n error?: StepError | undefined;\n}\n\n/**\n * Validates an incoming `engine.update` before it is delivered to the run. Throw (or return a\n * non-empty string) to reject — the run is left untouched. Return nothing/void to accept. May be\n * async (e.g. a business-rule check against a DB).\n */\n// A validator may return nothing (accept) or a reason string (reject); `void` is the intended\n// \"returned nothing\" case, sync or async.\nexport type UpdateValidator<TArg = unknown> =\n // biome-ignore lint/suspicious/noConfusingVoidType: `void` here means \"returned nothing\" (accept).\n (arg: TArg) => void | string | Promise<void | string>;\n\n/** Outcome of `engine.update`: rejected by the validator, or accepted and delivered. */\nexport type UpdateResult =\n | { accepted: false; reason: string }\n | { accepted: true; run: RunResult | null };\n\nexport type EngineEventType =\n | 'run.started'\n | 'run.completed'\n | 'run.failed'\n | 'run.suspended'\n | 'step.started'\n | 'step.completed'\n | 'step.failed'\n // A single step event (log line / sub-process outcome) emitted WHILE a step is still running, so\n // observers tail a long step's progress live instead of waiting for `step.completed` to deliver\n // the whole `events` array at once. Carries `event`; never persisted (live-tail only).\n | 'step.progress'\n // A run parked `blocked`: no live worker on its next-dispatch group is capability-capable +\n // protocol-compatible (handshake design §7.5/§7.6). Carries the structured `diagnostics` delta\n // (which capability/protocol gap, both descriptors) so the dashboard health panel + telescope\n // timeline render exactly WHY — never a bare boolean. The `error.code` is the machine code\n // (`capability.unavailable` / `protocol.incompatible`).\n | 'run.blocked';\n\n/**\n * A lifecycle event emitted by the engine. The observability surfaces (dashboard, OTel, the\n * Telescope integration) all subscribe to these rather than reaching into the store.\n */\nexport interface EngineEvent {\n type: EngineEventType;\n runId: string;\n workflow?: string | undefined;\n /** The run's worker-pool partition (see {@link WorkflowRun.namespace}), stamped on the `run.*`\n * lifecycle events (where the emitting call site already has the run in hand) so a tenant-event\n * re-publisher can scope without a per-event store read. Absent on `step.*` events. */\n namespace?: string | undefined;\n seq?: number | undefined;\n name?: string | undefined;\n kind?: StepKind | undefined;\n output?: unknown;\n error?: StepError | undefined;\n /** Wall-clock duration of the unit that just finished (step or run), when known. */\n durationMs?: number | undefined;\n /** For a remote step: how long it waited in the queue before a worker picked it up. */\n queueMs?: number | undefined;\n /** The live step event carried by a `step.progress` (the single log line / sub-process outcome a\n * running step just emitted). Absent on lifecycle events. */\n event?: StepEvent | undefined;\n /**\n * On a `step.started`: this dispatch is a lost-dispatch RE-DRIVE, not a first attempt — the step's\n * lease lapsed with no result and no heartbeat (the worker holding it is presumed gone), so the\n * engine re-enqueued it (see `WorkflowEngineDeps.remoteRedispatchMs`). Absent on a normal dispatch\n * and on a failure retry, so a dashboard/alert can tell \"re-driven after a lost worker\" apart from\n * \"retried after a failure\". The step's persisted event trail carries the same fact durably\n * (`step.redispatched`).\n */\n redispatched?: boolean | undefined;\n /** Capabilities the blocked dispatch required (on a `run.blocked` event). */\n requires?: string[] | undefined;\n /** The structured routing delta on a `run.blocked` event (design §7.6): which capability/protocol\n * gap fired, how many live workers were considered, and both descriptors — enough for the health\n * panel/telescope to render the reason. Absent on all other event types. */\n diagnostics?: DispatchDiagnostics | undefined;\n at: Date;\n}\n\nexport type EngineListener = (event: EngineEvent) => void;\n\n/** What a {@link StepInterceptor} is told about the local step it is wrapping. */\nexport interface StepInvocation {\n readonly runId: string;\n readonly workflow: string;\n /** The step name passed to `ctx.step(name, ...)` (also `'now'`/`'random'`/`'uuid'` internals). */\n readonly stepName: string;\n /** The step's logical position within the run. */\n readonly seq: number;\n /** 1-based attempt number — increments across `ctx.step` retries. */\n readonly attempt: number;\n}\n\n/**\n * Wraps the **real execution** of a local `ctx.step` (Template/Nest-style onion middleware). Call\n * `next()` to run the step body (or the next interceptor) and return — or transform — its result;\n * throw to fail the step. First-registered runs outermost. Interceptors fire only when a step\n * actually executes, NOT on replay (a replayed step returns its recorded output without running),\n * so they see true execution timing. Register with `engine.use`.\n */\nexport type StepInterceptor = (\n invocation: StepInvocation,\n next: () => Promise<unknown>,\n) => Promise<unknown>;\n","/**\n * Compute the worker group a tenant's run dispatches to. Mirrors the transport's\n * default-is-bare rule (unset/empty/`'default'` ⇒ bare): a\n * `tenant` of `undefined`, `''`, or `'default'` is the bare `baseGroup`, so a single-tenant\n * deployment (or the `'default'` tenant of a multi-tenant one) stays byte-identical to today.\n * Any other tenant suffixes the group as `<baseGroup>@<tenant>`, so an operator control plane\n * (namespace: undefined) can route each tenant's run to its own worker pool.\n */\nexport function tenantGroup(baseGroup: string, tenant: string | undefined): string {\n return tenant !== undefined && tenant !== '' && tenant !== 'default'\n ? `${baseGroup}@${tenant}`\n : baseGroup;\n}\n\n/**\n * Sanitize a handler/workflow name for use as a BullMQ queue token: BullMQ forbids `:` in queue\n * names (it uses the colon internally as a key separator), so every `:` is replaced with `-`. `.`\n * is legal in a BullMQ queue name and is left as-is — step/workflow names commonly use it as a\n * namespacing separator (e.g. `payments.charge-card`).\n */\nexport function sanitizeQueueToken(name: string): string {\n return name.replace(/:/g, '-');\n}\n","import type {\n HistoryEvent,\n Transport,\n WorkflowExecutor,\n WorkflowRun,\n WorkflowTask,\n} from './interfaces';\nimport { sanitizeQueueToken, tenantGroup } from './tenant-group';\n\n/**\n * A {@link WorkflowExecutor} backed by a {@link Transport}: it advances a remote workflow by\n * DISPATCHING a {@link WorkflowTask} over the broker under the ENGINE-SUPPLIED `taskId`, WITHOUT\n * awaiting the decision. Pass one to `engine.registerRemote(name, version, { group, executor })` so a\n * workflow authored in another SDK (e.g. the Python `durable-worker`) is driven over Redis/BullMQ.\n *\n * Routes by NAME, not a hand-declared group: the dispatched task's routing token is\n * `tenantGroup(sanitizeQueueToken(name), partition)` — the same formula a {@link import('./interfaces').StepDef}\n * uses — so `partition` is an optional isolation suffix, not a separate identity. Omit it to route by\n * the bare (sanitized) `name`.\n *\n * Multi-instance safe by construction: the executor holds NO in-memory state correlating a dispatched\n * turn to its decision. The engine records the `taskId` on the run as the awaited marker AND releases\n * the run's lease BEFORE calling `dispatch`, so the worker's {@link import('./interfaces').WorkflowDecision},\n * delivered over the transport's `onDecision` and applied DURABLY (by run id) on whatever engine\n * instance consumes it — even one that did not dispatch the turn — can never arrive ahead of its marker\n * or contend with a still-held lease and be dropped. A point-to-point broker can therefore hand the\n * decision to any instance without it being dropped (the bug this design fixes).\n *\n * Recovery-safe: if the engine crashes (or a decision is genuinely lost because the worker died), the\n * suspended turn's heartbeat-rearmed window (`remoteAdvanceSilenceMs`) lapses and the timer poller\n * re-dispatches a fresh task with the same history — the worker's replay is deterministic, so it\n * returns the same decision; a late decision for the old `taskId` no longer matches the run's\n * currently-awaited turn and is dropped.\n */\nexport class RemoteWorkflowExecutor implements WorkflowExecutor {\n constructor(\n private readonly transport: Transport,\n private readonly name: string,\n private readonly partition?: string | undefined,\n // Accepted for source compatibility; liveness now lives on the engine's suspended-turn window\n // (`remoteAdvanceSilenceMs`) + recovery re-drive, not an in-memory per-turn timeout.\n _opts: { timeoutMs?: number } = {},\n ) {}\n\n /**\n * Enqueue one workflow turn under the engine-supplied `taskId`. Does NOT await the decision — the\n * engine has already suspended the run on `taskId` and applies the decision durably via `onDecision`.\n */\n async dispatch(\n run: WorkflowRun,\n history: HistoryEvent[],\n taskId: string,\n pendingSignals?: WorkflowTask['pendingSignals'],\n ): Promise<void> {\n if (!this.transport.dispatchWorkflowTask) {\n throw new Error('transport does not support workflow tasks (dispatchWorkflowTask)');\n }\n const task: WorkflowTask = {\n taskId,\n runId: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n input: run.input,\n history,\n ...(pendingSignals ? { pendingSignals } : {}),\n group: tenantGroup(sanitizeQueueToken(this.name), this.partition),\n priority: run.priority,\n attempt: 1,\n };\n await this.transport.dispatchWorkflowTask(task);\n }\n}\n","import { EVENT_TOKEN_PREFIX, eventNameOf } from './events';\nimport type { RunWaiting, SignalWaiter, StateStore, WorkflowRun } from './interfaces';\n\n// Waiter-token prefixes the engine stamps (see `workflow-ctx.ts`): a webhook mints `wh:<runId>:<seq>`,\n// an awaited child parks on `child:<id>`, a `ctx.breakpoint` mints `bp:<runId>:<seq>` (see\n// `breakpointToken` in `protocol.ts`), a named event on `event:<b64 name>:…`. A plain\n// `ctx.waitForSignal(name)` uses `name` verbatim as the token, so an unrecognised token IS the signal\n// name.\nconst WEBHOOK_PREFIX = 'wh:';\nconst CHILD_PREFIX = 'child:';\nconst BREAKPOINT_PREFIX = 'bp:';\nconst EVENT_PREFIX = EVENT_TOKEN_PREFIX;\n\n/**\n * Resolve WHAT a suspended run is parked on from the token of the {@link SignalWaiter} it registered.\n * The token prefix carries the kind — no extra store lookup and no new persisted field. Used by the\n * store-backed run gateway to stamp {@link RunWaiting} onto each listed run so the dashboard can name\n * the wait in a row without fetching that run's timeline.\n *\n * `ctx.breakpoint` reuses the signal-waiter machinery (`engine.continue` resumes it via `signal()`\n * like any other), so without this case it would fall through to the generic `signal` branch with the\n * raw `bp:<runId>:<seq>` token as its display name — a real bug. Named `'breakpoint'` here instead;\n * the token carries no separate label to recover cheaply (see {@link RunWaiting.name}).\n */\nexport function classifyWaiterToken(token: string): RunWaiting {\n if (token.startsWith(WEBHOOK_PREFIX)) return { on: 'webhook', name: token };\n if (token.startsWith(BREAKPOINT_PREFIX)) return { on: 'breakpoint', name: 'breakpoint' };\n if (token.startsWith(CHILD_PREFIX))\n return { on: 'child', name: token.slice(CHILD_PREFIX.length) };\n if (token.startsWith(EVENT_PREFIX)) return { on: 'signal', name: eventNameOf(token) };\n return { on: 'signal', name: token };\n}\n\n/**\n * Resolve a suspended run's {@link RunWaiting} from the pending signal waiters (indexed by `runId`).\n * Event-only by design (see {@link RunWaiting}): a `waitForSignal`/`waitForEvent`/webhook/awaited-child\n * suspend registers a waiter and gets named here; every other suspend (a bare `ctx.sleep`, an in-flight\n * remote step, a reconcile-parked orphan) returns `undefined`, so the client layers its own display\n * state (no-worker, singleton, running) on top — none of which can be told apart from `wakeAt` alone.\n */\nexport function resolveRunWaiting(\n run: WorkflowRun,\n waiterByRun: ReadonlyMap<string, SignalWaiter>,\n): RunWaiting | undefined {\n if (run.status !== 'suspended') return undefined;\n const waiter = waiterByRun.get(run.id);\n return waiter ? classifyWaiterToken(waiter.token) : undefined;\n}\n\nconst RUN_ID_BATCH = 500;\n\n/**\n * The signal waiters of `runIds`: through the store's {@link StateStore.listSignalWaitersByRun} in\n * bounded batches, or, for a store without it, one scan of every waiter filtered to those runs.\n */\nexport async function listSignalWaitersOfRuns(\n store: StateStore,\n runIds: readonly string[],\n): Promise<SignalWaiter[]> {\n const unique = [...new Set(runIds)];\n if (unique.length === 0) return [];\n if (!store.listSignalWaitersByRun) {\n const ids = new Set(unique);\n return (await store.listSignalWaiters('')).filter((w) => ids.has(w.runId));\n }\n const out: SignalWaiter[] = [];\n for (let at = 0; at < unique.length; at += RUN_ID_BATCH) {\n out.push(...(await store.listSignalWaitersByRun(unique.slice(at, at + RUN_ID_BATCH))));\n }\n return out;\n}\n\n/** Index signal waiters by `runId`, keeping the first seen per run (a run parks on one waiter at a\n * time in the sequential case; the earliest is the one it's blocked on). */\nexport function indexWaitersByRun(waiters: readonly SignalWaiter[]): Map<string, SignalWaiter> {\n const byRun = new Map<string, SignalWaiter>();\n for (const w of waiters) if (!byRun.has(w.runId)) byRun.set(w.runId, w);\n return byRun;\n}\n","import { createRequire } from 'node:module';\nimport { resolveCronParse } from './cron-compat';\nimport type { WorkflowEngine } from './engine';\n\n// Resolve the optional `cron-parser` peer dependency in a way that works in BOTH the ESM and CJS\n// builds of this package (dual publish). `createRequire(import.meta.url)` gives a real `require` in\n// ESM output; in the CJS build, tsup's banner shims `import.meta.url` to the file URL, so the same\n// call resolves there too. This keeps the load synchronous (no async leak into the scheduler API).\nconst nodeRequire = createRequire(import.meta.url);\n\nexport interface ScheduledWorkflow {\n /** Stable key identifying this schedule — part of the deterministic run id. */\n key: string;\n workflow: string;\n input?: unknown;\n /** Start one run every `everyMs`. Mutually exclusive with `cron`. */\n everyMs?: number;\n /**\n * A cron expression (5 fields `m h dom mon dow`, or 6 with leading seconds) evaluated in\n * {@link ScheduledWorkflow.timezone}. Mutually exclusive with `everyMs`. Needs the optional peer\n * dependency `cron-parser`.\n */\n cron?: string;\n /** IANA timezone the `cron` fires in (e.g. `America/Sao_Paulo`). Defaults to UTC. */\n timezone?: string;\n /** Temporarily stop firing this schedule (kept registered). Defaults to false. */\n paused?: boolean;\n /**\n * What to do when the previous window's run hasn't finished yet (fixed-interval schedules only):\n * `'allow'` (default) starts the new window anyway; `'skip'` skips it while the prior run is still\n * `running`/`suspended`, so a slow run can't pile up overlapping executions.\n */\n overlap?: 'allow' | 'skip';\n /**\n * Randomly delay the dispatch by up to this many ms BEFORE firing, to spread load when many\n * instances tick on the same boundary (avoids a thundering herd). Opt-in; absent = fire immediately.\n *\n * This is dispatch-path jitter only — it does NOT affect the run id (still the time bucket), so\n * idempotency is unchanged: two instances jittering the same window still start it exactly once.\n * (The engine forbids `Math.random` inside workflow code; the scheduler dispatch path is not\n * workflow code, so jitter here is fine.)\n */\n jitter?: number;\n /**\n * Enqueue windows that were missed while the scheduler was down, instead of silently skipping\n * them. Opt-in; absent = only the current window fires. `maxCatchup` bounds how many PRIOR windows\n * are backfilled (a long outage can't flood the system). Backfilled runs use each missed window's\n * deterministic bucket run id, so `engine.start` idempotency skips any that already ran.\n */\n backfill?: { maxCatchup: number };\n}\n\n/** Injectable dispatch-path effects (kept out of the deterministic run-id logic). Defaults to real\n * `Math.random` + `setTimeout`; overridden in tests so jitter is deterministic and instant. */\nexport interface RunSchedulesOptions {\n random?: () => number;\n sleep?: (ms: number) => Promise<void>;\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms));\n\n/** Deterministic run id for a fixed-interval schedule's current time window. */\nexport function scheduledRunId(key: string, everyMs: number, nowMs: number): string {\n return `sched:${key}:${Math.floor(nowMs / everyMs)}`;\n}\n\nlet cronParser: unknown;\nfunction loadCronParser(): unknown {\n if (cronParser !== undefined) return cronParser;\n try {\n // Lazy + optional: core stays dependency-free; only users who schedule by cron need this.\n cronParser = nodeRequire('cron-parser');\n } catch {\n throw new Error(\n 'cron schedules need the optional peer dependency \"cron-parser\" — install it (e.g. `npm i cron-parser`).',\n );\n }\n return cronParser;\n}\n\n/**\n * Epoch ms of the most recent cron fire at or before `nowMs`, evaluated in `timezone` (default UTC).\n * This is the deterministic \"bucket\" a cron run is keyed on, so polling repeatedly within an\n * interval resolves to the same fire time — and thus the same idempotent run id.\n */\nexport function prevCronFireMs(expr: string, nowMs: number, timezone = 'UTC'): number {\n const parse = resolveCronParse(loadCronParser());\n if (!parse) {\n throw new Error(\n 'the installed \"cron-parser\" exposes neither v4\\'s parseExpression nor v5\\'s CronExpressionParser.parse — the supported range is ^4.0.0 || ^5.0.0.',\n );\n }\n // `+1` makes a fire landing exactly on `nowMs` count as \"at or before now\", not the prior one.\n return parse(expr, { currentDate: new Date(nowMs + 1), tz: timezone })\n .prev()\n .toDate()\n .getTime();\n}\n\n/**\n * Epoch ms of the first cron fire STRICTLY after `afterMs`, evaluated in `timezone` (default UTC) —\n * the forward counterpart of {@link prevCronFireMs}, used by persisted schedules to compute when a\n * schedule is next due.\n */\nexport function nextCronFireMs(expr: string, afterMs: number, timezone = 'UTC'): number {\n const parse = resolveCronParse(loadCronParser());\n if (!parse) {\n throw new Error(\n 'the installed \"cron-parser\" exposes neither v4\\'s parseExpression nor v5\\'s CronExpressionParser.parse — the supported range is ^4.0.0 || ^5.0.0.',\n );\n }\n return parse(expr, { currentDate: new Date(afterMs), tz: timezone })\n .next()\n .toDate()\n .getTime();\n}\n\n/** The deterministic, idempotent run id for a schedule at `nowMs` — its current fire window. */\nfunction scheduleRunIdAt(s: ScheduledWorkflow, nowMs: number): string {\n if (s.cron != null) return `sched:${s.key}:${prevCronFireMs(s.cron, nowMs, s.timezone)}`;\n if (s.everyMs != null) return scheduledRunId(s.key, s.everyMs, nowMs);\n throw new Error(`schedule \"${s.key}\" needs either \"everyMs\" or \"cron\"`);\n}\n\n/**\n * The run ids this schedule should fire at `nowMs`: the current window, plus — when `backfill` is set\n * — up to `maxCatchup` prior windows that may have been missed. Oldest-first, so a backfill catches\n * up in chronological order. Ids are the same deterministic buckets `scheduleRunIdAt` produces, so\n * `engine.start` idempotency drops any window that already ran.\n */\nfunction scheduleRunIdsAt(s: ScheduledWorkflow, nowMs: number): string[] {\n const current = scheduleRunIdAt(s, nowMs);\n if (!s.backfill || s.backfill.maxCatchup <= 0) return [current];\n\n const ids: string[] = [];\n if (s.everyMs != null) {\n const bucket = Math.floor(nowMs / s.everyMs);\n const oldest = Math.max(0, bucket - s.backfill.maxCatchup);\n for (let b = oldest; b < bucket; b += 1) ids.push(`sched:${s.key}:${b}`);\n } else if (s.cron != null) {\n // Walk back through prior cron fire times (most-recent missed first), then reverse to oldest-first.\n const prior: string[] = [];\n let cursor = prevCronFireMs(s.cron, nowMs, s.timezone);\n for (let i = 0; i < s.backfill.maxCatchup; i += 1) {\n // `cursor` (exclusive) → the fire strictly before it.\n const before = prevCronFireMs(s.cron, cursor - 1, s.timezone);\n prior.push(`sched:${s.key}:${before}`);\n cursor = before;\n }\n ids.push(...prior.reverse());\n }\n ids.push(current);\n return ids;\n}\n\n/**\n * Start each schedule's current-window run. The run id is the time bucket (a fixed-interval index,\n * or the cron fire time) and `engine.start` is idempotent, so firing this on an interval — or\n * racing two instances on the same tick — starts **each window exactly once**. Wire it to a\n * `setInterval`, the durable timer poller, or `@nestjs/schedule`. Returns the run ids for the\n * current windows.\n */\nexport async function runSchedules(\n engine: Pick<WorkflowEngine, 'start' | 'getRun'>,\n schedules: readonly ScheduledWorkflow[],\n nowMs: number,\n opts?: RunSchedulesOptions,\n): Promise<string[]> {\n const random = opts?.random ?? Math.random;\n const sleep = opts?.sleep ?? defaultSleep;\n const ids: string[] = [];\n for (const s of schedules) {\n if (s.paused) continue;\n // overlap:'skip' (fixed-interval): don't start this window while the previous window's run is\n // still in-flight, so a slow run can't pile up. Interval-only — cron windows aren't adjacent ids.\n if (s.overlap === 'skip' && s.everyMs) {\n const prevBucket = Math.floor(nowMs / s.everyMs) - 1;\n if (prevBucket >= 0) {\n const prev = await engine.getRun(`sched:${s.key}:${prevBucket}`);\n if (prev && (prev.status === 'running' || prev.status === 'suspended')) continue;\n }\n }\n // Dispatch-path jitter (not workflow code): spread same-boundary ticks across instances. Applied\n // once per schedule, before firing — the run ids below are unaffected, so idempotency holds.\n if (s.jitter && s.jitter > 0) await sleep(Math.floor(random() * s.jitter));\n for (const runId of scheduleRunIdsAt(s, nowMs)) {\n await engine.start(s.workflow, s.input, runId);\n ids.push(runId);\n }\n }\n return ids;\n}\n","/**\n * Reading a cron expression across both cron-parser majors.\n *\n * The peer range is `^4.0.0 || ^5.0.0` and the two majors do not share an entry\n * point: v4 exports `parseExpression`, v5 replaced it with\n * `CronExpressionParser.parse`. Typing the module as\n * `typeof import('cron-parser')` pins it to whichever major is dev-installed and\n * makes the other one a compile error — which is how the scheduler shipped\n * calling only v4 while advertising both, so every v5 install failed at runtime\n * with \"parser.parseExpression is not a function\": a message that reads as a\n * missing dependency rather than as the wrong major.\n *\n * Deliberately NOT re-exported from `index.ts`. This is interop plumbing, not\n * public API; the spec imports it from this path directly.\n */\n\nexport interface CronOptions {\n currentDate: Date;\n tz: string;\n}\n\nexport interface CronFire {\n prev(): { toDate(): Date };\n next(): { toDate(): Date };\n}\n\nexport type ParseCron = (expr: string, options: CronOptions) => CronFire;\n\n/**\n * Anything `Reflect.get` can read a member off.\n *\n * Admits functions as well as objects, because cron-parser v4's CommonJS export\n * *is* a function carrying `parseExpression` as a property — an object-only\n * guard rejects the very major this range exists to support.\n */\nfunction isIndexable(value: unknown): value is object {\n return (typeof value === 'object' && value !== null) || typeof value === 'function';\n}\n\n/** ESM/CJS interop: a `require` can hand back the namespace with the module under `default`. */\nexport function unwrapDefault(module_: unknown): unknown {\n if (!isIndexable(module_)) return module_;\n if (Reflect.get(module_, 'parseExpression') !== undefined) return module_;\n if (Reflect.get(module_, 'CronExpressionParser') !== undefined) return module_;\n const inner = Reflect.get(module_, 'default');\n return inner === undefined ? module_ : inner;\n}\n\n/** v4: `parseExpression(expr, options)`. */\nexport function v4Entry(module_: unknown): ParseCron | undefined {\n if (!isIndexable(module_)) return undefined;\n const parse = Reflect.get(module_, 'parseExpression');\n if (typeof parse !== 'function') return undefined;\n return (expr, options) => parse.call(module_, expr, options);\n}\n\n/** v5: `CronExpressionParser.parse(expr, options)`. */\nexport function v5Entry(module_: unknown): ParseCron | undefined {\n if (!isIndexable(module_)) return undefined;\n const parser = Reflect.get(module_, 'CronExpressionParser');\n if (!isIndexable(parser)) return undefined;\n const parse = Reflect.get(parser, 'parse');\n if (typeof parse !== 'function') return undefined;\n return (expr, options) => parse.call(parser, expr, options);\n}\n\n/**\n * The parse entry point of whichever major is installed.\n *\n * v4 is tried first only because it is the cheaper check; a module cannot\n * present both entry points, so the order carries no meaning beyond that.\n */\nexport function resolveCronParse(module_: unknown): ParseCron | undefined {\n const resolved = unwrapDefault(module_);\n return v4Entry(resolved) ?? v5Entry(resolved);\n}\n","import type { ConcurrencyQuota } from './concurrency';\nimport { parseDuration } from './duration';\nimport type { StartOptions } from './engine';\nimport type {\n RunResult,\n RunStatus,\n ScheduleQuery,\n ScheduleRecord,\n SearchAttributes,\n StateStore,\n WorkflowRun,\n} from './interfaces';\nimport { TERMINAL_RUN_STATUSES } from './interfaces';\nimport { nextCronFireMs, prevCronFireMs } from './scheduler';\nimport { type WorkflowRef, workflowName } from './workflow-ref';\n\n/**\n * A schedule definition — what `engine.schedules.create/upsert` take. Temporal-style: a persisted,\n * runtime-managed recurring start of `workflow` with `input`, fired by every driving engine's timer\n * poll (safe with many workers: each window's run id is deterministic, `start` is idempotent, and\n * advancing the schedule is a compare-and-set).\n */\nexport interface ScheduleOptions {\n /** Stable id, unique per store (e.g. `digest:user-42`). Part of every run id it starts. */\n id: string;\n /** The workflow to start — a registered name or `@Workflow` class. */\n workflow: WorkflowRef;\n /** The input every run starts with. */\n input?: unknown;\n /** Cron expression (5 fields, or 6 with leading seconds). Needs the `cron-parser` peer. */\n cron?: string | undefined;\n /** Fixed interval (`'15m'`, or ms), windows aligned to the epoch. Exclusive with `cron`. */\n every?: string | number | undefined;\n /** IANA timezone the cron is evaluated in (e.g. `America/Sao_Paulo`). Default UTC. */\n timezone?: string | undefined;\n /**\n * Delay each fire by up to this much (`'30s'` or ms) — a stable per-(schedule, window) offset, so\n * thousands of schedules on the same cron don't all start in the same second.\n */\n jitter?: string | number | undefined;\n /**\n * The previous run of this schedule is still in flight when the next window comes due:\n * `'allow'` (default) starts the new one anyway; `'skip'` skips that window.\n */\n overlap?: 'allow' | 'skip' | undefined;\n /**\n * Windows missed while nothing polled (all schedulers down): `'latest'` (default) fires the most\n * recent missed window once; `'skip'` drops them and waits for the next window. Never more than one\n * catch-up run per schedule.\n */\n catchup?: 'latest' | 'skip' | undefined;\n /** Create paused (never due until `resume`). On `upsert`, omit to keep the current paused state. */\n paused?: boolean | undefined;\n /** Free-form note shown with the schedule (why it exists / why it's paused). */\n note?: string | undefined;\n /** Namespace of the schedule and of the runs it starts. Defaults to the engine's own namespace. */\n namespace?: string | undefined;\n /** Labels to find the schedule by — also stamped on every run it starts (plus `schedule:<id>`). */\n tags?: string[] | undefined;\n /** Search attributes stamped on every run it starts. */\n searchAttributes?: SearchAttributes | undefined;\n /** Dispatch priority for the runs it starts. */\n priority?: number | undefined;\n /**\n * A start-time concurrency quota applied to every run it starts (see `StartOptions.concurrency`):\n * a window whose start would exceed it is recorded as the schedule's `lastError` and skipped, and\n * the schedule moves on to its next window.\n */\n concurrency?: ConcurrencyQuota | undefined;\n}\n\n/** A schedule as `engine.schedules.get/list` describe it. */\nexport interface ScheduleDescription {\n id: string;\n workflow: string;\n input: unknown;\n namespace: string;\n cron?: string | undefined;\n everyMs?: number | undefined;\n timezone?: string | undefined;\n jitterMs?: number | undefined;\n overlap: 'allow' | 'skip';\n catchup: 'latest' | 'skip';\n paused: boolean;\n note?: string | undefined;\n tags?: string[] | undefined;\n searchAttributes?: SearchAttributes | undefined;\n priority?: number | undefined;\n concurrency?: ConcurrencyQuota | undefined;\n /** When it is next due (jitter included), or null if it never fires again / paused. */\n nextFireAt: Date | null;\n /** The last window it fired for, and the run that window started. */\n lastFireAt?: Date | undefined;\n lastRunId?: string | undefined;\n /** How many windows it has fired (manual triggers excluded). */\n fires: number;\n /** The last start failure (e.g. a concurrency limit), cleared by the next successful start. */\n lastError?: string | undefined;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Filter for `engine.schedules.list`. */\nexport type ScheduleListQuery = Omit<ScheduleQuery, 'dueBy'>;\n\n/** Thrown by `engine.schedules.create` when the id is taken (use `upsert` to replace). */\nexport class ScheduleAlreadyExistsError extends Error {\n constructor(readonly scheduleId: string) {\n super(`schedule \"${scheduleId}\" already exists`);\n this.name = 'ScheduleAlreadyExistsError';\n }\n}\n\n/** Thrown by `engine.schedules.*` on an id that doesn't exist. */\nexport class ScheduleNotFoundError extends Error {\n constructor(readonly scheduleId: string) {\n super(`schedule \"${scheduleId}\" not found`);\n this.name = 'ScheduleNotFoundError';\n }\n}\n\n/** The persisted definition (`ScheduleRecord.spec`). Versioned so the shape can evolve. */\ninterface SpecDoc {\n v: 1;\n input?: unknown;\n cron?: string;\n everyMs?: number;\n timezone?: string;\n jitterMs?: number;\n overlap: 'allow' | 'skip';\n catchup: 'latest' | 'skip';\n note?: string;\n searchAttributes?: SearchAttributes;\n priority?: number;\n concurrency?: ConcurrencyQuota;\n}\n\n/** The persisted bookkeeping (`ScheduleRecord.state`). */\ninterface StateDoc {\n /** The nominal window `nextFireAt` belongs to (nextFireAt = window + jitter). */\n window?: number | null | undefined;\n lastFireAt?: number | undefined;\n lastRunId?: string | undefined;\n fires?: number | undefined;\n lastError?: string | undefined;\n}\n\n/** The engine surface the schedule client drives. */\nexport interface ScheduleHost {\n start(workflow: string, input: unknown, runId: string, opts?: StartOptions): Promise<RunResult>;\n getRun(runId: string): Promise<WorkflowRun | null>;\n /** True once the engine has begun shutting down; `tick` fires nothing more after that. */\n isDraining?(): boolean;\n}\n\n/** Engine-level knobs for the client. */\nexport interface ScheduleClientOptions {\n /** The engine's namespace: the default for new schedules, and which ones `tick` fires. */\n namespace?: string | undefined;\n clock?: (() => number) | undefined;\n}\n\nconst DEFAULT_NAMESPACE = 'default';\n/** How late a window may fire under `catchup: 'skip'` and still count as on time (plus jitter). */\nconst ON_TIME_GRACE_MS = 60_000;\nconst TICK_BATCH = 100;\n\n/**\n * Persisted, runtime-managed schedules — `engine.schedules`. Unlike the code-registered\n * `schedules` module option, these live in the store: create/update/pause/delete them at runtime\n * (one per user, per tenant, per automation…), and every driving engine's timer poll fires the due\n * ones via {@link tick}.\n *\n * Multi-worker safety comes from two properties, not from a lock: a window's run id is deterministic\n * (`sched:<id>:<windowMs>`), so racing starts of the same window collapse into one run; and a\n * schedule is advanced with a compare-and-set on its `nextFireAt`, so exactly one poller moves it on.\n * A crash between starting the run and advancing the schedule just re-fires the (idempotent) start.\n */\nexport class ScheduleClient {\n constructor(\n private readonly store: StateStore,\n private readonly host: ScheduleHost,\n private readonly options: ScheduleClientOptions = {},\n ) {}\n\n private now(): number {\n return (this.options.clock ?? Date.now)();\n }\n\n /** Whether the store persists schedules (implements the schedule methods). */\n get supported(): boolean {\n const s = this.store;\n return !!(\n s.saveSchedule &&\n s.getSchedule &&\n s.updateSchedule &&\n s.deleteSchedule &&\n s.listSchedules\n );\n }\n\n private requireStore(): Required<\n Pick<\n StateStore,\n 'saveSchedule' | 'getSchedule' | 'updateSchedule' | 'deleteSchedule' | 'listSchedules'\n >\n > {\n if (!this.supported) {\n throw new Error(\n 'persisted schedules need a store that implements saveSchedule/getSchedule/updateSchedule/deleteSchedule/listSchedules — every bundled store adapter does; this one does not',\n );\n }\n const s = this.store;\n return {\n saveSchedule: (r) => (s.saveSchedule as NonNullable<StateStore['saveSchedule']>).call(s, r),\n getSchedule: (id) => (s.getSchedule as NonNullable<StateStore['getSchedule']>).call(s, id),\n updateSchedule: (id, patch, expected) =>\n (s.updateSchedule as NonNullable<StateStore['updateSchedule']>).call(\n s,\n id,\n patch,\n expected,\n ),\n deleteSchedule: (id) =>\n (s.deleteSchedule as NonNullable<StateStore['deleteSchedule']>).call(s, id),\n listSchedules: (q) =>\n (s.listSchedules as NonNullable<StateStore['listSchedules']>).call(s, q),\n };\n }\n\n /** Create a schedule. Throws {@link ScheduleAlreadyExistsError} if the id is taken. */\n async create(opts: ScheduleOptions): Promise<ScheduleDescription> {\n const store = this.requireStore();\n if (await store.getSchedule(opts.id)) throw new ScheduleAlreadyExistsError(opts.id);\n return this.write(opts, null);\n }\n\n /**\n * Create the schedule, or replace the definition of an existing one (its history — last fire, last\n * run, fire count — is kept). The next fire is recomputed from now under the new definition, so a\n * window that already fired is never fired again by an upsert.\n */\n async upsert(opts: ScheduleOptions): Promise<ScheduleDescription> {\n const store = this.requireStore();\n return this.write(opts, await store.getSchedule(opts.id));\n }\n\n /** The schedule `id`, or null. */\n async get(id: string): Promise<ScheduleDescription | null> {\n const record = await this.requireStore().getSchedule(id);\n return record ? describe(record) : null;\n }\n\n /** Schedules matching `query`, soonest-due first. */\n async list(query: ScheduleListQuery = {}): Promise<ScheduleDescription[]> {\n return (await this.requireStore().listSchedules(query)).map(describe);\n }\n\n /** Delete the schedule. Runs it already started are left alone. Returns whether it existed. */\n delete(id: string): Promise<boolean> {\n return this.requireStore().deleteSchedule(id);\n }\n\n /** Stop firing until {@link resume}. `note` records why (shown by `get`/`list`). */\n async pause(id: string, note?: string): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const record = await this.mustGet(id);\n const spec = { ...(record.spec as unknown as SpecDoc) };\n if (note !== undefined) spec.note = note;\n await store.updateSchedule(id, {\n paused: true,\n spec: spec as unknown as Record<string, unknown>,\n updatedAt: new Date(this.now()),\n });\n return describe(await this.mustGet(id));\n }\n\n /**\n * Fire again from the next window after now — the windows skipped while paused are NOT caught up.\n */\n async resume(id: string): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const record = await this.mustGet(id);\n const spec = record.spec as unknown as SpecDoc;\n const window = nextWindowAfter(spec, this.now());\n await store.updateSchedule(id, {\n paused: false,\n nextFireAt: window === null ? null : window + jitterFor(record.id, window, spec),\n state: { ...record.state, window } as Record<string, unknown>,\n updatedAt: new Date(this.now()),\n });\n return describe(await this.mustGet(id));\n }\n\n /**\n * Start one run of the schedule right now, outside its cadence (paused or not). The run id is\n * `sched:<id>:manual:<nowMs>`; it doesn't move the schedule's next fire.\n */\n async trigger(id: string): Promise<RunResult> {\n const record = await this.mustGet(id);\n const runId = `sched:${id}:manual:${this.now()}`;\n return this.host.start(record.workflow, specOf(record).input, runId, startOptions(record));\n }\n\n /**\n * Fire every due schedule (in this engine's namespace; all namespaces for an operator engine):\n * start its window's run and advance it to the next window. Called by the NestJS timer poller on\n * each tick when `persistedSchedules` is on; call it yourself from any other driver. Returns the\n * run ids started (or re-found, for an idempotent re-fire).\n */\n async tick(nowMs: number = this.now()): Promise<string[]> {\n const store = this.requireStore();\n const started: string[] = [];\n for (let round = 0; round < 50; round++) {\n if (this.host.isDraining?.()) break;\n const due = await store.listSchedules({\n dueBy: nowMs,\n namespace: this.options.namespace,\n limit: TICK_BATCH,\n });\n for (const record of due) {\n if (this.host.isDraining?.()) return started; // shutting down: start nothing new\n const runId = await this.fire(record, nowMs);\n if (runId) started.push(runId);\n }\n if (due.length < TICK_BATCH) break;\n }\n return started;\n }\n\n /** Fire one due schedule and advance it. Returns the run id started, if any. */\n private async fire(record: ScheduleRecord, nowMs: number): Promise<string | undefined> {\n const store = this.requireStore();\n const spec = specOf(record);\n const state = record.state as StateDoc;\n let latest: number;\n let next: number | null;\n try {\n // The most recent window at or before now — the one (and only one) a late poll fires.\n latest = latestWindowAtOrBefore(spec, nowMs);\n next = nextWindowAfter(spec, latest);\n } catch (error) {\n // A definition that no longer evaluates (bad cron/timezone): stop it, loudly, instead of\n // failing on every tick forever.\n await store.updateSchedule(\n record.id,\n {\n paused: true,\n nextFireAt: null,\n state: { ...state, lastError: `invalid schedule: ${errorMessage(error)}` },\n updatedAt: new Date(nowMs),\n },\n record.nextFireAt,\n );\n return undefined;\n }\n const window = state.window ?? latest;\n const jitter = spec.jitterMs ?? 0;\n const onTime = nowMs - latest <= ON_TIME_GRACE_MS + jitter;\n let runId: string | undefined;\n let lastError: string | undefined;\n let fired = false;\n const skipMissed = spec.catchup === 'skip' && !onTime;\n const beforeWindow = latest < window; // clock skew: not actually due yet\n if (!skipMissed && !beforeWindow && !(await this.overlapping(spec, state))) {\n runId = `sched:${record.id}:${latest}`;\n try {\n await this.host.start(record.workflow, spec.input, runId, startOptions(record));\n fired = true;\n } catch (error) {\n // A racing poller may have created the same (deterministic) run first: that's a success.\n if (await this.host.getRun(runId)) fired = true;\n else lastError = errorMessage(error);\n }\n }\n const nextState: StateDoc = {\n ...state,\n window: next,\n ...(fired ? { lastFireAt: latest, lastRunId: runId, fires: (state.fires ?? 0) + 1 } : {}),\n lastError: fired ? undefined : (lastError ?? state.lastError),\n };\n await store.updateSchedule(\n record.id,\n {\n nextFireAt: next === null ? null : next + jitterFor(record.id, next, spec),\n state: stripUndefined(nextState) as Record<string, unknown>,\n updatedAt: new Date(nowMs),\n },\n record.nextFireAt,\n );\n return fired ? runId : undefined;\n }\n\n /** `overlap: 'skip'` and the previous run of this schedule is still in flight. */\n private async overlapping(spec: SpecDoc, state: StateDoc): Promise<boolean> {\n if (spec.overlap !== 'skip' || !state.lastRunId) return false;\n const prev = await this.host.getRun(state.lastRunId);\n return !!prev && !TERMINAL_RUN_STATUSES.includes(prev.status as RunStatus);\n }\n\n private async mustGet(id: string): Promise<ScheduleRecord> {\n const record = await this.requireStore().getSchedule(id);\n if (!record) throw new ScheduleNotFoundError(id);\n return record;\n }\n\n private async write(\n opts: ScheduleOptions,\n existing: ScheduleRecord | null,\n ): Promise<ScheduleDescription> {\n const store = this.requireStore();\n const spec = toSpec(opts);\n const now = this.now();\n // An upsert that doesn't say otherwise keeps a paused schedule paused.\n const paused = opts.paused ?? existing?.paused ?? false;\n const window = nextWindowAfter(spec, now); // also validates the cron/timezone up front\n const record: ScheduleRecord = {\n id: opts.id,\n namespace: opts.namespace ?? this.options.namespace ?? DEFAULT_NAMESPACE,\n workflow: workflowName(opts.workflow),\n paused,\n nextFireAt: window === null ? null : window + jitterFor(opts.id, window, spec),\n tags: opts.tags,\n spec: spec as unknown as Record<string, unknown>,\n state: stripUndefined({\n ...((existing?.state as StateDoc | undefined) ?? {}),\n window,\n }) as Record<string, unknown>,\n createdAt: existing?.createdAt ?? new Date(now),\n updatedAt: new Date(now),\n };\n await store.saveSchedule(record);\n return describe(record);\n }\n}\n\nfunction toSpec(opts: ScheduleOptions): SpecDoc {\n if ((opts.cron == null) === (opts.every == null)) {\n throw new Error(`schedule \"${opts.id}\" needs exactly one of \"cron\" or \"every\"`);\n }\n const everyMs = opts.every != null ? parseDuration(opts.every) : undefined;\n if (everyMs !== undefined && !(everyMs > 0)) {\n throw new Error(`schedule \"${opts.id}\": \"every\" must be a positive duration`);\n }\n const jitterMs = opts.jitter != null ? parseDuration(opts.jitter) : undefined;\n return stripUndefined({\n v: 1 as const,\n input: opts.input,\n cron: opts.cron,\n everyMs,\n timezone: opts.timezone,\n jitterMs: jitterMs && jitterMs > 0 ? jitterMs : undefined,\n overlap: opts.overlap ?? 'allow',\n catchup: opts.catchup ?? 'latest',\n note: opts.note,\n searchAttributes: opts.searchAttributes,\n priority: opts.priority,\n concurrency: opts.concurrency,\n }) as SpecDoc;\n}\n\nfunction specOf(record: ScheduleRecord): SpecDoc {\n return record.spec as unknown as SpecDoc;\n}\n\n/** The latest window at or before `atMs`. */\nfunction latestWindowAtOrBefore(spec: SpecDoc, atMs: number): number {\n if (spec.cron != null) return prevCronFireMs(spec.cron, atMs, spec.timezone);\n const every = spec.everyMs as number;\n return Math.floor(atMs / every) * every;\n}\n\n/** The first window strictly after `afterMs`. */\nfunction nextWindowAfter(spec: SpecDoc, afterMs: number): number | null {\n if (spec.cron != null) return nextCronFireMs(spec.cron, afterMs, spec.timezone);\n const every = spec.everyMs as number;\n return (Math.floor(afterMs / every) + 1) * every;\n}\n\n/** A stable offset in `[0, jitterMs)` per (schedule, window): FNV-1a over the pair. */\nfunction jitterFor(id: string, window: number, spec: SpecDoc): number {\n const max = spec.jitterMs ?? 0;\n if (max <= 0) return 0;\n let h = 0x811c9dc5;\n for (const ch of `${id}@${window}`) {\n h ^= ch.charCodeAt(0);\n h = Math.imul(h, 0x01000193) >>> 0;\n }\n return h % max;\n}\n\nfunction startOptions(record: ScheduleRecord): StartOptions {\n const spec = specOf(record);\n return stripUndefined({\n tags: [...(record.tags ?? []), `schedule:${record.id}`],\n namespace: record.namespace,\n searchAttributes: spec.searchAttributes,\n priority: spec.priority,\n concurrency: spec.concurrency,\n }) as StartOptions;\n}\n\nfunction describe(record: ScheduleRecord): ScheduleDescription {\n const spec = specOf(record);\n const state = record.state as StateDoc;\n return stripUndefined({\n id: record.id,\n workflow: record.workflow,\n input: spec.input,\n namespace: record.namespace,\n cron: spec.cron,\n everyMs: spec.everyMs,\n timezone: spec.timezone,\n jitterMs: spec.jitterMs,\n overlap: spec.overlap ?? 'allow',\n catchup: spec.catchup ?? 'latest',\n paused: record.paused,\n note: spec.note,\n tags: record.tags,\n searchAttributes: spec.searchAttributes,\n priority: spec.priority,\n concurrency: spec.concurrency,\n nextFireAt: record.paused || record.nextFireAt == null ? null : new Date(record.nextFireAt),\n lastFireAt: state.lastFireAt != null ? new Date(state.lastFireAt) : undefined,\n lastRunId: state.lastRunId,\n fires: state.fires ?? 0,\n lastError: state.lastError,\n createdAt: record.createdAt,\n updatedAt: record.updatedAt,\n }) as ScheduleDescription;\n}\n\nfunction stripUndefined<T extends object>(o: T): T {\n return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as T;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import { type RunStatus, TERMINAL_RUN_STATUSES, type WorkflowRun } from './interfaces';\n\n/** Reserved engine metadata: a durable singleton slot, independent of the execution lease. */\nexport const SINGLETON_ADMITTED_TAG = 'durable:singleton:admitted';\nexport const SINGLETON_ACTIVE_STATUSES: RunStatus[] = [\n 'pending',\n 'running',\n 'suspended',\n 'blocked',\n 'cancelling',\n];\n\n/** Call only inside a store's atomic admission transaction/critical section. */\nexport function singletonAdmissionTags(\n runs: WorkflowRun[],\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n): string[] | null {\n if (!Number.isInteger(limit) || limit < 1)\n throw new Error('singleton limit must be a positive integer');\n const active = runs.filter(\n (run) =>\n run.workflow === workflow &&\n SINGLETON_ACTIVE_STATUSES.includes(run.status) &&\n run.tags?.includes(tag),\n );\n const candidate = active.find((run) => run.id === runId);\n if (!candidate) return null;\n if (candidate.tags?.includes(SINGLETON_ADMITTED_TAG)) return candidate.tags;\n if (candidate.status === 'cancelling') return null;\n const holders = active.filter((run) => run.tags?.includes(SINGLETON_ADMITTED_TAG));\n const remaining = limit - holders.length;\n if (remaining <= 0) return null;\n const waiters = active\n .filter((run) => !run.tags?.includes(SINGLETON_ADMITTED_TAG))\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));\n if (!waiters.slice(0, remaining).some((run) => run.id === runId)) return null;\n return [...(candidate.tags ?? []), SINGLETON_ADMITTED_TAG];\n}\n\n/** Terminal runs release admission, including when later resumed directly rather than requeued. */\nexport async function clearTerminalSingletonAdmission(\n runId: string,\n patch: Partial<WorkflowRun>,\n getRun: (id: string) => Promise<WorkflowRun | null>,\n): Promise<Partial<WorkflowRun>> {\n if (!patch.status || !TERMINAL_RUN_STATUSES.includes(patch.status)) return patch;\n const tags = 'tags' in patch ? patch.tags : (await getRun(runId))?.tags;\n return { ...patch, tags: tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG) };\n}\n\n/** Persist denial while admission locks are held; a cancelling/terminal run must never revive. */\nexport function singletonAdmissionDenialPatch(\n runs: WorkflowRun[],\n runId: string,\n tag: string,\n workflow: string,\n retryWakeAt?: number,\n): { status: 'suspended'; wakeAt: number; updatedAt: Date } | undefined {\n if (retryWakeAt === undefined) return undefined;\n const candidate = runs.find(\n (run) =>\n run.id === runId &&\n run.workflow === workflow &&\n run.tags?.includes(tag) &&\n SINGLETON_ACTIVE_STATUSES.includes(run.status),\n );\n if (!candidate || candidate.status === 'cancelling') return undefined;\n return { status: 'suspended', wakeAt: retryWakeAt, updatedAt: new Date() };\n}\n","import type { SingletonConfig } from './engine';\nimport { SingletonQueueFullError } from './errors';\nimport type { StateStore, WorkflowRun } from './interfaces';\nimport { SINGLETON_ACTIVE_STATUSES, SINGLETON_ADMITTED_TAG } from './singleton-admission';\n\nconst SINGLETON_RETRY_MS = 1000;\n/**\n * Max jitter (ms, each direction) added to {@link SINGLETON_RETRY_MS} so a queue of N gated runs\n * doesn't wake in lockstep and stampede the admission scan. Each retry picks an independent offset\n * in `[-SINGLETON_RETRY_JITTER_MS, +SINGLETON_RETRY_JITTER_MS]`.\n */\nconst SINGLETON_RETRY_JITTER_MS = 250;\n\nexport interface SingletonGateDeps {\n store: Pick<StateStore, 'listRuns' | 'updateRun' | 'tryAdmitSingleton'>;\n clock: () => number;\n /** Hand a gated run to the run dispatcher (fire-and-forget, like the engine's other dispatches). */\n dispatch: (runId: string) => void;\n /** Resolve a settled run's singleton config from the engine's workflow registry. */\n configFor: (run: WorkflowRun) => SingletonConfig | undefined;\n}\n\n/**\n * Per-key serialization for singleton workflows — start-time back-pressure, durable atomic\n * admission, and notify-on-release wakeups. Extracted from {@link WorkflowEngine} so the whole\n * singleton feature lives in one place instead of being smeared across `start`, `execute`, both run\n * loops, and `cancel`.\n */\nexport class SingletonGate {\n constructor(private readonly deps: SingletonGateDeps) {}\n\n /** The tag a singleton run carries, so the gate can find others sharing its key. */\n tag(cfg: SingletonConfig, input: unknown): string {\n if (!this.deps.store.tryAdmitSingleton) {\n throw new Error(\n 'Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission',\n );\n }\n return `singleton:${cfg.key(input)}`;\n }\n\n /** Next wake time for a gated run: the base retry delay jittered to avoid a wakeup stampede. */\n retryWakeAt(): number {\n return (\n this.deps.clock() +\n SINGLETON_RETRY_MS +\n Math.floor((Math.random() * 2 - 1) * SINGLETON_RETRY_JITTER_MS)\n );\n }\n\n /**\n * Reject a start that would grow the same-key backlog past `limit + maxQueueDepth` (counting\n * `pending`/`running`/`suspended`/`blocked`/`cancelling` runs sharing the key in one scan). No-op when no `maxQueueDepth`\n * is configured.\n */\n async assertCapacity(workflow: string, cfg: SingletonConfig, input: unknown): Promise<void> {\n if (cfg.maxQueueDepth == null) return;\n const cap = (cfg.limit ?? 1) + cfg.maxQueueDepth;\n const queued = await this.deps.store.listRuns({\n tag: this.tag(cfg, input),\n workflow,\n statuses: SINGLETON_ACTIVE_STATUSES,\n });\n if (queued.length >= cap) {\n throw new SingletonQueueFullError(workflow, cfg.key(input), cfg.maxQueueDepth);\n }\n }\n\n /** Preserve durable holders and atomically claim one of the remaining slots. */\n async admit(run: WorkflowRun, cfg: SingletonConfig): Promise<boolean> {\n if (!this.deps.store.tryAdmitSingleton) {\n throw new Error(\n 'Singleton workflows require StateStore.tryAdmitSingleton for atomic durable admission',\n );\n }\n const admitted = await this.deps.store.tryAdmitSingleton(\n run.id,\n this.tag(cfg, run.input),\n run.workflow,\n cfg.limit ?? 1,\n this.retryWakeAt(),\n );\n if (admitted && !run.tags?.includes(SINGLETON_ADMITTED_TAG)) {\n run.tags = [...(run.tags ?? []), SINGLETON_ADMITTED_TAG];\n }\n return admitted;\n }\n\n /**\n * Notify-on-release: a singleton run settled (freeing a slot), so dispatch the oldest gated\n * (`suspended` + same tag) waiters now instead of waiting for their ~1s retry timer. Each re-checks\n * admission in the executor and runs only if it actually wins a slot, so FIFO/race-free guarantees\n * hold; the durable timer remains the cross-instance/crash fallback.\n */\n async wakeNext(settled: WorkflowRun): Promise<void> {\n const cfg = this.deps.configFor(settled);\n if (!cfg) return;\n const tag = settled.tags?.find((t) => t.startsWith('singleton:'));\n if (!tag) return;\n const gated = (\n await this.deps.store.listRuns({ tag, workflow: settled.workflow, statuses: ['suspended'] })\n ).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));\n for (const next of gated.slice(0, cfg.limit ?? 1)) {\n // Stamp a due-NOW wakeAt as the run is handed over. `dispatch` goes through the configured\n // `runDispatcher`, which may legitimately be a NO-OP (an API/dashboard pod that must not run\n // workflows still settles runs it observes, so it still lands here), which makes the durable\n // timer the only guaranteed pickup: a `suspended` run carrying no `wakeAt` is invisible to\n // every poll path — `listPendingRuns`, `listIncompleteRuns` and `listDueTimers` alike — and\n // never resumes. A dispatch + timer double-drive is safe: the run lock admits one executor and\n // the loser's pickup is a cheap no-op.\n await this.deps.store\n .updateRun(next.id, { wakeAt: this.deps.clock(), updatedAt: new Date() })\n .catch(() => undefined);\n this.deps.dispatch(next.id);\n }\n }\n}\n","import type { WorkerDescriptor } from './handshake/descriptor';\nimport type {\n GroupHealth,\n Heartbeat,\n NamedTransport,\n RemoteTask,\n StartRunMessage,\n StepResult,\n Transport,\n WorkerHeartbeat,\n WorkflowDecision,\n WorkflowStepEvent,\n} from './interfaces';\n\n/**\n * An ordered pool of named transports. The engine dispatches on the first and fails over to the\n * next on a dispatch error; a step can pin one by id. Pure transport plumbing — no run lifecycle —\n * so it lives apart from the engine.\n */\nexport class TransportPool {\n constructor(private readonly transports: NamedTransport[]) {}\n\n get size(): number {\n return this.transports.length;\n }\n\n /**\n * The primary (first) transport — the one `dispatch` prefers when no `preferId` is pinned. A\n * {@link RemoteWorkflowExecutor} built by `engine.remote()` rides it (it needs a single\n * `dispatchWorkflowTask`/`onDecision` Transport, not the whole failover pool). Throws if the pool\n * is empty — there is nothing to dispatch a remote workflow over.\n */\n get primary(): Transport {\n const first = this.transports[0];\n if (!first) {\n throw new Error(\n 'no transport configured — engine.remote() needs a transport (or transports)',\n );\n }\n return first.transport;\n }\n\n /** Register the engine's result/heartbeat/step-event handlers on EVERY transport — a result can come\n * back on whichever one delivered the task, so failover stays symmetric. `onStepEvent` is wired only\n * on transports that carry streamed workflow step lifecycle (BullMQ); others simply skip it. */\n bind(\n onResult: (result: StepResult) => Promise<void>,\n onHeartbeat: (beat: Heartbeat) => Promise<void>,\n onStepEvent?: (event: WorkflowStepEvent) => Promise<void>,\n onDecision?: (decision: WorkflowDecision) => Promise<void>,\n ): void {\n for (const { transport } of this.transports) {\n transport.onResult(onResult);\n transport.onHeartbeat(onHeartbeat);\n if (onStepEvent && transport.onStepEvent) {\n transport.onStepEvent(onStepEvent);\n }\n // A workflow-turn decision can come back on whichever transport carried the task — and on\n // whichever ENGINE INSTANCE consumes it (point-to-point), which may NOT be the dispatcher. The\n // engine applies it durably by run id, so binding it here (like onResult) is multi-instance safe.\n if (onDecision && transport.onDecision) {\n transport.onDecision(onDecision);\n }\n }\n }\n\n /**\n * Dispatch `task` over the pool: try the preferred (or first) transport, fail over to the next on\n * a dispatch error, and stamp the task with the id of the transport that accepted it (so a worker\n * replies on the matching one). Throws if every transport fails.\n */\n async dispatch(task: Omit<RemoteTask, 'transport'>, preferId?: string): Promise<void> {\n let lastErr: unknown;\n for (const { id, transport } of this.ordered(preferId)) {\n try {\n await transport.dispatch({ ...task, transport: id });\n return;\n } catch (err) {\n lastErr = err;\n }\n }\n throw lastErr ?? new Error('no transport accepted the dispatch');\n }\n\n /** Worker-health for `group`, merged across every transport that can report it (a group's queue\n * and its workers may live on any pinned transport). Undefined when no transport implements\n * `groupHealth` (e.g. a pure in-process transport — nothing to introspect). */\n async groupHealth(group: string): Promise<GroupHealth | undefined> {\n const reports: GroupHealth[] = [];\n for (const { transport } of this.transports) {\n if (transport.groupHealth) reports.push(await transport.groupHealth(group));\n }\n if (reports.length === 0) return undefined;\n return {\n group,\n depth: reports.reduce((sum, r) => sum + r.depth, 0),\n liveWorkers: reports.flatMap((r) => r.liveWorkers),\n };\n }\n\n /**\n * Register a control-plane `start-run` consumer on every transport that carries the channel. Only\n * control-plane-side transports implement {@link Transport.onStartRun}; a transport without it is\n * skipped, so a plain worker/in-process pool is a no-op. Mirrors {@link bind}'s per-transport wiring.\n */\n onStartRun(handler: (msg: StartRunMessage) => Promise<void>): void {\n for (const { transport } of this.transports) {\n transport.onStartRun?.(handler);\n }\n }\n\n /**\n * The live handshake descriptors advertised for `group` (design §7.2), merged across every transport\n * that can report them. Returns `[]` when NO transport implements\n * {@link Transport.readWorkerDescriptors} (a pure in-process pool) OR when descriptors are supported\n * but none is published — both are the \"guard disengaged / legacy assume-compatible\" case, so the\n * engine's routing guard treats an empty result identically (design §7.7).\n */\n async readWorkerDescriptors(group: string): Promise<WorkerDescriptor[]> {\n const descriptors: WorkerDescriptor[] = [];\n for (const { transport } of this.transports) {\n if (transport.readWorkerDescriptors) {\n descriptors.push(...(await transport.readWorkerDescriptors(group)));\n }\n }\n return descriptors;\n }\n\n /**\n * Every live descriptor in the deployment, merged across every transport that can report them and\n * de-duplicated by `instanceId` — one worker publishes the same descriptor under each token it\n * consumes, and it must count once. Returns `[]` when no transport implements\n * {@link Transport.readAllWorkerDescriptors} (a pure in-process pool advertises nothing).\n *\n * First writer wins on a duplicate id: the copies are the same bytes by construction (one process,\n * one descriptor, published N times), so there is nothing to choose between. Two DIFFERENT\n * processes sharing an `instanceId` would collapse into one here — that is a misconfiguration the\n * fleet already suffers from (they also share heartbeat and descriptor keys, so they overwrite each\n * other's advertisement), not something this read can repair.\n */\n async readAllWorkerDescriptors(): Promise<WorkerDescriptor[]> {\n const byInstance = new Map<string, WorkerDescriptor>();\n for (const { transport } of this.transports) {\n if (!transport.readAllWorkerDescriptors) continue;\n for (const descriptor of await transport.readAllWorkerDescriptors()) {\n if (!byInstance.has(descriptor.instanceId))\n byInstance.set(descriptor.instanceId, descriptor);\n }\n }\n return [...byInstance.values()];\n }\n\n /**\n * Every live worker heartbeat in the deployment, merged across every transport that can report\n * them and de-duplicated by `(group, instanceId)` — the same worker is one beat per token, and two\n * transports scanning the same keyspace must not double-count it.\n *\n * Returns `[]` when no transport implements {@link Transport.readAllWorkerHeartbeats}, which is\n * indistinguishable from \"nothing is beating\" on its own — {@link introspectsFleet} is what tells\n * those apart, and the directory reads it rather than guessing from an empty array.\n */\n async readAllWorkerHeartbeats(): Promise<WorkerHeartbeat[]> {\n const seen = new Map<string, WorkerHeartbeat>();\n for (const { transport } of this.transports) {\n if (!transport.readAllWorkerHeartbeats) continue;\n for (const beat of await transport.readAllWorkerHeartbeats()) {\n const key = `${beat.group}\u0000${beat.instanceId}`;\n if (!seen.has(key)) seen.set(key, beat);\n }\n }\n return [...seen.values()];\n }\n\n /**\n * Can ANY transport here introspect the fleet — descriptors or heartbeats? This is the difference\n * between \"the fleet is empty\" and \"nobody asked\", and it is a property of the POOL rather than of\n * a read's result, so it stays answerable when both reads legitimately come back empty.\n */\n get introspectsFleet(): boolean {\n return this.transports.some(\n ({ transport }) => transport.readAllWorkerDescriptors || transport.readAllWorkerHeartbeats,\n );\n }\n\n /** Distinct worker groups with a live heartbeat, merged across every transport that can report it. */\n async listWorkerGroups(): Promise<string[]> {\n const groups = new Set<string>();\n for (const { transport } of this.transports) {\n if (transport.listWorkerGroups) {\n for (const g of await transport.listWorkerGroups()) groups.add(g);\n }\n }\n return [...groups];\n }\n\n /**\n * The first transport (in pool order) reporting a LIVE heartbeat for `group` — the one a\n * convention-routed remote workflow must dispatch on. In a mixed pool (e.g. a tenant-scoped\n * control plane pairing its namespaced transport with a bare-prefix one for operator-convention\n * tenant workers), each transport sees a DIFFERENT keyspace: dispatching on `primary` while the\n * live worker heartbeats on another transport parks the task on a queue nobody consumes. Returns\n * `undefined` when no transport reports the group (mirrors the merged `listWorkerGroups` miss).\n */\n async transportWithLiveGroup(group: string): Promise<Transport | undefined> {\n for (const { transport } of this.transports) {\n if (!transport.listWorkerGroups) continue;\n if ((await transport.listWorkerGroups()).includes(group)) return transport;\n }\n return undefined;\n }\n\n /** Pinned `preferId` first, then the rest (failover order). */\n private ordered(preferId?: string): NamedTransport[] {\n if (!preferId) return this.transports;\n const pref = this.transports.filter((t) => t.id === preferId);\n if (pref.length === 0) throw new Error(`transport \"${preferId}\" is not registered`);\n return [...pref, ...this.transports.filter((t) => t.id !== preferId)];\n }\n}\n","/**\n * Cross-package step-name stamp. The `@Step` decorator (`@dudousxd/nestjs-durable`) writes a\n * method's derived routing name under this key; core's `ctx.step` reads it (via {@link stepNameOf})\n * to route a method-reference call to the same handler a worker registers by name.\n *\n * `Symbol.for` (the GLOBAL registry), NOT a plain `Symbol()` — so a duplicate copy of this module\n * (pnpm peer-dependency multiplexing, or a dual ESM/CJS load) still reads the SAME key. A plain\n * `Symbol()` would mint a distinct token per copy, so a decorator running against one core instance\n * could stamp a name core's `ctx.step` (a different instance) can never read back. Mirrors the\n * `STATE_STORE` token fix in `./tokens.ts`.\n */\nexport const DURABLE_STEP_NAME = Symbol.for('durable.step.name');\n\n/**\n * Cross-package step-DISPATCH-POLICY stamp. `@Step({ retries, backoff, backoffMs, backoffMaxMs,\n * jitter, timeoutMs })` (`@dudousxd/nestjs-durable`) writes the def-level durable-retry/liveness\n * policy under this key; core's `ctx.step` reads it (via {@link stepConfigOf}) and merges it with any\n * per-call {@link StepDispatchOpts} override to build the dispatched {@link StepDef}. Same\n * `Symbol.for` rationale as {@link DURABLE_STEP_NAME} — a duplicate copy of this module (pnpm\n * peer-dependency multiplexing, dual ESM/CJS) must still read back the SAME key.\n */\nexport const DURABLE_STEP_CONFIG = Symbol.for('durable.step.config');\n\n/**\n * The def-level durable-dispatch policy a `@Step(...)` can stamp on a method: retry/backoff and the\n * remote-liveness `timeoutMs` — the dispatch-relevant subset of the engine's `StepOptions`. Read off\n * a handler reference via {@link stepConfigOf}; a per-call {@link StepDispatchOpts} passed to\n * `ctx.step(ref, input, opts)` overrides these field-by-field.\n */\nexport interface StepConfig {\n /** Max attempts before the step (and run) fails. */\n retries?: number | undefined;\n /** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt). */\n backoff?: 'fixed' | 'exp' | undefined;\n /** Base delay in ms between retries. Omit (or 0) to retry with no delay. */\n backoffMs?: number | undefined;\n /** Upper bound on the (exponential) backoff delay. */\n backoffMaxMs?: number | undefined;\n /** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */\n jitter?: boolean | undefined;\n /** Liveness window for the dispatched step: no result/heartbeat within this many ms presumes the\n * worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per\n * `retries`). Omit to wait indefinitely. */\n timeoutMs?: number | undefined;\n /** Capabilities a live worker must advertise to run this step (handshake design §7.5). The\n * control-plane routes the step only to capable+compatible workers; if descriptors are published\n * on its group but none qualifies, the run parks `blocked`. Absent/empty = \"runs anywhere\". */\n requires?: string[] | undefined;\n}\n\nfunction isStepConfig(value: unknown): value is StepConfig {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * A method carrying its `@Step`-stamped routing name (and, optionally, its dispatch policy).\n * `ctx.step(ref, input)` reads the name via {@link stepNameOf} — the reference itself is never\n * invoked directly by the caller's process (the worker serving that name re-resolves the real\n * handler from DI), so an unbound `this` on `ref` is irrelevant; `ref` is purely a typed,\n * refactor-safe handle onto the stamped name (and policy).\n */\nexport type StepRef<TInput = unknown, TOutput = unknown> = ((\n input: TInput,\n) => Promise<TOutput> | TOutput) & {\n [DURABLE_STEP_NAME]?: string | undefined;\n [DURABLE_STEP_CONFIG]?: StepConfig | undefined;\n};\n\n/** Read the `@Step`-stamped routing name off a function ref. `undefined` for anything unstamped\n * (including a plain string — {@link stepNameOf} only reads function refs; a caller passing a\n * string already has the routing name and dispatches it directly). */\nexport function stepNameOf(ref: unknown): string | undefined {\n if (typeof ref !== 'function') return undefined;\n const stamped = (ref as { [DURABLE_STEP_NAME]?: unknown })[DURABLE_STEP_NAME];\n return typeof stamped === 'string' ? stamped : undefined;\n}\n\n/** Read the `@Step`-stamped dispatch policy off a function ref. `undefined` for anything unstamped\n * (including a plain string — a cross-runtime string-name call has no def-level policy to read; pass\n * it via {@link StepDispatchOpts} instead). */\nexport function stepConfigOf(ref: unknown): StepConfig | undefined {\n if (typeof ref !== 'function') return undefined;\n const stamped = (ref as { [DURABLE_STEP_CONFIG]?: unknown })[DURABLE_STEP_CONFIG];\n return isStepConfig(stamped) ? stamped : undefined;\n}\n","import { currentStepScope, runInStepScope } from './ambient-ctx';\nimport { runInStepLogger } from './ambient-step';\nimport { backoffDelay } from './backoff';\nimport { instantCheckpoint } from './checkpoints';\nimport { unwrapCompletion } from './completion';\nimport { parseDuration } from './duration';\nimport {\n ContinueAsNew,\n FatalError,\n GatherError,\n NestedWorkflowCallError,\n NonDeterminismError,\n SignalTimeoutError,\n WorkflowSuspended,\n} from './errors';\nimport { EVENT_BUFFER_SCAN_LIMIT, eventMatches, eventToken } from './events';\nimport {\n FOLDED_PREFIX,\n type FoldedChildren,\n allChildId,\n allFoldedName,\n allGroup,\n allWait,\n allWaves,\n fanJoin,\n} from './fan-join';\nimport type {\n AllOptions,\n ChildCallOptions,\n ChildWait,\n DurableWebhook,\n SearchAttributes,\n SearchAttributesSchema,\n StateStore,\n StepCheckpoint,\n StepDef,\n StepDispatchOpts,\n StepError,\n StepEvent,\n StepInvocation,\n StepKind,\n StepLogger,\n StepOptions,\n StepUndo,\n WorkflowCtx,\n} from './interfaces';\nimport { breakpointToken } from './protocol';\nimport { createStepLogger } from './step-logger';\nimport { type StepConfig, type StepRef, stepConfigOf, stepNameOf } from './step-name-symbol';\nimport { type WorkflowRef, workflowName } from './workflow-ref';\n\n/** Normalize the `ctx.child`/`ctx.startChild` 3rd arg: a bare string is shorthand for `{ childId }`. */\n/** How many children of a fan are registered per store round trip. */\nconst FAN_CHUNK = 500;\n/** The smallest fan whose settled waves are folded; a smaller one keeps per-child detail for the dashboard. */\nconst FOLD_MIN_FAN = 100;\n\nfunction normalizeChildOptions(options?: string | ChildCallOptions): ChildCallOptions {\n return typeof options === 'string' ? { childId: options } : (options ?? {});\n}\n\n/** Render a Standard Schema issue `path` (a mix of raw keys and `{ key }` segments) as a dotted\n * string, for a `searchAttributes` validation error — `['amount']` → `'amount'`, `[]`/`undefined` →\n * `'(root)'` (the merged object itself failed, not one of its keys). */\nfunction formatIssuePath(\n path: ReadonlyArray<PropertyKey | { readonly key: PropertyKey }> | undefined,\n): string {\n if (!path || path.length === 0) return '(root)';\n return path\n .map((segment) => String(typeof segment === 'object' ? segment.key : segment))\n .join('.');\n}\n\n/**\n * Merge a `@Step`-declared {@link StepConfig} with a per-call {@link StepDispatchOpts} override into\n * the dispatch-relevant `StepOptions` subset of a {@link StepDef} (`retries`/`backoff`/`backoffMs`/\n * `backoffMaxMs`/`jitter`/`timeoutMs`), `opts` winning field-by-field. Omits every field neither side\n * set — required under `exactOptionalPropertyTypes` (an explicit `undefined` value is a type error).\n */\nfunction resolveStepPolicy(\n config: StepConfig | undefined,\n opts: StepDispatchOpts | undefined,\n): StepOptions {\n const policy: StepOptions = {};\n const retries = opts?.retries ?? config?.retries;\n if (retries !== undefined) policy.retries = retries;\n const backoff = opts?.backoff ?? config?.backoff;\n if (backoff !== undefined) policy.backoff = backoff;\n const backoffMs = opts?.backoffMs ?? config?.backoffMs;\n if (backoffMs !== undefined) policy.backoffMs = backoffMs;\n const backoffMaxMs = opts?.backoffMaxMs ?? config?.backoffMaxMs;\n if (backoffMaxMs !== undefined) policy.backoffMaxMs = backoffMaxMs;\n const jitter = opts?.jitter ?? config?.jitter;\n if (jitter !== undefined) policy.jitter = jitter;\n const timeoutMs = opts?.timeoutMs ?? config?.timeoutMs;\n if (timeoutMs !== undefined) policy.timeoutMs = timeoutMs;\n const requires = opts?.requires ?? config?.requires;\n if (requires !== undefined) policy.requires = requires;\n return policy;\n}\n\n/**\n * A saga undo registered by a completed step, kept with its step name for visibility on failure.\n * Two shapes, pushed onto the SAME `compensations` stack so the engine unwinds them together in one\n * strict reverse-completion order, regardless of which kind each one is:\n * - `fn`: a LOCAL undo (`ctx.localStep`'s `compensate` closure) — run in-process.\n * - `dispatch`: a DISPATCHED undo (`ctx.step`'s `compensate` ref/string) — an ordinary `@Step` def\n * the engine dispatches to a worker at unwind time, called with the `StepUndo` envelope (`args`).\n */\nexport type Compensation =\n | { name: string; fn: () => Promise<void> }\n | {\n name: string;\n dispatch: {\n def: StepDef<StepUndo<unknown, unknown>, unknown>;\n args: StepUndo<unknown, unknown>;\n };\n };\n\n/** A finished local step the host should checkpoint and announce (completed or failed). */\nexport interface StepRecord {\n runId: string;\n seq: number;\n name: string;\n kind: StepKind;\n input?: unknown;\n events?: StepEvent[] | undefined;\n attempts: number;\n enqueuedAt: Date;\n startedAt: Date;\n workerGroup?: string | undefined;\n}\n\n/**\n * The narrow surface {@link createWorkflowCtx} needs from the engine — the seam between the\n * authoring API (this module) and the orchestrator (the engine owns lifecycle: emitting events,\n * suspending/resuming runs, dispatching remote steps).\n */\nexport interface CtxHost {\n readonly store: StateStore;\n /**\n * Per-execution checkpoint snapshot, loaded ONCE at execution start (the completed prefix this\n * replay walks). Lets each primitive read the prefix from memory instead of a per-call DB SELECT\n * (the O(N²) replay-reads fix). A seq ABSENT from the map is NOT cached — the primitive falls back\n * to the live store, so the checkpoint this resume is waking on (signal/timer/child, written after\n * the snapshot) is always read fresh. New checkpoints written during this execution are inserted\n * into the map so any later same-execution read sees them. Undefined ⇒ always hit the store.\n */\n readonly replay?: Map<number, StepCheckpoint> | undefined;\n clock(): number;\n webhookUrl?: ((token: string) => string) | undefined;\n /** Mark a local step's body as started — emits `step.started` and (optionally) a `running` checkpoint. */\n startStep(step: StepRecord): Promise<void>;\n completeStep(step: StepRecord & { output: unknown }): Promise<void>;\n failStep(step: StepRecord & { error: StepError }): Promise<void>;\n callRemote<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n queue?: string,\n transport?: string,\n admission?: { priority?: number | undefined; fairnessKey?: string | undefined },\n ): Promise<TOutput>;\n /** Start a child run once, deferred so it can't reentrantly resume a still-running parent.\n * `version` pins the child to that exact registered version (see `StartOptions.version`); omitted,\n * the child starts on the newest registered one. */\n startChild(\n workflow: string,\n input: unknown,\n id: string,\n priority?: number,\n version?: string,\n ): void;\n /**\n * Best-effort cancel of a child run — deferred for the SAME reason as `startChild` (so ctx code\n * can't reentrantly mutate engine state while the parent's own step is still executing\n * synchronously). Plain cancel, no saga undo; used by `ctx.all`'s `failFast` mode to stop the\n * surviving siblings once one has failed. Cancelling an already-terminal/cancelled run is a no-op\n * (`engine.cancel`'s own idempotency guard), so a replay that re-issues the same calls is safe.\n * Optional: hosts that never construct a `ctx.all` failFast call (e.g. test fakes) can omit it.\n */\n cancelChild?(childId: string): void;\n /** Shallow-merge `attrs` into the run's `searchAttributes` (see {@link WorkflowCtx.upsertSearchAttributes}). */\n upsertSearchAttributes(runId: string, attrs: SearchAttributes): Promise<void>;\n /** Deliver an op to a durable entity (deferred), optionally with a `reply` token for the result. */\n signalEntity?(name: string, key: string, op: string, arg: unknown, reply?: string): void;\n /** Run a local step body through the registered step interceptors (identity if none). */\n interceptStep?<T>(invocation: StepInvocation, body: () => Promise<T>): Promise<T>;\n}\n\n/** The per-run logical position counter. `rewind()` gives a position back (see `ctx.patched`). */\nclass Position {\n private seq = -1;\n next(): number {\n this.seq += 1;\n return this.seq;\n }\n rewind(): void {\n this.seq -= 1;\n }\n /** The position the NEXT primitive would claim, without claiming it. */\n peek(): number {\n return this.seq + 1;\n }\n}\n\n/**\n * Back-compat alias of {@link WorkflowCtx}. `localStep` — the checkpointed in-process step primitive\n * used for saga compensation — is now part of the public {@link WorkflowCtx}, so this type adds\n * nothing; it is kept only so internal consumers (the durable-entity runner) keep compiling.\n */\nexport type InternalWorkflowCtx = WorkflowCtx;\n\n/**\n * Build the {@link WorkflowCtx} handed to a workflow body. Every primitive is a closure over the\n * position counter (the per-run logical position) and the saga `compensations` stack, so `task`/\n * `child` compose `step`/`waitForSignal` directly. All durability goes through {@link CtxHost}, so\n * the workflow body stays deterministic.\n */\nexport function createWorkflowCtx(\n host: CtxHost,\n runId: string,\n compensations: Compensation[],\n workflow = '',\n searchAttributesSchema?: SearchAttributesSchema,\n): InternalWorkflowCtx {\n const { store, replay } = host;\n const pos = new Position();\n // This ctx's identity in the ambient step scope (see `runInStepScope`): lets a primitive tell \"I am\n // being called from inside one of MY step bodies\" apart from another run's body executing inline.\n const scopeOwner = {};\n\n // Read the checkpoint at `seq`: from the per-execution snapshot when present (no DB round-trip),\n // otherwise from the live store. Absence in the snapshot means \"written after the snapshot\" (the\n // signal/timer/child this resume wakes on, or nothing yet) — those MUST hit the store. Identical\n // behaviour to a raw `store.getCheckpoint`, just memoized for the completed prefix.\n const readCheckpoint = (seq: number): Promise<StepCheckpoint | null> | StepCheckpoint => {\n const hit = replay?.get(seq);\n if (hit !== undefined) return hit;\n return store.getCheckpoint(runId, seq);\n };\n\n // Persist a checkpoint AND reflect it in the snapshot, so a later same-execution read of this seq\n // (e.g. a re-read within the same call) sees it instead of falling back to the store.\n const writeCheckpoint = async (cp: StepCheckpoint): Promise<void> => {\n await store.saveCheckpoint(cp);\n replay?.set(cp.seq, cp);\n };\n\n // The in-process local-step runner: checkpointed, replayed, retried. No longer publicly exposed as\n // `ctx.step` (that name is now the ALWAYS-dispatched form below) — this backs the library's own\n // internal primitives that need a checkpointed in-process body: `ctx.task`'s dispatch step and the\n // deterministic capture helpers `ctx.now`/`ctx.sideEffect`.\n const localStep = async <T>(\n name: string,\n fn: (log: StepLogger) => Promise<T>,\n options?: StepOptions,\n ): Promise<T> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') {\n // Register the compensation on replay too, so a saga undoes ALL completed steps — even\n // those done in an earlier (since-suspended) pass — not just the ones run this pass.\n if (options?.compensate) compensations.push({ name, fn: options.compensate });\n return existing.output as T;\n }\n const maxAttempts = Math.max(1, options?.retries ?? 1);\n const startedAt = new Date();\n // Announce the body has begun (and, when enabled, checkpoint it `running`) so the step is\n // visible in flight — not only once it settles. Skipped on replay: a completed step returns\n // above before reaching here, so this fires once, when the body actually first runs.\n await host.startStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n });\n for (let attempt = 1; ; attempt += 1) {\n // Events are scoped per attempt — a retry starts a clean log, so the checkpoint reflects\n // only the attempt that actually completed (or the final failing one).\n const events: StepEvent[] = [];\n try {\n const invocation: StepInvocation = {\n runId,\n workflow,\n stepName: name,\n seq: current,\n attempt,\n };\n // The SAME logger goes to the body's argument and into the ambient storage, so code deep\n // inside the step emits into this attempt's `events` without the handle being threaded\n // down through every signature (see `ambient-step.ts`).\n const body = () => {\n const logger = createStepLogger(events, host.clock);\n return runInStepScope(scopeOwner, name, () => runInStepLogger(logger, () => fn(logger)));\n };\n const output = host.interceptStep\n ? await host.interceptStep(invocation, body)\n : await body();\n await host.completeStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n output,\n events,\n attempts: attempt,\n enqueuedAt: startedAt,\n startedAt,\n });\n if (options?.compensate) compensations.push({ name, fn: options.compensate });\n return output;\n } catch (err) {\n if (err instanceof FatalError || attempt >= maxAttempts) {\n await host.failStep({\n runId,\n seq: current,\n name,\n kind: 'local',\n error: {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n },\n events,\n attempts: attempt,\n enqueuedAt: startedAt,\n startedAt,\n });\n throw err;\n }\n // Wait out the backoff before the next attempt (no-op when backoffMs is unset).\n const wait = backoffDelay(attempt, options);\n if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));\n }\n }\n };\n\n // Exactly-once DB step: run the body and write the step checkpoint in ONE store transaction, so the\n // business write commits atomically with the \"done\" marker (a plain step checkpoints AFTER the body,\n // so a crash in between re-runs it). Replay returns the recorded output without re-running.\n const transaction = async <T>(name: string, fn: (tx: unknown) => Promise<T>): Promise<T> => {\n if (!store.transaction) {\n throw new Error(\n 'ctx.transaction needs a store that supports transactions (the SQL adapters do). Use ctx.step for non-transactional work.',\n );\n }\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') return existing.output as T;\n return store.transaction(async (tx) => {\n const output = await runInStepScope(scopeOwner, name, () => fn(tx.raw));\n const cp = instantCheckpoint({ runId, seq: current, name, kind: 'local', output });\n await tx.saveCheckpoint(cp);\n // Reflect the committed checkpoint in the snapshot, keeping the writeback invariant uniform.\n replay?.set(current, cp);\n return output;\n });\n };\n\n // Shared by sleep / sleepUntil: record a durable timer at this position and suspend until `wakeAt`\n // (epoch ms). The wakeAt is computed by the caller — but only used on the first run; on replay the\n // recorded checkpoint's wakeAt wins, so a clock change can't shift an already-scheduled timer.\n const suspendUntil = async (wakeAt: () => number): Promise<void> => {\n const current = pos.next();\n const now = host.clock();\n const existing = await readCheckpoint(current);\n if (existing) {\n // Timer already recorded: resume if due, otherwise re-suspend cheaply.\n if (now >= (existing.wakeAt ?? 0)) return;\n throw new WorkflowSuspended(existing.wakeAt ?? now);\n }\n const at = wakeAt();\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: 'sleep', kind: 'sleep', wakeAt: at }),\n );\n throw new WorkflowSuspended(at);\n };\n\n const sleep = (duration: string | number): Promise<void> =>\n suspendUntil(() => host.clock() + parseDuration(duration));\n\n const sleepUntil = (when: Date | number): Promise<void> =>\n suspendUntil(() => (typeof when === 'number' ? when : when.getTime()));\n\n // End this run and hand off to a fresh execution (clean history) with the new input. Terminal —\n // it always throws, so any code after it in the workflow is unreachable.\n const continueAsNew = (input?: unknown): Promise<never> => {\n throw new ContinueAsNew(input);\n };\n\n // NOTE (determinism): a bounded wait consumes TWO logical positions (deadline + wait), an\n // unbounded one consumes ONE. So adding or removing `{ timeoutMs }` on an existing `waitForSignal`\n // shifts the seq of every later step — treat it as a workflow-version change for in-flight runs.\n // Consume a buffered signal (one delivered before this run was waiting), recording it as the\n // signal checkpoint at `seq` so it resumes immediately instead of suspending. Replay-safe: the\n // checkpoint makes the consumption deterministic.\n const consumeBuffered = async <T>(token: string, seq: number): Promise<{ value: T } | null> => {\n const buffered = await store.takeBufferedSignal(token);\n if (!buffered) return null;\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq,\n name: `signal:${token}`,\n kind: 'signal',\n output: buffered.payload,\n }),\n );\n return { value: buffered.payload as T };\n };\n\n // Consume a buffered EVENT matching `match` (one published with no live waiter — see\n // engine.publishEvent's buffering), recording it as the resolving `signal:<token>` checkpoint at\n // `seq` so replay is deterministic — the event analog of `consumeBuffered` above, but match-aware:\n // an event's buffer is keyed by NAME only (many waiters can share a name with different `match`\n // criteria), so consumption scans the oldest candidates and evaluates each one's match HERE — the\n // match predicate belongs to the WAITER, never the store (see events.ts / interfaces.ts). A hit\n // atomically claims that one row via `removeBufferedEvent`'s boolean return, which arbitrates a\n // concurrent claim (notably engine.publishEvent's own late re-check reaching the same row first —\n // see the wiring in engine.ts); losing that race tries the NEXT oldest candidate instead of giving\n // up, so a later non-matching buffered event never blocks an earlier matching one behind it.\n const consumeBufferedEvent = async <T>(\n name: string,\n match: Record<string, unknown> | undefined,\n token: string,\n seq: number,\n ): Promise<{ value: T } | null> => {\n const candidates = await store.listBufferedEvents(name, EVENT_BUFFER_SCAN_LIMIT);\n for (const candidate of candidates) {\n if (!eventMatches(candidate.payload, match ?? {})) continue;\n if (!(await store.removeBufferedEvent(candidate.id))) continue; // raced away — try the next\n // Resolved it ourselves — remove OUR OWN waiter row via the exact match (not\n // `takeSignalWaiter(token)`; harmless here since an event token is unique per call, but exact\n // removal keeps this symmetric with the signal-side precedent in `waitForSignal` above).\n await store.removeSignalWaiter({ token, runId, seq });\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq,\n name: `signal:${token}`,\n kind: 'signal',\n output: candidate.payload,\n }),\n );\n return { value: candidate.payload as T };\n }\n return null;\n };\n\n // Durably stamp the deadline for a BOUNDED wait, ONCE: the first run computes `clock() + timeoutMs`\n // and records it as a timer checkpoint at `deadlineSeq`; every later replay reads the SAME recorded\n // `wakeAt` back instead of recomputing it — so a slow replay (or a clock that moved between the\n // original run and the replay) can never shift an already-scheduled deadline. `label` only affects\n // the checkpoint's `name` (cosmetic, for the dashboard timeline) — the shared mechanic behind every\n // bounded-wait primitive (`waitForSignal`, `waitForEvent`, `DurableWebhook.wait`).\n const stampDeadline = async (\n deadlineSeq: number,\n label: string,\n timeoutMs: number,\n ): Promise<number> => {\n const recorded = await readCheckpoint(deadlineSeq);\n const deadline = recorded?.wakeAt ?? host.clock() + timeoutMs;\n if (!recorded) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: deadlineSeq,\n name: `timeout:${label}`,\n kind: 'sleep',\n wakeAt: deadline,\n }),\n );\n }\n return deadline;\n };\n\n const waitForSignal = async <T>(token: string, opts?: { timeoutMs?: number }): Promise<T> => {\n if (opts?.timeoutMs == null) {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n const buffered = await consumeBuffered<T>(token, current);\n if (buffered) return buffered.value;\n // Register, THEN check the buffer again before suspending — closes the lost-wake window\n // between the check above and this registration: a signal delivered in that sliver found no\n // waiter (we hadn't registered yet) and no buffer either by the time IT checked, so it buffered\n // the payload; without this re-check we'd suspend with the payload sitting unpaired forever.\n // (Registering UNCONDITIONALLY before even the first check — instead of only on a miss like\n // here — reopens a worse window: a token an entity loop reuses across iterations would expose\n // a \"this turn is about to self-resolve from the buffer\" waiter row to a concurrent signal for\n // the NEXT iteration's payload, which can steal it via engine.signal's plain takeSignalWaiter\n // and misdeliver. Checking first, so we only ever register when we're sure no buffer already\n // existed, avoids that.) See the interleaving proof at engine.signal for the mirror-image\n // take→buffer→re-take on the signaling side that this pairs with.\n await store.putSignalWaiter({ token, runId, seq: current });\n const lateBuffered = await consumeBuffered<T>(token, current);\n if (lateBuffered) {\n // Resolved it ourselves — remove OUR OWN row via the exact match, not\n // `takeSignalWaiter(token)`, which deletes ANY row for this token and could steal a\n // different run's waiter that has since claimed the same token.\n await store.removeSignalWaiter({ token, runId, seq: current });\n return lateBuffered.value;\n }\n throw new WorkflowSuspended();\n }\n const timeoutMs = opts.timeoutMs;\n const deadlineSeq = pos.next();\n const waitSeq = pos.next();\n // The run also gets a run-level wakeAt (via WorkflowSuspended) so the timer poller resumes it at\n // the deadline.\n const deadline = await stampDeadline(deadlineSeq, token, timeoutMs);\n const waited = await readCheckpoint(waitSeq);\n if (waited && waited.status === 'completed') return waited.output as T;\n const buffered = await consumeBuffered<T>(token, waitSeq);\n if (buffered) return buffered.value;\n if (host.clock() >= deadline) {\n // A PRIOR replay of this same call may have already registered the waiter (below) before this\n // one found the deadline past — clean up that exact row (own token/runId/seq only; a plain\n // `takeSignalWaiter(token)` could otherwise steal a different run's waiter on the same token).\n // A no-op if nothing was ever registered.\n await store.removeSignalWaiter({ token, runId, seq: waitSeq }).catch(() => undefined);\n throw new SignalTimeoutError(token, timeoutMs);\n }\n // Same reorder as the unbounded arm above: check, THEN register, THEN re-check before suspending.\n await store.putSignalWaiter({ token, runId, seq: waitSeq });\n const lateBuffered = await consumeBuffered<T>(token, waitSeq);\n if (lateBuffered) {\n await store.removeSignalWaiter({ token, runId, seq: waitSeq });\n return lateBuffered.value;\n }\n throw new WorkflowSuspended(deadline);\n };\n\n // Wait for a named event delivered by engine.publishEvent(name, payload). Like waitForSignal, but\n // name-based pub/sub with optional `match` filtering — the token embeds name + match (see events.ts),\n // so a publish fans out to the runs whose match the payload satisfies.\n //\n // Buffering (reliable events — mirrors signalWithStart's reliability contract for signals, see the\n // \"Semantics\" doc on engine.publishEvent): a publish that finds no live waiter buffers ONE copy, and\n // this call's post-registration scan is what consumes it. UNLIKE waitForSignal, this registers its\n // waiter FIRST and scans the buffer only ONCE after — no separate \"check before registering\" pass.\n // That's deliberate, not an oversight: waitForSignal's own token is a caller-chosen string an entity\n // loop can legitimately REUSE across iterations, so registering before checking would expose a\n // \"this turn is about to self-resolve\" waiter row to a concurrent signal for the NEXT iteration's\n // token, which could steal it via engine.signal's plain takeSignalWaiter. An event token embeds this\n // call's OWN `runId#seq` (see eventToken in events.ts) — nothing else, ever, mints the same token —\n // so that hazard cannot arise here, and a single check-after-register closes the lost-wake window\n // symmetrically with engine.publishEvent's own buffer-then-recheck (see its wiring in engine.ts).\n const waitForEvent = async <T>(\n name: string,\n opts?: { match?: Record<string, unknown>; timeoutMs?: number },\n ): Promise<T> => {\n if (opts?.timeoutMs == null) {\n const current = pos.next();\n const token = eventToken(name, opts?.match, runId, current);\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n await store.putSignalWaiter({ token, runId, seq: current });\n const bufferedHit = await consumeBufferedEvent<T>(name, opts?.match, token, current);\n if (bufferedHit) return bufferedHit.value;\n throw new WorkflowSuspended();\n }\n const timeoutMs = opts.timeoutMs;\n const deadlineSeq = pos.next();\n const waitSeq = pos.next();\n const token = eventToken(name, opts.match, runId, waitSeq);\n const deadline = await stampDeadline(deadlineSeq, `event:${name}`, timeoutMs);\n const waited = await readCheckpoint(waitSeq);\n if (waited && waited.status === 'completed') return waited.output as T;\n if (host.clock() >= deadline) {\n // Exact removal (see waitForSignal above) — takeSignalWaiter(token) deletes ANY row for this\n // token and could steal a different run's waiter registered on it after ours timed out.\n await store.removeSignalWaiter({ token, runId, seq: waitSeq }).catch(() => undefined);\n throw new SignalTimeoutError(`event:${name}`, timeoutMs);\n }\n await store.putSignalWaiter({ token, runId, seq: waitSeq });\n const bufferedHit = await consumeBufferedEvent<T>(name, opts.match, token, waitSeq);\n if (bufferedHit) return bufferedHit.value;\n throw new WorkflowSuspended(deadline);\n };\n\n // An external task = a checkpointed dispatch + a wait for its async-completion `Completion`\n // (delivered by engine.completeTask/failTask). The whole \"fire at a foreign system, suspend,\n // resume when it reports back\" pattern as one call.\n const task = async <T>(\n name: string,\n dispatch: () => Promise<void>,\n options?: StepOptions,\n ): Promise<T> => {\n await localStep(`task:dispatch:${name}`, dispatch, options);\n return unwrapCompletion<T>(await waitForSignal(`task:${runId}:${name}`), `task \"${name}\"`);\n };\n\n // Child workflow (await result): start it once, then suspend on a `child:<id>` waiter the child\n // signals on its terminal state (see engine.notifyParent).\n const child = async <T>(\n workflow: WorkflowRef,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<T> => {\n const { childId, priority, version } = normalizeChildOptions(options);\n const current = pos.next();\n const id = childId ?? `${runId}.child.${current}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') {\n return unwrapCompletion<T>(existing.output, `child \"${id}\"`);\n }\n // A placeholder proves the waiter was put; re-putting it could leave one for a child that\n // already settled after this execution's snapshot, which nothing would ever take.\n if (!existing) await store.putSignalWaiter({ token: `child:${id}`, runId, seq: current });\n // Lost-wake guard (mirrors the engine's remote `startChild` command path): the child may have\n // ALREADY completed while no waiter was registered — e.g. this run failed on the child's\n // failure, the child was retried to completion, and this run is now being retried — leaving its\n // completion BUFFERED. Consume it here or the re-registered waiter waits forever for a signal\n // that already fired. Resolve exactly as engine.signal would: overwrite the placeholder with\n // the completed signal checkpoint, then unwrap.\n const buffered = await store.takeBufferedSignal(`child:${id}`);\n if (buffered) {\n await store.removeSignalWaiter({ token: `child:${id}`, runId, seq: current });\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: `signal:child:${id}`,\n kind: 'signal',\n output: buffered.payload,\n }),\n );\n return unwrapCompletion<T>(buffered.payload, `child \"${id}\"`);\n }\n if (!(await store.getRun(id)))\n host.startChild(workflowName(workflow), input, id, priority, version);\n // Make the awaited child visible in the parent's timeline WHILE it runs: a `running` placeholder\n // at this seq with the same `signal:child:<id>` name the signal resolution later overwrites as\n // `completed`. So the dashboard shows the child node (and can inline-expand it) live, instead of\n // it appearing only when it finishes. Written once (skipped on replay, where `existing` is set);\n // `running` is ignored by replay history, so it never short-circuits determinism.\n if (!existing) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: `signal:child:${id}`,\n kind: 'signal',\n status: 'running',\n }),\n );\n }\n throw new WorkflowSuspended(\n undefined,\n fanJoin([{ waiterPrefix: `child:${id}`, checkpointPrefix: `signal:child:${id}` }]),\n );\n };\n\n // Parallel child workflows (wait-all): dispatch N children CONCURRENTLY and wait for ALL their\n // outputs. Reserves a contiguous position block in list order FIRST (the determinism anchor), then\n // dispatches every not-yet-completed item and suspends once. The engine's join barrier holds the\n // parent's wake until the fan's last waiter is consumed (or, for failFast, the first failure), so\n // the parent replays about once per fan rather than once per child — the fan stays O(N).\n // With `concurrency`, children go out in waves and the parent wakes once per settled wave to send\n // the next one. When all resolve, outputs are returned in INPUT order (waitAll), or a GatherError\n // is thrown carrying the per-item failures. Parity with the Python SDK's `gather_children`.\n const all = async <T = unknown>(\n workflow: WorkflowRef,\n inputs: unknown[],\n opts?: AllOptions,\n ): Promise<T[]> => {\n // Empty: reserve no positions and produce no side effects (degenerate identity).\n if (inputs.length === 0) return [];\n const mode = opts?.mode ?? 'waitAll';\n const name = workflowName(workflow);\n const waves = allWaves(inputs.length, opts?.concurrency);\n // Reserve the whole block in list order BEFORE any dispatch — replay re-derives identical seqs.\n const positions = inputs.map(() => pos.next());\n const firstSeq = positions[0] as number;\n const group = allGroup(firstSeq, mode);\n const waveOf = (i: number) => (waves ? Math.floor(i / waves.waveSize) : undefined);\n const id = (i: number) => allChildId(runId, firstSeq, i, waveOf(i));\n const { checkpoints: existing, folded } = await readFan(positions, [\n allWait(runId, firstSeq).checkpointPrefix,\n allFoldedName(runId, firstSeq),\n ]);\n // The unbounded fan is a single wave.\n const waveCount = waves ? Math.ceil(inputs.length / waves.waveSize) : 1;\n const waveItems = (k: number): number[] => {\n if (!waves) return inputs.map((_, i) => i);\n const from = k * waves.waveSize;\n return inputs.map((_, i) => i).slice(from, from + waves.waveSize);\n };\n\n // failFast: bail the moment any already-completed item is a failed Completion.\n if (mode === 'failFast') {\n for (let i = 0; i < inputs.length; i += 1) {\n const cp = existing[i];\n const c =\n cp?.status === 'completed' ? (cp.output as { ok?: boolean; error?: string }) : null;\n if (c && c.ok === false) {\n // Cancel every sibling that hasn't completed yet — plain cancel, no saga undo. Best-effort:\n // a sibling mid-step only observes the cancellation at its NEXT checkpoint (it isn't\n // force-killed mid-synchronous-execution), so a fast-enough sibling can still slip through\n // and complete before it notices. `cancelChild` is deferred (like `startChild`), and\n // cancelling an already-terminal/cancelled run is a no-op, so replaying this branch after a\n // resume (which re-executes this loop and re-issues the same cancels) is safe.\n for (let j = 0; j < inputs.length; j += 1) {\n if (j !== i && existing[j]?.status !== 'completed') host.cancelChild?.(id(j));\n }\n throw new GatherError(\n [{ index: i, id: id(i), error: c.error ?? 'unknown' }],\n inputs.length,\n );\n }\n }\n }\n\n // Fold every wave whose children all succeeded into one checkpoint, so the parent's later turns\n // load one row for it instead of one per child. A wave with a failure keeps its per-child\n // checkpoints: requeue resets exactly those to retry the failed children.\n if (store.compactCheckpoints && inputs.length >= FOLD_MIN_FAN) {\n for (let k = 0; k < waveCount; k += 1) {\n const items = waveItems(k);\n const first = items[0] as number;\n const last = items[items.length - 1] as number;\n if (folded[first]) continue;\n const values: unknown[] = [];\n for (const i of items) {\n const c = existing[i]?.status === 'completed' ? existing[i]?.output : undefined;\n if (!c || typeof c !== 'object' || (c as { ok?: boolean }).ok !== true) break;\n values.push((c as { value?: unknown }).value);\n }\n if (values.length < items.length) continue;\n const into = instantCheckpoint({\n runId,\n seq: positions[first] as number,\n name: allFoldedName(runId, firstSeq, waves ? k : undefined),\n kind: 'signal',\n output: { from: first, values } satisfies FoldedChildren,\n parallelGroup: group,\n });\n await store.compactCheckpoints(\n runId,\n positions[first] as number,\n positions[last] as number,\n into,\n );\n for (const i of items) replay?.delete(positions[i] as number);\n replay?.set(into.seq, into);\n }\n }\n\n // A wave has been sent once any of its children has a checkpoint. Send more waves until\n // `maxWaves` are unsettled, in order.\n const sent = (k: number) => waveItems(k).some((i) => existing[i]);\n const settled = (k: number) => waveItems(k).every((i) => existing[i]?.status === 'completed');\n const active: number[] = [];\n let unsettled = 0;\n for (let k = 0; k < waveCount; k += 1) {\n if (settled(k)) continue;\n if (sent(k) || unsettled < (waves?.maxWaves ?? 1)) {\n active.push(k);\n unsettled += 1;\n }\n }\n\n if (active.length > 0) {\n const toRegister: number[] = [];\n const toEnsure: number[] = [];\n for (const k of active) {\n for (const i of waveItems(k)) {\n const cp = existing[i];\n if (cp?.status === 'completed') continue;\n // A placeholder proves its waiter was put (registerChildWaits writes the waiter first), so\n // a replay never re-puts it. A child that settled after this execution's snapshot has\n // already consumed its waiter; re-putting it would leave one nothing ever takes, and the\n // join barrier would wait on it forever.\n (cp ? toEnsure : toRegister).push(i);\n }\n }\n for (let at = 0; at < toRegister.length; at += FAN_CHUNK) {\n const chunk = toRegister.slice(at, at + FAN_CHUNK);\n const entries = chunk.map((i) => ({\n // Carry the fan `group` onto the waiter too: the child's terminal `signal:child:`\n // checkpoint is (re)written by engine.signal when the child notifies the parent,\n // OVERWRITING the running placeholder at the same seq — so without this the resolved\n // checkpoint would lose the group and the dashboard would render the resolved fan as a\n // sequential chain.\n waiter: {\n token: `child:${id(i)}`,\n runId,\n seq: positions[i] as number,\n parallelGroup: group,\n },\n checkpoint: instantCheckpoint({\n runId,\n seq: positions[i] as number,\n name: `signal:child:${id(i)}`,\n kind: 'signal',\n status: 'running',\n parallelGroup: group,\n }),\n }));\n await registerChildWaits(entries);\n // `start` is idempotent by id, so a child a crashed turn already started is not doubled.\n for (const i of chunk) host.startChild(name, inputs[i], id(i));\n }\n // A placeholder written by a turn that crashed before the deferred start ran: start it now.\n for (let at = 0; at < toEnsure.length; at += FAN_CHUNK) {\n await Promise.all(\n toEnsure.slice(at, at + FAN_CHUNK).map(async (i) => {\n if (!(await store.getRun(id(i)))) host.startChild(name, inputs[i], id(i));\n }),\n );\n }\n }\n if (active.length > 0) {\n throw new WorkflowSuspended(\n undefined,\n fanJoin(active.map((k) => allWait(runId, firstSeq, waves ? k : undefined))),\n );\n }\n\n // All resolved: build outputs in INPUT order, aggregating any failures.\n const outputs: T[] = [];\n const failures: { index: number; id: string; error: string }[] = [];\n for (let i = 0; i < inputs.length; i += 1) {\n const c = existing[i]?.output as { ok?: boolean; value?: T; error?: string } | null;\n if (c && typeof c === 'object' && 'ok' in c && c.ok === false) {\n failures.push({ index: i, id: id(i), error: c.error ?? 'unknown' });\n outputs.push(undefined as T);\n } else {\n outputs.push((c as { value?: T } | null)?.value as T);\n }\n }\n if (failures.length > 0) throw new GatherError(failures, inputs.length);\n return outputs;\n };\n\n // A fan's checkpoints: from the replay snapshot, plus ONE prefix query for any the snapshot does\n // not hold (on the first dispatch, all of them) instead of a lookup per child. A folded checkpoint\n // is expanded back into one completed checkpoint per child it stands for; `folded` marks those.\n const readFan = async (\n positions: number[],\n prefixes: string[],\n ): Promise<{ checkpoints: (StepCheckpoint | null)[]; folded: boolean[] }> => {\n const checkpoints = positions.map((seq) => replay?.get(seq) ?? null);\n const folded = positions.map(() => false);\n const expand = () => {\n for (let i = 0; i < checkpoints.length; i += 1) {\n const cp = checkpoints[i];\n if (!cp?.name.startsWith(FOLDED_PREFIX) || folded[i]) continue;\n const fold = cp.output as Partial<FoldedChildren> | null | undefined;\n // A malformed fold must stop the replay: treating it as absent would re-dispatch every child\n // it stands for.\n if (!fold || typeof fold.from !== 'number' || !Array.isArray(fold.values)) {\n throw new Error(`ctx.all: folded checkpoint \"${cp.name}\" at seq ${cp.seq} is malformed`);\n }\n const { from, values } = fold as FoldedChildren;\n values.forEach((value, j) => {\n checkpoints[from + j] = {\n ...cp,\n seq: positions[from + j] as number,\n output: { ok: true, value },\n };\n folded[from + j] = true;\n });\n }\n };\n expand();\n const missing = positions.filter((_, i) => !checkpoints[i]);\n if (missing.length === 0) return { checkpoints, folded };\n if (missing.length > 1 && store.listCheckpointsByNamePrefix) {\n const bySeq = new Map<number, StepCheckpoint>();\n for (const cp of await store.listCheckpointsByNamePrefix(runId, prefixes)) {\n bySeq.set(cp.seq, cp);\n }\n positions.forEach((seq, i) => {\n checkpoints[i] ??= bySeq.get(seq) ?? null;\n });\n } else {\n await Promise.all(\n positions.map(async (seq, i) => {\n checkpoints[i] ??= await readCheckpoint(seq);\n }),\n );\n }\n expand();\n return { checkpoints, folded };\n };\n\n const registerChildWaits = async (entries: ChildWait[]): Promise<void> => {\n if (store.registerChildWaits) {\n await store.registerChildWaits(entries);\n } else {\n await Promise.all(\n entries.map(async (e) => {\n await store.putSignalWaiter(e.waiter);\n await store.saveCheckpoint(e.checkpoint);\n }),\n );\n }\n for (const e of entries) replay?.set(e.checkpoint.seq, e.checkpoint);\n };\n\n // Child workflow (fire-and-forget): dispatch it once and return its id WITHOUT suspending. The\n // start is checkpointed at this position so replay returns the same id without re-dispatching, and\n // is idempotent by id, so `child(..., sameId)` later joins the same run rather than starting a new\n // one (start + join scatter-gather).\n const startChild = async (\n workflow: WorkflowRef,\n input: unknown,\n options?: string | ChildCallOptions,\n ): Promise<string> => {\n const { childId, priority, version } = normalizeChildOptions(options);\n const current = pos.next();\n const id = childId ?? `${runId}.child.${current}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as string;\n if (!(await store.getRun(id)))\n host.startChild(workflowName(workflow), input, id, priority, version);\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: `spawn:${id}`, kind: 'local', output: id }),\n );\n return id;\n };\n\n // Call a durable entity op and await its result: register a reply waiter at this position, dispatch\n // the op with the reply token, and suspend until the entity signals the result back (checkpointed,\n // so replay returns it without re-dispatching).\n const callEntity = async <R>(\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<R> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as R;\n const reply = `entityreply:${runId}:${current}`;\n await store.putSignalWaiter({ token: reply, runId, seq: current });\n host.signalEntity?.(name, key, op, arg, reply);\n throw new WorkflowSuspended();\n };\n\n // Send a durable entity op without awaiting a result — dispatched once (checkpointed, replay-safe).\n const signalEntity = async (\n name: string,\n key: string,\n op: string,\n arg?: unknown,\n ): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return;\n host.signalEntity?.(name, key, op, arg);\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: `entitysig:${name}:${key}`, kind: 'local' }),\n );\n };\n\n // A breakpoint = a visible `pending` checkpoint + a signal waiter the dashboard resumes via\n // `engine.continue`. Reuses the signal machinery, so resume overwrites the pending checkpoint\n // with a completed one and the run replays past it.\n const breakpoint = async (label?: string): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return;\n if (!existing) {\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: label ? `breakpoint:${label}` : 'breakpoint',\n kind: 'signal',\n status: 'pending',\n }),\n );\n await store.putSignalWaiter({ token: breakpointToken(runId, current), runId, seq: current });\n }\n throw new WorkflowSuspended();\n };\n\n // Guard an in-place change: a fresh run records a `patch:<id>` marker here and takes the new\n // branch; a run recorded under the OLD code finds a real step at this position instead, so we\n // rewind the logical position (the marker is transparent to it) and return false — its replay\n // reads that old step next and follows the old branch. No position shift → no corruption.\n const patched = async (id: string): Promise<boolean> => {\n const marker = `patch:${id}`;\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing) {\n if (existing.name === marker) return true;\n if (existing.name.startsWith('patch:')) {\n throw new NonDeterminismError(runId, current, marker, existing.name);\n }\n pos.rewind(); // not a marker: an old run's step lives here — give the position back to it\n return false;\n }\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name: marker, kind: 'local', output: true }),\n );\n return true;\n };\n\n // An update point: suspend on a run-scoped `update:<runId>:<name>` token that engine.update\n // delivers to (after its validator passes). Reuses the signal machinery; run-scoped like task/child.\n const onUpdate = <T>(name: string, opts?: { timeoutMs?: number }): Promise<T> =>\n waitForSignal<T>(`update:${runId}:${name}`, opts);\n\n // A queryable named value: a checkpoint whose `name` is `event:<key>`, so the latest value for a\n // key is just the highest-seq such checkpoint (read by engine.getEvent). Replay-idempotent.\n const setEvent = async (key: string, value: unknown): Promise<void> => {\n const current = pos.next();\n const name = `event:${key}`;\n const existing = await readCheckpoint(current);\n if (existing && existing.name !== name) {\n throw new NonDeterminismError(runId, current, name, existing.name);\n }\n if (existing && existing.status === 'completed') return; // replay: already published\n await writeCheckpoint(\n instantCheckpoint({ runId, seq: current, name, kind: 'local', output: value }),\n );\n };\n\n // A durable webhook reserves a logical position NOW to mint a stable token, so the url can be\n // handed to a third party before `wait()` suspends. `wait()` then parks on that same position\n // until the callback lands as engine.signal(token, body) — single position, replay-safe. The\n // deadline (when `wait({ timeoutMs })` is used) is a SEPARATE, later position — reserved lazily by\n // `wait()` itself, not at mint time, since the mint site has no `opts` to know a timeout was\n // requested. That's fine: `wait()` runs in the same deterministic order on every replay, so the\n // deadline seq it claims is stable too.\n const webhook = <T>(): DurableWebhook<T> => {\n const current = pos.next();\n const token = `wh:${runId}:${current}`;\n const wait = async (opts?: { timeoutMs?: number }): Promise<T> => {\n // A bounded wait claims its deadline position UNCONDITIONALLY, before the completed-replay\n // early return: the same `wait({ timeoutMs })` call re-runs on every replay, so the position\n // walk must be identical whether the callback has landed yet or not. (Claiming it lazily after\n // the early return would shift every later primitive by one on the post-callback replay and\n // trip the NonDeterminism guard on the stamped `timeout:*` checkpoint.)\n const timeoutMs = opts?.timeoutMs;\n const deadlineSeq = timeoutMs == null ? -1 : pos.next();\n const existing = await readCheckpoint(current);\n if (existing && existing.status === 'completed') return existing.output as T;\n if (timeoutMs == null) {\n await store.putSignalWaiter({ token, runId, seq: current });\n throw new WorkflowSuspended();\n }\n const deadline = await stampDeadline(deadlineSeq, token, timeoutMs);\n if (host.clock() >= deadline) {\n await store.takeSignalWaiter(token).catch(() => undefined);\n throw new SignalTimeoutError(token, timeoutMs);\n }\n await store.putSignalWaiter({ token, runId, seq: current });\n throw new WorkflowSuspended(deadline);\n };\n return { token, url: host.webhookUrl?.(token), wait };\n };\n\n // Deterministic capture: run `fn` once, checkpoint its output, and replay the SAME value verbatim\n // afterwards (fn is NOT re-run on replay). The general primitive for any non-deterministic value the\n // author controls the generator for — `ctx.sideEffect(() => uuidv7())`, `() => Math.random()`, a\n // config/env read. A raw `Date.now()`/`Math.random()` in a workflow body differs across replays and\n // corrupts the run; this captures it deterministically.\n const sideEffect = <T>(fn: () => T | Promise<T>): Promise<T> =>\n localStep('sideEffect', async () => fn());\n // `now` is the one ubiquitous convenience (a single obvious implementation, epoch ms like\n // `Date.now()`); everything else uses `sideEffect` so the author picks the generator.\n const now = () => localStep('now', async () => host.clock());\n\n // Merge into this run's searchAttributes exactly once: a checkpoint at this position marks it done,\n // so a replay SKIPS the write (mirrors `transaction` / the instant primitives) instead of re-merging\n // on every turn. Nondeterminism-guarded by the recorded marker name.\n const upsertSearchAttributes = async (attrs: SearchAttributes): Promise<void> => {\n const current = pos.next();\n const existing = await readCheckpoint(current);\n if (existing) {\n if (existing.name !== 'searchAttributes') {\n throw new NonDeterminismError(runId, current, 'searchAttributes', existing.name);\n }\n // Replayed: the write already happened on a prior turn — skip it, and (deliberately) skip\n // re-validating too. Validation only ever needs to run once, at the position it's recorded;\n // re-running it on replay would be redundant at best and, for a schema whose rules change\n // between deploys, a source of a replay throwing on history a live run already accepted.\n return;\n }\n if (searchAttributesSchema) {\n // The schema describes the whole run's search-attribute shape (optional keys included), so\n // validate the MERGED result — this call's `attrs` shallow-merged onto what's already on the\n // run — not `attrs` alone. Mirrors the merge `host.upsertSearchAttributes` itself performs;\n // read here is best-effort (not transactional with the host's own read+write), same as that\n // merge already is.\n const run = await store.getRun(runId);\n const merged = { ...(run?.searchAttributes ?? {}), ...attrs };\n const result = searchAttributesSchema['~standard'].validate(merged);\n if (result instanceof Promise) {\n throw new Error(\n `workflow \"${workflow}\": ctx.upsertSearchAttributes schema validation must be synchronous (the searchAttributes schema's \\`~standard.validate\\` returned a Promise) — replay-determinism requires a sync validator; drop any async refinement from the schema passed to @Workflow({ searchAttributes }).`,\n );\n }\n if (result.issues) {\n const offendingKeys = [\n ...new Set(result.issues.map((issue) => formatIssuePath(issue.path))),\n ];\n const details = result.issues\n .map((issue) => `${formatIssuePath(issue.path)}: ${issue.message}`)\n .join('; ');\n throw new Error(\n `workflow \"${workflow}\": ctx.upsertSearchAttributes rejected by its searchAttributes schema — ` +\n `offending key(s) ${offendingKeys.join(', ')} — ${details}`,\n );\n }\n }\n await host.upsertSearchAttributes(runId, attrs);\n await writeCheckpoint(\n instantCheckpoint({\n runId,\n seq: current,\n name: 'searchAttributes',\n kind: 'local',\n output: attrs,\n }),\n );\n };\n\n // Resolve a `ctx.step(..., { compensate })` ref/string into the undo's own dispatchable StepDef —\n // same routing-name resolution as the step it's attached to (see `step` below), but its dispatch\n // policy comes ONLY from its own `@Step`-stamped config (stepConfigOf), never the compensated\n // call's per-call `opts`: the undo is a separately-declared handler with its own retry/backoff, not\n // an extension of the step it undoes. The string form (cross-runtime, unchecked) has no stamped\n // config, so it dispatches with engine defaults. Takes `unknown` (like `stepNameOf`/`stepConfigOf`\n // themselves) rather than a `StepRef<StepUndo<TInput, TOutput>, ...>` — the caller's TInput/TOutput\n // are call-site type parameters with no runtime shape to check here; the compile-time contract is\n // already enforced by `WorkflowCtx.step`'s overload signature (interfaces.ts) that typed `opts`.\n function resolveCompensateDef(compensate: unknown): StepDef<StepUndo<unknown, unknown>, unknown> {\n const name = typeof compensate === 'string' ? compensate : stepNameOf(compensate);\n if (name === undefined) {\n throw new Error(\n 'ctx.step: compensate handler is not a @Step reference (no stamped step name) — pass a @Step-decorated method or a step name string',\n );\n }\n const config = typeof compensate === 'string' ? undefined : stepConfigOf(compensate);\n return { name, ...resolveStepPolicy(config, undefined) };\n }\n\n // ONE durable step primitive: always dispatched, always engine-scheduled — no local/remote\n // placement choice for the workflow author (see `WorkflowCtx.step`). Resolve the routing name off\n // a `@Step`-stamped handler reference, or take it literally for the cross-runtime string form; the\n // reference itself is NEVER invoked here — only its stamped name (and dispatch policy) is read (the\n // serving worker re-resolves the real handler from DI), so an unbound `this` on `handlerOrName` is\n // irrelevant. The effective durable-retry/liveness policy is `{ ...stepConfigOf(handlerOrName),\n // ...opts }` — the `@Step`-declared def-level policy, with a per-call `opts` field winning wherever\n // it's set. The string form has no stamped config, so it uses `opts` only. Carrying this policy onto\n // the `StepDef` re-enables `callRemote`'s durable retry/backoff and liveness-timeout branches (see\n // `engine.ts`), which were otherwise orphaned.\n function step<TInput, TOutput>(\n handlerOrName: StepRef<TInput, TOutput> | string,\n input: TInput,\n opts?: StepDispatchOpts & { compensate?: StepRef<StepUndo<TInput, TOutput>, unknown> | string },\n ): Promise<TOutput> {\n const name = typeof handlerOrName === 'string' ? handlerOrName : stepNameOf(handlerOrName);\n if (name === undefined) {\n throw new Error(\n 'ctx.step: handler is not a @Step reference (no stamped step name) — pass a @Step-decorated method or a step name string',\n );\n }\n const config = typeof handlerOrName === 'string' ? undefined : stepConfigOf(handlerOrName);\n const def: StepDef<TInput, TOutput> = { name, ...resolveStepPolicy(config, opts) };\n return host\n .callRemote(runId, pos.next(), def, input, opts?.queue, opts?.transport, {\n priority: opts?.priority,\n fairnessKey: opts?.fairnessKey,\n })\n .then((output) => {\n // `callRemote` resolves ONLY once this step is durably complete — the replay-completed branch\n // (a checkpointed output) or the in-memory `timeoutMs` liveness path once the live result\n // lands (engine.ts). Register the compensation HERE, after that resolution, so a saga only\n // ever undoes steps that actually finished. Mirrors `localStep`'s rebuild-on-replay: the\n // workflow body re-passes `compensate` on every replay of a completed call, and `input`/\n // `output` come straight from this call (the checkpointed ones on replay) — no store-schema\n // change needed to carry the undo's args.\n if (opts?.compensate) {\n compensations.push({\n name,\n dispatch: { def: resolveCompensateDef(opts.compensate), args: { input, output } },\n });\n }\n return output;\n });\n }\n\n // Fail fast when a primitive is called from INSIDE one of this ctx's step bodies (directly, or via\n // a `MyWorkflow.start()`/`.execute()` static resolving the ambient ctx). The step replays from its\n // checkpoint without re-running its body, so the nested call's journal position would never be\n // claimed again and every later position would shift — a NonDeterminismError on the next replay,\n // far from the cause. See {@link NestedWorkflowCallError}.\n //\n // Versioning: a run journaled BEFORE this guard existed may legitimately re-run such a body (its\n // step never completed) with the nested call already recorded at the position it would claim. That\n // position being occupied means the history predates the guard — let the call through so the\n // existing journal keeps replaying exactly as it was written. Only a call that would write NEW\n // history is refused. The check costs nothing outside a step body (the common path is a sync\n // pass-through, so primitive timing is unchanged).\n const nestedStep = (): string | undefined => {\n const scope = currentStepScope();\n return scope !== undefined && scope.owner === scopeOwner ? scope.step : undefined;\n };\n const guard = <F extends (...args: never[]) => Promise<unknown>>(primitive: string, fn: F): F =>\n ((...args: Parameters<F>) => {\n const stepName = nestedStep();\n if (stepName === undefined) return fn(...args);\n return (async () => {\n if (await readCheckpoint(pos.peek())) return fn(...args);\n throw new NestedWorkflowCallError(runId, primitive, stepName);\n })();\n }) as F;\n // `webhook` is synchronous (it returns a handle): same rule, checked against the replay snapshot.\n const guardedWebhook = <T>(): DurableWebhook<T> => {\n const stepName = nestedStep();\n if (stepName !== undefined && !replay?.get(pos.peek())) {\n throw new NestedWorkflowCallError(runId, 'webhook', stepName);\n }\n return webhook<T>();\n };\n\n return {\n runId,\n step: guard('step', step as (...args: never[]) => Promise<unknown>) as typeof step,\n localStep: guard('localStep', localStep),\n upsertSearchAttributes: guard('upsertSearchAttributes', upsertSearchAttributes),\n transaction: guard('transaction', transaction),\n callEntity: guard('callEntity', callEntity),\n signalEntity: guard('signalEntity', signalEntity),\n sleep: guard('sleep', sleep),\n sleepUntil: guard('sleepUntil', sleepUntil),\n continueAsNew,\n waitForSignal: guard('waitForSignal', waitForSignal),\n waitForEvent: guard('waitForEvent', waitForEvent),\n task: guard('task', task),\n child: guard('child', child),\n all: guard('all', all),\n startChild: guard('startChild', startChild),\n breakpoint: guard('breakpoint', breakpoint),\n webhook: guardedWebhook,\n setEvent: guard('setEvent', setEvent),\n onUpdate: guard('onUpdate', onUpdate),\n patched: guard('patched', patched),\n now: guard('now', now),\n sideEffect: guard('sideEffect', sideEffect),\n };\n}\n","import { type AdmissionBackend, InMemoryAdmissionBackend } from './admission';\nimport { runInWorkflowCtx } from './ambient-ctx';\nimport { backoffDelay } from './backoff';\nimport { instantCheckpoint, lostStepEvent, stepCheckpoint } from './checkpoints';\nimport { type Completion, isFailedCompletion } from './completion';\nimport {\n type ConcurrencyConfig,\n type ConcurrencyQuota,\n assertConcurrency,\n concurrencyTag,\n resolveConcurrency,\n} from './concurrency';\nimport { parseDuration } from './duration';\nimport { Entities, type EntityConfig } from './entities';\nimport {\n ContinueAsNew,\n type FanJoin,\n FatalError,\n NonDeterminismError,\n RemoteStepTimeout,\n RemoteWorkflowTimeout,\n SignalTimeoutError,\n WorkflowSuspended,\n} from './errors';\nimport { EventAccumulators, type EventBatchConfig } from './event-accumulators';\nimport {\n EVENT_BUFFER_SCAN_LIMIT,\n eventMatchOf,\n eventMatches,\n eventNameOf,\n eventPrefix,\n isEventToken,\n} from './events';\nimport { runDurableExecution } from './execution-hooks';\nimport { FOLDED_PREFIX, fanOfWaiter, foldedChildIds } from './fan-join';\nimport {\n type AnnouncedWorkflow,\n type BlockedDispatch,\n type DispatchPlan,\n type WorkerDescriptor,\n WorkflowBlocked,\n type WorkflowDirectory,\n aggregateAnnouncements,\n buildWorkflowDirectory,\n controlPlaneDescriptor,\n planDispatch,\n} from './handshake/index';\nimport type {\n ControlPlane,\n EngineEvent,\n EngineListener,\n GroupHealth,\n NamedTransport,\n RemoteTask,\n RunDispatcher,\n RunQuery,\n RunResult,\n RunStatus,\n SearchAttributes,\n SearchAttributesSchema,\n SignalWaiter,\n StateStore,\n StepCheckpoint,\n StepDef,\n StepError,\n StepEvent,\n StepInterceptor,\n StepInvocation,\n StepKind,\n StepResult,\n StepUndo,\n Transport,\n UpdateResult,\n UpdateValidator,\n WorkflowCommand,\n WorkflowCtx,\n WorkflowDecision,\n WorkflowExecutor,\n WorkflowRun,\n WorkflowStepEvent,\n} from './interfaces';\nimport type { HistoryEvent, RunScope } from './interfaces';\nimport { TERMINAL_RUN_STATUSES, isNonEmptyRunScope } from './interfaces';\nimport { breakpointToken, stepId } from './protocol';\nimport type { QueueConfig } from './queue';\nimport { RemoteWorkflowExecutor } from './remote-workflow-executor';\nimport { indexWaitersByRun, listSignalWaitersOfRuns } from './run-waiting';\nimport { ScheduleClient } from './schedules';\nimport { SINGLETON_ADMITTED_TAG } from './singleton-admission';\nimport { SingletonGate } from './singleton-gate';\nimport { sanitizeQueueToken, tenantGroup } from './tenant-group';\nimport { TransportPool } from './transport-pool';\nimport {\n type Compensation,\n type CtxHost,\n type InternalWorkflowCtx,\n type StepRecord,\n createWorkflowCtx,\n} from './workflow-ctx';\nimport {\n type WorkflowClass,\n type WorkflowInputOf,\n type WorkflowRef,\n workflowName,\n} from './workflow-ref';\n\n// The engine ALWAYS runs a body with the InternalWorkflowCtx `createWorkflowCtx` produces (it carries\n// the internal `localStep` the entity runner + capture helpers need). Public authors type their body\n// with the narrower `WorkflowCtx`; contravariance keeps those assignable to this param, so the internal\n// type never leaks into the public authoring surface while `EntityHost.register` still lines up.\ntype WorkflowFn = (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>;\n\n/**\n * Options for {@link WorkflowEngine.start}.\n *\n * Note the absence of `origin`: {@link WorkflowRun.origin} says which PACKAGE declared the workflow,\n * which is a property of the registered code, not of whoever started it. It is taken from the\n * registration and nothing here can override it — otherwise one caller could label its runs as\n * another lib's, and an origin filter would quietly lie.\n */\nexport interface StartOptions {\n /**\n * Start THIS registered version instead of the newest one. Omit (the default) and the run starts on\n * the newest registered version, exactly as it always has — this option only ever narrows.\n *\n * Resolved against the by-name@version registry, so it pins anything explicitly registered:\n * {@link WorkflowEngine.register}, {@link WorkflowEngine.registerRemote}, {@link WorkflowEngine.remote}.\n * A version that is NOT registered throws before a run row is created and NEVER falls back to\n * `latest` — a silent fallback is the exact failure this option exists to prevent (a caller that\n * asked for `name@3` and got `name@4` has no way to tell, and its run is already going).\n *\n * NOT available on the two SYNTHESIZED registration paths, which exist precisely because nothing is\n * registered: a child inheriting its remote ancestor's routing (see `findInheritedRegistration`),\n * and convention routing to a live worker group of the same name (`resolveRemoteByConvention`).\n * Both INVENT the version they stamp — the ancestor's, and the `'1'` convention default — as a\n * routing placeholder; neither is evidence that the worker has a body at the version you asked for.\n * A pinned start that reaches them therefore throws rather than pretending to have honoured the pin.\n * To pin a cross-SDK workflow, register it for real — `engine.remote('name', { version: '2', group })`\n * — which puts `name@2` in the registry and pins like any other registration.\n */\n version?: string | undefined;\n /** Run-scoped tags, merged with the workflow's static `@Workflow({ tags })` onto the run. */\n tags?: string[] | undefined;\n /** Typed, queryable run data stamped on the run (e.g. `{ amount: 200, tier: 'pro' }`). */\n searchAttributes?: SearchAttributes | undefined;\n /**\n * Dispatch priority for a remote run — stamped on the run and carried onto every {@link WorkflowTask}\n * the engine dispatches to advance it. Higher wins; absent = unprioritised. See {@link WorkflowRun.priority}.\n */\n priority?: number | undefined;\n /**\n * Override the namespace stamped on the run. Defaults to the engine's own `namespace`. Set by the\n * control plane when it starts a run on behalf of a tenant (a {@link StartRunMessage}'s `tenant`\n * maps here), so one DB-less-tenant-facing engine can create runs across many namespaces.\n */\n namespace?: string | undefined;\n /**\n * A start-time concurrency quota for this start — at most `limit` runs sharing `key` in flight;\n * over it, `start` throws {@link ConcurrencyLimitError} and creates nothing. Overrides the\n * workflow's registered `concurrency`. See {@link ConcurrencyQuota}.\n */\n concurrency?: ConcurrencyQuota | undefined;\n}\n\n/**\n * Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).\n * Excess runs are admitted in creation order, `limit` at a time; the rest wait (suspended) and retry\n * admission on a timer until a slot frees. The store atomically reserves durable slots before\n * ordering unadmitted waiters by `(createdAt, id)`, so later starts cannot displace a holder.\n */\nexport interface SingletonConfig {\n /** Derive the serialization key from the workflow input. */\n key: (input: unknown) => string;\n /** Max concurrent runs sharing the key. Default 1 (a mutex). */\n limit?: number;\n /**\n * Max GATED (waiting-for-admission) runs allowed to queue behind the `limit` in-flight ones. When\n * set, `start` rejects with {@link SingletonQueueFullError} once in-flight + gated reaches\n * `limit + maxQueueDepth` — back-pressure against an unbounded same-key backlog. Omit for the\n * default unbounded queue. Counts pending/running/suspended/blocked/cancelling runs sharing the key.\n */\n maxQueueDepth?: number;\n}\n\n/** Union of a workflow's static tags and a run's start-time tags, de-duplicated, or undefined if none. */\nfunction mergeTags(staticTags?: string[], runTags?: string[]): string[] | undefined {\n if (!staticTags?.length && !runTags?.length) return undefined;\n return [...new Set([...(staticTags ?? []), ...(runTags ?? [])])];\n}\n\n/** A breakpoint checkpoint's `name` is `breakpoint` (or `breakpoint:<label>`). This name — not the\n * reused `signal` kind — is the explicit marker the dashboard and `continue()` detect it by. */\nconst BREAKPOINT = 'breakpoint';\nconst isBreakpoint = (cp: { status: string; name: string }): boolean =>\n cp.status === 'pending' && cp.name.startsWith(BREAKPOINT);\n\ninterface RegisteredWorkflow {\n name: string;\n version: string;\n fn: WorkflowFn;\n /** Static `@Workflow({ tags })` — merged with per-run tags onto each run at start. */\n tags?: string[] | undefined;\n /** Per-key serialization (a durable mutex). See {@link SingletonConfig}. */\n singleton?: SingletonConfig | undefined;\n /** Start-time concurrency quota (reject over the limit). See {@link ConcurrencyConfig}. */\n concurrency?: ConcurrencyConfig | undefined;\n /** Max wall-clock lifetime (ms) before a run is cancelled by `sweepTimeouts`. */\n executionTimeoutMs?: number | undefined;\n /** Validate the input at start; throw to reject before a run is created. Validator-agnostic. */\n validateInput?: ((input: unknown) => void | Promise<void>) | undefined;\n /** Typed/validated `searchAttributes` shape. When set, `ctx.upsertSearchAttributes` validates the\n * merged result against it (see `createWorkflowCtx`). See `WorkflowMeta.searchAttributes`. */\n searchAttributesSchema?: SearchAttributesSchema | undefined;\n /** Event names that start a fresh run of this workflow when published. See `publishEvent`. */\n onEvent?: string[] | undefined;\n /** Coalesce `onEvent` triggers: debounce (fire once it's quiet) or batch (fire on size/window). */\n eventBatch?: EventBatchConfig | undefined;\n /** Set for a workflow advanced by DISPATCH instead of an inline `fn`: a cross-SDK (e.g. Python)\n * body via {@link WorkflowEngine.registerRemote}, OR a group-served TS body via\n * `register(..., { group, executor })`. The engine hands the run's history to `executor` (which\n * dispatches a workflow task to `group`) rather than running `fn` in-process. See\n * {@link WorkflowExecutor}. */\n remote?: { group: string; executor: WorkflowExecutor };\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake design §7.5).\n * Enforced before each remote turn's dispatch: if descriptors are published on its group but none is\n * capable+compatible, the run parks `blocked`. Absent/empty = \"runs anywhere\". */\n requires?: string[] | undefined;\n /** True when `fn` is a real in-process body (`register`), false/absent for a body-less remote whose\n * `fn` is the throwing stub (`registerRemote` / a synthesized remote child). Gates\n * {@link WorkflowEngine.workflowBody} so an in-app worker only ever gets a runnable body. */\n hasBody?: boolean | undefined;\n /** The package that declared this workflow, stamped onto every run it starts. See\n * {@link WorkflowRun.origin}. Absent = unknown; the engine never substitutes a default. */\n origin?: string | undefined;\n /**\n * Whether {@link version} is a fact somebody stated or the engine's placeholder.\n *\n * Only ever `false` on a registration synthesized by convention resolution against a fleet that\n * announced no version. Every other registration carries the version its author wrote, so the\n * field is absent (= stated) and nothing changes for them.\n *\n * It exists because the alternative — a `'1'` that nobody chose, indistinguishable from a `'1'`\n * somebody did — is what let a version pin pass by construction. See {@link VERSION_UNDECLARED_TAG}.\n */\n versionDeclared?: boolean | undefined;\n}\n\n/**\n * Stamped on a run whose workflow version NOBODY declared: a remote resolved by convention, served\n * by a worker that announces no version for it (an SDK too old to publish a descriptor, or a body\n * whose author simply never stated one).\n *\n * ## Why a run has to carry this\n *\n * Such a run's `workflowVersion` is `'1'`, the engine's convention default. That value is a routing\n * placeholder, not an observation — and read back later it is indistinguishable from a worker that\n * genuinely declared version `'1'`. Any check comparing an authored pin against it therefore passes\n * whenever the pin is `'1'` and fails whenever it is not, regardless of what the callee actually is.\n * A check that cannot fail is worse than no check, because it reads as a guarantee.\n *\n * The tag is the difference, carried ON the run so a retrospective check needs no second read: a\n * caller that pinned a version can see that the version it is comparing against was never stated,\n * and say so, instead of reporting a match it did not really make. It is deliberately a tag rather\n * than a new column — every store already persists and queries tags, so this needs no migration and\n * shows up in run listings and dashboards for free. Follows the `singleton:<key>` precedent for an\n * engine-stamped reserved tag.\n *\n * A run whose callee DOES declare a version never carries it; that run's version is the declared one\n * and a pin against it is genuinely checked.\n */\nexport const VERSION_UNDECLARED_TAG = 'version:undeclared';\n\nconst versionKey = (name: string, version: string): string => `${name}@${version}`;\n\n/**\n * The routing token a dispatched step lands on: the step's own name, suffixed by the tenant the RUN\n * belongs to. `runNamespace` — not the executing engine's namespace — is the tenant axis, because an\n * operator (namespace unset) drives runs of EVERY tenant: deriving the token from the engine would\n * send a tenant's work to the operator's own bare pool. This mirrors what an out-of-process worker\n * already does for the bodies it replays (it stamps its own partition onto each emitted `call`\n * command, see the worker SDK's `resolveCallGroup`) — the in-process executor had no equivalent,\n * which is exactly the gap this closes.\n *\n * An explicit {@link StepDef.partition} still wins, so a step pinned to a dedicated pool stays pinned.\n * `tenantGroup` maps `undefined`/`''`/`'default'` to the BARE token, so a single-tenant deployment\n * (and every `default`-namespace run) keeps byte-identical wire names.\n */\nfunction stepGroup(step: { name: string; partition?: string | undefined }, runNamespace?: string) {\n return tenantGroup(sanitizeQueueToken(step.name), step.partition ?? runNamespace);\n}\n\n/** The id for the next continuation of a run: `r` → `r~1` → `r~2` … (stable, traceable lineage). */\nfunction nextContinuationId(runId: string): string {\n const m = runId.match(/^(.*)~(\\d+)$/);\n return m ? `${m[1]}~${Number(m[2]) + 1}` : `${runId}~1`;\n}\n\n/** True when version `a` is newer than `b` (numeric when both parse as numbers, else natural sort). */\nfunction isNewerVersion(a: string, b: string): boolean {\n const na = Number(a);\n const nb = Number(b);\n if (!Number.isNaN(na) && !Number.isNaN(nb)) return na > nb;\n return a.localeCompare(b, undefined, { numeric: true }) > 0;\n}\n\n/** What a remote worker hands back: the output plus when it actually began (for queue-wait timing). */\ninterface RemoteResolution {\n output: unknown;\n startedAt?: number | undefined;\n events?: StepEvent[] | undefined;\n}\n\ninterface PendingRemote {\n resolve: (result: RemoteResolution) => void;\n reject: (error: Error) => void;\n}\n\n/** A terminal/suspended transition handed to {@link WorkflowEngine.settleRun}. */\ntype RunOutcome =\n | { kind: 'completed'; output: unknown }\n | { kind: 'failed'; error: StepError }\n | { kind: 'suspended'; wakeAt?: number | undefined }\n | { kind: 'blocked'; blocked: BlockedDispatch };\n\n/**\n * What {@link WorkflowEngine.unwindCompensations} returns when the run must keep waiting on a\n * dispatched compensation — `wakeAt` set while backing off a durable retry (the due-timer poller\n * re-drives it once elapsed), absent while freshly dispatched/in flight (only the worker's result,\n * via `completeRemoteResult`, re-drives it). `undefined` (no `UnwindPending`) means every\n * compensation resolved. Deliberately NOT a `RunResult`: the two callers persist \"still unwinding\"\n * differently (a plain `suspended` run for the failure path; `cancelling` held as-is for the cancel\n * path — see `compensateAndCancel`), so the settling is left to them.\n */\ninterface UnwindPending {\n wakeAt?: number | undefined;\n}\n\nexport interface WorkflowEngineDeps {\n store: StateStore;\n /** A single task transport. Shorthand for a one-entry `transports` pool (id `default`). */\n transport?: Transport | undefined;\n /**\n * An ordered pool of named transports. The engine dispatches on the first and fails over to the\n * next on a dispatch error; a step pins one via `ctx.step(step, input, { transport: id })`. Use\n * this instead of `transport` for failover / multi-broker setups.\n */\n transports?: NamedTransport[] | undefined;\n /**\n * Cross-instance broadcast pub/sub for lifecycle events + cancellation (see {@link ControlPlane}).\n * Separate from the task `transport`; omit for a single-instance / local-only setup. A transport\n * that can also broadcast may be passed here as well.\n */\n controlPlane?: ControlPlane | undefined;\n /** Epoch-ms clock; injectable for tests. Defaults to `Date.now`. */\n clock?: (() => number) | undefined;\n /**\n * Flow-control admission backend for `ctx.step(step, input, { queue })`. Defaults to an in-process\n * {@link InMemoryAdmissionBackend} (per-instance caps). Inject a store/Redis-backed backend to make\n * concurrency / rate-limit / ordering GLOBAL across engine replicas.\n */\n admission?: AdmissionBackend | undefined;\n /** Unique id for this engine instance, used for recovery leases. Defaults to a random id. */\n instanceId?: string | undefined;\n /**\n * Worker-pool partition for this engine. Stamped on every run it creates; the poll paths\n * (`runPending`/`recoverIncomplete`/`resumeDueTimers`/`sweepTimeouts`) only act on runs in this\n * namespace. Set distinct values to safely share ONE state store across non-interchangeable pools\n * (e.g. local dev vs a cluster). **Omit it to make this engine an OPERATOR** — an unset namespace\n * drives/recovers/resumes runs of EVERY namespace (the poll filters no-op, the resume/decision\n * guards fall through) and leaves the transport on its bare prefix. This is the hosted control\n * plane: \"ver tudo = ausência de namespace\".\n */\n namespace?: string | undefined;\n /** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */\n leaseMs?: number | undefined;\n /**\n * Cap how many times crash-recovery may pick up the same still-`running` run before giving up and\n * moving it to the `dead` dead-letter state (a poison pill that crashes the process every boot).\n * Omit for unlimited (the default — recovery always retries).\n */\n maxRecoveryAttempts?: number | undefined;\n /**\n * Opt-in liveness deadline (ms) for a remote workflow `advance`. If the worker neither returns a\n * decision NOR sends a run-scoped {@link Heartbeat} within this window, the engine presumes it dead:\n * it rejects the advance with {@link RemoteWorkflowTimeout}, releases the lease, and lets recovery\n * re-drive (replaying completed steps from history). Each beat REARMS the window, so a worker still\n * legitimately replaying a long turn (it keeps beating) is never re-driven — closing the duplicate-\n * side-effect hazard a fixed {@link RemoteWorkflowExecutor} `timeoutMs` cannot avoid. Omit (default)\n * for the prior unbounded await — byte-identical behavior when unset. If a `RemoteWorkflowExecutor` is\n * ALSO constructed with its own `timeoutMs`, the shorter of the two deadlines wins; prefer setting only\n * one (this rearmed window for heartbeat-aware workers, or the fixed `timeoutMs` otherwise).\n */\n remoteAdvanceSilenceMs?: number | undefined;\n /**\n * Fallback re-drive window (ms) for a run that SUSPENDS with no natural timer — i.e. it's waiting on\n * an EVENT to wake it (a child's completion, a signal, a remote step with no `timeoutMs`) rather than\n * a `ctx.sleep`. Those events re-drive the run directly; but if the wake is LOST (the delivering pod\n * crashed / rolled mid-handoff), the run would otherwise sit `suspended` forever with `wakeAt: null` —\n * invisible to both the timer poller (no `wakeAt`) and crash-recovery (no lease). This stamps a\n * fallback `wakeAt` so {@link resumeDueTimers} re-drives it after the window; the re-drive is an\n * idempotent replay (a still-pending dependency re-suspends via the checkpoint guard, a settled one\n * advances), so it's a safe self-heal, not a retry that can double-dispatch. The primary event path\n * still wins first for a healthy run (it re-drives long before this fires), so this only ever fires\n * for a genuinely-orphaned run. Default 5min; set `0` to disable (the prior wake-forever behavior).\n */\n reconcileMs?: number | undefined;\n /**\n * Retention for a BUFFERED event that no `waitForEvent` ever claims (see\n * {@link WorkflowEngine.publishEvent}'s buffering — a publish matching no live waiter keeps ONE\n * copy around for a later matching wait). Default `undefined`: keep it until consumed, same as\n * {@link StateStore.bufferSignal}'s buffered signals — no silent expiry. Set a duration (ms) to\n * have the {@link resumeDueTimers} reconcile pass prune rows past `publishedAt + eventBufferTtlMs`\n * as it encounters them. Scoped to event NAMES the current reconcile tick's registered waiters\n * reference (the sweep has no reason to otherwise enumerate every buffered name) — a name with a\n * stale buffered event but zero waiters ever registered against it is not visited by this pass; that\n * is an accepted gap given `listBufferedEvents` is name-scoped by design (see interfaces.ts), not a\n * bug to route around here.\n */\n eventBufferTtlMs?: number | undefined;\n /**\n * Opt-in self-heal window (ms) for a remote step with NO `timeoutMs` whose dispatched job was LOST —\n * the worker crashed mid-step leaving no result, or the transport dropped the job (a Redis\n * flush/eviction, or BullMQ moving a stalled job to `failed` and removing it). The `pending`\n * checkpoint then has no result to resume on, and — BY DESIGN (see {@link reconcileMs}) — the\n * reconcile re-drive re-suspends a still-pending step rather than re-dispatching, so a slow-but-live\n * worker is never double-run. That safety means a genuinely-lost dispatch would otherwise hang\n * forever. When set, a reconcile re-drive that finds a remote step still `pending` PAST this window\n * re-dispatches it (bumping `attempts`, bounded by {@link remoteRedispatchMax}). Off by default:\n * re-dispatch can double-run a step whose original job is merely slow, so the window MUST exceed the\n * longest such step and the step MUST be idempotent. Prefer a per-step `timeoutMs` (tighter,\n * heartbeat-aware) where you can; this is the store-driven net for no-timeout steps that must\n * survive a lost dispatch. {@link WorkflowEngine.redispatchPending} is the manual counterpart.\n */\n remoteRedispatchMs?: number | undefined;\n /**\n * Max times {@link remoteRedispatchMs} re-dispatches one lost remote step before giving up and\n * failing it as a {@link RemoteStepError} (`code: 'remote_step_lost'`), so the run fails / dead-letters\n * instead of re-dispatching forever. Default 10. Ignored when `remoteRedispatchMs` is unset.\n */\n remoteRedispatchMax?: number | undefined;\n /**\n * How long (ms) a run parked `blocked` (no capability-capable + protocol-compatible live worker,\n * handshake design §7.5) waits before the blocked-recovery poll re-drives it to re-check the live\n * fleet. Default 5000. The run proceeds the moment a capable+compatible worker appears; until then it\n * re-parks with a fresh `wakeAt` each poll. Only relevant once a step/workflow declares `requires`\n * AND descriptors are published (a legacy fleet never parks blocked).\n */\n blockedPollMs?: number | undefined;\n /**\n * Build the public callback URL for a `ctx.webhook()` token (e.g.\n * ``(t) => `https://api.example.com/durable/webhooks/${t}` ``). Populates\n * {@link DurableWebhook.url}. Omit if you build URLs yourself from the token.\n */\n webhookUrl?: ((token: string) => string) | undefined;\n /**\n * Provide the current W3C `traceparent` to stamp on each dispatched {@link RemoteTask}, so a\n * worker (including the Python SDK) continues the distributed trace. Keep core OTel-free: supply\n * `otelTraceparent` from `@dudousxd/nestjs-durable-otel`, or your own context reader. Omit to send none.\n */\n traceparent?: (() => string | undefined) | undefined;\n /**\n * Provide an opaque context carrier (tenant / user / correlation ids) to attach to each dispatched\n * {@link RemoteTask} as its `context`, so a worker (including the Python SDK) re-exposes it to the\n * step handler — cross-process propagation alongside the {@link traceparent}. Keep core dependency-free:\n * supply this from `@dudousxd/nestjs-context` or your own request-scoped reader. The engine never\n * inspects the returned object's shape. Omit to send none.\n *\n * Re-evaluated at each (re)dispatch — including a retry or a resume that the engine drives AFTER a\n * crash/scale-down, which runs OUTSIDE the originating request scope. On such a path this provider\n * may return empty or stale values (the request-scoped tenant/user is gone). Treat the carrier as\n * best-effort correlation/propagation metadata only — do NOT treat it as an authorization boundary.\n */\n context?: (() => Record<string, unknown> | undefined) | undefined;\n /**\n * Re-hydrate the originating context around a LOCAL step body, so a `@DurableStep` reader sees the\n * tenant / user / correlation ids that were live when the run was started — even on a path the\n * engine drives outside the originating request scope (a resume after crash/scale-down, a timer).\n * Given the carrier produced by {@link context} (may be empty/undefined) and the step body `fn`, it\n * runs `fn` with that context ambiently established (e.g. inside `@dudousxd/nestjs-context`'s ALS)\n * and returns its result. Keep core dependency-free: supply this from the nestjs wiring (which owns\n * nestjs-context) or your own ALS bridge. The handler signature is unchanged — re-hydration is\n * ambient. Default: passthrough (`(_, fn) => fn()`), so behavior is byte-identical when unset.\n */\n rehydrate?: (<T>(carrier: Record<string, unknown> | undefined, fn: () => T) => T) | undefined;\n /**\n * Attempts for each saga compensation when the run fails (a transient undo — e.g. a refund API\n * hiccup — gets another try). Default 1 (no retry). Compensations must be idempotent.\n */\n compensationRetries?: number | undefined;\n /**\n * Persist a `running` checkpoint when a local step's body begins, so an in-flight step shows up\n * in the dashboard (and a fresh page load / REST query) the moment it starts — not only once it\n * completes. The `step.started` lifecycle event is emitted either way (the live SSE view always\n * sees the start); this flag only controls the extra checkpoint write. Default `true`. Set\n * `false` on hot paths with many short local steps to halve their checkpoint writes — you keep\n * the live event but lose reload-survivable in-flight visibility.\n */\n trackStepStart?: boolean | undefined;\n /**\n * Where a freshly-`start`ed run executes (see {@link RunDispatcher}). Defaults to in-process: the\n * run executes on this instance asynchronously (a microtask), so `start` returns without blocking.\n * Pass a no-op dispatcher on a caller that must NOT run workflows (e.g. an API/dashboard pod), and\n * run `runPending` on a worker pod to pick those up; or a broker-backed one for a worker pool.\n */\n runDispatcher?: RunDispatcher | undefined;\n}\n\n/** Thrown by {@link WorkflowEngine.resume} when the run belongs to a different namespace. */\nclass NamespaceMismatch extends Error {\n constructor() {\n super('namespace-mismatch');\n }\n}\n\n/**\n * The orchestrator. Owns workflow state and replays runs deterministically: each step's\n * result is checkpointed, so on resume a completed step returns its saved output instead of\n * re-executing. Remote steps are dispatched over the Transport; their results checkpoint the\n * same way local steps do.\n */\nexport class WorkflowEngine {\n private readonly store: StateStore;\n /** Ordered transport pool (dispatch + failover). Empty = no remote steps. */\n private readonly pool: TransportPool;\n private readonly controlPlane?: ControlPlane | undefined;\n private readonly clock: () => number;\n private readonly instanceId: string;\n private readonly namespace: string | undefined;\n private readonly leaseMs: number;\n private readonly maxRecoveryAttempts?: number | undefined;\n private readonly remoteAdvanceSilenceMs?: number | undefined;\n private readonly reconcileMs: number | undefined;\n private readonly eventBufferTtlMs: number | undefined;\n private readonly remoteRedispatchMs: number | undefined;\n private readonly remoteRedispatchMax: number;\n /** How long a `blocked` run waits before the recovery poll re-checks the live fleet (design §7.5). */\n private readonly blockedPollMs: number;\n /** This engine's control-plane handshake descriptor — negotiated against each worker (design §7.3). */\n private readonly cpDescriptor: WorkerDescriptor;\n private readonly webhookUrl?: ((token: string) => string) | undefined;\n private readonly traceparent?: (() => string | undefined) | undefined;\n private readonly context?: (() => Record<string, unknown> | undefined) | undefined;\n /** Establish the originating context ambiently around a local step body (see {@link WorkflowEngineDeps.rehydrate}). Default passthrough. */\n private readonly rehydrate: <T>(carrier: Record<string, unknown> | undefined, fn: () => T) => T;\n private readonly compensationRetries: number;\n /** Persist a `running` checkpoint at the start of a local step body (see {@link WorkflowEngineDeps.trackStepStart}). */\n private readonly trackStepStart: boolean;\n /** Where a freshly-started run executes — in-process by default (see {@link RunDispatcher}). */\n private readonly runDispatcher: RunDispatcher;\n\n /** Per-key serialization for singleton workflows (admission, back-pressure, notify-on-release). */\n private readonly singletons: SingletonGate;\n /**\n * Persisted, runtime-managed schedules: create/upsert/pause/resume/delete/list/trigger them, and\n * `tick()` fires the due ones (the NestJS timer poller does it when `persistedSchedules` is on).\n * Needs a store that persists schedules — every bundled adapter does. See {@link ScheduleClient}.\n */\n readonly schedules: ScheduleClient;\n /** Every registered workflow, keyed by `name@version` — so old versions stay runnable. */\n private readonly workflows = new Map<string, RegisteredWorkflow>();\n /** The newest registered version per workflow name — used to `start` new runs. */\n private readonly latest = new Map<string, RegisteredWorkflow>();\n /** Event name → workflow names started when that event is published (see `onEvent`). */\n private readonly eventTriggers = new Map<string, Set<string>>();\n /** Durable-entity subsystem (registers the `__entity` runner; see `registerEntity`). */\n private readonly entities: Entities;\n /** Event debounce/batch accumulators (register the `__evt_*` runners; see `accumulators.route`). */\n private readonly accumulators: EventAccumulators;\n /** In-flight remote steps awaiting a worker result, keyed by stepId. */\n private readonly pending = new Map<string, PendingRemote>();\n /** \"Reset the liveness timer\" callbacks keyed by the beat's target — a stepId (in-flight remote step)\n * or a runId (in-flight remote workflow turn) — invoked when a matching heartbeat arrives. The two id\n * shapes don't collide in practice: a stepId is `${runId}:${seq}`, a run key is the bare runId. */\n private readonly heartbeatResets = new Map<string, () => void>();\n private readonly listeners = new Set<EngineListener>();\n /** Step interceptors (onion middleware around real local-step execution), first = outermost. */\n private readonly interceptors: StepInterceptor[] = [];\n /** Callbacks notified (on any instance) when a run is cancelled — for cooperative cancellation. */\n private readonly cancelListeners = new Set<(runId: string) => void>();\n /** Callbacks notified when a run is enqueued elsewhere — for low-latency cross-pod dispatch. */\n private readonly enqueuedListeners = new Set<(runId: string) => void>();\n /** Notified when a run is dead-lettered (moved to `dead`) — a hook for a DLQ handler. */\n private readonly deadListeners = new Set<(run: WorkflowRun) => void>();\n /** Validators gating `engine.update`, keyed by `<workflow>:<updateName>`. */\n private readonly updateValidators = new Map<string, UpdateValidator>();\n /** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */\n private readonly cancelRequested = new Set<string>();\n /** Flow-control admission backend for remote steps (see {@link registerQueue}). */\n private readonly admission: AdmissionBackend;\n /** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */\n private readonly queueWaiters = new Map<string, Set<string>>();\n /** Which queue a dispatched step took a slot from, by stepId — so the result can release it. */\n private readonly stepQueue = new Map<string, string>();\n /** Executions currently in flight, so a graceful shutdown can wait for them to settle. */\n private readonly inflight = new Set<Promise<RunResult>>();\n private draining = false;\n /** Wait already spent on this shutdown before `drain()` (see `beginDrain`). */\n private drainSpentMs = 0;\n /** Re-arms the deadline of every `drain()` currently waiting, when more wait is reported. */\n private readonly drainRearms = new Set<() => void>();\n\n constructor(deps: WorkflowEngineDeps) {\n this.store = deps.store;\n this.pool = new TransportPool(\n deps.transports ?? (deps.transport ? [{ id: 'default', transport: deps.transport }] : []),\n );\n this.controlPlane = deps.controlPlane;\n this.clock = deps.clock ?? Date.now;\n this.admission = deps.admission ?? new InMemoryAdmissionBackend(this.clock);\n // Wake this instance's admission-blocked runs the moment a slot frees anywhere in the fleet,\n // instead of waiting for their retry tick. Best-effort (the retry tick remains the guarantee).\n this.admission.onFreed?.((queue) => this.wakeQueueWaiters(queue));\n this.instanceId = deps.instanceId ?? globalThis.crypto.randomUUID();\n this.namespace = deps.namespace;\n // The engine's namespace deliberately does NOT touch the transport(s). The two tenancy axes are\n // orthogonal and encode differently ON PURPOSE (the cross-SDK canonical wire convention):\n // - `namespace` scopes the STORE (which runs this engine drives/recovers) and stamps every run\n // it starts; per-run routing then suffixes GROUP tokens (`<name>@<tenant>`, see tenantGroup)\n // on the transport's own prefix — the same convention every worker SDK (Python, the TS\n // tenant role) speaks natively.\n // - Whole-DEPLOYMENT isolation on a shared broker is the transport's `prefix`/`namespace`\n // constructor options — explicit, never inferred from the engine.\n // (An earlier design auto-folded a scoped engine's namespace into the transport prefix,\n // producing a keyspace no tenant worker could see — the tenant ended up encoded twice, once in\n // the prefix and once in the group suffix, and cross-runtime discovery silently failed.)\n this.leaseMs = deps.leaseMs ?? 30_000;\n this.maxRecoveryAttempts = deps.maxRecoveryAttempts;\n this.remoteAdvanceSilenceMs = deps.remoteAdvanceSilenceMs;\n // Default 5min; an explicit 0 disables the fallback (opt back into wake-forever-on-lost-event).\n this.reconcileMs = deps.reconcileMs === undefined ? 300_000 : deps.reconcileMs || undefined;\n // Opt-in: unset (or 0) keeps buffered events around forever, same as buffered signals.\n this.eventBufferTtlMs = deps.eventBufferTtlMs || undefined;\n // Opt-in: unset (or 0) leaves the by-design \"re-suspend a lost dispatch, never re-dispatch\" behavior.\n this.remoteRedispatchMs = deps.remoteRedispatchMs || undefined;\n this.remoteRedispatchMax = Math.max(1, deps.remoteRedispatchMax ?? 10);\n this.blockedPollMs = deps.blockedPollMs ?? 5000;\n // The control-plane descriptor this engine negotiates against each worker's advertised descriptor\n // (design §7.3): it speaks the current protocol band and is scoped to this engine's namespace so a\n // pool-mismatched worker isn't considered. Capabilities empty — the CP routes, it doesn't execute.\n this.cpDescriptor = controlPlaneDescriptor({\n instanceId: `cp-${this.instanceId}`,\n ...(this.namespace !== undefined ? { namespace: this.namespace } : {}),\n });\n this.webhookUrl = deps.webhookUrl;\n this.traceparent = deps.traceparent;\n this.context = deps.context;\n // Default passthrough: with no bridge supplied, a local step body runs exactly as before.\n this.rehydrate = deps.rehydrate ?? ((_carrier, fn) => fn());\n this.compensationRetries = Math.max(1, deps.compensationRetries ?? 1);\n this.trackStepStart = deps.trackStepStart ?? true;\n // Default: execute the run on this instance, asynchronously, so `start` never blocks on the body.\n // A failed pickup is swallowed here (the run stays `pending` for a `runPending` poll to retry);\n // run failures themselves are handled inside `execute` and surfaced as the run's `failed` state.\n this.runDispatcher = deps.runDispatcher ?? {\n dispatch: (runId) => queueMicrotask(() => void this.runOne(runId).catch(() => {})),\n };\n this.singletons = new SingletonGate({\n store: this.store,\n clock: this.clock,\n dispatch: (runId) => {\n this.runDispatcher.dispatch(runId);\n },\n configFor: (run) =>\n (\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n this.latest.get(run.workflow)\n )?.singleton,\n });\n this.schedules = new ScheduleClient(\n this.store,\n {\n start: (workflow, input, runId, opts) => this.start(workflow, input, runId, opts),\n getRun: (runId) => this.store.getRun(runId),\n isDraining: () => this.draining,\n },\n { namespace: this.namespace, clock: this.clock },\n );\n this.pool.bind(\n async (result) => {\n // In-memory path (a `timeoutMs` step awaiting on THIS instance): resolve its pending promise.\n const waiter = this.pending.get(result.stepId);\n if (waiter) {\n this.pending.delete(result.stepId);\n if (result.status === 'completed') {\n waiter.resolve({\n output: result.output,\n startedAt: result.startedAt,\n events: result.events,\n });\n } else {\n waiter.reject(new RemoteStepError(result.error));\n }\n return;\n }\n // Durable path: no in-memory waiter (the step suspended the run, possibly on another\n // instance) → complete the checkpoint and resume the run here.\n await this.completeRemoteResult(result);\n },\n // A heartbeat resets the liveness window for whatever it targets: an in-flight long STEP (keyed\n // by stepId, see callRemote) or — when stepId is absent — the in-flight workflow TURN (keyed by\n // runId). For an INLINE-advance turn the reset is an in-memory callback; without one (the step\n // or turn suspended durably, possibly on another instance) the beat rearms the DURABLE deadline\n // instead: the suspended turn's `wakeAt` for a run-scoped beat, the step's lease for a\n // step-scoped one — either way keeping a live worker's work from being presumed lost.\n async (beat) => {\n const reset = this.heartbeatResets.get(beat.stepId ?? beat.runId);\n if (reset) {\n reset();\n return;\n }\n if (beat.stepId === undefined) {\n await this.rearmDecisionDeadline(beat.runId);\n return;\n }\n await this.rearmStepLease(beat.runId, beat.seq);\n },\n // A remote workflow worker streams each local step's lifecycle (running → completed/failed) so\n // it's checkpointed live, not all-at-once when the long turn ends.\n async (event) => {\n await this.persistStepEvent(event);\n },\n // A workflow-turn DECISION delivered over the broker — applied durably (by run id) on whatever\n // instance consumes it, NOT correlated to an in-memory promise on the dispatcher. This is the\n // multi-instance fix: a point-to-point broker may hand the decision to a non-dispatching instance.\n async (decision) => {\n await this.completeRemoteDecision(decision);\n },\n );\n // Control-plane start-run: a DB-less tenant worker publishes a StartRunMessage and this\n // (control-plane) engine turns it into a durable run stamped with the tenant's namespace. Guarded\n // by the transport's `onStartRun` capability (like the other optional transport hooks) — a pool\n // whose transport can't carry the channel simply never registers, so a worker-only engine no-ops.\n this.pool.onStartRun(async (message) => {\n await this.start(\n message.workflow,\n message.input,\n message.runId ?? globalThis.crypto.randomUUID(),\n {\n namespace: message.tenant,\n tags: message.tags,\n searchAttributes: message.searchAttributes,\n },\n );\n });\n // Control plane: re-broadcast lifecycle events from OTHER instances to this instance's\n // subscribers (cross-pod live-tail), and act on cancellations issued elsewhere. A broker may\n // echo our own publish back — ignore those (we already handled them locally) to avoid duplicates.\n this.controlPlane?.onControl((msg) => {\n if (msg.from === this.instanceId) return;\n if (msg.kind === 'event') {\n // `at` may be a string after JSON transit (Redis) — normalize back to a Date.\n this.deliver({ ...msg.event, at: new Date(msg.event.at) });\n } else if (msg.kind === 'cancel') {\n this.notifyCancelled(msg.runId);\n } else if (msg.kind === 'enqueued') {\n // A run was enqueued on another instance — let worker subscribers pick it up immediately\n // instead of waiting for the next poll. (Self-broadcasts are already filtered above.)\n for (const fn of this.enqueuedListeners) {\n try {\n fn(msg.runId);\n } catch {\n /* an enqueue listener must not break the engine */\n }\n }\n }\n });\n this.accumulators = new EventAccumulators(this);\n this.entities = new Entities(this);\n }\n\n /**\n * Register a **durable entity** (a virtual object): a keyed actor whose `handlers` run **serialized\n * per key** over **durable state**, exactly once. Drive it with `signalEntity` (fire) /\n * `ctx.callEntity` (call + await result) and read its state with `getEntityState`. See {@link Entities}.\n */\n registerEntity<S>(name: string, config: EntityConfig<S>): void {\n this.entities.register(name, config);\n }\n\n /** Send an operation to an entity (fire-and-forget). Ordered + exactly-once per key. */\n signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void> {\n return this.entities.signal(name, key, op, arg);\n }\n\n /** Read an entity's current durable state (published after each op), or undefined if it has none yet. */\n getEntityState<S = unknown>(name: string, key: string): Promise<S | undefined> {\n return this.entities.getState<S>(name, key);\n }\n\n /**\n * Be notified when a run is enqueued on ANOTHER instance (via the control plane), so a worker can\n * pick it up at once — e.g. `engine.onEnqueued((runId) => engine.runOne(runId))`. Returns an\n * unsubscribe function. Only wire this on instances that should execute runs (workers).\n */\n onEnqueued(listener: (runId: string) => void): () => void {\n this.enqueuedListeners.add(listener);\n return () => this.enqueuedListeners.delete(listener);\n }\n\n /** Fire cooperative-cancellation listeners for `runId` (a worker bridge aborts in-flight work). */\n private notifyCancelled(runId: string): void {\n for (const fn of this.cancelListeners) {\n try {\n fn(runId);\n } catch {\n /* a cancel listener must not break the engine */\n }\n }\n }\n\n /**\n * Register a workflow version. Register multiple versions of the same name to keep in-flight\n * runs working across a breaking change: old runs resume on the version they started on, new\n * runs start on the newest registered version.\n *\n * GROUP-SERVED (uniform dispatch, opt-in): pass `{ group, executor }` to have the engine DISPATCH\n * this workflow's turns to a worker `group` (via `executor.advance`) instead of running `fn`\n * inline — exactly as {@link registerRemote} does for a cross-SDK (e.g. Python) body, EXCEPT the\n * body is a TS `fn` the engine retains so an IN-APP worker on `group` can fetch it by name\n * ({@link workflowBody}) and run it. This is \"one app, both roles\": the same process owns the\n * engine AND consumes its own group. Recovery, timers, singleton, cancel and dead-lettering stay\n * engine concerns, identical to a remote run. OMIT `group`/`executor` (the default) to keep the\n * inline fast path — `fn` runs in-process and the run pays zero dispatch round-trips. The first\n * step toward routing every run through a group with no local/remote flag (Phase 3).\n */\n register(\n name: string,\n version: string,\n fn: WorkflowFn,\n opts?: {\n tags?: string[] | undefined;\n singleton?: SingletonConfig | undefined;\n /** Start-time concurrency quota — see {@link ConcurrencyConfig}. */\n concurrency?: ConcurrencyConfig | undefined;\n executionTimeout?: string | number | undefined;\n validateInput?: ((input: unknown) => void | Promise<void>) | undefined;\n /** Typed/validated `searchAttributes` shape — see `RegisteredWorkflow.searchAttributesSchema`. */\n searchAttributesSchema?: SearchAttributesSchema | undefined;\n onEvent?: string[] | undefined;\n eventBatch?: EventBatchConfig | undefined;\n /** Worker group to DISPATCH this workflow's turns to (uniform dispatch). Requires `executor`.\n * Omit for the default inline fast path. See the method doc. */\n group?: string | undefined;\n /** Advances a turn by dispatching a {@link WorkflowTask} to `group`. Requires `group`. For an\n * in-app worker, pair a transport-backed {@link RemoteWorkflowExecutor} (group consumed by a\n * worker that calls {@link workflowBody}) so the retained `fn` runs through the transport hop. */\n executor?: WorkflowExecutor | undefined;\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5).\n * Only meaningful with `group`/`executor` (a remote/group-served workflow). Absent = runs anywhere. */\n requires?: string[] | undefined;\n /** The package that DECLARED this workflow, stamped onto every run started from it (see\n * {@link WorkflowRun.origin}). Supplied by the registering integration — `@dudousxd/nestjs-durable`\n * derives it from the `@Workflow` class's declaring file — never by whoever calls `start`. Omit\n * when it cannot be derived with confidence: absent means UNKNOWN, and an absent origin is far\n * cheaper to live with than a wrong one. */\n origin?: string | undefined;\n },\n ): void {\n // Group-served is all-or-nothing: a `group` with no `executor` (or vice-versa) is a wiring bug —\n // fail loudly at registration rather than silently falling back to the inline path at dispatch.\n if ((opts?.group == null) !== (opts?.executor == null)) {\n throw new Error(\n `workflow ${name}@${version}: register({ group, executor }) needs BOTH group and executor (or neither)`,\n );\n }\n const registered: RegisteredWorkflow = {\n name,\n version,\n fn,\n tags: opts?.tags,\n singleton: opts?.singleton,\n concurrency: opts?.concurrency,\n executionTimeoutMs:\n opts?.executionTimeout != null ? parseDuration(opts.executionTimeout) : undefined,\n validateInput: opts?.validateInput,\n searchAttributesSchema: opts?.searchAttributesSchema,\n onEvent: opts?.onEvent,\n eventBatch: opts?.eventBatch,\n requires: opts?.requires,\n origin: opts?.origin,\n // A real, retained in-process body — so `workflowBody` can hand it to an in-app worker, and so\n // it is NOT confused with the throwing stub `registerRemote` installs for a body-less remote.\n hasBody: true,\n };\n // When group-served, route DISPATCH through the executor (the same `remote` branch a Python\n // workflow takes); `fn` above stays usable for the in-app worker. Omitted = inline fast path.\n if (opts?.group != null && opts?.executor != null) {\n registered.remote = { group: opts.group, executor: opts.executor };\n }\n this.workflows.set(versionKey(name, version), registered);\n const current = this.latest.get(name);\n if (!current || isNewerVersion(version, current.version)) this.latest.set(name, registered);\n for (const event of opts?.onEvent ?? []) {\n const subscribers = this.eventTriggers.get(event) ?? new Set<string>();\n subscribers.add(name);\n this.eventTriggers.set(event, subscribers);\n }\n }\n\n /**\n * The retained in-process body for `name@version`, for an IN-APP worker that consumes this engine's\n * own group to SERVE a group-served `register(..., { group, executor })` workflow (uniform dispatch):\n * the worker fetches the body by name when it picks up the dispatched {@link WorkflowTask}, replays\n * it, and returns the {@link WorkflowDecision}. `undefined` for an unregistered name or a body-less\n * remote (a `registerRemote` / synthesized child carries only a throwing stub, never handed out).\n */\n workflowBody(name: string, version: string): WorkflowFn | undefined {\n const reg = this.workflows.get(versionKey(name, version));\n return reg?.hasBody ? reg.fn : undefined;\n }\n\n /** The registered versions of `name`, for the pinned-start error — \"2 is not registered\" is a\n * guess-the-typo error without them, and the answer (which versions this deploy actually carries)\n * is right here. `none` when the name is unknown entirely. */\n private registeredVersions(name: string): string {\n const versions = [...this.workflows.values()]\n .filter((w) => w.name === name)\n .map((w) => w.version);\n return versions.length ? versions.join(', ') : 'none';\n }\n\n /**\n * Register a workflow whose body runs in another SDK (e.g. Python). The engine owns the run exactly\n * as for a TS workflow — it persists checkpoints, recovers, runs timers — but advances it by handing\n * the run's history to `executor` (which dispatches a {@link WorkflowTask} to the worker) and applying\n * the {@link WorkflowDecision} the worker's replay returns. The worker never touches the store.\n */\n registerRemote(\n name: string,\n version: string,\n opts: {\n group: string;\n executor: WorkflowExecutor;\n tags?: string[];\n singleton?: SingletonConfig;\n concurrency?: ConcurrencyConfig;\n executionTimeout?: string | number;\n validateInput?: (input: unknown) => void | Promise<void>;\n /** Capabilities a live worker must advertise to run this remote workflow's turns (handshake §7.5). */\n requires?: string[];\n },\n ): void {\n const registered: RegisteredWorkflow = {\n name,\n version,\n // A remote workflow has no in-process body; execute() branches on `remote` before this is read.\n fn: () => {\n throw new Error(`workflow ${name} is remote — it has no in-process body`);\n },\n tags: opts.tags,\n singleton: opts.singleton,\n concurrency: opts.concurrency,\n executionTimeoutMs:\n opts.executionTimeout != null ? parseDuration(opts.executionTimeout) : undefined,\n validateInput: opts.validateInput,\n requires: opts.requires,\n remote: { group: opts.group, executor: opts.executor },\n };\n this.workflows.set(versionKey(name, version), registered);\n const current = this.latest.get(name);\n if (!current || isNewerVersion(version, current.version)) this.latest.set(name, registered);\n }\n\n /**\n * The convenience form of {@link registerRemote}: register a workflow whose body runs on a worker\n * `group` (e.g. the Python `durable-worker`, or a separate TS worker), without hand-building a\n * {@link RemoteWorkflowExecutor}. It wires the standard broker executor — a `RemoteWorkflowExecutor`\n * over the engine's own transport, dispatching to `opts.group` — for you, so you write\n * `engine.remote('processing', { group: 'processing' })` instead of\n * `engine.registerRemote('processing', '1', { group: 'processing', executor: new RemoteWorkflowExecutor(transport, 'processing') })`.\n *\n * Defaults the version to `'1'`. All the other {@link registerRemote} options\n * (`tags` / `singleton` / `executionTimeout` / `validateInput`) pass straight through. Reach for the\n * low-level {@link registerRemote} when you need a custom {@link WorkflowExecutor} (a different\n * transport, a fixed `timeoutMs`, a polyglot stub) — `remote()` is the standard wiring on the rails.\n */\n remote(\n name: string,\n opts: {\n /** Worker group this workflow's turns are dispatched to (also the executor's target group). */\n group: string;\n /** Workflow version. Defaults to `'1'`. */\n version?: string;\n tags?: string[];\n singleton?: SingletonConfig;\n concurrency?: ConcurrencyConfig;\n executionTimeout?: string | number;\n validateInput?: (input: unknown) => void | Promise<void>;\n /** Capabilities a live worker must advertise to run this workflow's turns (handshake §7.5). */\n requires?: string[];\n },\n ): void {\n const { group, version, ...rest } = opts;\n const executor = new RemoteWorkflowExecutor(this.pool.primary, group);\n this.registerRemote(name, version ?? '1', { group, executor, ...rest });\n }\n\n /**\n * Register a flow-control queue referenced by `ctx.step(step, input, { queue })`. Caps concurrent\n * in-flight steps and/or the admission rate; blocked calls re-suspend and retry, so the limit is\n * durable. Per engine instance (see {@link QueueConfig}). Registering the same name replaces it.\n */\n registerQueue(config: QueueConfig): void {\n this.admission.register(config);\n }\n\n /** Subscribe to lifecycle events. Returns an unsubscribe function. */\n subscribe(listener: EngineListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Register a {@link StepInterceptor} — onion middleware run around the real execution of every\n * local `ctx.step` (timing, logging, tracing, error enrichment, context propagation). First\n * registered is outermost; interceptors fire only when a step executes, never on replay. Returns\n * an unsubscribe function.\n */\n use(interceptor: StepInterceptor): () => void {\n this.interceptors.push(interceptor);\n return () => {\n const i = this.interceptors.indexOf(interceptor);\n if (i >= 0) this.interceptors.splice(i, 1);\n };\n }\n\n /**\n * Fold the registered interceptors around a local step body (identity when there are none), then\n * run the whole thing inside the re-hydrated originating context. The carrier is read at execution\n * time from {@link context} — the SAME reader stamped on dispatched remote tasks — so a local step\n * sees the live tenant / user / trace ids ambiently (via the {@link rehydrate} bridge). Default\n * `rehydrate` is a passthrough, so this is byte-identical to a bare body call when unwired.\n */\n private interceptStep<T>(invocation: StepInvocation, body: () => Promise<T>): Promise<T> {\n const carrier = this.context?.();\n const run = (): Promise<T> => {\n if (this.interceptors.length === 0) return body();\n const chain = this.interceptors.reduceRight<() => Promise<unknown>>(\n (next, interceptor) => () => interceptor(invocation, next),\n body as () => Promise<unknown>,\n );\n return chain() as Promise<T>;\n };\n return this.rehydrate(carrier, run);\n }\n\n /**\n * Be notified when a run is cancelled — on ANY instance, via the transport control plane. A\n * worker bridge can use this for cooperative cancellation: abort the in-flight work for `runId`\n * instead of finishing it just to have the result discarded. Returns an unsubscribe function.\n */\n onCancel(listener: (runId: string) => void): () => void {\n this.cancelListeners.add(listener);\n return () => this.cancelListeners.delete(listener);\n }\n\n /**\n * Be notified when a run is **dead-lettered** — moved to `dead` after exceeding\n * `maxRecoveryAttempts`. The listener receives the dead run (status `dead`, with its error), so a\n * DLQ handler can do something other than just leaving it parked: alert, push to a real queue, or\n * start a dead-letter workflow (e.g. `engine.onDead((run) => engine.start('pipeline-dlq', run, ...))`).\n * Returns an unsubscribe function.\n */\n onDead(listener: (run: WorkflowRun) => void): () => void {\n this.deadListeners.add(listener);\n return () => this.deadListeners.delete(listener);\n }\n\n private notifyDead(run: WorkflowRun): void {\n for (const fn of this.deadListeners) {\n try {\n fn(run);\n } catch {\n /* a dead-letter handler must not break recovery */\n }\n }\n }\n\n /** Emit a locally-produced lifecycle event: deliver to subscribers AND broadcast it on the\n * control plane so other instances (e.g. a dashboard pod) can live-tail this run. */\n private emit(event: Omit<EngineEvent, 'at'>): void {\n const full: EngineEvent = { ...event, at: new Date() };\n this.deliver(full);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'event', event: full, from: this.instanceId })\n .catch(() => {\n // control-plane delivery is best-effort observability; never break execution\n });\n }\n }\n\n /** Deliver an event to local subscribers only (no re-broadcast) — used for both locally-produced\n * events and ones received from the control plane, so an event shows up once on every instance. */\n private deliver(event: EngineEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // a misbehaving subscriber must never break workflow execution\n }\n }\n }\n\n async start<C extends WorkflowClass>(\n workflow: C,\n input: WorkflowInputOf<C>,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n async start<TInput>(\n workflow: string,\n input: TInput,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult>;\n async start(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n opts?: StartOptions,\n ): Promise<RunResult> {\n const name = workflowName(workflow);\n // PINNED (`opts.version`) resolves the by-name@version registry and stops there: no `latest`, and\n // none of the synthesized fallbacks below, because none of them can prove the version exists (see\n // {@link StartOptions.version}). Unpinned — every caller that has ever existed — takes `latest`\n // and the fallback chain, byte-for-byte as before.\n const pinned = opts?.version;\n let registered =\n pinned === undefined ? this.latest.get(name) : this.workflows.get(versionKey(name, pinned));\n if (!registered && pinned === undefined) {\n // An unregistered run inherits remote routing from its spawning ancestor (see\n // {@link findInheritedRegistration}): the child of a remote workflow can be started without a\n // redundant `registerRemote` for its name. The child run doesn't exist yet, but its parent\n // already wrote the `child:<runId>` waiter BEFORE calling start (the remote `startChild` command\n // and `ctx.child`/`ctx.all` all put the waiter first), so the ancestor is discoverable now.\n const ancestor = await this.findRemoteAncestor(runId);\n if (ancestor) registered = this.synthesizeRemoteChild(name, ancestor.version, ancestor);\n }\n if (!registered && pinned === undefined) {\n // Convention routing: if the transport reports a live group of the same name, synthesize a\n // remote registration on the fly.\n //\n // The `'1'` below is a FALLBACK, not the answer. It used to be the answer: this synthetic run\n // was stamped `'1'` and the resolver echoed it straight back as `registered.version`, so the\n // run row recorded a version nothing had observed — and a pin compared against it could only\n // ever pass on `'1'` and fail on everything else, whatever the worker really was. So the\n // resolver is asked to consult the fleet (`askFleetForVersion`) and this value survives only\n // when the fleet declares nothing, in which case the run is tagged {@link VERSION_UNDECLARED_TAG}\n // so a later check can tell an assumed version from a stated one.\n const conventionRun: WorkflowRun = {\n id: runId,\n workflow: name,\n workflowVersion: '1',\n status: 'pending',\n // Stamp the namespace the REAL run will carry (below) so convention routing resolves the same\n // tenant-suffixed group the run will dispatch to — an operator starting a tenant's run via the\n // `onStartRun` wire (opts.namespace = tenant) must find the live `<workflow>@<tenant>` group,\n // not the bare group. Without this the start-run entry path can't reach a suffixed-only worker.\n namespace: opts?.namespace ?? this.namespace,\n input,\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n registered = await this.resolveRemoteByConvention(conventionRun, {\n askFleetForVersion: true,\n });\n }\n if (!registered) {\n throw new Error(\n pinned === undefined\n ? `workflow ${name} is not registered`\n : `workflow ${versionKey(name, pinned)} is not registered — a pinned start never falls back to the newest version (registered: ${this.registeredVersions(name)})`,\n );\n }\n // Validate the input up front — a bad payload is rejected before any run is created.\n await registered.validateInput?.(input);\n // Idempotent by run id: a redelivered trigger (at-least-once queues) or a scheduler re-tick for\n // the same id is a no-op, returning the existing run's state instead of starting a duplicate.\n const prior = await this.store.getRun(runId);\n if (prior) {\n return { runId, status: prior.status, output: prior.output, error: prior.error };\n }\n // Start-time concurrency quota (per-start override, else the workflow's): reject BEFORE creating\n // anything when the key's in-flight runs already reach the limit. See {@link ConcurrencyQuota}.\n const quota = await resolveConcurrency(opts?.concurrency, registered.concurrency, input);\n if (quota) await assertConcurrency(this.store, name, quota);\n const now = new Date();\n // A singleton workflow stamps a `singleton:<key>` tag so the admission gate (in execute) can find\n // the other in-flight runs sharing the key via a tag+status query. A convention-resolved remote\n // whose version nobody declared stamps `version:undeclared` on the same principle: the fact has\n // to travel WITH the run, because whoever checks a pin later reads the run row and nothing else.\n const stampedTags = [\n ...(opts?.tags ?? []),\n ...(registered.singleton ? [this.singletons.tag(registered.singleton, input)] : []),\n ...(quota ? [concurrencyTag(quota.key)] : []),\n ...(registered.versionDeclared === false ? [VERSION_UNDECLARED_TAG] : []),\n ];\n // Admission is owned by the store, never supplied or inherited by a fresh run.\n const tags = mergeTags(registered.tags, stampedTags)?.filter(\n (tag) => tag !== SINGLETON_ADMITTED_TAG,\n );\n // Singleton back-pressure: reject a start that would grow the same-key backlog past\n // `limit + maxQueueDepth` (no-op when no maxQueueDepth is configured).\n if (registered.singleton) {\n await this.singletons.assertCapacity(name, registered.singleton, input);\n }\n const run: WorkflowRun = {\n id: runId,\n workflow: name,\n workflowVersion: registered.version,\n status: 'pending',\n namespace: opts?.namespace ?? this.namespace,\n // DERIVED from the registration, exactly like `namespace` is derived from this engine — there is\n // deliberately no `opts.origin`, so a caller cannot label its run as another package's work.\n // `undefined` when the registration carried none (remote/convention/synthesized child, or a\n // registrar that could not resolve the declaring package): unknown, not \"the app\".\n origin: registered.origin,\n input,\n tags,\n searchAttributes: opts?.searchAttributes,\n priority: opts?.priority,\n createdAt: now,\n updatedAt: now,\n };\n await this.store.createRun(run);\n // The run is durably enqueued; a dispatcher (in-process by default) executes it — `start` does\n // NOT run the body inline. Await the terminal/suspended state with `waitForRun(runId)` if needed.\n await this.runDispatcher.dispatch(runId);\n // Nudge worker instances to pick it up now instead of on their next poll (no-op without a control\n // plane; self-receipt is filtered, so it only helps OTHER pods — e.g. an API pod's enqueue).\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'enqueued', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n return { runId, status: 'pending' };\n }\n\n /** Read a run's current persisted state (or null if unknown). A thin pass-through to the store. */\n getRun(runId: string): Promise<WorkflowRun | null> {\n return this.store.getRun(runId);\n }\n\n /**\n * Re-execute a run's body (replaying its checkpoints). This is the EXPLICIT entry point: besides\n * driving a live run, it re-drives a `failed` run — the manual retry (prefer {@link requeue}, which\n * also resets the failure state so replay re-attempts the failed parts). Completed / cancelled /\n * dead runs are never re-executed. The engine's own implicit wake-ups (signals, step results,\n * timers, redelivered dispatches) go through {@link resumeImplicit}, which treats `failed` as\n * terminal too.\n */\n resume(runId: string): Promise<RunResult> {\n return this.resumeRun(runId, true);\n }\n\n /**\n * {@link resume} for every IMPLICIT wake-up — a delivered signal/child completion, a late step\n * result, a due timer, a redelivered dispatch, a queue-slot wake. A `failed` run is terminal to\n * these: only an explicit retry ({@link requeue} / {@link resume}) may re-drive it. Otherwise a\n * stale waiter or a late result left behind by a failed run silently re-executes its body.\n */\n private resumeImplicit(runId: string): Promise<RunResult> {\n return this.resumeRun(runId, false);\n }\n\n private async resumeRun(runId: string, allowFailed: boolean): Promise<RunResult> {\n const run = await this.store.getRun(runId);\n if (!run) throw new Error(`run ${runId} not found`);\n // A definitively-finished run must not be re-executed (e.g. a worker result landing after the\n // run was cancelled, or a duplicate resume) — that would replay the body and clobber the\n // terminal state. `failed` is terminal too unless this is an explicit retry (see `resume`).\n if (\n run.status === 'cancelled' ||\n run.status === 'completed' ||\n run.status === 'dead' ||\n (run.status === 'failed' && !allowFailed)\n ) {\n return { runId, status: run.status, output: run.output, error: run.error };\n }\n // Namespace guard: release the lock and bail when this run belongs to a different worker pool.\n // Piggybacked on the existing store.getRun above — no extra async step on the happy path.\n // An undefined namespace (a store adapter that doesn't persist the field yet) is treated as\n // \"belongs to everyone\" for back-compat: don't skip it. Likewise, this ENGINE having an\n // undefined namespace means it's an operator control plane — it belongs to every namespace too,\n // so the guard never applies to it.\n if (\n this.namespace !== undefined &&\n run.namespace !== undefined &&\n run.namespace !== this.namespace\n ) {\n await this.store.releaseRunLock(runId);\n throw new NamespaceMismatch();\n }\n // Pin to the version the run STARTED on — replay is positional, so running a changed\n // workflow body against old checkpoints would corrupt the run. The direct lookup is synchronous\n // (`??` short-circuits): a registered run never awaits here, so its resume timing is unchanged —\n // only an UNREGISTERED run pays the inheritance walk (see {@link findInheritedRegistration}).\n // A failed run being explicitly retried must compete for a slot again. This also handles\n // terminal records retained from before the store cleared admission markers on settlement.\n if (run.status === 'failed' && run.tags?.includes(SINGLETON_ADMITTED_TAG)) {\n run.tags = run.tags.filter((tag) => tag !== SINGLETON_ADMITTED_TAG);\n await this.store.updateRun(run.id, { tags: run.tags });\n }\n const registered =\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n (await this.findInheritedRegistration(run)) ??\n (await this.resolveRemoteByConvention(run));\n if (!registered) {\n throw new Error(\n `workflow ${run.workflow}@${run.workflowVersion} is not registered — keep the prior version deployed so in-flight runs can drain (skew protection)`,\n );\n }\n return this.track(this.execute(run, registered.fn));\n }\n\n /**\n * The registration for an UNREGISTERED run, INHERITED from its nearest REMOTE ancestor — or\n * `undefined` if it has none (the skew-protection error case in {@link resume}). Callers check the\n * flat registry FIRST (so an explicit `registerRemote(name, …)` ALWAYS wins, and a registered run\n * never reaches here); this resolves only the new case: a child spawned by a remote workflow (e.g. a\n * Python `gather_children` / `start_child` fan-out) of a name the host never `registerRemote`-ed. It\n * is driven as a remote run on the ancestor's group + the SAME executor instance, so the host needs\n * no redundant registration per child name.\n *\n * RECOMPUTED per resume rather than memoized into `this.workflows`: a synthesized child is not a real\n * registration and must not leak into `latest`, `knownGroups`, or `sweepTimeouts` (which iterate the\n * registry); recomputing also stays correct if the ancestor's remote registration is re-pointed at a\n * new executor across a deploy. Only unregistered runs pay it, so registered workflows pay nothing.\n */\n private async findInheritedRegistration(\n run: WorkflowRun,\n ): Promise<RegisteredWorkflow | undefined> {\n const ancestor = await this.findRemoteAncestor(run.id);\n if (!ancestor) return undefined;\n return this.synthesizeRemoteChild(run.workflow, run.workflowVersion, ancestor);\n }\n\n /**\n * A throwaway {@link RegisteredWorkflow} that routes `name@version` as a remote run on the ancestor's\n * group via the ancestor's SAME executor instance. The executor is group-scoped (it dispatches a\n * {@link WorkflowTask} carrying `run.workflow`, and the worker picks the body by name), so reusing it\n * is correct AND required — a second executor on the same group would race the worker for results.\n * Only `remote` is inherited; the child gets none of the ancestor's singleton/timeout/validator, so\n * its identity stays its own.\n */\n private synthesizeRemoteChild(\n name: string,\n version: string,\n ancestor: RegisteredWorkflow,\n ): RegisteredWorkflow {\n // `ancestor` always carries `remote` (findRemoteAncestor / start only pass a remote registration);\n // the guard narrows the optional type without an unsafe cast and documents the invariant.\n const remote = ancestor.remote;\n if (!remote) throw new Error(`workflow ${ancestor.name} is not a remote workflow`);\n return {\n name,\n version,\n fn: () => {\n throw new Error(`workflow ${name} is remote — it has no in-process body`);\n },\n remote,\n };\n }\n\n /**\n * Attempt to route an unregistered workflow to the live worker group of the same name: if the\n * transport reports a live heartbeat for group `run.workflow`, synthesize a throwaway\n * {@link RegisteredWorkflow} that dispatches to that group over the primary transport. Returns\n * `undefined` when the group is not live. Always attempted — there is no opt-in flag; an explicit\n * `register`/`registerRemote` still takes precedence (this only runs when nothing is registered).\n *\n * Recomputed per call (never memoized into `this.workflows`) so it stays correct if group\n * liveness changes between calls, exactly as {@link synthesizeRemoteChild} does.\n */\n private async resolveRemoteByConvention(\n run: WorkflowRun,\n opts: { askFleetForVersion?: boolean } = {},\n ): Promise<RegisteredWorkflow | undefined> {\n // Workers register/heartbeat their liveGroups under the SANITIZED token (`sanitizeQueueToken`),\n // so the membership check must sanitize too — else a `:`-named workflow's live worker is under\n // `orders-fulfill` while this computes `orders:fulfill` and never matches.\n const group = tenantGroup(sanitizeQueueToken(run.workflow), run.namespace);\n // Resolve the TRANSPORT the group is live on, not just membership in the merged list: in a\n // mixed pool (a tenant-scoped control plane pairing its namespaced transport with a bare-prefix\n // one for operator-convention tenant workers), each transport scans a different keyspace —\n // dispatching on `primary` while the worker heartbeats on another transport would park the turn\n // on a queue nobody consumes.\n const liveTransport = await this.pool.transportWithLiveGroup(group);\n if (!liveTransport) return undefined;\n // Feed the workflow NAME + namespace-as-partition through, rather than the pre-combined\n // `group` string above — the executor computes the identical token itself (name+partition is\n // the new routing primitive; `group` here still exists only for the liveGroups membership check).\n const executor = new RemoteWorkflowExecutor(liveTransport, run.workflow, run.namespace);\n // The version a START records must come from the fleet, never from the caller. `resume` is the\n // opposite case and passes nothing: replay is positional, so a resumed run is pinned to the\n // version it BEGAN on and asking the fleet again could re-point a live run mid-flight.\n const declared = opts.askFleetForVersion\n ? await this.declaredVersion(liveTransport, group, run.workflow)\n : undefined;\n return {\n name: run.workflow,\n version: declared ?? run.workflowVersion,\n fn: () => {\n throw new Error(`remote workflow ${run.workflow} has no local body`);\n },\n hasBody: false,\n remote: { group, executor },\n ...(opts.askFleetForVersion ? { versionDeclared: declared !== undefined } : {}),\n };\n }\n\n /**\n * The version the LIVE fleet declares for `workflow` on `group`, or `undefined` when it declares\n * none — which is a fact about the fleet, not a failure to read it.\n *\n * The read is the descriptor advertisement, scoped to the one group being resolved: the workers on\n * that queue, their `registrations`, the entry whose `name` matches. That is where a version can\n * come from at all — a heartbeat has no room for one, so a worker on an SDK too old to publish a\n * descriptor declares nothing and the caller is told so rather than handed a default.\n *\n * `undefined` when the announcers DISAGREE, and deliberately: two live workers claiming different\n * versions of one name is a deployment in the middle of something, and picking either would stamp\n * a run with a version half the fleet does not serve. Undeclared is the honest reading of a\n * contradiction, and it is the reading that refuses to let a pin pass on a coin flip.\n */\n private async declaredVersion(\n transport: Transport,\n group: string,\n workflow: string,\n ): Promise<string | undefined> {\n if (!transport.readWorkerDescriptors) return undefined;\n let descriptors: WorkerDescriptor[];\n try {\n descriptors = await transport.readWorkerDescriptors(group);\n } catch {\n // A live read can fail every way a network call can. Undeclared, not thrown: this decides how a\n // version is LABELLED, and a Redis blip must not stop a run from starting.\n return undefined;\n }\n const versions = new Set<string>();\n for (const announced of aggregateAnnouncements(descriptors)) {\n if (announced.name === workflow && announced.version !== undefined) {\n versions.add(announced.version);\n }\n }\n const only = [...versions];\n return only.length === 1 ? only[0] : undefined;\n }\n\n /**\n * Walk the parent chain of `childRunId` to the nearest ancestor registered as REMOTE, returning its\n * registration (or `undefined` if there is none). The parent of an awaited child is found via its\n * live `child:<childId>` signal waiter — present for as long as the parent is suspended awaiting the\n * child, i.e. throughout the child's executable lifetime (start, every resume, crash recovery, cancel\n * cascade), which is exactly when we resolve. A registered-but-LOCAL parent stops the walk (an\n * unregistered child of a TS workflow is a genuine misconfiguration → skew error); only an\n * unregistered parent keeps walking, so a child of an inherited child still reaches the remote root.\n * `visited` guards against a pathological cyclic id graph.\n */\n private async findRemoteAncestor(\n childRunId: string,\n visited = new Set<string>(),\n ): Promise<RegisteredWorkflow | undefined> {\n if (visited.has(childRunId)) return undefined;\n visited.add(childRunId);\n const parentRunId = await this.findParentRunId(childRunId);\n if (!parentRunId) return undefined;\n const parent = await this.store.getRun(parentRunId);\n if (!parent) return undefined;\n const parentReg = this.workflows.get(versionKey(parent.workflow, parent.workflowVersion));\n if (parentReg?.remote) return parentReg;\n if (parentReg) return undefined;\n return this.findRemoteAncestor(parent.id, visited);\n }\n\n /**\n * The run that spawned `childRunId`, via its live `child:<childRunId>` signal waiter — every awaited\n * child (`ctx.child`, `ctx.all`, a remote `start_child`) suspends its parent on exactly this waiter,\n * and the waiter is written BEFORE the child is started. Only reached for an UNREGISTERED child, so\n * registered runs never pay the scan; returns `undefined` once the parent has settled the child (the\n * waiter is consumed), but by then the child is terminal and no longer resolved.\n */\n private async findParentRunId(childRunId: string): Promise<string | undefined> {\n const token = `child:${childRunId}`;\n // The token is the waiter's key: a prefix read of the token itself, filtered to the exact match.\n const waiters = await this.store.listSignalWaiters(token);\n return waiters.find((waiter) => waiter.token === token)?.runId;\n }\n\n /** Track an in-flight execution so {@link drain} can wait for it. */\n private track(p: Promise<RunResult>): Promise<RunResult> {\n this.inflight.add(p);\n const done = () => {\n this.inflight.delete(p);\n };\n void p.then(done, done);\n return p;\n }\n\n /**\n * Stop picking up new work without waiting: recovery, timer, schedule and timeout sweeps (and\n * their per-run lock loops) start nothing once this is called, and {@link runOne} returns null. A\n * poller calls it on its own shutdown so an in-flight sweep stops locking runs before it is awaited.\n *\n * `spentMs` is wait time ALREADY spent on this shutdown (the poller awaiting its in-flight sweep).\n * It is deducted from the budget of a later {@link drain}, so that wait plus the drain stay within\n * one `shutdownTimeoutMs`. Only time actually spent waiting is charged: time that merely passes\n * between this call and `drain()` (other hooks, the HTTP server closing) never is. Calls add up.\n */\n beginDrain(spentMs = 0): void {\n this.draining = true;\n // Non-finite values (NaN, Infinity) and negatives are ignored: one bad report must not turn\n // every later drain into a 1 ms wait.\n if (Number.isFinite(spentMs) && spentMs > 0) {\n this.drainSpentMs += spentMs;\n for (const rearm of this.drainRearms) rearm();\n }\n }\n\n /**\n * Graceful shutdown: stop picking up new runs (recovery/timer become no-ops) and wait for\n * in-flight executions to settle, up to `timeoutMs`. Call from your app's shutdown hook so a\n * deploy hands off cleanly instead of leaving runs to the lease timeout.\n *\n * `timeoutMs` is the total budget for waiting on in-flight runs; any wait already reported through\n * {@link beginDrain} (`spentMs`) is deducted, so a shutdown that already waited on the timer poll\n * for part of it waits only for the remainder. With nothing reported, the full `timeoutMs` applies.\n */\n async drain(timeoutMs = 10_000): Promise<void> {\n this.beginDrain();\n if (this.inflight.size === 0) return;\n // The deadline is `start + timeoutMs - spent`, re-read whenever `beginDrain(spentMs)` reports more\n // wait, so a drain that starts while the poller is still waiting is shortened once it reports.\n const start = Date.now();\n let rearm = (): void => {};\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const timer = new Promise<void>((resolve) => {\n rearm = () => {\n clearTimeout(timeout);\n const remaining = Math.max(0, start + timeoutMs - this.drainSpentMs - Date.now());\n timeout = setTimeout(resolve, remaining);\n (timeout as { unref?: () => void }).unref?.();\n };\n rearm();\n });\n this.drainRearms.add(rearm);\n try {\n await Promise.race([Promise.allSettled([...this.inflight]), timer]);\n } finally {\n this.drainRearms.delete(rearm);\n clearTimeout(timeout);\n }\n }\n\n /**\n * Cancel in-flight runs that have outlived their workflow's `executionTimeout`. Call it from the\n * timer poller alongside {@link resumeDueTimers}. A timed-out run is moved to `cancelled` with an\n * `execution_timeout` error (terminal, so a late step result can't resurrect it), AND its children\n * are cascaded exactly as an explicit {@link cancel} cascades them.\n *\n * WHY THE TERMINAL WRITE IS DIRECT, not a call to {@link cancel}. Two reasons, both still standing:\n * the run must land with the `execution_timeout` error `cancel` knows nothing about (`cancel` writes\n * a plain `cancelled`, and the code is what a dashboard/alert distinguishes a timeout by), and this\n * is a SCAN — it walks every in-flight run of every timed workflow on every poller tick, so it must\n * not pay `cancel`'s per-run re-read and singleton/control-plane work on runs it isn't cancelling.\n * The cascade below is charged only to the runs that ACTUALLY timed out, which are rare by\n * construction; the scan itself is unchanged.\n *\n * The subtree, though, has no reason to differ, and before this it did: a timed-out parent's\n * children kept running with the parent gone and nothing pointing at them — a silent orphan you\n * could only find by reading the runs table by hand. {@link cancelChildren} is the SAME recursive\n * walk `cancel` uses, so children of children go too, and it inherits that path's two guards:\n * `cancel` returns early on a run that is already `completed`/`cancelled`/`dead` (a child that beat\n * the sweep to the finish is never clobbered, and a re-cancel is a no-op), and it writes the\n * parent's terminal status BEFORE recursing, so a cyclic parent→child graph terminates on the\n * second visit instead of looping. Two pollers sweeping the same run concurrently therefore write\n * the same terminal state twice and cascade into already-cancelled children — idempotent, not\n * corrupting. The one window it does NOT close is the pre-existing check-then-write race an\n * explicit `cancel` has always had (a child that completes between `cancel`'s read and its write);\n * closing that needs a compare-and-set in the store contract, not a change here.\n *\n * Cascade failures are swallowed per subtree for the same reason `cancelChildren` swallows them per\n * child: one unreachable child must not abort the sweep and leave every LATER timed-out run alive.\n */\n async sweepTimeouts(now: number = this.clock()): Promise<void> {\n for (const reg of new Set(this.latest.values())) {\n if (this.draining) return;\n if (reg.executionTimeoutMs == null) continue;\n const deadline = now - reg.executionTimeoutMs;\n const inflight = [\n ...(await this.store.listRuns({\n workflow: reg.name,\n status: 'running',\n namespace: this.namespace,\n })),\n ...(await this.store.listRuns({\n workflow: reg.name,\n status: 'suspended',\n namespace: this.namespace,\n })),\n ];\n for (const run of inflight) {\n if (this.draining) return;\n if (run.createdAt.getTime() > deadline) continue;\n const error = { message: 'execution timeout', code: 'execution_timeout' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n // The parent is terminal FIRST (above), so a child that cascades back into it stops there.\n await this.cancelChildren(run.id).catch(() => undefined);\n }\n }\n }\n\n /**\n * Resume every run left incomplete by a crash or deploy. Called on boot. Completed steps\n * replay from their checkpoints, so only the work that had not finished runs again.\n */\n async recoverIncomplete(nowMs: number = this.clock()): Promise<RunResult[]> {\n if (this.draining) return [];\n const results: RunResult[] = [];\n for (const listed of await this.store.listIncompleteRuns(this.namespace)) {\n if (this.draining) break;\n // An IN-PROCESS turn renews its lease, so an acquirable lease means no turn is executing this\n // run right now. Skip the ones still owned. NOTE this is NOT the same as \"the worker crashed\" —\n // see the dispatched-step guard below for the case it doesn't cover.\n const acquired = await this.store.tryLockRun(\n listed.id,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) continue;\n // Decide on the run as it is NOW that the lease is held, never on the listing. The listing is a\n // snapshot taken before this loop reached the row, and a live run moves on in between: the turn\n // that was executing it (`running`) suspends and releases its lease, a fast step result resumes\n // it, it may even complete. Trusting the listed `running` then reads \"free lease, no step in\n // flight\" as a crashed turn — and the branches below count a recovery attempt, rewrite the run\n // to `pending` and re-enqueue it, i.e. start a SECOND execution beside the legitimate one (or\n // resurrect a finished run). Only a run that still reads incomplete under the lease is ours.\n const run = await this.store.getRun(listed.id);\n if (!run || (run.status !== 'running' && run.status !== 'cancelling')) {\n await this.store.releaseRunLock(listed.id);\n continue;\n }\n // NOT AN ORPHAN: a run with an in-flight (`pending`) remote step is not being executed in\n // process at all — its work is sitting on the transport, run by a worker that holds NO run\n // lease. So \"the lease is acquirable\" proves nothing about it, and by contract such a run is\n // durably SUSPENDED (see `StepCheckpoint.status`), not `running`; finding it `running` means a\n // turn ended without restoring that invariant. Counting it as a crash-recovery attempt burns\n // the poison-pill budget on a perfectly healthy run — repeat it `maxRecoveryAttempts` times and\n // the run is dead-lettered with a generic `max_recovery_attempts` error WHILE its worker is\n // still happily executing the step (observed in the wild: 10 attempts in 57s). Re-assert the\n // contract instead — park it `suspended` on the reconcile timer, which is exactly where a\n // dispatched-and-waiting run belongs: the worker's result resumes it, and `resumeDueTimers`\n // re-drives it as the safety net (replaying straight back to `callRemote`'s pending guard, or\n // re-dispatching when `remoteRedispatchMs` is set). A LOST dispatch is still not this pass's\n // job — `remoteRedispatchMs` / `redispatchPending` own that, unchanged.\n //\n // `cancelling` is deliberately excluded: it must keep its status (see below), so it stays on\n // the counted path rather than being parked `suspended` and losing the cancel intent.\n if (run.status === 'running') {\n const dispatched = await this.inFlightRemoteStep(run.id);\n if (dispatched) {\n await this.store.updateRun(run.id, {\n status: 'suspended',\n wakeAt: this.reconcileWakeAt(dispatched.wakeAt ?? undefined),\n updatedAt: new Date(),\n });\n await this.store.releaseRunLock(run.id);\n results.push({ runId: run.id, status: 'suspended' });\n continue;\n }\n }\n // Count the attempt / dead-letter a poison pill past maxRecoveryAttempts.\n const settled = await this.countRecovery(run);\n if (settled) {\n results.push(settled);\n continue;\n }\n // Re-enqueue rather than resume inline: recovery must NOT block (boot, or a poll tick) on a\n // long workflow step. A dispatcher/worker re-runs it, replaying its checkpoints.\n await this.store.releaseRunLock(run.id);\n // A `cancelling` run keeps its status (resetting to `pending` would lose the persisted cancel\n // intent and resurrect the run): the re-driven turn re-derives it from the status and finishes\n // the cancel. Every other run re-enqueues as `pending` for a clean (re)start.\n if (run.status !== 'cancelling') {\n await this.store.updateRun(run.id, { status: 'pending', updatedAt: new Date() });\n }\n await this.runDispatcher.dispatch(run.id);\n results.push({\n runId: run.id,\n status: run.status === 'cancelling' ? 'cancelling' : 'pending',\n });\n }\n return results;\n }\n\n /**\n * The remote step this run dispatched and is still awaiting a result for, if any — the signature\n * that tells {@link recoverIncomplete} \"this run's work is ON THE TRANSPORT, not in a crashed\n * process\". A `pending` remote checkpoint is written BEFORE the dispatch and settled by the\n * worker's result, so its presence is the durable marker of an in-flight dispatched step.\n */\n private async inFlightRemoteStep(runId: string): Promise<StepCheckpoint | undefined> {\n const checkpoints = await this.store.listCheckpoints(runId);\n return checkpoints.find((cp) => cp.kind === 'remote' && cp.status === 'pending');\n }\n\n /**\n * Per-recovery bookkeeping (called once the lease is held): count the attempt, or — past\n * `maxRecoveryAttempts` — move a poison pill to the `dead` dead-letter state. Returns a terminal\n * result to skip the resume, or `undefined` to proceed.\n */\n private async countRecovery(run: WorkflowRun): Promise<RunResult | undefined> {\n const attempts = (run.recoveryAttempts ?? 0) + 1;\n if (this.maxRecoveryAttempts != null && attempts > this.maxRecoveryAttempts) {\n const error = {\n message: `run exceeded maxRecoveryAttempts (${this.maxRecoveryAttempts}) — moved to dead-letter`,\n code: 'max_recovery_attempts',\n };\n await this.store.updateRun(run.id, { status: 'dead', error, updatedAt: new Date() });\n await this.store.releaseRunLock(run.id);\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n this.notifyDead({ ...run, status: 'dead', error, recoveryAttempts: attempts });\n return { runId: run.id, status: 'dead', error };\n }\n // Count BEFORE resuming, so a crash mid-resume still advances the counter.\n await this.store.updateRun(run.id, { recoveryAttempts: attempts, updatedAt: new Date() });\n return undefined;\n }\n\n /**\n * Resume every suspended run whose durable timer is due. Call periodically (a poller) and on\n * boot. A run still not due re-suspends cheaply without running new work.\n *\n * Piggy-backs the signal/event-waiter reconcile safety net (see {@link reconcileSignalWaiter}): a\n * crash between the waiter/buffer pairing ops on EITHER side (this run's own `putSignalWaiter` →\n * `takeBufferedSignal`/`listBufferedEvents`, or the other side's `takeSignalWaiter`/fan-out →\n * `bufferSignal`/`bufferEvent` → re-check — see `signal`'s interleaving proof, which `publishEvent`\n * mirrors for events) can leave both rows stranded with nothing left to pair them: the waiter's turn\n * already suspended, the other side that buffered it already returned. Event-wait suspends already\n * carry a `reconcileMs` fallback `wakeAt` (see {@link reconcileWakeAt}) precisely so they show up\n * HERE — that's what makes this due-timer pass the natural place for the sweep (and, for events, also\n * where an `eventBufferTtlMs` prune piggy-backs — see {@link reconcileBufferedEvent}). One bulk waiter\n * scan, filtered to just this tick's batch, keeps it cheap regardless of store size.\n */\n async resumeDueTimers(nowMs: number = this.clock()): Promise<RunResult[]> {\n const due = await this.store.listDueTimers(nowMs, this.namespace);\n // ALSO re-drive runs parked `blocked` whose recovery poll is due (handshake design §7.5): re-driving\n // re-checks the live fleet, so a run proceeds the moment a capable+compatible worker appears (else it\n // re-parks with a fresh `wakeAt`). `listDueTimers` targets `suspended`+`wakeAt`, so blocked runs are\n // gathered separately here rather than widening every store adapter's timer query.\n const blocked = await this.dueBlockedRuns(nowMs);\n if (due.length === 0 && blocked.length === 0) return [];\n const waiterByRun = indexWaitersByRun(\n await listSignalWaitersOfRuns(\n this.store,\n [...due, ...blocked].map((run) => run.id),\n ),\n );\n return this.resumeLeased([...due, ...blocked], nowMs, (run) =>\n this.reconcileSignalWaiter(run, waiterByRun.get(run.id)),\n );\n }\n\n /**\n * The reconcile safety net's per-run check (see {@link resumeDueTimers}): if this suspended run has\n * a registered signal OR event waiter and a matching payload is already buffered, pair and deliver\n * them directly instead of falling through to a full replay. Child/breakpoint waiter tokens are\n * never buffered (a child/breakpoint notifies via `signal` only once its counterpart is already\n * registered) — `takeBufferedSignal` on those is a guaranteed miss, so this only ever does real work\n * for a plain signal or an event waiter (classified via {@link isEventToken}).\n *\n * Also opportunistically prunes expired buffered EVENTS for this waiter's name when\n * {@link eventBufferTtlMs} is set (see its doc — scoped to names a registered waiter references in\n * this tick's batch, piggy-backing the SAME scan rather than a separate pass), even on a miss.\n *\n * Returns `undefined` (not settled — `resumeLeased` proceeds with its normal `resume`) when there's\n * no waiter or no buffered hit. Deliberately never returns `null`: a delivered signal always resumes\n * via {@link deliverSignal}, and even a `NamespaceMismatch` there is reported as a real (non-nullish)\n * result — returning `null` would read as \"not settled\" to `resumeLeased`'s `??` fallback and\n * trigger a second, redundant `resume` call on the same run.\n */\n private async reconcileSignalWaiter(\n run: WorkflowRun,\n waiter: SignalWaiter | undefined,\n ): Promise<RunResult | undefined> {\n if (!waiter) return undefined;\n if (isEventToken(waiter.token)) return this.reconcileBufferedEvent(run, waiter);\n const buffered = await this.store.takeBufferedSignal(waiter.token);\n if (!buffered) return undefined;\n await this.store.removeSignalWaiter(waiter);\n const settled = await this.deliverSignal(waiter, buffered.payload);\n return settled ?? { runId: run.id, status: run.status };\n }\n\n /**\n * The EVENT half of {@link reconcileSignalWaiter}: scan this waiter's name for a matching buffered\n * event (same list+evaluate+claim shape as `waitForEvent`'s own consumption — the match predicate\n * belongs to the waiter, never the store), pruning any expired candidates it encounters along the\n * way when {@link eventBufferTtlMs} is configured. A pruned-but-non-matching candidate does not stop\n * the scan; only a MATCHING hit (or exhausting the scan window) does.\n */\n private async reconcileBufferedEvent(\n run: WorkflowRun,\n waiter: SignalWaiter,\n ): Promise<RunResult | undefined> {\n const name = eventNameOf(waiter.token);\n const match = eventMatchOf(waiter.token);\n const candidates = await this.store.listBufferedEvents(name, EVENT_BUFFER_SCAN_LIMIT);\n const nowMs = this.clock();\n for (const candidate of candidates) {\n if (this.eventBufferTtlMs != null && nowMs - candidate.publishedAt > this.eventBufferTtlMs) {\n await this.store.removeBufferedEvent(candidate.id); // expired — prune regardless of match\n continue;\n }\n if (!eventMatches(candidate.payload, match)) continue;\n if (!(await this.store.removeBufferedEvent(candidate.id))) continue; // raced away — try the next\n await this.store.removeSignalWaiter(waiter);\n const settled = await this.deliverSignal(waiter, candidate.payload);\n return settled ?? { runId: run.id, status: run.status };\n }\n return undefined;\n }\n\n /**\n * Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so\n * exactly one instance runs it), then resumes the body. Returns the result, or null if another\n * instance holds the lease or the engine is draining. The default in-process dispatcher calls this;\n * a broker-backed worker calls it per consumed run id.\n */\n async runOne(runId: string): Promise<RunResult | null> {\n if (this.draining) return null;\n const nowMs = this.clock();\n const acquired = await this.store.tryLockRun(\n runId,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) return null;\n // resume() checks the namespace and throws NamespaceMismatch when it doesn't match — no extra\n // await before the call, so the microtask ordering (critical for cancel-safety) is unchanged.\n return this.resumeImplicit(runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * Re-enqueue a run for a worker to (re-)execute — the dispatch-model **retry**. Sets it back to\n * `pending`, clears any stale lease, and dispatches; a worker resumes it (replaying its checkpoints,\n * re-attempting the failed step). Returns the enqueued state immediately — never runs the body\n * inline — or null if the run is unknown. The dashboard \"retry\" goes through here so it can't block\n * the HTTP request on workflow execution.\n */\n async requeue(runId: string, _seen?: Set<string>): Promise<RunResult | null> {\n const seen = _seen ?? new Set<string>();\n if (seen.has(runId)) return null;\n seen.add(runId);\n const run = await this.store.getRun(runId);\n if (!run) return null;\n // A FAILED/DEAD run's replay deterministically re-throws its recorded failures — an exhausted\n // failed checkpoint rethrows, and an awaited child's failure completion rethrows through\n // unwrapCompletion — so \"retry\" without resetting that state is a no-op that re-fails in\n // milliseconds. Reset the failure state first so replay RE-EXECUTES the failed parts:\n // - a `failed` checkpoint becomes retryable-now (attempts 0, wake immediately, `retryable`\n // forced back on): the durable-retry machinery re-dispatches it as a fresh first attempt;\n // - an awaited-child `signal:child:` checkpoint holding a FAILURE completion returns to its\n // live `running` placeholder, so replay re-registers the `child:<id>` waiter — a separately\n // retried child's completion (already buffered, or still to come) then resumes this run.\n // Retry child and parent in either order; signal buffering makes it converge.\n // - the run-level `recoveryAttempts` budget goes back to zero (see the final `updateRun`).\n const resurrecting = run.status === 'failed' || run.status === 'dead';\n if (resurrecting) {\n const isFailureCompletion = (v: unknown): boolean =>\n typeof v === 'object' && v !== null && (v as { ok?: unknown }).ok === false;\n for (const cp of await this.store.listCheckpoints(runId)) {\n if (cp.status === 'failed') {\n await this.store.saveCheckpoint({\n ...cp,\n attempts: 0,\n wakeAt: this.clock(),\n ...(cp.error ? { error: { ...cp.error, retryable: true } } : {}),\n });\n } else if (\n cp.kind === 'signal' &&\n cp.name.startsWith('signal:child:') &&\n cp.status === 'completed' &&\n isFailureCompletion(cp.output)\n ) {\n // CASCADE: retrying only the parent is useless in a live engine — replay re-registers\n // the `child:<id>` waiter and the reconciler re-delivers the child's still-FAILED\n // terminal state within seconds, re-failing the parent with the same error. Requeue the\n // failed child too so the pair converges: whichever finishes the handshake last (waiter\n // registered vs completion buffered) resumes the parent.\n //\n // Exception: a SUCCESS already buffered on this token (a completed `~retry~` fix of the\n // child — see notifyParent's origin delivery) is the outcome, so re-running the failed\n // origin would be pure waste: settle the checkpoint with it right here.\n const childId = cp.name.slice('signal:child:'.length);\n // Drain-and-restore keeps relative order (a partial take+re-buffer would rotate it).\n const parked: unknown[] = [];\n for (;;) {\n const buffered = await this.store.takeBufferedSignal(`child:${childId}`);\n if (!buffered) break;\n parked.push(buffered.payload);\n }\n const successAt = parked.findIndex(\n (payload) =>\n typeof payload === 'object' &&\n payload !== null &&\n (payload as { ok?: unknown }).ok === true,\n );\n const success = successAt === -1 ? undefined : parked.splice(successAt, 1)[0];\n for (const payload of parked) await this.store.bufferSignal(`child:${childId}`, payload);\n const bufferedSuccess = success !== undefined;\n if (bufferedSuccess) {\n await this.store.saveCheckpoint({ ...cp, output: success });\n } else {\n // Back to a live `running` placeholder. Its waiter goes first: replay reads a\n // placeholder as proof its waiter exists and never re-puts it.\n await this.store.putSignalWaiter({\n token: `child:${childId}`,\n runId,\n seq: cp.seq,\n parallelGroup: cp.parallelGroup,\n });\n await this.store.saveCheckpoint({ ...cp, status: 'running', output: undefined });\n }\n if (!bufferedSuccess) {\n const child = await this.store.getRun(childId);\n if (child && (child.status === 'failed' || child.status === 'dead')) {\n await this.requeue(childId, seen);\n }\n }\n }\n }\n }\n await this.store.releaseRunLock(runId);\n // Explicit `error: undefined` CLEARS the stale failure (both stores spread the patch over the\n // run) — otherwise the dashboard keeps showing the old error while the run is re-executing.\n //\n // RESURRECTING a `failed`/`dead` run ALSO clears `recoveryAttempts`, or the retry is a lie: a run\n // dead-lettered AT the cap comes back `pending`, the very next `recoverIncomplete` pass computes\n // `maxRecoveryAttempts + 1` and kills it again within seconds — accepted retry, zero progress,\n // same generic `max_recovery_attempts` error (observed in the wild). The budget bounds ONE\n // crash-loop episode; an operator asking to resurrect a run that already came to rest is starting\n // a new one. This is the run-level half of the same \"reset the failure state\" the checkpoint loop\n // above does — the docstring promised it, the code only did the per-step part.\n //\n // ZERO, not `undefined`: the stores disagree on what an undefined patch value means. `toRunEntity`\n // skips it (`if (run.recoveryAttempts !== undefined)`) and the TypeORM adapter passes it straight\n // into `.set()`, so on both of those `undefined` would silently leave the old count in place. `0`\n // writes a real column value everywhere, and reads back identically — `countRecovery` does\n // `(run.recoveryAttempts ?? 0) + 1`.\n //\n // Gated on `resurrecting` on purpose: requeueing a run that is still `running`/`suspended` is not\n // a resurrection, and zeroing there would let a crash-looping run be kept alive forever by a\n // retry loop — the poison-pill guarantee has to survive this fix.\n await this.store.updateRun(runId, {\n status: 'pending',\n error: undefined,\n ...(resurrecting\n ? {\n recoveryAttempts: 0,\n tags: run.tags?.filter((tag) => tag !== SINGLETON_ADMITTED_TAG),\n }\n : {}),\n updatedAt: new Date(),\n });\n await this.runDispatcher.dispatch(runId);\n return { runId, status: 'pending' };\n }\n\n /**\n * Explicitly re-dispatch every remote step of `runId` stuck `pending` — the OPERATOR escape hatch for\n * a run whose dispatched step job was LOST (worker crashed with no result, or a transport that dropped\n * the job). No automatic recovery re-drives these: a reconcile re-drive re-suspends a still-pending\n * step by design (unless `remoteRedispatchMs` is set), `recoverIncomplete` explicitly SKIPS a run with\n * an in-flight `pending` remote step (it re-asserts the durably-suspended invariant instead of counting\n * a recovery attempt — see there), and `requeue` just replays back to the pending guard. This\n * re-enqueues the same `stepId` so the (idempotent) step re-runs and its result resumes the run.\n * Safe to call on a healthy run — it re-runs\n * only in-flight `pending` remote steps, which are idempotent by the durable contract. Returns the\n * run's current status (with the count re-dispatched), or null if the run is unknown.\n */\n async redispatchPending(runId: string): Promise<(RunResult & { redispatched: number }) | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n const pending = (await this.store.listCheckpoints(runId)).filter(\n (cp) => cp.kind === 'remote' && cp.status === 'pending',\n );\n let redispatched = 0;\n for (const cp of pending) {\n if (!cp.stepId) continue;\n const reAttempt = cp.attempts + 1;\n const reEnqueuedAt = new Date();\n await this.store.saveCheckpoint({\n ...cp,\n attempts: reAttempt,\n enqueuedAt: reEnqueuedAt,\n startedAt: reEnqueuedAt,\n finishedAt: reEnqueuedAt,\n });\n await this.dispatchRemoteTask({\n runId,\n seq: cp.seq,\n name: cp.name,\n stepId: cp.stepId,\n group: cp.workerGroup ?? sanitizeQueueToken(cp.name),\n input: cp.input,\n attempt: reAttempt,\n });\n redispatched += 1;\n }\n return { runId, status: run.status, redispatched };\n }\n\n /**\n * **Fix-and-replay**: re-run a run (typically a `dead`/`failed` one) with a corrected `input`, as a\n * fresh run with clean history. It's a NEW run — `newRunId` defaults to `<runId>~retry~<uuid>` — so\n * the original stays inspectable. Returns the new run's id, or null if `runId` is unknown.\n */\n async retryWithInput(\n runId: string,\n input: unknown,\n newRunId?: string,\n ): Promise<{ runId: string } | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n const id = newRunId ?? `${runId}~retry~${globalThis.crypto.randomUUID().slice(0, 8)}`;\n // Inherit the original run's namespace so a retry of a tenant's run stays that tenant's — on an\n // operator (this.namespace === undefined) an unstamped retry would fall to 'default' and route to\n // the bare worker group, orphaning it if only the tenant-suffixed worker is live.\n await this.start(run.workflow, input, id, { tags: run.tags, namespace: run.namespace });\n return { runId: id };\n }\n\n /**\n * Pick up and execute every `pending` run — the poll-based side of dispatch for a worker pod with\n * no broker. Runs enqueued by other pods (or by a caller using a no-op dispatcher) sit `pending`\n * in the store until polled; leasing ensures exactly one pod runs each. Call periodically alongside\n * {@link resumeDueTimers}.\n */\n async runPending(nowMs: number = this.clock()): Promise<RunResult[]> {\n // Oldest-first (FIFO), capped per call so a backlog drains over several polls without one sweep\n // fetching unboundedly. A run not picked up this tick is picked up the next.\n return this.resumeLeased(await this.store.listPendingRuns(100, this.namespace), nowMs);\n }\n\n /**\n * Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or\n * suspended (handed off to a timer/signal/event). The async counterpart to dispatch: pair it with\n * `start` when a call site needs the outcome — `await start(...); const r = await waitForRun(id)`.\n */\n waitForRun(\n runId: string,\n opts?: { timeoutMs?: number; until?: 'settled' | 'terminal' },\n ): Promise<RunResult> {\n // `cancelling` is NON-terminal (the saga undo is still running), so a `waitForRun` after a\n // compensating cancel keeps waiting until the run reaches the terminal `cancelled`.\n //\n // A run in the DISPATCH-AND-SUSPEND liveness state — `suspended` while still awaiting a dispatched\n // workflow TURN's decision (`awaitingDecisionTaskId` set) — is mid-turn, NOT settled: that\n // `suspended` is the engine's re-drive marker, not a body-emitted sleep/signal suspend. Resolving on\n // it would hand back a half-applied turn (e.g. a sleep whose `wakeAt` the decision hasn't written\n // yet). Wait until the decision lands and clears the marker (a real suspend) or the run goes terminal.\n //\n // `until: 'terminal'` skips settling on a real suspend too — it resolves only on\n // completed/failed/cancelled/dead (the wait behind `MyWorkflow.execute()` outside a workflow).\n const TERMINAL: ReadonlySet<string> = new Set(['completed', 'failed', 'cancelled', 'dead']);\n const isSettled = (run: WorkflowRun): boolean =>\n opts?.until === 'terminal'\n ? TERMINAL.has(run.status)\n : run.status !== 'pending' &&\n run.status !== 'running' &&\n run.status !== 'cancelling' &&\n !(run.status === 'suspended' && run.awaitingDecisionTaskId !== undefined);\n const toResult = (run: WorkflowRun): RunResult => ({\n runId,\n status: run.status,\n output: run.output,\n error: run.error,\n });\n return new Promise<RunResult>((resolve, reject) => {\n let done = false;\n let off: () => void = () => {};\n const timer =\n opts?.timeoutMs != null\n ? setTimeout(() => {\n if (done) return;\n done = true;\n if (poller) clearInterval(poller);\n off();\n reject(new Error(`waitForRun(${runId}) timed out after ${opts.timeoutMs}ms`));\n }, opts.timeoutMs)\n : undefined;\n const finish = (run: WorkflowRun): void => {\n if (done) return;\n done = true;\n if (timer) clearTimeout(timer);\n if (poller) clearInterval(poller);\n off();\n resolve(toResult(run));\n };\n const fail = (error: unknown): void => {\n if (done) return;\n done = true;\n if (timer) clearTimeout(timer);\n if (poller) clearInterval(poller);\n off();\n reject(error);\n };\n const check = (): void => {\n if (done) return;\n void this.store.getRun(runId).then((run) => {\n if (run && isSettled(run)) finish(run);\n }, fail);\n };\n // Terminal mode also polls: cancelled/dead transitions have no `run.*` lifecycle event to\n // react to (and a resume may happen on ANOTHER instance), so events alone can miss them.\n const poller =\n opts?.until === 'terminal'\n ? (() => {\n const interval = setInterval(check, 250);\n interval.unref?.();\n return interval;\n })()\n : undefined;\n // React only to this run's settling events (not its every step event), and subscribe BEFORE the\n // initial read so a run that settles in between isn't missed.\n off = this.subscribe((ev) => {\n if (\n ev.runId === runId &&\n (ev.type === 'run.completed' || ev.type === 'run.failed' || ev.type === 'run.suspended')\n ) {\n check();\n }\n });\n check();\n });\n }\n\n /**\n * Resume each run only if this instance can acquire its recovery lease — so when several\n * replicas recover or poll at once, each run is picked up by exactly one of them.\n *\n * A run this instance cannot resume is SKIPPED, not allowed to abort the batch. The canonical\n * case is skew protection: mid-rolling-deploy a pod leases a run whose workflow it does not have\n * and `resume` throws by design — but the rest of the batch is runs it can drive perfectly well,\n * and every caller here is a recovery sweep. Letting the first such run end the loop means one\n * row stops recovery for the whole deployment, and (since the callers are pollers) sends the\n * rejection into a lifecycle hook. Skipping leaves the run locked only until its lease expires,\n * for a pod that does have the workflow — which is exactly what the skew-protection error asks\n * for. Same posture as `publishEvent`'s per-subscriber isolation.\n */\n private async resumeLeased(\n runs: WorkflowRun[],\n nowMs: number = this.clock(),\n onLocked?: (run: WorkflowRun) => Promise<RunResult | undefined>,\n ): Promise<RunResult[]> {\n if (this.draining) return []; // shutting down — don't pick up new runs\n const results: RunResult[] = [];\n for (const run of runs) {\n if (this.draining) break; // drain began mid-batch: lock and start nothing more\n const acquired = await this.store.tryLockRun(\n run.id,\n this.instanceId,\n nowMs + this.leaseMs,\n nowMs,\n );\n if (!acquired) continue;\n if (this.draining) {\n // Drain began while the lock was being taken. Starting the run now would hand `drain()` (which\n // already snapshotted its in-flight set) something it will not wait for, and an exit would\n // strand the lease until it expires. Give the lease back; the run stays for the next instance.\n await this.store.releaseRunLock(run.id);\n break;\n }\n try {\n // A per-run hook (recovery counting / dead-lettering) may settle the run terminally instead.\n const settled = onLocked ? await onLocked(run) : undefined;\n results.push(settled ?? (await this.resumeImplicit(run.id)));\n } catch (error) {\n // Loud, because a skip is not nothing: the run is still there and still not progressing, and\n // the reason (a version skew, a store that just went away) is the only thing that tells an\n // operator which of those it is.\n console.error(\n `[nestjs-durable] could not resume run ${run.id} (${run.workflow}@${run.workflowVersion}); leaving it for another instance:`,\n error,\n );\n }\n }\n return results;\n }\n\n /**\n * Deliver an external signal to the run waiting on `token` and resume it with `payload`.\n * Returns the run result, or null if no run is waiting for that token.\n */\n /**\n * Publish a named event. It does two things, and returns how many runs it touched (the sum):\n * 1. **Resumes** every in-flight run waiting on it via `ctx.waitForEvent(name, { match })` whose\n * match the payload satisfies (fan-out, vs `signal`'s point-to-point token).\n * 2. **Starts** a fresh run of every workflow registered with `onEvent: [name]`, passing the\n * payload as input. Idempotent by `evt:<id>:<workflow>` — pass `opts.id` to dedupe redeliveries\n * of the same logical event (default: a fresh uuid, so each publish triggers once).\n *\n * Semantics (deliberate — mirrors `signalWithStart`'s reliability contract, so document it exactly):\n * a publish that resumes ≥1 live waiter, OR routes into an `eventBatch` accumulator / starts ≥1\n * subscriber, behaves exactly as above and is NOT buffered — fan-out stays live-only, same as\n * today. A publish that touches NEITHER — no live waiter matched, no subscriber exists/started —\n * buffers ONE copy (via {@link StateStore.bufferEvent}) unless `opts.buffer === false`, so it isn't\n * silently dropped just because nobody happened to be listening yet. That buffered copy is consumed\n * by the FIRST future `ctx.waitForEvent(name, { match })` whose match accepts its payload —\n * point-to-point on redelivery, by design (only one waiter ever gets it, even though the LIVE path\n * above is fan-out) — never by a second, later-registered onEvent subscriber (subscriber starts stay\n * live-only; `opts.id` dedupe applies to those only, unchanged). Right after buffering, this re-checks\n * `listSignalWaiters` ONCE — sandwich parity with `signal`'s own take → buffer → re-check — so a\n * waiter that registers in the sliver between the initial miss and the buffer write is still paired\n * instead of leaving both rows stranded (see `signal`'s interleaving proof; `waitForEvent`'s own\n * post-registration buffer scan is the mirror-image half of this same race).\n */\n async publishEvent(\n name: string,\n payload: unknown,\n opts?: { id?: string; buffer?: boolean },\n ): Promise<number> {\n let touched = 0;\n const waiters = await this.store.listSignalWaiters(eventPrefix(name));\n for (const w of waiters) {\n if (eventMatches(payload, eventMatchOf(w.token))) {\n await this.signal(w.token, payload);\n touched += 1;\n }\n }\n const subscribers = this.eventTriggers.get(name);\n if (subscribers?.size) {\n const eventId = opts?.id ?? globalThis.crypto.randomUUID();\n for (const workflow of subscribers) {\n // A subscriber that rejects the payload (validateInput) must not block the others or the\n // waiters — its run simply never starts, mirroring fire-and-forget dead-letter routing.\n try {\n const batch = this.latest.get(workflow)?.eventBatch;\n if (batch) {\n // Coalesce: route the event into a per-workflow accumulator (one long-lived run that\n // debounces/batches and then starts the target with the collected payload(s)).\n await this.accumulators.route(workflow, batch, payload);\n } else {\n await this.start(workflow, payload, `evt:${eventId}:${workflow}`);\n }\n touched += 1;\n } catch {\n // skip this subscriber\n }\n }\n }\n // Nobody received it live (no waiter matched, no subscriber exists/started) — buffer ONE copy\n // unless the caller opted out. `touched > 0` covers BOTH the waiter fan-out and the subscriber\n // loop above, matching the \"no one received it\" condition the semantics doc promises.\n if (touched > 0 || opts?.buffer === false) return touched;\n const bufferedId = globalThis.crypto.randomUUID();\n await this.store.bufferEvent({ name, payload, id: bufferedId, publishedAt: this.clock() });\n // Re-check: a waiter may have registered in the window between the miss above and this buffer\n // write (see the interleaving proof at `signal` — this is the events-side mirror of it). Only the\n // FIRST late-registered matching waiter is considered: only one buffered copy exists, so once a\n // claim attempt below either succeeds or finds the buffer already gone, there is nothing left for\n // any other candidate regardless.\n const lateWaiters = await this.store.listSignalWaiters(eventPrefix(name));\n const lateWaiter = lateWaiters.find((w) => eventMatches(payload, eventMatchOf(w.token)));\n if (!lateWaiter) return touched;\n if (!(await this.store.removeBufferedEvent(bufferedId))) return touched; // claimed elsewhere already\n // `takeSignalWaiter` is safe here even though it deletes ANY row for the token: an event token\n // embeds this ONE `waitForEvent` call's own `runId#seq` (see eventToken in events.ts), so no other\n // registration could ever share it.\n const waiter = await this.store.takeSignalWaiter(lateWaiter.token);\n if (waiter) {\n const settled = await this.deliverSignal(waiter, payload);\n if (settled) touched += 1;\n }\n // If `waiter` is null, that exact registration resolved itself some other way in the interim (most\n // likely its own timeout deadline landing in this same sliver) — the buffered copy is already\n // spent (claimed above), so — mirroring `signal`'s own reclaim precedent — drop it rather than\n // resuming a run a second time or re-buffering for a THIRD, unrelated waiter to pick up later.\n return touched;\n }\n\n /**\n * Deliver a signal to an already-known waiter: write its resolving `signal:<token>` checkpoint and\n * resume the run. Shared by {@link signal}'s direct hit, its post-buffer re-check reclaim, and the\n * due-timer reconcile sweep ({@link reconcileSignalWaiter}) — all three resolve a waiter the exact\n * same way.\n */\n private async deliverSignal(waiter: SignalWaiter, payload: unknown): Promise<RunResult | null> {\n await this.store.saveCheckpoint(\n instantCheckpoint({\n runId: waiter.runId,\n seq: waiter.seq,\n name: `signal:${waiter.token}`,\n kind: 'signal',\n output: payload,\n // Carry the awaiting command's fan group (set when a `ctx.gather_children`/`ctx.all` fan-out\n // registered this waiter) onto the resolving `signal:child:<id>` checkpoint, so the dashboard\n // groups the child fan-out vertically instead of rendering it as a sequential chain. Undefined\n // for an ordinary (non-fan) signal/child await.\n parallelGroup: waiter.parallelGroup,\n }),\n );\n if (await this.fanStillWaiting(waiter, payload)) {\n return { runId: waiter.runId, status: 'suspended' };\n }\n return this.resumeImplicit(waiter.runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * The `ctx.all` join barrier: true when `waiter` was one child of a fan (or of one wave of it)\n * whose siblings are still out, so waking the parent now would only replay the fan and re-suspend.\n * Skipping that wake is what keeps a fan of N children at O(N) work instead of N replays of N items.\n *\n * Safe because the LAST sibling to settle always wakes the parent: each child consumes its own\n * waiter before it asks, so whichever asks last sees none left. A failed child of a failFast fan\n * always wakes it. Anything that is not a `ctx.all` waiter, or a store that cannot answer the\n * question cheaply, wakes the parent as before.\n */\n private async fanStillWaiting(waiter: SignalWaiter, payload: unknown): Promise<boolean> {\n if (!this.store.hasSignalWaiter) return false;\n const fan = fanOfWaiter(waiter);\n if (!fan) return false;\n if (fan.failFast && isFailedCompletion(payload)) return false;\n return this.store.hasSignalWaiter(waiter.runId, fan.waiterPrefix);\n }\n\n /**\n * Re-drive a run that just suspended on awaited children (a `ctx.all` fan or wave, a `ctx.child`)\n * which, by now, have settled.\n *\n * {@link execute} drops a wake that finds the run's lease held. So if a child settles while the\n * parent is still executing (the turn that dispatched it, or one woken by an earlier child), that\n * wake is spent, and the turn suspends on a snapshot that predates the child. With the `ctx.all`\n * barrier that wake was the only one the fan would get. Nothing would wake the run until the\n * `reconcileMs` sweep, minutes later.\n *\n * Called after the turn released its lease, so any child that settles from here on wakes the run\n * itself. Only re-drives for a group with no waiter left whose checkpoints are all settled, which\n * the next turn is then guaranteed to see — so it cannot loop.\n */\n private async redriveSettledChildren(runId: string, fan: FanJoin): Promise<void> {\n if (!this.store.hasSignalWaiter) return;\n for (const wait of fan.waits) {\n if (await this.store.hasSignalWaiter(runId, wait.waiterPrefix)) continue;\n const checkpoints = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(runId, [wait.checkpointPrefix])\n : (await this.store.listCheckpoints(runId)).filter((cp) =>\n cp.name.startsWith(wait.checkpointPrefix),\n );\n if (checkpoints.length > 0 && checkpoints.every((cp) => cp.status === 'completed')) {\n await this.resumeImplicit(runId);\n return;\n }\n }\n }\n\n /**\n * Deliver an external signal to the run waiting on `token`, resume it with `payload`, and return\n * the run result — or null if no run is (or ends up) waiting for it.\n *\n * Race with the waiter side (`waitForSignal`'s check → `putSignalWaiter` → re-check, same shape in\n * the remote `waitSignal` command): a waiter can register in the sliver between this method's\n * initial `takeSignalWaiter` miss and its `bufferSignal` write, and the naive old flow (buffer and\n * return) would then leave BOTH a buffered payload and a registered waiter sitting in the store with\n * nothing left to pair them — a lost wake, forever suspended.\n *\n * The interleaving proof: the waiter side does check → put → re-check, this side does take → buffer\n * → re-check. Whichever side's SECOND look runs last is guaranteed to observe the other side's\n * write, because it always follows that write in real time:\n * - If the waiter's `put` lands before this method's first `take`, the take just finds it directly\n * (the pre-existing, non-racy path).\n * - If the waiter's `put` lands after this method's `bufferSignal`, our re-check below either sees\n * it (if `put` also lands before the re-check) or the waiter's OWN post-put re-check sees our\n * buffer (if `put` lands after our re-check but the waiter hasn't re-checked yet either — its\n * re-check strictly follows its own put).\n * - If the waiter's `put` lands between this method's `take` and its re-`take`, the re-check below\n * catches it.\n * Either way, the destructive `take*` ops (on the waiter row, on the buffer) arbitrate: whichever\n * side actually removes the row is the one that delivers, so a signal is never delivered twice.\n */\n async signal(token: string, payload: unknown): Promise<RunResult | null> {\n const waiter = await this.store.takeSignalWaiter(token);\n if (waiter) return this.deliverSignal(waiter, payload);\n // No one was waiting yet — buffer it so the next `waitForSignal(token)` consumes it instead of\n // dropping it (reliable signals; the basis of `signalWithStart`).\n await this.store.bufferSignal(token, payload);\n // Re-check: a waiter may have registered in the window between the miss above and this buffer\n // write (see the interleaving proof above).\n const lateWaiter = await this.store.takeSignalWaiter(token);\n if (!lateWaiter) return null;\n const reclaimed = await this.store.takeBufferedSignal(token);\n if (!reclaimed) {\n // The waiter side won the race to consume the buffer itself (its own checkpoint+resume already\n // delivered the payload) in the sliver between our takeSignalWaiter and takeBufferedSignal just\n // above. We've already (destructively) taken `lateWaiter` off the store, but there is nothing\n // left to deliver — drop it deliberately rather than resuming the run a second time.\n return null;\n }\n return this.deliverSignal(lateWaiter, reclaimed.payload);\n }\n\n /**\n * Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to\n * signal buffering: if the run is new (or busy / not yet waiting), the signal is buffered and\n * consumed when it reaches `waitForSignal(token)`. The canonical **durable-entity / accumulator**\n * pattern: one long-lived run per key (the `runId`) that loops on `waitForSignal`, fed events by\n * many `signalWithStart` calls. `start` is idempotent by `runId`, so concurrent callers converge on\n * one run. (Use a per-run `token`, e.g. derived from `runId`, so the signal targets this entity.)\n */\n async signalWithStart(\n workflow: WorkflowRef,\n input: unknown,\n runId: string,\n signal: { token: string; payload?: unknown },\n opts?: StartOptions,\n ): Promise<{ runId: string }> {\n // `start` is overloaded per ref kind (class | string); a `WorkflowRef` union fits neither\n // overload, so resolve to the string overload (the engine handles both at runtime).\n await this.start(workflow as string, input, runId, opts); // idempotent: no-op if run exists\n await this.signal(signal.token, signal.payload);\n return { runId };\n }\n\n /**\n * Report the result of a `ctx.task(name, …)` back to its run (async completion). The external\n * worker that the task dispatched to calls this when done; the run resumes with `result`. Returns\n * null if no run is waiting on the task (e.g. a duplicate/late delivery) — a safe no-op.\n */\n async completeTask(runId: string, name: string, result: unknown): Promise<RunResult | null> {\n return this.signal(`task:${runId}:${name}`, {\n ok: true,\n value: result,\n } satisfies Completion<unknown>);\n }\n\n /** Report that a `ctx.task` failed — the run resumes and throws a FatalError at the task. */\n async failTask(runId: string, name: string, error: string): Promise<RunResult | null> {\n return this.signal(`task:${runId}:${name}`, { ok: false, error } satisfies Completion<never>);\n }\n\n /**\n * Notify a parent that's waiting on `runId` as a child of its terminal outcome (the `ctx.child`\n * rendezvous). A no-op when no parent is waiting, so `execute()` can call it on every run without\n * knowing about the child feature.\n */\n private notifyParent(runId: string, completion: Completion<unknown>): void {\n void this.signal(`child:${runId}`, completion).catch(() => undefined);\n // A fix-and-replay run (`<origin>~retry~<hash>`) is standalone, but its SUCCESS is the\n // origin's outcome for all practical purposes: deliver it on the ORIGIN's token too, so a\n // parent that failed on that child and is retried later consumes this success (buffered or\n // live) instead of waiting on a child nobody re-runs. Failures stay retry-only — a failed\n // fix attempt must not poison the origin's token.\n const at = runId.lastIndexOf('~retry~');\n if (at !== -1 && completion.ok) {\n void this.signal(`child:${runId.slice(0, at)}`, completion).catch(() => undefined);\n }\n }\n\n /**\n * Deferred child start shared by the in-process ctx host and the remote `startChild` command.\n * Deferred (microtask) so a fast child can't reentrantly resume a still-suspending parent. A start\n * that THROWS (unregistered/unroutable workflow, input validation, singleton back-pressure, store\n * failure) must NOT be swallowed: the parent is already suspended on `child:<childId>` (the waiter\n * is put BEFORE start on every path), so a silent drop parks it in suspended-forever, invisibly\n * re-attempting on every recovery wake — a misconfigured remote child looks exactly like a healthy\n * long wait. Instead the failure is delivered to that waiter like a failed child (notifyParent):\n * the parent resumes and fails loudly with the cause. For a fire-and-forget `ctx.startChild`\n * (spawn — no waiter) the completion is buffered; a later join by the same id consumes it and\n * correctly observes the failed start.\n */\n private startChildDeferred(\n workflow: string,\n input: unknown,\n childId: string,\n opts?: StartOptions,\n ): void {\n queueMicrotask(\n () =>\n void this.start(workflow, input, childId, opts).catch((err) => {\n const message = err instanceof Error ? err.message : String(err);\n this.notifyParent(childId, {\n ok: false,\n error: `child workflow \"${workflow}\" failed to start: ${message}`,\n });\n }),\n );\n }\n\n /**\n * Cancel a run (e.g. from the dashboard). Returns null if the run does not exist. Pass\n * `{ compensate: true }` to undo the saga first: the suspended run is resumed so its completed\n * steps' compensations run in reverse (visible as `compensate:<step>` events), then it's marked\n * cancelled. Without it, cancellation is immediate (no undo).\n */\n async cancel(runId: string, opts?: { compensate?: boolean }): Promise<RunResult | null> {\n const run = await this.store.getRun(runId);\n if (!run) return null;\n // Terminal runs are IMMUTABLE: cancelling one is a no-op that echoes its current state. That\n // covers EVERY terminal status — `failed` included (a timed-out run is persisted `cancelled`).\n // It must never rewrite the run (a `failed` run silently becoming `cancelled` loses its real\n // outcome) and must never reach the child cascade below: a finished parent's children can be\n // live, unrelated work — e.g. the next queued chat turn an agent queue already started as a\n // child of the turn that just failed. This also stops the cascade from looping.\n if (TERMINAL_RUN_STATUSES.includes(run.status)) {\n return { runId, status: run.status, output: run.output, error: run.error };\n }\n // Already compensating (status persisted as `cancelling`): idempotent — don't re-queue the resume,\n // and crucially don't fall through to the instant-cancel path below (which would mark `cancelled`\n // and SKIP the in-flight saga undo). A repeat cancel just echoes the in-progress status.\n if (run.status === 'cancelling') {\n return { runId, status: 'cancelling' };\n }\n // Compensating cancel: resume the run with a cancellation pending — replay re-registers the saga,\n // and at the suspension point execute() runs the undo and marks it cancelled. Run that resume in\n // the BACKGROUND so the caller (e.g. an HTTP request) never blocks on replaying the workflow +\n // compensations. `execute` holds the run's lease, so this can't double-run one a live worker owns\n // (its lease acquire fails and it no-ops); the broadcast tells that worker to abort cooperatively.\n if (opts?.compensate && (run.status === 'suspended' || run.status === 'running')) {\n this.cancelRequested.add(runId);\n // Persist `cancelling` so the dashboard/API show \"compensation in progress\" instead of a\n // misleading `running`/`suspended` while the background undo runs. NON-TERMINAL: the admission\n // gate still counts it and recovery re-drives it on crash (runExecution re-derives the cancel\n // intent from this status), so the cancel is durable; it flips to `cancelled` when the resumed\n // replay finishes compensating.\n await this.store.updateRun(runId, { status: 'cancelling', updatedAt: new Date() });\n run.status = 'cancelling';\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n queueMicrotask(() => {\n void this.resumeImplicit(runId)\n .then(() => this.notifyCancelled(runId))\n .catch(() => undefined);\n });\n await this.cancelChildren(runId, opts);\n return { runId, status: 'cancelling' };\n }\n const error = { message: 'cancelled' };\n await this.store.updateRun(runId, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n await this.cancelChildren(runId, opts);\n // Notify local cancel listeners now (a worker on this pod), and broadcast so the instance/worker\n // actually running this run learns of it and can abort cooperatively (the store already records\n // `cancelled`, but a busy worker won't re-read it).\n this.notifyCancelled(runId);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId, from: this.instanceId })\n .catch(() => undefined);\n }\n // A cancelled singleton run frees its slot — wake the next gated waiter now (notify-on-release).\n void this.singletons.wakeNext(run).catch(() => undefined);\n return { runId, status: 'cancelled', error };\n }\n\n /**\n * Bulk-cancel every run matching a filter — e.g. cancel all `order` runs tagged `vip`, or every run\n * whose `tier` search attribute is `free`. The filter is a {@link RunQuery} (workflow / status / tag\n * / search-attribute predicates), so it reuses the same matching the dashboard list uses. Each match\n * is run through {@link cancel}, so the same plumbing applies per run: child cascade, the optional\n * saga `compensate`, local cancel listeners, and the control-plane broadcast that tells the owning\n * worker to abort. Returns one {@link RunResult} per matched run (already-finished matches report\n * their terminal status — `cancel` is a no-op on them, never clobbering a completed/dead run).\n */\n async cancelWhere(\n filter: Omit<RunQuery, 'limit' | 'offset'>,\n opts?: { compensate?: boolean },\n ): Promise<RunResult[]> {\n const runs = await this.store.listRuns(filter);\n const results: RunResult[] = [];\n for (const run of runs) {\n const r = await this.cancel(run.id, opts);\n if (r) results.push(r);\n }\n return results;\n }\n\n /**\n * Hard-delete a run and its entire subtree. Unlike {@link cancel} (which marks a run `cancelled`\n * but keeps it as history), delete REMOVES the run and all its rows (checkpoints, signal waiters,\n * search-attribute rows) — it vanishes from {@link getRun} and {@link listRuns}. Use it to purge a\n * finished run whose data is being deleted (e.g. a pipeline run whose result rows are cleared).\n *\n * Cascades depth-first via {@link getRunChildren} so children are gone before the parent (no\n * orphaned child runs). Prefer {@link cancel} first for a live run — deleting one mid-flight orphans\n * its worker (its next checkpoint write fails). Returns the number of runs deleted (0 if absent).\n */\n async deleteRun(runId: string): Promise<number> {\n const run = await this.store.getRun(runId);\n if (!run) return 0;\n // Collect children BEFORE deleting this run's checkpoints (getRunChildren reads them).\n let deleted = 0;\n for (const childId of await this.getRunChildren(runId)) {\n deleted += await this.deleteRun(childId);\n }\n await this.store.deleteRun(runId);\n return deleted + 1;\n }\n\n /**\n * Hard-delete EVERY run matching `scope` — plus, by default, each one's whole child subtree — in\n * bounded batches. The \"forget this tenant\" / \"drop this feature's history\" operation: where\n * {@link deleteRun} removes one tree you already know the id of, this drains everything a scope\n * selects (`{ namespace: 'acme' }`, `{ tag: 'tenant:acme' }`, `{ workflows: [...] }`, attribute\n * predicates …) through the store API, so no caller has to reach into the `durable_*` tables.\n *\n * - **Live runs** (not yet terminal) are {@link cancel cancelled} first (plain cancel, no saga\n * undo), which tells any worker holding one to stop, and then deleted with the rest. Pass\n * `cancelLive: false` to leave live runs (and live descendants of finished ones) alone and\n * delete terminal history only.\n * - **Children** are found through the same parent→child edges as {@link getRunChildren} and deleted\n * with their root even when they don't match `scope` themselves (children inherit `namespace`,\n * but not `tags`). `children: false` deletes exactly the matching runs.\n * - **Batched**: `batchSize` runs (default 500) per round, each round one bulk\n * {@link StateStore.deleteRuns} (falling back to per-run {@link StateStore.deleteRun}).\n *\n * An EMPTY scope is rejected — it would delete every run in the store. Returns how many runs were\n * deleted (children included).\n */\n async purgeRuns(\n scope: RunScope,\n opts?: { batchSize?: number; cancelLive?: boolean; children?: boolean },\n ): Promise<number> {\n if (!isNonEmptyRunScope(scope)) {\n throw new Error(\n 'purgeRuns: refusing an empty scope (it would delete every run) — pass at least one predicate, e.g. { namespace }',\n );\n }\n const batchSize = Math.max(1, opts?.batchSize ?? 500);\n const cancelLive = opts?.cancelLive ?? true;\n const withChildren = opts?.children ?? true;\n const statuses = cancelLive ? undefined : [...TERMINAL_RUN_STATUSES];\n let deleted = 0;\n let previous = '';\n for (;;) {\n const batch = await this.store.listRuns({ ...scope, statuses, limit: batchSize });\n if (batch.length === 0) break;\n const fingerprint = batch.map((r) => r.id).join('\\u0000');\n // Every listed run is deleted below, so the next page is new rows — the same page twice means\n // the store is not deleting (a broken adapter); stop instead of spinning forever.\n if (fingerprint === previous) {\n throw new Error('purgeRuns: the store returned the same runs after deleting them');\n }\n previous = fingerprint;\n const known = new Map(batch.map((r) => [r.id, r.status] as const));\n const ids = withChildren\n ? await this.collectSubtrees(batch.map((r) => r.id))\n : batch.map((r) => r.id);\n const doomed: string[] = [];\n for (const id of ids) {\n const status = known.has(id) ? known.get(id) : (await this.store.getRun(id))?.status;\n if (status === undefined) continue; // already gone\n if (!TERMINAL_RUN_STATUSES.includes(status)) {\n // A live descendant of a finished root: cancel it with the tree, or leave it be.\n if (!cancelLive) continue;\n await this.cancel(id).catch(() => undefined);\n }\n doomed.push(id);\n }\n await this.deleteRunIds(doomed);\n deleted += doomed.length;\n if (batch.length < batchSize) break;\n }\n return deleted;\n }\n\n /**\n * {@link purgeRuns} for one namespace — every run (and child) a tenant/partition owns. Children\n * inherit their parent's namespace, so a namespace purge is complete by construction.\n */\n purgeNamespace(\n namespace: string,\n opts?: { batchSize?: number; cancelLive?: boolean },\n ): Promise<number> {\n return this.purgeRuns({ namespace }, opts);\n }\n\n /** The given runs plus every descendant, children before parents. One waiter scan for the batch. */\n private async collectSubtrees(rootIds: string[]): Promise<string[]> {\n const prefixes = CHILD_EDGE_PREFIXES;\n const childrenOf = async (parent: string): Promise<string[]> => {\n const ids = new Set(await this.awaitedChildIds(parent));\n const cps = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(parent, prefixes)\n : (await this.store.listCheckpoints(parent)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n for (const id of childIdsOf(cps)) ids.add(id);\n return [...ids];\n };\n const ordered: string[] = [];\n const seen = new Set<string>();\n const visit = async (id: string): Promise<void> => {\n if (seen.has(id)) return;\n seen.add(id);\n for (const child of await childrenOf(id)) await visit(child);\n ordered.push(id); // post-order: children first\n };\n for (const id of rootIds) await visit(id);\n return ordered;\n }\n\n /** Bulk-delete through the store's `deleteRuns`, or one `deleteRun` per id when it has none. */\n private async deleteRunIds(ids: string[]): Promise<void> {\n if (ids.length === 0) return;\n if (this.store.deleteRuns) {\n await this.store.deleteRuns(ids);\n return;\n }\n for (const id of ids) await this.store.deleteRun(id);\n }\n\n /**\n * Cascade cancellation to a run's children — both awaited (`ctx.child`, found via its live\n * `child:<id>` waiter) and fire-and-forget (`ctx.startChild`, found via its `spawn:<id>`\n * checkpoint). Recursive, so a whole subtree is cancelled; the terminal guard in `cancel` stops it\n * at finished / already-cancelled runs (no loops, no re-cancel).\n *\n * Two callers, deliberately the same walk: an explicit {@link cancel}, and {@link sweepTimeouts}\n * when a parent hits its `executionTimeout` — a timed-out parent's subtree dies the same way an\n * explicitly cancelled one's does, or the children are orphans nobody is holding a reference to.\n */\n private async cancelChildren(\n parentRunId: string,\n opts?: { compensate?: boolean },\n ): Promise<void> {\n for (const id of await this.getRunChildren(parentRunId)) {\n await this.cancel(id, opts).catch(() => undefined);\n }\n }\n\n /**\n * The ids of the runs a run spawned — both awaited (`ctx.child`) and fire-and-forget\n * (`ctx.startChild`, found via its `spawn:<id>` checkpoint). The canonical parent→children edge,\n * used for both cancellation cascades and the dashboard run-tree.\n *\n * An awaited child is discovered two ways, because the live `child:<id>` waiter only exists WHILE\n * the parent is suspended on it: the waiter resolves and is consumed the moment the child settles,\n * so a completed parent (or a completed awaited child) would otherwise drop out of the tree. The\n * `signal:child:<id>` checkpoint (the placeholder written when the parent first awaits the child,\n * overwritten as completed/failed when it settles) persists across completion, so we read both and\n * dedupe — the edge stays stable for a finished run, not just a live one. A settled `ctx.all`\n * group folded into one `fan:` checkpoint stands for every child in it.\n */\n /** The children `parentRunId` is awaiting right now, read off its own live `child:` waiters. */\n private async awaitedChildIds(parentRunId: string): Promise<string[]> {\n return (await listSignalWaitersOfRuns(this.store, [parentRunId]))\n .filter((w) => w.token.startsWith('child:'))\n .map((w) => w.token.slice('child:'.length));\n }\n\n async getRunChildren(parentRunId: string): Promise<string[]> {\n const childIds = new Set(await this.awaitedChildIds(parentRunId));\n // Targeted read: only the child-edge checkpoints, not the whole history. Falls\n // back to a full listCheckpoints + in-JS prefix scan for a custom store that omits the method.\n const prefixes = CHILD_EDGE_PREFIXES;\n const childCheckpoints = this.store.listCheckpointsByNamePrefix\n ? await this.store.listCheckpointsByNamePrefix(parentRunId, prefixes)\n : (await this.store.listCheckpoints(parentRunId)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n for (const id of childIdsOf(childCheckpoints)) childIds.add(id);\n return [...childIds];\n }\n\n /** The worker groups this engine dispatches to: every registered remote workflow's group, plus any\n * `extra` the caller declares. Local-step groups (a group consumed by in-process `@DurableStep`\n * workers, e.g. `pipeline`) aren't derivable from registrations — pass them via `extra` so a group\n * with backlog and ZERO workers is still reported (the alert case has no heartbeat to discover). */\n knownGroups(extra: string[] = []): string[] {\n const groups = new Set<string>(extra);\n for (const def of this.workflows.values()) {\n if (def.remote?.group) groups.add(def.remote.group);\n }\n return [...groups];\n }\n\n /** Per-group worker health (queue backlog + live worker heartbeats). Covers {@link knownGroups}\n * (so a registered group with backlog and ZERO workers still reports — the alert case) UNION the\n * groups discovered from live heartbeats (so a local-step group like `pipeline`, not derivable\n * from registrations, shows once its workers beat). Empty when no transport can introspect health\n * (only the BullMQ transport implements `groupHealth`). */\n async workerHealth(extra: string[] = []): Promise<GroupHealth[]> {\n const groups = new Set([\n ...this.knownGroups(extra),\n ...(await this.pool.listWorkerGroups()),\n ...(await this.inflightStepGroups()),\n ]);\n // Classify each group workflow-vs-step from the registry (authoritative — no name heuristic): a\n // group whose base token is a registered workflow serves a `@Workflow` body; anything else (an\n // in-process `@Step`, a remote `handle_*` step) is a step. A LOCAL workflow's queue token is\n // `sanitizeQueueToken(name)`; a REMOTE one (e.g. Python) routes to its `remote.group`, which can\n // differ from the name — so seed the workflow-token set with BOTH.\n const workflowTokens = new Set<string>();\n for (const def of this.workflows.values()) {\n workflowTokens.add(sanitizeQueueToken(def.name));\n if (def.remote?.group) workflowTokens.add(def.remote.group);\n }\n const out: GroupHealth[] = [];\n for (const group of groups) {\n const health = await this.pool.groupHealth(group);\n if (!health) continue;\n const at = group.lastIndexOf('@');\n const baseToken = at === -1 ? group : group.slice(0, at);\n out.push({ ...health, kind: workflowTokens.has(baseToken) ? 'workflow' : 'step' });\n }\n return out;\n }\n\n /**\n * What workflows the LIVE fleet announces it can execute — the deployment-wide registry a picker\n * (\"call this existing workflow\") needs, and the one question this engine's own registry cannot\n * answer. {@link workflowBody} answers only for this process, and a missing body is ambiguous: it\n * means \"not registered here\", but equally \"registered via {@link registerRemote} against another\n * SDK\" or \"a group resolved by convention against a worker\". An inferred answer would therefore\n * differ per replica. This one does not: every pod folds the same published announcements.\n *\n * Scoped like every other poll surface — an engine WITH a `namespace` sees only workers in it, and\n * an operator (namespace unset) sees the whole deployment (\"ver tudo = ausência de namespace\"). A\n * descriptor that states no namespace is `default`, matching how a single-tenant fleet publishes.\n *\n * Cost: one advertisement scan per CALL, on demand. Nothing is added to the poll loop and nothing\n * is retained — no pod holds a table of the fleet's registrations. Empty when no transport can\n * introspect the advertisement keyspace (a pure in-process transport advertises nothing).\n *\n * Workflows only, and deliberately: see the \"steps are out of scope\" note in `handshake/announced`.\n */\n async announcedWorkflows(): Promise<AnnouncedWorkflow[]> {\n return (await this.workflowDirectory()).workflows;\n }\n\n /**\n * {@link announcedWorkflows}, plus the thing a list of workflows can never say: why it is the\n * length it is. See {@link WorkflowDirectory} for the three states an empty array used to collapse\n * into one — \"nobody asked\", \"nothing is live\", and the partition mismatch that reads exactly like\n * the second from the caller's side.\n *\n * Two live reads, both on demand and neither retained: the descriptor advertisement (what workers\n * SAY they serve) and the heartbeat keyspace (what is demonstrably consuming a queue right now).\n * The second is why a worker on an SDK too old to publish a descriptor appears here at all — it\n * beats and never describes itself, and reading only descriptors reported such a fleet as empty\n * while `resolveRemoteByConvention`, a few lines away in this same class, was routing calls to it\n * off those very keys. Two answers out of one Redis, disagreeing. Now they agree, and the entry\n * says which of the two kinds of evidence it rests on rather than flattening them together.\n */\n async workflowDirectory(): Promise<WorkflowDirectory> {\n return buildWorkflowDirectory({\n descriptors: await this.pool.readAllWorkerDescriptors(),\n heartbeats: await this.pool.readAllWorkerHeartbeats(),\n namespace: this.namespace,\n supported: this.pool.introspectsFleet,\n sanitize: sanitizeQueueToken,\n });\n }\n\n /**\n * The routing groups of every in-flight run's still-`pending` remote step — the queues where work is\n * dispatched and awaiting a worker. Folded into {@link workerHealth} so a step waiting on a group\n * that is NEITHER a registration NOR heartbeating (the exact shape of a run stuck on an offline\n * tenant pool) still reports its backlog: without this the health scan can't \"see\" that queue, and\n * the dashboard shows the run as running instead of no-worker. Only the BullMQ transport introspects\n * health, so on any other transport this is harmless (the groups just resolve to no `groupHealth`).\n *\n * Cost: one `listRuns` over the non-terminal runs plus a checkpoint read each — a diagnostic-path\n * scan, not a hot path. Scoped to `running`/`suspended`/`blocked` (a `pending` run has dispatched no\n * step yet) and deduped to distinct groups.\n */\n private async inflightStepGroups(): Promise<string[]> {\n const inflight = await this.store.listRuns({ statuses: ['running', 'suspended', 'blocked'] });\n const groups = new Set<string>();\n for (const run of inflight) {\n for (const cp of await this.store.listCheckpoints(run.id)) {\n if (cp.kind === 'remote' && cp.status === 'pending' && cp.workerGroup) {\n groups.add(cp.workerGroup);\n }\n }\n }\n return [...groups];\n }\n\n /**\n * Persist a streamed local-step lifecycle event from a remote workflow worker (see\n * {@link WorkflowStepEvent}). A Python `@workflow` runs its `ctx.step`s inline over one turn that\n * can last minutes; the worker streams each step's start/finish so the engine checkpoints it LIVE —\n * a step shows `running` the moment its body begins, then resolves to `completed`/`failed` with its\n * real wall-clock window and sub-process events — instead of every step appearing at once when the\n * turn ends. The turn's final `recordStep` command re-persists the same (runId, seq) checkpoint\n * idempotently, so this is purely additive observability and never changes the run's outcome.\n */\n private async persistStepEvent(event: WorkflowStepEvent): Promise<void> {\n const startedAt = new Date(event.startedAt);\n if (event.phase === 'running') {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n status: 'running',\n events: event.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt: startedAt, // placeholder until the step settles\n parallelGroup: event.parallelGroup,\n }),\n );\n this.emit({\n type: 'step.started',\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n });\n return;\n }\n const failed = event.phase === 'failed';\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n status: failed ? 'failed' : 'completed',\n output: failed ? undefined : event.output,\n error: failed ? event.error : undefined,\n events: event.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt: event.finishedAt != null ? new Date(event.finishedAt) : new Date(),\n parallelGroup: event.parallelGroup,\n }),\n );\n this.emit({\n type: failed ? 'step.failed' : 'step.completed',\n runId: event.runId,\n seq: event.seq,\n name: event.name,\n kind: 'local',\n output: failed ? undefined : event.output,\n error: failed ? event.error : undefined,\n });\n }\n\n /**\n * Announce a local step's body has begun and (when `trackStepStart`) checkpoint it as `running`,\n * so it's visible in flight rather than appearing only on completion. The checkpoint is a\n * placeholder overwritten by {@link completeStep}/{@link failStep}; it never short-circuits replay\n * (only `completed` does), so a crash mid-body just re-runs the step. The `step.started` event\n * fires regardless — the live SSE view sees the start even with persistence off.\n */\n private async startStep(step: StepRecord): Promise<void> {\n if (this.trackStepStart) {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'running',\n input: step.input,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: step.startedAt, // placeholder until the body settles\n }),\n );\n }\n this.emit({\n type: 'step.started',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n });\n }\n\n /** Checkpoint a finished step and announce it — the two things that must always happen together. */\n private async completeStep(step: StepRecord & { output: unknown }): Promise<void> {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'completed',\n input: step.input,\n output: step.output,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: new Date(),\n }),\n );\n this.emit({\n type: 'step.completed',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n output: step.output,\n queueMs: step.startedAt.getTime() - step.enqueuedAt.getTime(),\n durationMs: Date.now() - step.startedAt.getTime(),\n });\n }\n\n /** Checkpoint a step that failed terminally, so the failure point is visible (not just the run). */\n private async failStep(step: StepRecord & { error: StepError }): Promise<void> {\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n status: 'failed',\n input: step.input,\n error: step.error,\n events: step.events,\n attempts: step.attempts,\n workerGroup: step.workerGroup,\n enqueuedAt: step.enqueuedAt,\n startedAt: step.startedAt,\n finishedAt: new Date(),\n }),\n );\n this.emit({\n type: 'step.failed',\n runId: step.runId,\n seq: step.seq,\n name: step.name,\n kind: step.kind,\n error: step.error,\n queueMs: step.startedAt.getTime() - step.enqueuedAt.getTime(),\n durationMs: Date.now() - step.startedAt.getTime(),\n });\n }\n\n /** Admission persists the wait atomically; never overwrite a cancellation after it returns. */\n private async singletonWaitResult(run: WorkflowRun): Promise<RunResult> {\n const current = await this.store.getRun(run.id);\n await this.store.releaseRunLock(run.id);\n if (!current) throw new Error(`run ${run.id} was deleted during singleton admission`);\n if (current.status === 'suspended') {\n this.emit({\n type: 'run.suspended',\n runId: current.id,\n workflow: current.workflow,\n namespace: current.namespace,\n });\n }\n return {\n runId: current.id,\n status: current.status,\n output: current.output,\n error: current.error,\n };\n }\n\n private async execute(run: WorkflowRun, fn: WorkflowFn): Promise<RunResult> {\n // Synchronous fast path (`??` short-circuits) for registered runs — no extra await, so execution\n // timing for the common case is unchanged; only an unregistered (inherited-remote) run awaits.\n const registered =\n this.workflows.get(versionKey(run.workflow, run.workflowVersion)) ??\n (await this.findInheritedRegistration(run)) ??\n (await this.resolveRemoteByConvention(run));\n // Hold the lease for the WHOLE execution — whatever path got us here (leased sweep, a signal, a\n // remote result, a dashboard action). The leased sweeps already own it; the event-driven paths\n // don't, so acquire it here. If another instance owns it, don't double-run. While we run, renew\n // the lease periodically so a long run keeps it (a crashed worker's lease still expires and is\n // reclaimed by periodic recovery).\n const lockNow = this.clock();\n if (run.lockedBy !== this.instanceId || (run.lockedUntil ?? 0) <= lockNow) {\n if (\n !(await this.store.tryLockRun(run.id, this.instanceId, lockNow + this.leaseMs, lockNow))\n ) {\n return { runId: run.id, status: run.status };\n }\n }\n const renew = setInterval(\n () => {\n void this.store\n .renewRunLock(run.id, this.instanceId, this.clock() + this.leaseMs)\n .catch(() => undefined);\n },\n Math.max(50, Math.floor(this.leaseMs / 2)),\n );\n renew.unref?.();\n try {\n // A remote (e.g. Python) workflow is advanced by dispatching workflow tasks, not by running an\n // in-process body — but everything around it (lease, recovery, timers, the resume that lands us\n // here on a step result) is identical, so it branches here under the same lease.\n const result = registered?.remote\n ? await this.runRemoteExecution(run, registered)\n : await this.runExecution(run, fn, registered);\n // Notify-on-release: a singleton run that just reached a terminal state freed a slot — wake the\n // next gated waiter(s) now instead of waiting for the ~1s retry timer. Fire-and-forget so it\n // never blocks the settling run; the durable timer is still the cross-instance/crash fallback.\n if (\n registered?.singleton &&\n (result.status === 'completed' ||\n result.status === 'failed' ||\n result.status === 'cancelled' ||\n result.status === 'dead')\n ) {\n void this.singletons.wakeNext(run).catch(() => undefined);\n }\n return result;\n } finally {\n clearInterval(renew);\n }\n }\n\n /**\n * Advance a remote (cross-SDK) workflow one turn: hand its history to the executor (which dispatches\n * a workflow task to the worker and awaits its replay) and apply the decision. Mirrors\n * {@link runExecution}'s settle/suspend; the lease is held by {@link execute}. The result that lands\n * us back here (a remote step finished, a timer fired) goes through `resume` like any TS workflow.\n */\n /**\n * Apply a terminal/suspended transition once: persist the new run status, emit the matching\n * lifecycle event, and (on completion/failure) wake a waiting parent. Both the TS and remote\n * executors funnel their completed/failed/suspended outcomes through here so a status update can\n * never drift from its event or `notifyParent` call. Does NOT touch the run lock — each executor\n * keeps its own lease handling (the TS executor's `finally`, the remote path's caller).\n */\n private async settleRun(run: WorkflowRun, outcome: RunOutcome): Promise<RunResult> {\n const updatedAt = new Date();\n if (outcome.kind === 'completed') {\n // Clear any error from an earlier failed-then-retried attempt — a completed run is a success.\n await this.store.updateRun(run.id, {\n status: 'completed',\n output: outcome.output,\n error: undefined,\n updatedAt,\n });\n this.emit({\n type: 'run.completed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n output: outcome.output,\n });\n void this.notifyParent(run.id, { ok: true, value: outcome.output });\n return { runId: run.id, status: 'completed', output: outcome.output };\n }\n if (outcome.kind === 'failed') {\n await this.store.updateRun(run.id, { status: 'failed', error: outcome.error, updatedAt });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error: outcome.error,\n });\n void this.notifyParent(run.id, { ok: false, error: outcome.error.message });\n return { runId: run.id, status: 'failed', error: outcome.error };\n }\n if (outcome.kind === 'blocked') return this.parkBlocked(run, outcome.blocked);\n // This outcome was computed by a turn that started from a possibly-stale run snapshot. If the run\n // was cancelled WHILE that turn was still executing (e.g. `ctx.all`'s failFast cancelling a\n // sibling mid-turn — plain `cancel()` writes `cancelled` directly, without waiting for the target's\n // in-flight turn to notice), this now-stale \"suspended\" outcome must not resurrect it: re-check the\n // CURRENT persisted status right before writing and echo it instead of clobbering a real cancel.\n const latest = await this.store.getRun(run.id);\n if (latest?.status === 'cancelled') {\n return { runId: run.id, status: 'cancelled', error: latest.error };\n }\n await this.store.updateRun(run.id, {\n status: 'suspended',\n wakeAt: this.reconcileWakeAt(outcome.wakeAt),\n updatedAt,\n });\n this.emit({\n type: 'run.suspended',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n return { runId: run.id, status: 'suspended' };\n }\n\n /**\n * A wakeAt to persist on a suspend: the natural timer if the turn produced one (a `ctx.sleep`, a\n * remote-step deadline), else the {@link reconcileMs} fallback so an event-waiting run (child/signal/\n * timeout-less remote step) can't be orphaned forever if its wake is lost. `undefined` only when the\n * fallback is disabled (`reconcileMs: 0`). See {@link WorkflowEngineDeps.reconcileMs}.\n */\n private reconcileWakeAt(wakeAt: number | undefined): number | undefined {\n if (wakeAt != null) return wakeAt;\n return this.reconcileMs != null ? this.clock() + this.reconcileMs : undefined;\n }\n\n private async runRemoteExecution(\n run: WorkflowRun,\n registered: RegisteredWorkflow,\n ): Promise<RunResult> {\n // Compensating cancel in flight for a remote workflow: its steps execute in the worker, so there\n // are no TS-side compensations to replay here — finalize to cancelled. Re-broadcast so a live worker\n // mid-turn aborts cooperatively; on recovery (the broadcast was lost to a crash) this still settles\n // the run deterministically instead of resurrecting it by re-advancing.\n if (run.status === 'cancelling') {\n const error = { message: 'cancelled' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n this.notifyCancelled(run.id);\n if (this.controlPlane) {\n void this.controlPlane\n .publishControl({ kind: 'cancel', runId: run.id, from: this.instanceId })\n .catch(() => undefined);\n }\n await this.store.releaseRunLock(run.id);\n return { runId: run.id, status: 'cancelled', error };\n }\n const remote = registered.remote as NonNullable<RegisteredWorkflow['remote']>;\n if (run.status === 'pending') {\n await this.store.updateRun(run.id, { status: 'running', updatedAt: new Date() });\n run.status = 'running';\n this.emit({\n type: 'run.started',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n }\n if (registered.singleton && !(await this.singletons.admit(run, registered.singleton))) {\n return this.singletonWaitResult(run);\n }\n\n // Capability/protocol routing guard for the remote workflow turn (handshake design §7.5): if\n // descriptors are published on its group but none is capability-capable + protocol-compatible, park\n // `blocked` (never dispatch into a queue nobody consumes). No descriptors → skip (legacy, §7.7). The\n // routing token mirrors the executor's own `tenantGroup(sanitizeQueueToken(group), …)` dispatch\n // target — see RemoteWorkflowExecutor. Settled inline here (this path releases its own lease), unlike\n // the step guard which parks via the run-execution catch.\n const wfPlan = await this.planRoute(\n tenantGroup(sanitizeQueueToken(remote.group), undefined),\n registered.requires,\n );\n if (wfPlan?.status === 'blocked') return this.parkBlocked(run, wfPlan);\n\n const history = await this.remoteHistory(run.id);\n\n // DISPATCH-AND-SUSPEND (broker-backed executors): SUSPEND-then-ENQUEUE. The engine generates the\n // turn's `taskId`, records it on the run as the awaited marker, and RELEASES the lease — all BEFORE\n // enqueuing the turn — so a fast worker's decision (delivered over `onDecision`, applied durably by\n // `completeRemoteDecision` on WHATEVER instance consumes it) can NEVER arrive ahead of its marker,\n // nor contend with a still-held lease, and be dropped. (The original dispatch-then-mark order lost a\n // sub-millisecond cached-replay decision that round-tripped the in-cluster broker before the marker\n // write to the remote store committed — the multi-instance decision-drop's deeper race.) Liveness is\n // the suspended turn's heartbeat-rearmed window (`remoteAdvanceSilenceMs` → `wakeAt`): if no\n // decision/heartbeat lands before it lapses (including a dispatch that throws below), the timer\n // poller re-drives by re-marking + re-enqueuing a fresh turn.\n if (remote.executor.dispatch) {\n const taskId = `${run.id}:wf:${globalThis.crypto.randomUUID().slice(0, 8)}`;\n const silenceMs = this.remoteAdvanceSilenceMs;\n const wakeAt = silenceMs != null ? this.clock() + silenceMs : undefined;\n // MARK FIRST: record the awaited turn before it is enqueued. No resurrection risk — unlike the old\n // mark-AFTER-dispatch order, nothing rewrites `status` past this point, so a parent-cancel that\n // writes a terminal status during the enqueue below simply wins (its decision is later dropped by\n // `completeRemoteDecision`'s terminal-status check).\n await this.store.updateRun(run.id, {\n status: 'suspended',\n awaitingDecisionTaskId: taskId,\n wakeAt,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.suspended',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n // RELEASE BEFORE ENQUEUE: the decision must be able to BOTH match the marker AND acquire the lease\n // the instant it arrives — even a few ms after the enqueue. Holding the lease through the enqueue\n // would drop a fast decision at lock contention. Idempotent vs. `execute`'s own finally release.\n await this.store.releaseRunLock(run.id);\n // THEN enqueue. A failed/lost dispatch leaves the run suspended-awaiting with `wakeAt` set, so the\n // timer poller re-drives it — no lost run.\n await remote.executor.dispatch(run, history, taskId);\n return { runId: run.id, status: 'suspended' };\n }\n\n // INLINE advance (in-process group-served executors): the decision is produced in-process, so await\n // it under the lease. Single-instance by nature; the dispatch path above is the multi-instance one.\n const advanceExecutor = remote.executor.advance;\n if (!advanceExecutor) {\n throw new Error(\n `workflow ${run.workflow}@${run.workflowVersion}: executor implements neither advance nor dispatch`,\n );\n }\n let decision: WorkflowDecision;\n try {\n // When `remoteAdvanceSilenceMs` is configured, wrap the advance in a heartbeat-rearmed deadline\n // keyed by `run.id`: a worker replaying this turn beats (a run-scoped Heartbeat) to keep it alive,\n // and only a genuinely-silent worker trips RemoteWorkflowTimeout → recovery re-drive. Unset = the\n // prior unbounded await. INVARIANT: `advance()` is created and passed to awaitWithLivenessDeadline\n // SYNCHRONOUSLY (no await between), so the `heartbeatResets` entry is registered before the event\n // loop can deliver any beat — an early beat is never lost. If the executor ALSO carries its own\n // `timeoutMs`, the shorter of the two deadlines wins (both raise the same RemoteWorkflowTimeout,\n // handled identically by the catch below).\n const silenceMs = this.remoteAdvanceSilenceMs;\n const advance = advanceExecutor.call(remote.executor, run, history);\n decision =\n silenceMs != null\n ? await this.awaitWithLivenessDeadline(\n run.id,\n advance,\n silenceMs,\n () => new RemoteWorkflowTimeout(run.id, silenceMs),\n )\n : await advance;\n } catch (err) {\n // A RemoteWorkflowTimeout is NOT a failure: the advance only timed out (the decision was likely\n // dropped, while the work may have actually completed). Failing the run here would be wrong — and\n // would notify the parent of a false failure. Instead RELEASE the lease and leave the run in its\n // current `running` state so `recoverIncomplete` re-acquires the now-free lease and re-drives it;\n // the re-driven turn replays completed steps from history and, if the work was done, returns the same\n // `completed` decision → settles → notifies the parent. Opt-in: only reachable when the executor\n // was constructed with a `timeoutMs` (absent = prior unbounded await, unchanged).\n //\n // FIXED-TIMEOUT HAZARD: a bare RemoteWorkflowExecutor `timeoutMs` that fires while a worker is\n // LEGITIMATELY still executing a not-yet-checkpointed step re-drives → DUPLICATE side effects, so\n // that knob is only safe set GENEROUSLY (> the longest legitimate single turn). The robust fix is\n // the heartbeat-rearmed deadline above (`remoteAdvanceSilenceMs`): the worker beats while it works,\n // so only a genuinely-silent (dead) worker trips the timeout — no re-drive of a live turn.\n //\n // Lease lifecycle: `execute` clears its renew interval in its `finally` once this returns, so the\n // lease (released just below) stays free. `releaseRunLock` is idempotent, and `renewRunLock` is a\n // no-op once `lockedBy` is cleared, so a renew tick racing the release cannot re-acquire it.\n if (err instanceof RemoteWorkflowTimeout) {\n await this.store.releaseRunLock(run.id);\n // The suspended path returned early above; run is always `running` here — left for recovery to re-drive.\n return { runId: run.id, status: 'running' as const };\n }\n const error = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n // terminal failure: lease expires naturally — no recovery re-drive will race it\n await this.store.updateRun(run.id, { status: 'failed', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n return { runId: run.id, status: 'failed', error };\n }\n\n return this.applyDecision(run, decision);\n }\n\n /**\n * Apply a remote workflow turn's {@link WorkflowDecision}: persist the local steps it ran, then\n * settle (completed/failed/cancelled) or dispatch its blocking ops and suspend (continue). Shared by\n * the INLINE-advance path ({@link runRemoteExecution}, under the held lease) and the durable\n * DISPATCH path ({@link completeRemoteDecision}, which holds the lease itself). Idempotent transitions\n * — the caller has already ensured this is the decision for the currently-awaited turn.\n */\n private async applyDecision(run: WorkflowRun, decision: WorkflowDecision): Promise<RunResult> {\n if (decision.status === 'completed') {\n // Persist the local steps THIS turn ran before marking the run done. A workflow that runs\n // straight to completion in a single turn (every step inline, never suspending — e.g. a Python\n // @workflow whose body is a sequence of ctx.step calls) emits ALL its recordStep commands on\n // this terminal turn; without applying them the run shows `completed` with zero recorded steps.\n // Only this turn's NEW steps are present (prior turns' steps replay as `found`, emitting no\n // command), so there's no duplication.\n await this.applyCommands(run, decision.commands);\n return this.settleRun(run, { kind: 'completed', output: decision.output });\n }\n if (decision.status === 'failed') {\n // Same as completed: persist the steps this turn ran — including the failed one (the worker\n // records a failed-step command before raising) — so the dashboard shows WHERE it failed.\n await this.applyCommands(run, decision.commands);\n return this.settleRun(run, {\n kind: 'failed',\n error: decision.error ?? { message: 'workflow failed' },\n });\n }\n\n if (decision.status === 'cancelled') {\n // The worker bailed at an op boundary because the run was cancelled mid-turn — `cancel` already\n // set status=cancelled, cascaded to children and emitted the lifecycle event. Persist the steps\n // that DID run this turn (partial progress / where it stopped) and reassert `cancelled`\n // (idempotent with `cancel`'s write; preserves the existing error). The point is to NOT resurrect\n // the run to `suspended` or flip it to `failed` — both of which a normal turn result would do.\n await this.applyCommands(run, decision.commands);\n await this.store.updateRun(run.id, { status: 'cancelled', updatedAt: new Date() });\n return { runId: run.id, status: 'cancelled' };\n }\n\n // continue: persist any local steps the replay ran, dispatch the blocking ops, then suspend. When\n // those resolve (a result lands, a timer fires) `resume` brings us back for the next turn.\n //\n // Guard: re-read the run BEFORE writing `suspended` — a parent-cancel cascade may have written\n // `cancelled` to the store WHILE the executor was replaying this turn (the advance() awaited above\n // runs outside the store transaction). Overwriting `cancelled` → `suspended` would let recovery\n // re-drive the run forever. If the store already shows a terminal/cancelled state, bail without\n // touching it — identical to the guard in `completeRemoteResult` for remote step results.\n const fresh = await this.store.getRun(run.id);\n if (\n fresh &&\n (fresh.status === 'cancelled' || fresh.status === 'completed' || fresh.status === 'dead')\n ) {\n return { runId: run.id, status: fresh.status, output: fresh.output, error: fresh.error };\n }\n const wakeAt = await this.applyCommands(run, decision.commands, true);\n const suspended = await this.settleRun(run, { kind: 'suspended', wakeAt });\n // This turn may have been computed from a history older than the store's, in which case it just\n // parked on ops that are already settled — see {@link redriveIfTurnSawStaleHistory}.\n await this.redriveIfTurnSawStaleHistory(run.id, decision.commands);\n return suspended;\n }\n\n /**\n * Re-drive a run whose turn was computed from a history OLDER than the store's.\n *\n * A turn replays against a SNAPSHOT, and an op can settle while its decision is in flight. The\n * canonical case is a remote `gather_calls` fan-out whose last call lands during the decision's\n * lease window: `completeRemoteResult` -> `resume` -> `execute` finds the lease held and returns\n * silently, so that call's wake is spent with nothing to show for it, and the decision then parks\n * the run on a `call` that is already complete. Nothing would ever wake it again — only the\n * `reconcileMs` orphan sweep, minutes later.\n *\n * The tell is precise: the turn (re)declared a blocking op whose checkpoint is already settled. A\n * turn with an up-to-date history never does that, because a settled op is in its history and the\n * replay skips it. That also makes this convergent — the re-driven turn sees the op resolved and\n * cannot re-declare it, so one lost wake costs exactly one extra turn, never a loop.\n *\n * Scheduled off the current stack so it runs after the caller released the run lease.\n */\n private async redriveIfTurnSawStaleHistory(\n runId: string,\n commands: WorkflowCommand[],\n ): Promise<void> {\n const blocking = commands.filter(\n (cmd) => cmd.kind === 'call' || cmd.kind === 'startChild' || cmd.kind === 'waitSignal',\n );\n if (blocking.length === 0) return;\n for (const cmd of blocking) {\n const checkpoint = await this.store.getCheckpoint(runId, cmd.seq);\n if (checkpoint && checkpoint.status !== 'pending') {\n setTimeout(() => {\n void this.resumeImplicit(runId).catch(() => undefined);\n }, 0).unref?.();\n return;\n }\n }\n }\n\n /**\n * A polyglot workflow's re-emitted `call` whose checkpoint already exists: decide whether the step\n * is still out for delivery, or whether its dispatch was LOST and has to be re-driven. Returns the\n * lease deadline to park the run on (so the next decision lands exactly when it's due), or\n * `undefined` when there is nothing to wait for.\n *\n * WHY THIS EXISTS. A worker process killed mid-step (OOM, exit 137 — a pod's memory ceiling, not a\n * bug in anyone's code) takes its in-flight job with it: BullMQ's stalled-check eventually fails the\n * job, and for a consumer that can't bridge a terminal job failure back into a `StepResult` (any\n * non-TS SDK) NOTHING settles the checkpoint. It stays `pending` — \"out for delivery\" — and the\n * `applyCommands` idempotency guard, which exists so a `ctx.gather_calls` fan-out doesn't\n * double-dispatch its still-in-flight siblings on every partial resume, skips it on every later turn.\n * The run then wakes on the reconcile sweep, dispatches a turn, has the call re-emitted, skips it\n * again, and sleeps. Forever. Observed in the wild on a six-run `gather_calls` fan-out: `pending`,\n * `attempts = 1`, `wakeAt` NULL, over an hour, no retry.\n *\n * THE POLICY (mirrors {@link callRemote}'s `ctx.step` self-heal, which this path silently did not\n * share — so `remoteRedispatchMs` simply did not apply to a fan-out):\n * - a SETTLED checkpoint always wins: a step that completed just before the crash is never re-run;\n * - `remoteRedispatchMs` unset (the default) keeps the by-design \"re-suspend, never re-dispatch\";\n * - otherwise the pending checkpoint carries a LEASE in `wakeAt` — a result or a step heartbeat\n * ({@link rearmStepLease}) renews it, so a live worker still holding the step is never\n * double-dispatched — and only a LAPSED lease re-dispatches, bounded by `remoteRedispatchMax`;\n * - past the bound the step is failed `remote_step_lost` and the failure enters the run's history,\n * so the workflow's own error path surfaces it instead of the engine looping.\n */\n private async redriveLostCall(run: WorkflowRun, cp: StepCheckpoint): Promise<number | undefined> {\n // Settled (or a non-remote seq): the checkpoint is the truth, nothing to re-drive.\n if (cp.kind !== 'remote' || cp.status !== 'pending') return undefined;\n if (this.remoteRedispatchMs == null) return undefined;\n // First sight of this pending step under the self-heal: stamp its lease (clock-space, persisted,\n // stable across replays and crashes) and park the run on it.\n if (cp.wakeAt == null) {\n const lease = this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint({ ...cp, wakeAt: lease });\n return this.stepLeaseWakeAt(lease);\n }\n if (this.clock() < cp.wakeAt) return this.stepLeaseWakeAt(cp.wakeAt);\n // The lease lapsed with no result and no heartbeat: the dispatch is presumed lost.\n if (cp.attempts >= this.remoteRedispatchMax) {\n const error = {\n message: `remote step \"${cp.name}\" lost — no result after ${cp.attempts} dispatch(es)`,\n code: 'remote_step_lost',\n retryable: false,\n };\n const now = new Date();\n // Settling it `failed` puts the failure in the run's history (see {@link remoteHistory}), where\n // the worker's replay raises it. The caller's `redriveIfTurnSawStaleHistory` sees a blocking op\n // that is no longer pending and re-drives the run, so that next turn happens immediately.\n await this.store.saveCheckpoint({\n ...cp,\n status: 'failed',\n error,\n wakeAt: undefined,\n finishedAt: now,\n events: [...(cp.events ?? []), lostStepEvent(this.clock(), cp.attempts, 'lost')],\n });\n this.emit({\n type: 'step.failed',\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n kind: 'remote',\n error,\n });\n return undefined;\n }\n const attempts = cp.attempts + 1;\n const lease = this.clock() + this.remoteRedispatchMs;\n const at = new Date();\n await this.store.saveCheckpoint({\n ...cp,\n attempts,\n wakeAt: lease,\n // The re-dispatch restarts the step's wall-clock window; the old one measured a worker that died.\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n // Observability: the step's own trail says WHY it ran again — a lost worker, not a failure retry.\n events: [...(cp.events ?? []), lostStepEvent(this.clock(), attempts, 'redispatched')],\n });\n await this.dispatchRemoteTask({\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n stepId: cp.stepId ?? stepId(run.id, cp.seq),\n group: cp.workerGroup ?? sanitizeQueueToken(cp.name),\n input: cp.input,\n attempt: attempts,\n });\n this.emit({\n type: 'step.started',\n runId: run.id,\n seq: cp.seq,\n name: cp.name,\n kind: 'remote',\n redispatched: true,\n });\n return this.stepLeaseWakeAt(lease);\n }\n\n /**\n * The run `wakeAt` a step lease should park on: the lease itself, but never LATER than the\n * `reconcileMs` safety net would have woken the run anyway. A long lease (a fan-out step that\n * legitimately runs for half an hour) must not stretch the orphan sweep's cadence for this run —\n * an early wake just re-parks on the un-lapsed lease, which is cheap and convergent.\n */\n private stepLeaseWakeAt(lease: number): number {\n const reconcile = this.reconcileMs;\n return reconcile == null ? lease : Math.min(lease, this.clock() + reconcile);\n }\n\n /** Earliest clock time a step's lease is worth LOOKING at again (`stepId` → clock ms) — the read\n * throttle for {@link rearmStepLease}, the step-scoped sibling of {@link decisionDeadlineRearms}. */\n private readonly stepLeaseRearms = new Map<string, number>();\n\n /**\n * A step-scoped heartbeat for a durably-suspended remote step: push its LEASE forward so a worker\n * that is still working on it is never presumed dead and double-dispatched. The durable counterpart\n * of {@link callRemoteInMemory}'s in-memory `heartbeatResets` rearm (which only exists on the\n * instance that dispatched a `timeoutMs` step), and the step-scoped sibling of\n * {@link rearmDecisionDeadline}. No-op unless the lost-dispatch self-heal is on — without\n * `remoteRedispatchMs` nothing ever re-dispatches, so there is no lease to defend.\n *\n * THROTTLED BY THE LEASE ITSELF, not a fixed interval: a renewal buys at most ONE window, so it is\n * only WORTH a write once the window is half spent. Beats arrive every couple of seconds from a hot\n * worker loop — and a `gather_calls` fan-out multiplies that by its in-flight steps — so an\n * unthrottled rearm is a per-beat SELECT + UPDATE storm (plus a `getRun` + `updateRun` whenever the\n * run is parked exactly on this step's lease). The `cp.wakeAt >= renewed` guard it replaces never\n * short-circuited anything, because `renewed` advances with the clock. So:\n * - a beat that finds more than half the window still on the clock writes nothing, and records the\n * half-spent mark so subsequent beats skip even the `getCheckpoint` READ until then;\n * - a beat at or past the mark renews, leaving a full half-window of headroom — the lease can never\n * lapse under a worker whose beats are anywhere near their normal cadence.\n *\n * That bounds the cost at ONE read + ONE write per half `remoteRedispatchMs` per in-flight step,\n * independent of beat frequency (with a 30-minute window: two writes an hour). The in-memory mark is\n * a pure optimisation — cold on a fresh instance, or on the one that didn't dispatch the step — and\n * the durable half-spent check below re-derives the same answer from the checkpoint, so nothing\n * depends on it surviving. Cleared wholesale past 1024 entries: a rare extra read, never a leak.\n */\n private async rearmStepLease(runId: string, seq: number): Promise<void> {\n if (this.remoteRedispatchMs == null) return;\n const id = stepId(runId, seq);\n const now = this.clock();\n const lookAgainAt = this.stepLeaseRearms.get(id);\n if (lookAgainAt !== undefined && now < lookAgainAt) return;\n // EVERY store call below is swallowed, reads AND writes: this runs inside the transport's beat\n // handler, which delivers beats serially and does not catch — a throwing rearm would take the whole\n // beat loop down (and on `bullmq`, where the subscriber does `void handler(...)`, surface as an\n // unhandled rejection that can kill the process). A lost beat is harmless by the same headroom\n // argument that justifies the throttle: the lease still has at least half its window left, and the\n // half-spent mark is only advanced AFTER a successful write, so the very next beat retries.\n try {\n const cp = await this.store.getCheckpoint(runId, seq);\n if (!cp || cp.kind !== 'remote' || cp.status !== 'pending') {\n // Settled (or gone): stop tracking it, so a long-lived worker's stale beats don't keep the entry.\n this.stepLeaseRearms.delete(id);\n return;\n }\n const halfWindow = Math.ceil(this.remoteRedispatchMs / 2);\n // More than half the window left: nothing to buy, and nothing to look at until it is half spent.\n if (cp.wakeAt != null && cp.wakeAt > now + halfWindow) {\n this.stepLeaseRearms.set(id, cp.wakeAt - halfWindow);\n return;\n }\n const renewed = now + this.remoteRedispatchMs;\n const previous = cp.wakeAt;\n await this.store.saveCheckpoint({ ...cp, wakeAt: renewed });\n if (this.stepLeaseRearms.size > 1024) this.stepLeaseRearms.clear();\n this.stepLeaseRearms.set(id, renewed - halfWindow);\n // If the run is parked EXACTLY on this step's old lease, carry its wake forward too — otherwise a\n // beating worker costs one wasted turn per renewal window. Only on an exact match: any other\n // `wakeAt` belongs to some other timer (a sleep, a sibling's shorter lease) and moving it would\n // delay that instead.\n if (previous == null) return;\n const run = await this.store.getRun(runId);\n if (run?.status === 'suspended' && run.wakeAt === previous) {\n await this.store.updateRun(runId, { wakeAt: renewed, updatedAt: new Date() });\n }\n } catch {\n // Best-effort liveness: a store blip costs one skipped renewal, never the beat loop. The mark was\n // not advanced unless the lease write itself already committed, so nothing is silently left stale.\n }\n }\n\n /** The run's resolved durable ops as replay inputs: completed/failed steps + elapsed timers. */\n private async remoteHistory(runId: string): Promise<HistoryEvent[]> {\n const checkpoints = await this.store.listCheckpoints(runId);\n const kindOf: Record<StepKind, HistoryEvent['kind']> = {\n remote: 'call',\n local: 'step',\n sleep: 'timer',\n signal: 'signal',\n };\n const events: HistoryEvent[] = [];\n for (const cp of checkpoints) {\n if (cp.status === 'completed' || cp.status === 'failed') {\n // A child run resolves THROUGH the signal machinery (a `child:<id>` waiter notified on the\n // child's terminal state), so its checkpoint is kind `signal` with a `signal:child:` name and\n // a Completion payload. Surface it as a `child` event with the value/error unwrapped.\n if (cp.kind === 'signal' && cp.name.startsWith('signal:child:')) {\n const completion = cp.output as Completion<unknown> | undefined;\n events.push({\n seq: cp.seq,\n kind: 'child',\n output: completion?.ok ? completion.value : undefined,\n error:\n completion && completion.ok === false ? { message: completion.error } : undefined,\n });\n continue;\n }\n events.push({\n seq: cp.seq,\n kind: kindOf[cp.kind] ?? 'step',\n // A signal checkpoint's name is the internal `signal:<token>`, not the workflow-level signal\n // name the replay used — omit it so the replay matches on seq + kind (its determinism anchor).\n name: cp.kind === 'signal' ? undefined : cp.name,\n output: cp.status === 'completed' ? cp.output : undefined,\n error: cp.status === 'failed' ? cp.error : undefined,\n });\n } else if (cp.kind === 'sleep' && cp.wakeAt != null && cp.wakeAt <= this.clock()) {\n // a still-`pending` sleep whose deadline has passed reads as a resolved timer on replay.\n events.push({ seq: cp.seq, kind: 'timer', name: cp.name });\n }\n }\n return events.sort((a, b) => a.seq - b.seq);\n }\n\n /** Apply a turn's commands: persist recorded local steps, dispatch remote calls, schedule timers.\n * Returns the earliest timer deadline to suspend on (or undefined — suspended on a result).\n *\n * `redriveLost` is set only by the `continue` path: a turn that PARKS on its blocking ops is the\n * one that may find a re-emitted `call` whose dispatch was lost and needs re-driving (see\n * {@link redriveLostCall}). A terminal turn (completed/failed/cancelled) applies its commands only\n * to record what already ran, and must never dispatch anything new. */\n private async applyCommands(\n run: WorkflowRun,\n commands: WorkflowCommand[],\n redriveLost = false,\n ): Promise<number | undefined> {\n let wakeAt: number | undefined;\n for (const cmd of commands) {\n const at = new Date();\n const id = stepId(run.id, cmd.seq);\n if (cmd.kind === 'recordStep') {\n // Prefer the step's real wall-clock window + sub-process events (carried by the command, and\n // already streamed live via persistStepEvent) so the checkpoint shows a true duration and its\n // p-process trail — not a 0ms placeholder. Fall back to apply-time for older workers.\n const startedAt = cmd.startedAt != null ? new Date(cmd.startedAt) : at;\n const finishedAt = cmd.finishedAt != null ? new Date(cmd.finishedAt) : at;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'local',\n status: cmd.error ? 'failed' : 'completed',\n output: cmd.output,\n error: cmd.error,\n events: cmd.events,\n attempts: 1,\n enqueuedAt: startedAt,\n startedAt,\n finishedAt,\n // Carry the worker's `parallelGroup` (a Python `ctx.gather` tags every step in the fan with\n // the same group) onto the checkpoint, so the dashboard can render the steps as one parallel\n // group instead of a sequential list. Additive: undefined for ordinary sequential steps.\n parallelGroup: cmd.parallelGroup,\n }),\n );\n this.emit({\n type: cmd.error ? 'step.failed' : 'step.completed',\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'local',\n output: cmd.output,\n error: cmd.error,\n });\n } else if (cmd.kind === 'call') {\n // Idempotency (load-bearing for `ctx.gather_calls`): a fan-out re-emits its still-pending\n // `call` commands on every PARTIAL resume (a sibling settled, but not all). Without this guard\n // each re-emit would re-persist + re-dispatch an already-in-flight (or already-completed) step,\n // double-dispatching the worker and resetting attempts. So if a checkpoint for (run.id, seq)\n // already exists — pending OR terminal — skip the save + dispatch entirely; its result lands\n // independently via completeRemoteResult (keyed by seq, so concurrent calls never clobber).\n // Mirrors the `startChild` `getRun(childId)` guard below.\n //\n // What that guard must NOT do is treat \"a checkpoint exists\" as \"somebody is still going to\n // deliver it\". A dispatched job can be LOST — the worker was OOM-killed mid-step, so the job\n // died with the process and no result will ever come — and the checkpoint still reads\n // `pending`. Skipping such a command forever is how a fan-out orphans its run (see\n // {@link redriveLostCall}, which owns that decision; a settled checkpoint always wins).\n const existing = await this.store.getCheckpoint(run.id, cmd.seq);\n if (existing) {\n const leaseAt = redriveLost ? await this.redriveLostCall(run, existing) : undefined;\n if (leaseAt != null) wakeAt = wakeAt == null ? leaseAt : Math.min(wakeAt, leaseAt);\n continue;\n }\n // The dispatched step's LEASE: when the lost-dispatch self-heal is on (`remoteRedispatchMs`),\n // stamp the deadline by which a result (or a step heartbeat renewing it) must have landed, and\n // suspend the run ON it — so the re-drive lands when it's due instead of waiting for the\n // reconcile sweep. Unset (default) leaves `wakeAt` NULL exactly as before.\n const lease =\n this.remoteRedispatchMs == null ? undefined : this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'remote',\n status: 'pending',\n input: cmd.input,\n attempts: 1,\n wakeAt: lease,\n // `cmd.group` is the routing declaration the worker's replay emitted (cross-SDK, or a\n // group-served TS body) — treated as an isolation partition on top of the step's own\n // name, mirroring the StepDef formula below (identical expression everywhere).\n workerGroup: tenantGroup(sanitizeQueueToken(cmd.name), cmd.group),\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n // A `ctx.gather_calls([...])` fan-out stamps every dispatched `call` in the fan with the\n // same group, so the dashboard renders the dispatched steps as one parallel fan (parity\n // with the gathered `recordStep`/`startChild` tags). Undefined for a lone sequential `ctx.step`.\n parallelGroup: cmd.parallelGroup,\n }),\n );\n await this.pool.dispatch(\n {\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n stepId: id,\n group: tenantGroup(sanitizeQueueToken(cmd.name), cmd.group),\n input: cmd.input,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt: 1,\n },\n undefined,\n );\n this.emit({\n type: 'step.started',\n runId: run.id,\n seq: cmd.seq,\n name: cmd.name,\n kind: 'remote',\n });\n if (lease != null) {\n const leaseWake = this.stepLeaseWakeAt(lease);\n wakeAt = wakeAt == null ? leaseWake : Math.min(wakeAt, leaseWake);\n }\n } else if (cmd.kind === 'sleep') {\n const deadline = this.clock() + cmd.ms;\n await this.store.saveCheckpoint(\n stepCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: `sleep:${cmd.seq}`,\n kind: 'sleep',\n status: 'pending',\n attempts: 1,\n wakeAt: deadline,\n enqueuedAt: at,\n startedAt: at,\n finishedAt: at,\n }),\n );\n wakeAt = wakeAt == null ? deadline : Math.min(wakeAt, deadline);\n } else if (cmd.kind === 'waitSignal') {\n // Park on a signal: register a waiter at this seq so engine.signal(token) lands the resolving\n // `signal` checkpoint here and resumes the run. The token is the signal name, so an external\n // engine.signal(name, payload) delivers it. If the signal was already delivered (buffered\n // before the workflow reached this point — e.g. signalWithStart), resolve it now and re-drive\n // on a macrotask, AFTER this turn suspends and frees the run lock (a re-entrant resume bails).\n //\n // NOTE: `WorkflowCommand` has no `waitEvent` kind — a polyglot (remote-executor) workflow has\n // no way to issue `ctx.waitForEvent(name, { match })` today; only in-process TS workflows\n // (`workflow-ctx.ts`) can. So buffered EVENTS (`bufferEvent`/`listBufferedEvents`/\n // `removeBufferedEvent`) are reachable only from `engine.publishEvent` and the in-process\n // `waitForEvent`/reconcile paths — never from this remote command loop. Extending the\n // polyglot protocol with an event-wait command is future work, not something to invent here.\n const deliverBuffered = async (payload: unknown): Promise<void> => {\n await this.store.saveCheckpoint(\n instantCheckpoint({\n runId: run.id,\n seq: cmd.seq,\n name: `signal:${cmd.signal}`,\n kind: 'signal',\n output: payload,\n }),\n );\n setTimeout(() => void this.resumeImplicit(run.id).catch(() => undefined), 0);\n };\n const buffered = await this.store.takeBufferedSignal(cmd.signal);\n if (buffered) {\n await deliverBuffered(buffered.payload);\n } else {\n // Same reorder as the in-process ctx.waitForSignal (see there for why registering\n // UNCONDITIONALLY before even the first check is unsafe — it would expose a \"this turn is\n // about to self-resolve\" waiter row to a concurrent signal for a token a polyglot entity\n // loop reuses, which could steal it and misdeliver): check first, and only on a miss\n // register, then re-check once more before suspending — closing the lost-wake window where\n // a signal races in between the miss above and the registration below (see the interleaving\n // proof at engine.signal).\n await this.store.putSignalWaiter({ token: cmd.signal, runId: run.id, seq: cmd.seq });\n const lateBuffered = await this.store.takeBufferedSignal(cmd.signal);\n if (lateBuffered) {\n // Resolved it ourselves — remove OUR OWN row via the exact match (not\n // takeSignalWaiter(cmd.signal), which deletes ANY row for this token and could steal a\n // different run's waiter that has since claimed the same token).\n await this.store.removeSignalWaiter({ token: cmd.signal, runId: run.id, seq: cmd.seq });\n await deliverBuffered(lateBuffered.payload);\n }\n }\n } else if (cmd.kind === 'startChild') {\n // Start a child run and await it (the worker's ctx.start_child suspends until the child's\n // result is in history). Mirror the in-process `ctx.child`: register a `child:<id>` waiter at\n // this seq — the child notifies it on its terminal state (engine.notifyParent) — then start the\n // child once, deferred so a fast child can't reentrantly resume this still-suspending parent,\n // and id-idempotent so replay/recovery never double-starts it.\n const childId = `${run.id}.child.${cmd.seq}`;\n await this.store.putSignalWaiter({\n token: `child:${childId}`,\n runId: run.id,\n seq: cmd.seq,\n // A `ctx.gather_children`/`ctx.all` fan-out stamps every `startChild` in the fan with the same\n // group. Thread it onto the waiter so the child's terminal `signal:child:<id>` checkpoint\n // (written by engine.signal when the child notifies the parent) carries the group and the\n // dashboard renders the fan as one parallel group. Undefined for a lone (non-fan) child.\n parallelGroup: cmd.parallelGroup,\n });\n if (!(await this.store.getRun(childId))) {\n // Inherit the parent run's namespace (see ctxHostFor.startChild) so a remote workflow's\n // child stays on the parent's tenant/partition regardless of which engine executes it.\n this.startChildDeferred(cmd.workflow, cmd.input, childId, { namespace: run.namespace });\n }\n } else {\n throw new Error(\n `remote workflow command '${(cmd as { kind: string }).kind}' is not supported yet`,\n );\n }\n }\n return wakeAt;\n }\n\n /**\n * Undo the registered saga compensations in reverse and settle the run `cancelled`. Shared by EVERY\n * exit path of a run with a compensating cancel in flight — whether the resumed replay returned,\n * suspended, hit continue-as-new, or threw — so a cancel is never lost just because the body didn't\n * stop at a suspension point.\n *\n * A dispatched compensation still in flight (or backing off a retry) needs the run to keep waiting:\n * unlike the failure path (which is fine going `suspended` — a resumable state no different from an\n * ordinary in-flight `ctx.step`), THIS run must stay `cancelling` — `engine.cancel`'s idempotent\n * re-check, `waitForRun`'s non-terminal treatment, and crash recovery (`recoverIncomplete` only\n * re-drives `running`/`cancelling` runs — a `cancelling` one with a free lease, whatever it's\n * internally waiting on) all key off that status. So on a pending unwind this returns WITHOUT\n * touching `status` (already `cancelling`, untouched since `engine.cancel` set it) — the in-memory\n * cancel flag stays too, re-derived from the status on any later re-drive regardless.\n */\n private async compensateAndCancel(\n run: WorkflowRun,\n compensations: Compensation[],\n replay?: Map<number, StepCheckpoint>,\n ): Promise<RunResult> {\n const pending = await this.unwindCompensations(run, compensations, replay);\n if (pending) return { runId: run.id, status: 'cancelling' };\n this.cancelRequested.delete(run.id);\n const error = { message: 'cancelled' };\n await this.store.updateRun(run.id, { status: 'cancelled', error, updatedAt: new Date() });\n this.emit({\n type: 'run.failed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n });\n return { runId: run.id, status: 'cancelled', error };\n }\n\n /**\n * The run body, lease held + renewed by {@link execute}, wrapped in the registered\n * {@link runDurableExecution} wrappers so an observability scope covers ONE WHOLE TURN.\n *\n * The wrap goes here — around the entire turn — rather than tightly around the `fn(ctx, input)`\n * call, because the store writes that bracket the body (the `pending` → `running` transition, the\n * step checkpoints, the terminal `settleRun` update) are exactly the queries an operator wants\n * correlated to the turn that issued them. Narrowing the wrap to the body would leave them\n * uncorrelated for the sake of a purity that buys nothing.\n *\n * Only the TS path is wrapped. {@link runRemoteExecution} does not execute a body at all — it\n * dispatches a workflow task and awaits the worker's decision — so a scope opened there would\n * describe a dispatch, not an execution, and would mislead anyone reading the trace.\n */\n private runExecution(\n run: WorkflowRun,\n fn: WorkflowFn,\n registered: RegisteredWorkflow | undefined,\n ): Promise<RunResult> {\n return runDurableExecution(\n {\n unit: 'workflow',\n runId: run.id,\n workflow: run.workflow,\n name: undefined,\n seq: undefined,\n attempt: undefined,\n },\n () => this.runExecutionTurn(run, fn, registered),\n );\n }\n\n private async runExecutionTurn(\n run: WorkflowRun,\n fn: WorkflowFn,\n registered: RegisteredWorkflow | undefined,\n ): Promise<RunResult> {\n // A run persisted as `cancelling` is a compensating cancel in flight — possibly re-driven by\n // recovery after a crash that lost the in-memory cancel flag. Re-derive the intent from the status\n // so the replay below reaches the WorkflowSuspended + cancelRequested branch and compensates →\n // cancelled (this is what makes a compensating cancel durable across a crash).\n if (run.status === 'cancelling') this.cancelRequested.add(run.id);\n // First execution of an enqueued run: mark it running and announce the start, BEFORE the singleton\n // gate. A resumed run is already past `pending`, so this fires exactly once.\n if (run.status === 'pending') {\n await this.store.updateRun(run.id, { status: 'running', updatedAt: new Date() });\n run.status = 'running';\n this.emit({\n type: 'run.started',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n }\n // Singleton admission gate: if this run shares its key with `limit` older in-flight runs, wait\n // (suspend on a short timer) until a slot frees instead of running now. Re-checked on each resume.\n // A `cancelling` run skips the gate — it is tearing down, not competing for a slot, and suspending\n // it here would clobber the `cancelling` status.\n if (\n run.status !== 'cancelling' &&\n registered?.singleton &&\n !(await this.singletons.admit(run, registered.singleton))\n ) {\n return this.singletonWaitResult(run);\n }\n // Saga compensations registered by completed steps; run in reverse if the run later fails.\n const compensations: Compensation[] = [];\n // Load this run's checkpoints ONCE and key them by seq, so replaying the completed prefix reads\n // from memory instead of one `getCheckpoint` SELECT per primitive (the O(N²) replay-reads fix).\n // Read once at execution start: a checkpoint written AFTER this snapshot (the signal/timer/child\n // this resume wakes on, or one written later in this same execution) is absent from the map, and\n // the ctx falls back to the live store for any absent seq — so replay semantics are unchanged.\n const snapshot = await this.store.listCheckpoints(run.id);\n const replay = new Map<number, StepCheckpoint>();\n for (const cp of snapshot) replay.set(cp.seq, cp);\n let suspendedOnFan: FanJoin | undefined;\n const ctx = createWorkflowCtx(\n this.ctxHostFor(replay, run.namespace),\n run.id,\n compensations,\n run.workflow,\n registered?.searchAttributesSchema,\n );\n // Every settle below is `return await`ed, never a bare `return this.settleRun(...)`: inside\n // `try … finally` a bare return runs the `finally` — which RELEASES THE LEASE — as soon as the\n // return expression is evaluated, while the settle's own writes are still in flight. The run then\n // sits unlocked but still reading `running`, which is exactly the shape `recoverIncomplete` takes\n // for a crashed turn: it re-enqueued the run and a second execution replayed it alongside the one\n // a fast step result had legitimately resumed. The lease must outlive the state it protects.\n try {\n // The ambient-context wrap is what lets class-first statics (`MyWorkflow.execute()`) find\n // this ctx from anywhere on the body's async path — first run and every replay alike.\n const output = await runInWorkflowCtx(ctx, () => fn(ctx, run.input));\n // A compensating cancel may have been requested while this turn ran (or re-derived from a\n // `cancelling` status on recovery): undo + settle cancelled rather than completing, so the cancel\n // is never lost when the body returns without first hitting a suspension point.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n return await this.settleRun(run, { kind: 'completed', output });\n } catch (err) {\n if (err instanceof ContinueAsNew) {\n // A cancel in flight wins over continue-as-new: undo + cancel instead of spawning the next run.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n // Hand off to a fresh execution with a clean history: complete this run, then start the next\n // (`<id>~N`) with the new input. Deferred + idempotent by the continuation id, so a crash\n // mid-handoff re-derives the same next run instead of forking.\n await this.store.updateRun(run.id, {\n status: 'completed',\n output: undefined,\n error: undefined,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.completed',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n });\n void this.notifyParent(run.id, { ok: true, value: undefined });\n const nextId = nextContinuationId(run.id);\n queueMicrotask(\n () => void this.start(run.workflow, err.input, nextId).catch(() => undefined),\n );\n return { runId: run.id, status: 'completed' };\n }\n if (err instanceof WorkflowBlocked) {\n // No live worker can run the next dispatch (capability/protocol gap) — park the run `blocked`\n // (design §7.5/§7.6) with the structured diagnostics, instead of writing a `pending` checkpoint\n // + dispatching into a queue nobody consumes. The blocked-recovery poll re-drives it when a\n // capable+compatible worker appears. A compensating cancel in flight still wins.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n return await this.settleRun(run, { kind: 'blocked', blocked: err.plan });\n }\n if (err instanceof WorkflowSuspended) {\n // A compensating cancel resumed this run to reach here: undo + cancel instead of re-suspending.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n const suspended = await this.settleRun(run, { kind: 'suspended', wakeAt: err.wakeAt });\n suspendedOnFan = err.fan;\n return suspended;\n }\n // A cancel in flight that surfaced as a thrown error still settles cancelled (not failed) — the\n // saga undo runs either way; this just keeps the terminal status faithful to the cancel request.\n if (this.cancelRequested.has(run.id)) {\n return await this.compensateAndCancel(run, compensations, replay);\n }\n const error = {\n message: err instanceof Error ? err.message : String(err),\n stack: err instanceof Error ? err.stack : undefined,\n };\n // Saga: undo completed steps in reverse — local ones in-process, dispatched ones as durable\n // remote-step dispatches (see `unwindCompensations`) — each made VISIBLE as a `compensate:<step>`\n // step event/checkpoint so a stranded undo is never silently swallowed; a failing one is still\n // skipped so it can't mask the original failure or strand the rest (compensations should be\n // idempotent). A dispatched undo still in flight (or backing off a retry) SUSPENDS the run\n // exactly like an ordinary `ctx.step` dispatch — the next re-drive (the worker's result landing,\n // or the retry backoff elapsing) resumes `unwindCompensations` right where it left off.\n const pending = await this.unwindCompensations(run, compensations, replay);\n if (pending) return await this.settleRun(run, { kind: 'suspended', wakeAt: pending.wakeAt });\n return await this.settleRun(run, { kind: 'failed', error });\n } finally {\n // Release the recovery lease once the run reaches a terminal/suspended state, so the\n // next instance (or the timer poller) can pick it up promptly.\n await this.store.releaseRunLock(run.id);\n if (suspendedOnFan) {\n void this.redriveSettledChildren(run.id, suspendedOnFan).catch(() => undefined);\n }\n }\n }\n\n /**\n * Undo every registered saga compensation in strict reverse order — the shared unwind both the\n * run-failure path (`runExecution`'s catch) and the compensating-cancel path\n * (`compensateAndCancel`) drive. Every entry, LOCAL or DISPATCHED, gets a NEGATIVE checkpoint seq\n * `-(k + 1)` for its position `k` (0, 1, 2… walking the stack in reverse) — reserved space that can\n * never collide with a body position (those start at 0), so a saga's undo trail composes onto the\n * run's ordinary checkpoint history with no store-schema change, and shows up in run detail exactly\n * like any other step. Deterministic because `compensations` is rebuilt identically on every replay\n * (see `workflow-ctx.ts`), so the same comp always lands on the same negative seq across a crash +\n * re-drive — the crash-safety this whole scheme rests on.\n *\n * A LOCAL entry runs in-process (`runCompensation`), which checkpoints its own outcome — completed,\n * or failed once `compensationRetries` are exhausted — so a crash mid-unwind SKIPS an\n * already-resolved one on the next pass instead of re-running it (and re-spending its retry budget)\n * from attempt 1. A DISPATCHED entry is an ordinary remote-step dispatch under the hood\n * (`dispatchCompensation`): when it needs the run to WAIT — freshly dispatched, still in flight, or\n * backing off a durable retry — this function returns that wait signal immediately (skipping every\n * comp after it in this pass); the CALLER decides how to represent \"still unwinding\" (see\n * `compensateAndCancel`'s doc comment for why that differs between the two callers). Either way, the\n * run resumes later exactly like any other dispatched step: `completeRemoteResult` completes the\n * negative-seq checkpoint and re-drives, the body replays and deterministically re-throws the same\n * exit it took before (the original failure, or the suspension `compensateAndCancel` resumed from),\n * this function runs again, the now-resolved comp is skipped, and the unwind continues from there.\n *\n * Returns `undefined` once every compensation has resolved — the caller then finalizes the run\n * (`failed` with the ORIGINAL body error, never masked by a comp outcome; or `cancelled`).\n */\n private async unwindCompensations(\n run: WorkflowRun,\n compensations: Compensation[],\n replay?: Map<number, StepCheckpoint>,\n ): Promise<UnwindPending | undefined> {\n for (let i = compensations.length - 1; i >= 0; i -= 1) {\n const comp = compensations[i];\n if (!comp) continue;\n const seq = -(compensations.length - i);\n if ('fn' in comp) {\n const existing = replay?.get(seq) ?? (await this.store.getCheckpoint(run.id, seq));\n if (existing) continue; // already resolved (completed or exhausted-failed) in an earlier pass\n await this.runCompensation(run, comp, seq, replay);\n continue;\n }\n const pending = await this.dispatchCompensation(run, comp, seq, replay);\n if (pending) return pending;\n }\n return undefined;\n }\n\n /**\n * Run one LOCAL saga compensation, retried up to `compensationRetries`, emitting a\n * `compensate:<step>` step event for its outcome so a stranded undo is visible. Never throws — a\n * permanently-failing compensation is skipped so it can't mask the original failure. Checkpoints\n * its outcome at `seq` (a negative unwind position reserved by {@link unwindCompensations}) so a\n * crash mid-unwind skips an already-resolved undo on a later pass instead of re-running it (and\n * re-spending its retry budget) from attempt 1 — the checkpoint is durability/visibility only; the\n * runtime retry-in-process-back-to-back semantics of `comp.fn()` are unchanged.\n */\n private async runCompensation(\n run: WorkflowRun,\n comp: Extract<Compensation, { fn: () => Promise<void> }>,\n seq: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<void> {\n const name = `compensate:${comp.name}`;\n const enqueuedAt = new Date();\n for (let attempt = 1; attempt <= this.compensationRetries; attempt += 1) {\n const startedAt = new Date();\n try {\n await comp.fn();\n this.emit({\n type: 'step.completed',\n runId: run.id,\n workflow: run.workflow,\n name,\n kind: 'local',\n durationMs: Date.now() - startedAt.getTime(),\n });\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'local',\n status: 'completed',\n attempts: attempt,\n enqueuedAt,\n startedAt,\n finishedAt: new Date(),\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n return;\n } catch (err) {\n if (attempt >= this.compensationRetries) {\n const error = { message: err instanceof Error ? err.message : String(err) };\n this.emit({\n type: 'step.failed',\n runId: run.id,\n workflow: run.workflow,\n name,\n kind: 'local',\n error,\n durationMs: Date.now() - startedAt.getTime(),\n });\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'local',\n status: 'failed',\n attempts: attempt,\n error,\n enqueuedAt,\n startedAt,\n finishedAt: new Date(),\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n }\n }\n }\n }\n\n /**\n * Resolve (or advance) ONE dispatched saga compensation at its reserved negative `seq` — the undo\n * handler is an ordinary remote `@Step`, so this mirrors `callRemote`'s pending/failed/absent\n * branches (engine.ts's `callRemote`), minus the queue/admission and in-memory-`timeoutMs` paths\n * (V1: dispatch direct by name, always durable). Returns the wait signal when the run must pause for\n * this compensation (freshly dispatched, still in flight, or backing off before a durable retry);\n * `undefined` once it's resolved — completed (crash-safe skip), or retries exhausted/non-retryable\n * (already visible: `completeRemoteResult` emitted `step.failed` for `compensate:<name>` when that\n * checkpoint landed — never re-emitted here, and never allowed to block the rest of the unwind or\n * mask the run's original failure).\n */\n private async dispatchCompensation(\n run: WorkflowRun,\n comp: Extract<Compensation, { dispatch: unknown }>,\n seq: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<UnwindPending | undefined> {\n const { def, args } = comp.dispatch;\n const name = `compensate:${comp.name}`;\n const existing = replay?.get(seq) ?? (await this.store.getCheckpoint(run.id, seq));\n if (existing?.status === 'completed') return undefined;\n if (existing?.status === 'pending') return {}; // dispatched, awaiting the worker's result\n if (existing?.status === 'failed') {\n const maxAttempts = Math.max(1, def.retries ?? 1);\n const retryable = existing.error?.retryable !== false;\n if (!retryable || existing.attempts >= maxAttempts) return undefined;\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + backoffDelay(existing.attempts, def);\n const withWakeAt = { ...existing, wakeAt };\n await this.store.saveCheckpoint(withWakeAt);\n replay?.set(seq, withWakeAt);\n return { wakeAt };\n }\n if (this.clock() < existing.wakeAt) return { wakeAt: existing.wakeAt };\n await this.dispatchCompensationAttempt(\n run,\n seq,\n name,\n def,\n args,\n existing.attempts + 1,\n replay,\n );\n return {};\n }\n // Absent: first dispatch.\n await this.dispatchCompensationAttempt(run, seq, name, def, args, 1, replay);\n return {};\n }\n\n /**\n * Dispatch (or re-dispatch, on a durable retry) one compensation's undo handler — mirrors\n * `callRemote`'s dispatch block (persist the `pending` checkpoint BEFORE handing off to the\n * transport, so a fast result always finds it to complete). Two DIFFERENT names are in play: the\n * checkpoint's `name` is `compensate:<originalStepName>` (what makes this undo show up on the run's\n * timeline, and what `completeRemoteResult` emits `step.completed`/`step.failed` under); the WIRE\n * task's `name` is the undo handler's OWN routing name (`def.name`) — a worker dispatches to the\n * `@Step` it registered, not to this saga-visibility label.\n */\n private async dispatchCompensationAttempt(\n run: WorkflowRun,\n seq: number,\n name: string,\n def: StepDef<StepUndo<unknown, unknown>, unknown>,\n args: StepUndo<unknown, unknown>,\n attempt: number,\n replay?: Map<number, StepCheckpoint>,\n ): Promise<void> {\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // The undo belongs to the tenant that ran the step it undoes — route it off the RUN, never off\n // the executing engine (see {@link stepGroup}).\n const group = stepGroup(def, run.namespace);\n const enqueuedAt = new Date();\n const cp = stepCheckpoint({\n runId: run.id,\n seq,\n name,\n kind: 'remote',\n status: 'pending',\n input: args,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt: enqueuedAt,\n finishedAt: enqueuedAt,\n });\n await this.store.saveCheckpoint(cp);\n replay?.set(seq, cp);\n await this.pool.dispatch({\n runId: run.id,\n seq,\n name: def.name,\n stepId: cp.stepId,\n group,\n input: args,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt,\n });\n this.emit({ type: 'step.started', runId: run.id, seq, name, kind: 'remote' });\n }\n\n /** The seam handed to {@link createWorkflowCtx}: the authoring API reaches durability + lifecycle\n * (checkpointing, dispatch, child start) through this, so the ctx primitives live in their own\n * module and the engine stays the orchestrator. */\n private ctxHostFor(replay?: Map<number, StepCheckpoint>, parentNamespace?: string): CtxHost {\n return {\n store: this.store,\n replay,\n clock: this.clock,\n webhookUrl: this.webhookUrl,\n startStep: (s) => this.startStep(s),\n completeStep: (s) => this.completeStep(s),\n failStep: (s) => this.failStep(s),\n // Route the dispatch by the RUN's tenant (same reason as `startChild` below): the executing\n // engine may be an operator driving every namespace, so the token must come from the run, not\n // from this engine. See {@link stepGroup}.\n callRemote: (runId, seq, step, input, queue, transport, admission) =>\n this.callRemote(runId, seq, step, input, queue, transport, replay, admission, {\n namespace: parentNamespace,\n }),\n // Defer so a fast child can't reentrantly resume a still-running parent. Stamp the child with\n // the PARENT run's namespace (not this engine's) so a child belongs to the tenant/partition of\n // the run it was spawned from — even when an operator (namespace: undefined, drives every\n // namespace) is the one executing the parent. Otherwise an operator recovery-resuming a\n // `davi-local` pipeline would stamp its `processing` child `default` and it would leak off the\n // tenant's worker pool onto the shared/dev workers.\n startChild: (workflow, input, id, priority, version) => {\n this.startChildDeferred(workflow, input, id, {\n priority,\n namespace: parentNamespace,\n // Absent unless the body pinned one (`ctx.child(ref, input, { version })`) — an omitted\n // pin must stay omitted, so the child keeps resolving `latest` exactly as before.\n version,\n });\n },\n // Deferred for the same reentrancy reason as `startChild` above. `cancel()` is already\n // idempotent on a terminal/cancelled run (returns its existing status without side effects), so\n // no extra guard is needed here for the failFast replay case (re-issuing the same cancel calls).\n cancelChild: (childId) => {\n queueMicrotask(() => void this.cancel(childId).catch(() => undefined));\n },\n // Shallow-merge into the run's searchAttributes (the ctx primitive makes this exactly-once).\n upsertSearchAttributes: async (runId, attrs) => {\n const run = await this.store.getRun(runId);\n await this.store.updateRun(runId, {\n searchAttributes: { ...(run?.searchAttributes ?? {}), ...attrs },\n updatedAt: new Date(),\n });\n },\n signalEntity: (name, key, op, arg, reply) => {\n queueMicrotask(\n () => void this.entities.dispatch(name, key, op, arg, reply).catch(() => undefined),\n );\n },\n interceptStep: (invocation, body) => this.interceptStep(invocation, body),\n };\n }\n\n /**\n * Resume a run paused at a {@link WorkflowCtx.breakpoint} (e.g. the dashboard \"continue\" button).\n * Finds the run's pending breakpoint checkpoint and signals it. Returns null if the run isn't\n * paused at a breakpoint.\n */\n async continue(runId: string): Promise<RunResult | null> {\n const checkpoints = await this.store.listCheckpoints(runId);\n const bp = checkpoints.find(isBreakpoint);\n if (!bp) return null;\n return this.signal(breakpointToken(runId, bp.seq), undefined);\n }\n\n /**\n * Read the latest value a run published for `key` via {@link WorkflowCtx.setEvent} — a\n * side-effect-free query of a live (or finished) run's state. Returns `undefined` if the run\n * never published that key. The suspend-model counterpart of a Temporal query.\n */\n async getEvent<TValue = unknown>(runId: string, key: string): Promise<TValue | undefined> {\n const name = `event:${key}`;\n // Targeted read: the highest-seq checkpoint for this name is the most recent value (a re-published\n // key overwrites at a higher seq), matching the old \"last in seq order wins\" scan. Falls back to a\n // full listCheckpoints scan (last match in seq-ascending order wins) for a store that omits it.\n if (this.store.getLatestCheckpointByName) {\n const latest = await this.store.getLatestCheckpointByName(runId, name);\n return latest?.output as TValue | undefined;\n }\n // listCheckpoints is ordered by seq ascending, so the last match is the most recent value.\n let latest: TValue | undefined;\n for (const cp of await this.store.listCheckpoints(runId))\n if (cp.name === name) latest = cp.output as TValue;\n return latest;\n }\n\n /**\n * Register a validator gating `engine.update(runId, name, …)` for runs of `workflow`. The\n * validator runs BEFORE the update is delivered, so a rejection leaves the run untouched. One\n * validator per (workflow, update name); registering again replaces it.\n */\n registerUpdateValidator<TArg>(\n workflow: string,\n name: string,\n validate: UpdateValidator<TArg>,\n ): void {\n this.updateValidators.set(`${workflow}:${name}`, validate as UpdateValidator);\n }\n\n /**\n * Deliver a validated update to the run waiting at `ctx.onUpdate(name)`. Runs the registered\n * validator (if any) first: on rejection returns `{ accepted: false, reason }` without disturbing\n * the run; otherwise delivers `arg` and resumes, returning `{ accepted: true, run }` (`run` is null\n * if nothing was waiting — a too-early or duplicate update).\n */\n async update(runId: string, name: string, arg: unknown): Promise<UpdateResult> {\n const run = await this.store.getRun(runId);\n if (!run) return { accepted: false, reason: `run ${runId} not found` };\n const validate = this.updateValidators.get(`${run.workflow}:${name}`);\n if (validate) {\n try {\n const reason = await validate(arg);\n if (typeof reason === 'string' && reason.length > 0) return { accepted: false, reason };\n } catch (err) {\n return { accepted: false, reason: err instanceof Error ? err.message : String(err) };\n }\n }\n const result = await this.signal(`update:${runId}:${name}`, arg);\n return { accepted: true, run: result };\n }\n\n /**\n * Plan a dispatch to `token` for a handler requiring `requires` (handshake design §7.5). Returns:\n * - `undefined` — NO live descriptors published on this token: the guard does not engage, so a\n * pre-handshake fleet (or an in-process transport that advertises none) keeps flowing exactly as\n * before (design §7.7);\n * - a `routable` plan — ≥1 live worker is capability-capable AND protocol-compatible (dispatch);\n * - a `blocked` plan — descriptors exist but none can run it (park the run, never dispatch into it).\n */\n private async planRoute(\n token: string,\n requires: string[] | undefined,\n ): Promise<DispatchPlan | undefined> {\n const descriptors = await this.pool.readWorkerDescriptors(token);\n if (descriptors.length === 0) return undefined; // legacy / no-descriptor path — skip the guard\n return planDispatch(requires ?? [], descriptors, this.cpDescriptor, token);\n }\n\n /** Throw {@link WorkflowBlocked} when no live worker can run a dispatch to `token` — so the caller's\n * run-execution catch parks the run `blocked` (with the plan) instead of persisting a `pending`\n * checkpoint + dispatching into a queue nobody consumes (design §7.5). A no-op when the guard does\n * not engage (no descriptors) or a capable+compatible worker exists. */\n private async ensureRoutable(token: string, requires: string[] | undefined): Promise<void> {\n const plan = await this.planRoute(token, requires);\n if (plan?.status === 'blocked') throw new WorkflowBlocked(plan);\n }\n\n /**\n * Park a run `blocked` (handshake design §7.5/§7.6): no live worker on its next-dispatch group is\n * capability-capable + protocol-compatible. Persists the `blocked` status with a human reason + the\n * machine `code` + a `wakeAt` so the blocked-recovery poll re-drives it, emits the LOUD structured\n * `capability.unavailable`/`protocol.incompatible` diagnostics (both descriptors + the precise delta),\n * and releases the run lease so any instance can re-drive it. Re-checks the persisted status first so\n * a concurrent cancel/complete is never clobbered. `releaseRunLock` is idempotent, so a caller whose\n * own `finally` also releases (the run-execution path) is safe.\n */\n private async parkBlocked(run: WorkflowRun, blocked: BlockedDispatch): Promise<RunResult> {\n const current = await this.store.getRun(run.id);\n if (current && (current.status === 'cancelled' || current.status === 'completed')) {\n await this.store.releaseRunLock(run.id);\n return {\n runId: run.id,\n status: current.status,\n output: current.output,\n error: current.error,\n };\n }\n const error: StepError = { message: blocked.reason, code: blocked.code, retryable: true };\n await this.store.updateRun(run.id, {\n status: 'blocked',\n error,\n wakeAt: this.clock() + this.blockedPollMs,\n updatedAt: new Date(),\n });\n this.emit({\n type: 'run.blocked',\n runId: run.id,\n workflow: run.workflow,\n namespace: run.namespace,\n error,\n requires: blocked.requires,\n diagnostics: blocked.diagnostics,\n });\n await this.store.releaseRunLock(run.id);\n return { runId: run.id, status: 'blocked', error };\n }\n\n /** Runs parked `blocked` whose recovery poll is due (`wakeAt <= nowMs`), namespace-scoped like\n * {@link resumeDueTimers}. Re-driving one re-checks the live fleet: it dispatches if a\n * capable+compatible worker has appeared, else re-parks with a fresh `wakeAt` (design §7.5). */\n private async dueBlockedRuns(nowMs: number): Promise<WorkflowRun[]> {\n const blocked = await this.store.listRuns({ statuses: ['blocked'] });\n return blocked.filter(\n (r) =>\n (this.namespace === undefined ||\n r.namespace === undefined ||\n r.namespace === this.namespace) &&\n r.wakeAt !== undefined &&\n r.wakeAt <= nowMs,\n );\n }\n\n private async callRemote<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n queue?: string,\n transport?: string,\n replay?: Map<number, StepCheckpoint>,\n admission?: { priority?: number | undefined; fairnessKey?: string | undefined },\n routing?: { namespace?: string | undefined },\n ): Promise<TOutput> {\n const group = stepGroup(step, routing?.namespace);\n // Read the prefix from the per-execution snapshot (avoids the O(N²) replay SELECTs); a seq absent\n // from the snapshot — not yet dispatched, or written after the snapshot — falls back to the store.\n let existing = replay?.get(seq) ?? (await this.store.getCheckpoint(runId, seq));\n // A `pending` step in the SNAPSHOT may already have its result: the snapshot is taken when this\n // execution starts, and the result can land any time after. Every branch below that sees\n // `pending` either suspends on it or WRITES the checkpoint back (`{ ...existing, wakeAt }` stamping\n // the lost-dispatch lease, or a re-dispatch) — written from a stale row, that overwrites the landed\n // `completed` result with `pending` and parks the run on a lease an hour out. So a pending step is\n // re-read from the store before anything acts on it (one read, only at a suspension point).\n if (existing?.status === 'pending' && replay?.has(seq)) {\n existing = (await this.store.getCheckpoint(runId, seq)) ?? existing;\n }\n if (existing && existing.name !== step.name) {\n throw new NonDeterminismError(runId, seq, step.name, existing.name);\n }\n if (existing?.status === 'completed') return existing.output as TOutput;\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // A step with a liveness `timeoutMs` keeps the in-memory await + heartbeat path (re-dispatch a\n // presumed-dead worker). Without one, the call SUSPENDS DURABLY: dispatch, persist a `pending`\n // checkpoint, and let the result resume the run on whichever instance receives it — so a worker\n // pod can scale down or crash mid-step without losing the run or re-running completed work.\n if (step.timeoutMs) return this.callRemoteInMemory(runId, seq, step, input, transport, group);\n if (existing?.status === 'pending') {\n // Dispatched; normally we just keep waiting for the result to resume the run. But a LOST dispatch\n // (worker crashed with no result, or the transport dropped the job) would hang here forever — a\n // reconcile re-drive replays straight back to this guard. Opt-in self-heal: once the step has been\n // pending longer than `remoteRedispatchMs`, re-dispatch the same stepId (the idempotent step\n // re-runs, its result resumes the run), bounded by `remoteRedispatchMax` so a never-settling step\n // fails instead of looping. Unset (default) keeps the by-design \"re-suspend, never re-dispatch\".\n if (this.remoteRedispatchMs == null) throw new WorkflowSuspended();\n // Stamp a redispatch deadline (clock-space, persisted) the first time we see this pending step,\n // stable across replays and crashes — mirrors the failed-retry backoff below. The run's wakeAt\n // becomes this deadline, so a reconcile re-drive lands exactly when it's due to re-dispatch.\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + this.remoteRedispatchMs;\n await this.store.saveCheckpoint({ ...existing, wakeAt });\n throw new WorkflowSuspended(wakeAt);\n }\n if (this.clock() < existing.wakeAt) throw new WorkflowSuspended(existing.wakeAt);\n // Past the deadline with no result — the dispatch is presumed lost. Re-dispatch (bounded by\n // `remoteRedispatchMax` so a step that never settles fails the run instead of looping forever).\n if (existing.attempts >= this.remoteRedispatchMax) {\n throw new RemoteStepError({\n message: `remote step \"${step.name}\" lost — no result after ${existing.attempts} re-dispatch(es)`,\n code: 'remote_step_lost',\n });\n }\n const reAttempt = existing.attempts + 1;\n const nextDeadline = this.clock() + this.remoteRedispatchMs;\n const reEnqueuedAt = new Date();\n await this.store.saveCheckpoint({\n ...existing,\n attempts: reAttempt,\n wakeAt: nextDeadline,\n enqueuedAt: reEnqueuedAt,\n startedAt: reEnqueuedAt,\n finishedAt: reEnqueuedAt,\n // Same observable marker the polyglot `call` path stamps (see redriveLostCall): the step's own\n // trail distinguishes a lost-dispatch re-drive from a failure retry.\n events: [\n ...(existing.events ?? []),\n lostStepEvent(this.clock(), reAttempt, 'redispatched'),\n ],\n });\n await this.dispatchRemoteTask({\n runId,\n seq,\n name: step.name,\n stepId: existing.stepId ?? stepId(runId, seq),\n group: existing.workerGroup ?? group,\n input: existing.input,\n priority: admission?.priority,\n attempt: reAttempt,\n transport,\n });\n this.emit({\n type: 'step.started',\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n redispatched: true,\n });\n throw new WorkflowSuspended(nextDeadline);\n }\n\n // Durable retry: a failed attempt re-dispatches up to `retries`, spacing attempts by `backoff` —\n // unless the worker marked the error non-retryable (a deterministic verdict like a declined card).\n // The retry deadline is stamped on the failed checkpoint as `wakeAt` (clock-space, persisted) the\n // first time we see it, so it's stable across replays and survives a crash.\n let attempt = 1;\n if (existing?.status === 'failed') {\n const maxAttempts = Math.max(1, step.retries ?? 1);\n const retryable = existing.error?.retryable !== false;\n if (!retryable || existing.attempts >= maxAttempts) throw new RemoteStepError(existing.error);\n if (existing.wakeAt == null) {\n const wakeAt = this.clock() + backoffDelay(existing.attempts, step);\n await this.store.saveCheckpoint({ ...existing, wakeAt });\n throw new WorkflowSuspended(wakeAt);\n }\n if (this.clock() < existing.wakeAt) throw new WorkflowSuspended(existing.wakeAt);\n attempt = existing.attempts + 1;\n }\n\n // Capability/protocol routing guard (handshake design §7.5): BEFORE consuming an admission slot or\n // writing a `pending` checkpoint, ensure a live worker on this step's group is capability-capable\n // AND protocol-compatible. If descriptors are published on the group but none qualifies, throw\n // `WorkflowBlocked` — the run-execution catch parks the run `blocked` (with a `wakeAt` for the\n // recovery poll) so it neither dispatches into a queue nobody consumes nor leaves a `pending` row a\n // later re-drive mistakes for \"already dispatched\". No descriptors published → guard skipped, the\n // legacy fleet keeps flowing (design §7.7).\n await this.ensureRoutable(group, step.requires);\n\n const id = stepId(runId, seq);\n // Flow control: a queued call that can't be admitted (concurrency/rate) does NOT dispatch — the\n // run re-suspends with the queue's retry time and the timer poller re-tries admission later, so\n // the limit is durable. The admitted slot is released when the result lands (completeRemoteResult).\n if (queue && this.admission.handles(queue)) {\n // Admission carries the per-call priority + fairness key (default the runId so each run is its\n // own fairness bucket), and the stepId as a STABLE waiter id so the backend tracks one waiter\n // across this call's durable retries. Ordering lives in the backend (in-process by default, or\n // global) — this is the dispatch/admission layer, not the positional replay path.\n const decision = await this.admission.tryAdmit(queue, {\n priority: admission?.priority,\n key: admission?.fairnessKey ?? runId,\n waiterId: id,\n });\n if (!decision.ok) {\n // Remember this run as blocked on `queue` so a freed-slot signal can wake it early.\n const waiters = this.queueWaiters.get(queue) ?? new Set<string>();\n waiters.add(runId);\n this.queueWaiters.set(queue, waiters);\n throw new WorkflowSuspended(decision.retryAt);\n }\n this.queueWaiters.get(queue)?.delete(runId);\n this.stepQueue.set(id, queue);\n }\n\n const enqueuedAt = new Date();\n // Persist the pending checkpoint BEFORE dispatching, so a fast result always finds it to complete.\n await this.store.saveCheckpoint({\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n stepId: id,\n status: 'pending',\n input,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt: enqueuedAt, // placeholders until the worker result lands\n finishedAt: enqueuedAt,\n });\n await this.dispatchRemoteTask({\n runId,\n seq,\n name: step.name,\n stepId: id,\n group,\n input,\n priority: admission?.priority,\n attempt,\n transport,\n });\n this.emit({ type: 'step.started', runId, seq, name: step.name, kind: 'remote' });\n throw new WorkflowSuspended();\n }\n\n /** Enqueue a remote step task to its worker group via the transport pool. Shared by the initial\n * dispatch, the opt-in self-heal re-dispatch (see `remoteRedispatchMs`), and the explicit\n * {@link redispatchPending}. Carries the current trace/context so a re-dispatch is traceable. */\n private dispatchRemoteTask(task: {\n runId: string;\n seq: number;\n name: string;\n stepId: string;\n group: string;\n input: unknown;\n attempt: number;\n priority?: number | undefined;\n transport?: string | undefined;\n }): Promise<void> {\n return this.pool.dispatch(\n {\n runId: task.runId,\n seq: task.seq,\n name: task.name,\n stepId: task.stepId,\n group: task.group,\n input: task.input,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n priority: task.priority,\n attempt: task.attempt,\n },\n task.transport,\n );\n }\n\n /**\n * Complete a durable remote step from its worker result and resume the run — runs on whichever\n * instance receives the result (the dispatching one may be gone), so the run is crash/scale-safe.\n * A no-op if the checkpoint isn't `pending` (a duplicate or late delivery).\n */\n private async completeRemoteResult(result: StepResult): Promise<void> {\n const cp = await this.store.getCheckpoint(result.runId, result.seq);\n if (!cp || cp.status !== 'pending') return;\n // A result settling this step frees its flow-control slot (no-op if it wasn't queued). Done\n // before the cancelled-run early-return below, so a cancellation can't leak the slot. Released\n // fire-and-forget: the slot/notify is best-effort (a global backend self-heals via lease), and\n // not awaiting keeps it off the result-processing critical path (no ordering shift).\n void this.releaseQueueSlot(cp.stepId).catch(() => undefined);\n // Drop a late result for a run that was cancelled/finished meanwhile — don't complete the step\n // or resume (the run is already terminal). This is the engine side of cooperative cancellation.\n const run = await this.store.getRun(result.runId);\n if (run && (run.status === 'cancelled' || run.status === 'completed')) return;\n const finishedAt = new Date();\n const startedAt = result.startedAt ? new Date(result.startedAt) : cp.startedAt;\n await this.store.saveCheckpoint({\n ...cp,\n status: result.status,\n output: result.status === 'completed' ? result.output : cp.output,\n error: result.error,\n events: result.events ?? cp.events,\n startedAt,\n finishedAt,\n });\n this.emit({\n type: result.status === 'completed' ? 'step.completed' : 'step.failed',\n runId: result.runId,\n seq: result.seq,\n name: cp.name,\n kind: cp.kind,\n output: result.output,\n error: result.error,\n queueMs: startedAt.getTime() - cp.enqueuedAt.getTime(),\n durationMs: finishedAt.getTime() - startedAt.getTime(),\n });\n await this.resumeImplicit(result.runId).catch((err) => {\n if (err instanceof NamespaceMismatch) return null;\n throw err;\n });\n }\n\n /**\n * Apply a remote workflow-turn {@link WorkflowDecision} durably — runs on WHATEVER instance receives\n * it over the broker (the dispatching one may be gone, or a point-to-point broker handed it to a\n * non-dispatcher). The durable, multi-instance-safe twin of {@link completeRemoteResult} for the\n * workflow TURN: look the run up by `decision.runId`, verify the decision matches the run's\n * CURRENTLY-awaited turn (`awaitingDecisionTaskId`) — so a stale / duplicate / foreign / re-driven\n * decision is dropped (applied AT MOST ONCE) — lease it, clear the marker, and apply the decision.\n */\n private async completeRemoteDecision(decision: WorkflowDecision): Promise<void> {\n // Cheap pre-checks before contending for the lease: only the run currently awaiting THIS taskId\n // (and not already terminal) is a candidate. A re-driven turn has a different taskId, so a late\n // decision for the prior turn is dropped here.\n const run = await this.store.getRun(decision.runId);\n if (!run || run.awaitingDecisionTaskId !== decision.taskId) return;\n if (run.status === 'cancelled' || run.status === 'completed' || run.status === 'dead') return;\n if (\n this.namespace !== undefined &&\n run.namespace !== undefined &&\n run.namespace !== this.namespace\n ) {\n return;\n }\n const nowMs = this.clock();\n // Lease so exactly one instance applies it — serialized with a concurrent timer re-drive of the\n // same run. If the lease is held (a re-drive in flight), drop: the re-driven turn produces a fresh\n // decision. The common single-decision path is uncontended, so this acquires immediately.\n if (\n !(await this.store.tryLockRun(decision.runId, this.instanceId, nowMs + this.leaseMs, nowMs))\n ) {\n return;\n }\n const renew = setInterval(\n () => {\n void this.store\n .renewRunLock(decision.runId, this.instanceId, this.clock() + this.leaseMs)\n .catch(() => undefined);\n },\n Math.max(50, Math.floor(this.leaseMs / 2)),\n );\n renew.unref?.();\n try {\n // Re-read under the lease and re-check the marker — it may have changed (a re-drive applied\n // first, or another decision raced in) between the unlocked pre-check and acquiring the lease.\n const fresh = await this.store.getRun(decision.runId);\n if (!fresh || fresh.awaitingDecisionTaskId !== decision.taskId) return;\n if (fresh.status === 'cancelled' || fresh.status === 'completed' || fresh.status === 'dead') {\n return;\n }\n // Clear the awaited-turn marker and the re-drive deadline: this turn is now being applied exactly\n // once. `applyDecision` resets `wakeAt` itself when it suspends on the turn's blocking ops.\n await this.store.updateRun(decision.runId, {\n awaitingDecisionTaskId: undefined,\n wakeAt: undefined,\n updatedAt: new Date(),\n });\n fresh.awaitingDecisionTaskId = undefined;\n await this.applyDecision(fresh, decision);\n } finally {\n clearInterval(renew);\n await this.store.releaseRunLock(decision.runId);\n }\n }\n\n /** Earliest clock time a suspended turn's deadline is worth LOOKING at again (`runId` → clock ms) —\n * the read throttle for {@link rearmDecisionDeadline}, the run-scoped sibling of\n * {@link stepLeaseRearms}. */\n private readonly decisionDeadlineRearms = new Map<string, number>();\n\n /**\n * A run-scoped heartbeat for a run suspended awaiting a workflow-turn decision (the dispatch path):\n * push its durable re-drive deadline (`wakeAt`) forward so a still-working worker's turn is not\n * re-dispatched. The durable counterpart of an inline turn's in-memory `heartbeatResets` rearm.\n *\n * THROTTLED exactly as {@link rearmStepLease} is, and for the same reason: a long workflow turn's\n * worker beats every couple of seconds, and each beat otherwise cost a `getRun` + `updateRun`.\n * The window here is `remoteAdvanceSilenceMs`, and a renewal buys at most one of them — so it is\n * only worth a write once the window is half spent, which leaves a full half-window of headroom\n * before the timer poller would re-drive the turn. The in-memory mark is a pure optimisation: a\n * cold (or different) instance re-derives the same answer from the run's own `wakeAt`.\n */\n private async rearmDecisionDeadline(runId: string): Promise<void> {\n const silenceMs = this.remoteAdvanceSilenceMs;\n if (silenceMs == null) return;\n const now = this.clock();\n const lookAgainAt = this.decisionDeadlineRearms.get(runId);\n if (lookAgainAt !== undefined && now < lookAgainAt) return;\n // Read AND write swallowed, for the same reason {@link rearmStepLease} swallows its own: the\n // transport's beat loop is serial and uncaught, so a throwing rearm takes it (or the process) down,\n // while a skipped beat costs nothing while half the window remains — and the mark is only advanced\n // after the write commits, so the next beat retries.\n try {\n const run = await this.store.getRun(runId);\n if (!run || run.status !== 'suspended' || run.awaitingDecisionTaskId === undefined) {\n // Not awaiting a turn any more (settled, or re-driven under a fresh taskId): stop tracking it.\n this.decisionDeadlineRearms.delete(runId);\n return;\n }\n const halfWindow = Math.ceil(silenceMs / 2);\n // More than half the window left: nothing to buy, and nothing to look at until it is half spent.\n if (run.wakeAt != null && run.wakeAt > now + halfWindow) {\n this.decisionDeadlineRearms.set(runId, run.wakeAt - halfWindow);\n return;\n }\n const renewed = now + silenceMs;\n await this.store.updateRun(runId, { wakeAt: renewed, updatedAt: new Date() });\n if (this.decisionDeadlineRearms.size > 1024) this.decisionDeadlineRearms.clear();\n this.decisionDeadlineRearms.set(runId, renewed - halfWindow);\n } catch {\n // Best-effort liveness: a store blip costs one skipped renewal, never the beat loop.\n }\n }\n\n /**\n * A slot freed on `queue` (a fleet-wide signal): resume this instance's runs blocked on it so they\n * re-contend now instead of at their retry tick. Snapshot-and-clear — a run still blocked after the\n * retry re-registers itself, and one that's gone (cancelled/admitted) is dropped. Best-effort.\n */\n private wakeQueueWaiters(queue: string): void {\n const waiters = this.queueWaiters.get(queue);\n if (!waiters || waiters.size === 0) return;\n const runIds = [...waiters];\n waiters.clear();\n for (const runId of runIds) void this.resumeImplicit(runId).catch(() => undefined);\n }\n\n /** Release the flow-control slot a dispatched step held (if any), by its stepId. */\n private async releaseQueueSlot(id: string): Promise<void> {\n const queue = this.stepQueue.get(id);\n if (queue === undefined) return;\n this.stepQueue.delete(id);\n await this.admission.release(queue, id);\n }\n\n /** In-memory await path for a remote step with a liveness `timeoutMs` (re-dispatch on timeout). */\n private async callRemoteInMemory<TInput, TOutput>(\n runId: string,\n seq: number,\n step: StepDef<TInput, TOutput>,\n input: TInput,\n transport?: string,\n /** The run-tenant-aware routing token, computed by {@link callRemote} (see {@link stepGroup}). */\n group = stepGroup(step, undefined),\n ): Promise<TOutput> {\n if (this.pool.size === 0) throw new Error('remote steps require a Transport');\n // Capability/protocol routing guard (handshake design §7.5), same as the durable `callRemote` path:\n // BEFORE the first dispatch, ensure a live worker on this step's group is capability-capable AND\n // protocol-compatible. If descriptors are published on the group but none qualifies, throw\n // `WorkflowBlocked` — the run-execution catch parks the run `blocked` instead of dispatching into a\n // queue nobody consumes (this `timeoutMs` path would otherwise burn its liveness window + retries\n // waiting on a worker that can't run it). No descriptors published → guard skipped (legacy, §7.7).\n await this.ensureRoutable(group, step.requires);\n // A bare `@Step()` (no `input`/`output` schemas attached) skips validation.\n const validInput = step.input ? step.input.parse(input) : input;\n const id = stepId(runId, seq);\n const enqueuedAt = new Date();\n this.emit({ type: 'step.started', runId, seq, name: step.name, kind: 'remote' });\n // Retry policy differs from an in-process step on purpose: the internal in-process primitives\n // (`ctx.task`'s dispatch, `ctx.now`/`ctx.sideEffect`) retry any non-fatal throw (the work is in-process),\n // but a dispatched `ctx.step` only re-dispatches on a liveness TIMEOUT (presumed-dead worker). A\n // worker that *reported* an error returned a deterministic verdict, so we surface it to the\n // workflow instead of hammering the worker. Timeout retries need a window to detect death, so\n // they're gated on `timeoutMs` being set.\n const maxAttempts = step.timeoutMs ? Math.max(1, step.retries ?? 1) : 1;\n\n for (let attempt = 1; ; attempt += 1) {\n const resultPromise = new Promise<RemoteResolution>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n });\n await this.pool.dispatch(\n {\n runId,\n seq,\n name: step.name,\n stepId: id,\n group,\n input: validInput,\n traceparent: this.traceparent?.(),\n context: this.context?.(),\n attempt,\n },\n transport,\n );\n try {\n const resolution = step.timeoutMs\n ? await this.awaitWithHeartbeat(id, resultPromise, step.timeoutMs)\n : await resultPromise;\n const output = step.output\n ? (step.output.parse(resolution.output) as TOutput)\n : (resolution.output as TOutput);\n // The worker reports when it actually picked the task up; fall back to dispatch time if a\n // transport doesn't carry it (queue-wait then reads as zero rather than going negative).\n const startedAt = resolution.startedAt ? new Date(resolution.startedAt) : enqueuedAt;\n await this.completeStep({\n runId,\n seq,\n name: step.name,\n kind: 'remote',\n input: validInput,\n output,\n events: resolution.events,\n attempts: attempt,\n workerGroup: group,\n enqueuedAt,\n startedAt,\n });\n return output;\n } catch (err) {\n this.pending.delete(id);\n if (err instanceof RemoteStepTimeout && attempt < maxAttempts) continue;\n throw err;\n }\n }\n }\n\n /**\n * Await `resultPromise`, but reject with `onTimeout()` if neither it settles nor a heartbeat for `id`\n * arrives within `timeoutMs`. Each heartbeat (delivered via `transport.onHeartbeat`, looked up in\n * `heartbeatResets` by `id`) REARMS the window, so a worker that keeps beating stays alive past\n * `timeoutMs`. Shared by the remote-STEP liveness (keyed by stepId) and the remote-WORKFLOW advance\n * liveness (keyed by runId); the caller supplies the timeout error and any extra cleanup via `onTimeout`.\n */\n private awaitWithLivenessDeadline<T>(\n id: string,\n resultPromise: Promise<T>,\n timeoutMs: number,\n onTimeout: () => Error,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout>;\n const cleanup = () => {\n clearTimeout(timer);\n this.heartbeatResets.delete(id);\n };\n const arm = () => {\n timer = setTimeout(() => {\n cleanup();\n reject(onTimeout());\n }, timeoutMs);\n (timer as { unref?: () => void }).unref?.();\n };\n this.heartbeatResets.set(id, () => {\n clearTimeout(timer);\n arm();\n });\n arm();\n resultPromise.then(\n (value) => {\n cleanup();\n resolve(value);\n },\n (err) => {\n cleanup();\n reject(err);\n },\n );\n });\n }\n\n /** Remote-STEP liveness: await a worker result, timing out (with the step's pending-map cleanup) to\n * `RemoteStepTimeout` if it neither lands nor beats within `timeoutMs`. See {@link awaitWithLivenessDeadline}. */\n private awaitWithHeartbeat(\n id: string,\n resultPromise: Promise<RemoteResolution>,\n timeoutMs: number,\n ): Promise<RemoteResolution> {\n return this.awaitWithLivenessDeadline(id, resultPromise, timeoutMs, () => {\n this.pending.delete(id);\n return new RemoteStepTimeout(id, timeoutMs);\n });\n }\n}\n\n/** Raised inside the workflow when a remote worker reports a step failure. */\nexport class RemoteStepError extends Error {\n readonly stepError?: StepError | undefined;\n constructor(stepError?: StepError) {\n super(stepError?.message ?? 'remote step failed');\n this.name = 'RemoteStepError';\n this.stepError = stepError;\n }\n}\n\n/** Checkpoint names that record a parent→child edge: an awaited child, a folded group of them, a spawn. */\nconst CHILD_EDGE_PREFIXES = ['signal:child:', FOLDED_PREFIX, 'spawn:'];\n\n/** The child run ids a parent's {@link CHILD_EDGE_PREFIXES} checkpoints point at. */\nfunction childIdsOf(checkpoints: StepCheckpoint[]): string[] {\n const ids: string[] = [];\n for (const cp of checkpoints) {\n if (cp.name.startsWith('signal:child:')) ids.push(cp.name.slice('signal:child:'.length));\n if (cp.name.startsWith(FOLDED_PREFIX)) ids.push(...foldedChildIds(cp));\n if (cp.name.startsWith('spawn:') && typeof cp.output === 'string') ids.push(cp.output);\n }\n return ids;\n}\n","import type { RunFacetRow, RunStatus } from './interfaces';\n\n/**\n * The origin a facet cell is filed under. An origin that is absent, null, or blank is all the same\n * thing to an operator — a run no package claims — so they collapse to `null` here. Without this the\n * \"unknown\" chip would count only one of those spellings while `origin IS NULL` paging returned\n * another, and the chip's number would not match the page it opens.\n */\nexport function facetOrigin(origin: string | null | undefined): string | null {\n return origin?.trim() ? origin : null;\n}\n\n/**\n * Fold `(status, origin)` counts into one cell per pair, normalising origins via {@link facetOrigin}.\n * Store adapters group in SQL and pipe their rows through this, so every adapter — and the in-memory\n * store the tests run against — agrees on what lands in the unattributed bucket instead of each\n * collapsing blanks its own way.\n */\nexport function mergeRunFacetRows(\n rows: readonly { status: RunStatus; origin: string | null | undefined; count: number }[],\n): RunFacetRow[] {\n const cells = new Map<string, RunFacetRow>();\n for (const row of rows) {\n const origin = facetOrigin(row.origin);\n const key = JSON.stringify([row.status, origin]);\n const cell = cells.get(key);\n if (cell) cell.count += row.count;\n else cells.set(key, { status: row.status, origin, count: row.count });\n }\n return [...cells.values()];\n}\n","import type {\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n WorkflowRun,\n} from './interfaces';\nimport { facetOrigin } from './run-facets';\n\n/** Rows a value picker gets when the caller names no bound — enough to fill a dropdown several times\n * over, small enough that an axis with unbounded cardinality (tags) can't return a listing. */\nexport const RUN_VALUE_FACET_LIMIT = 100;\n\n/** Runs read when an axis has to be counted in-process (see {@link RunValueFacetOptions.scan}). */\nexport const RUN_VALUE_FACET_SCAN = 5000;\n\n/**\n * Tag prefixes the ENGINE mints one of PER KEY — `singleton:<key>` is stamped on every run of a\n * singleton workflow so the admission gate can find its siblings.\n *\n * A picker ranks these last. They are machine bookkeeping with cardinality that grows with the data,\n * and on a real deployment they crowd out everything an operator would actually choose: measured on\n * a 12k-run control plane, 82 of the top 100 tags were `singleton:*`, pushing genuine tags like\n * `type:mvr` to the edge of the list and past it.\n *\n * Ranked, not REMOVED: a singleton tag is still a legitimate thing to filter by (a run row's tag chip\n * sets exactly that), so it stays offered — just after the tags a human wrote. `version:undeclared`\n * is engine-minted too but is a single fixed value, so it competes fairly and is not listed here.\n */\nexport const ENGINE_MINTED_TAG_PREFIXES = ['singleton:', 'concurrency:'] as const;\n\n/** Is this a tag the engine mints one of per key? See {@link ENGINE_MINTED_TAG_PREFIXES}. */\nexport function isEngineMintedTag(value: string | null): boolean {\n return value !== null && ENGINE_MINTED_TAG_PREFIXES.some((prefix) => value.startsWith(prefix));\n}\n\n/**\n * Is this axis a plain column on the runs table, and so countable with a `GROUP BY` over the whole\n * matching set?\n *\n * The other three are not: the value isn't in a column of the row being counted. A run's tags live\n * inside ONE json array column, and its search attributes in a side table. Neither has a form that\n * is the same across sqlite/MySQL/Postgres — each engine expands a JSON array its own way — so an\n * adapter either writes that dialect SQL (the MikroORM one does, and answers those axes exactly) or\n * counts them in-process over a bounded scan ({@link runValueFacetsFromRuns}), where the counts\n * describe that window rather than the whole store. This function is what the second kind uses.\n */\nexport function axisIsRunColumn(\n axis: RunValueAxis,\n): axis is { field: 'workflow' | 'status' | 'origin' | 'namespace' } {\n return (\n axis.field === 'workflow' ||\n axis.field === 'status' ||\n axis.field === 'origin' ||\n axis.field === 'namespace'\n );\n}\n\n/** The values one run contributes to an axis — several for `tag` (a run carries a set), one for the\n * column axes, and none when the run has nothing on that axis (an absent search-attribute key). */\nfunction valuesOf(run: WorkflowRun, axis: RunValueAxis): Array<string | null> {\n switch (axis.field) {\n case 'workflow':\n return [run.workflow];\n case 'status':\n return [run.status];\n case 'origin':\n return [facetOrigin(run.origin)];\n case 'namespace':\n return run.namespace === undefined ? [] : [run.namespace];\n case 'tag':\n return run.tags ?? [];\n case 'attributeKey':\n return Object.keys(run.searchAttributes ?? {});\n case 'attributeValue': {\n const value = run.searchAttributes?.[axis.key];\n return value === undefined ? [] : [String(value)];\n }\n }\n}\n\n/**\n * Fold, order, search and bound raw `(value, count)` rows into the answer callers see: highest count\n * first, ties broken alphabetically so a picker's order is stable between polls (and therefore\n * pageable), the unattributed bucket (`null`) last, and one `limit`-sized page from `offset`.\n *\n * Every store pipes its `GROUP BY` through this — the same role {@link mergeRunFacetRows} plays for\n * status/origin counts — so a picker lists the same values in the same order whichever adapter is\n * underneath, rather than each SQL dialect's default ordering leaking into the UI.\n */\nexport function mergeRunValueFacetRows(\n rows: readonly { value: string | null | undefined; count: number }[],\n opts?: RunValueFacetOptions,\n): RunValueFacetRow[] {\n const counts = new Map<string | null, number>();\n for (const row of rows) {\n const value = row.value ?? null;\n counts.set(value, (counts.get(value) ?? 0) + Number(row.count));\n }\n const needle = opts?.search?.trim().toLowerCase();\n const merged = [...counts]\n .map(([value, count]) => ({ value, count }))\n .filter((row) => row.count > 0)\n // Applied here rather than by the caller so every store searches identically — and before the\n // bound, so a match outside the top slice is still reachable, which is the whole point of a\n // search box on a list that was cut to fit.\n .filter((row) => !needle || row.value?.toLowerCase().includes(needle))\n .sort((a, b) => {\n // Engine-minted per-key tags rank after everything else, however common they are — see\n // ENGINE_MINTED_TAG_PREFIXES for what they otherwise do to a picker.\n const engineA = isEngineMintedTag(a.value);\n const engineB = isEngineMintedTag(b.value);\n if (engineA !== engineB) return engineA ? 1 : -1;\n if (b.count !== a.count) return b.count - a.count;\n if (a.value === null) return 1;\n if (b.value === null) return -1;\n return a.value.localeCompare(b.value);\n });\n const offset = opts?.offset ?? 0;\n return merged.slice(offset, offset + (opts?.limit ?? RUN_VALUE_FACET_LIMIT));\n}\n\n/**\n * Count an axis's distinct values across runs already narrowed by the caller's predicates — the\n * in-process path, used by the in-memory store for every axis and by a SQL store for the axes it\n * cannot group in the database (see {@link axisIsRunColumn}). `runs` must be ordered newest-first\n * and already bounded to {@link RunValueFacetOptions.scan}, since that window is what the counts\n * then describe.\n */\nexport function runValueFacetsFromRuns(\n runs: readonly WorkflowRun[],\n axis: RunValueAxis,\n opts?: RunValueFacetOptions,\n): RunValueFacetRow[] {\n const rows: { value: string | null; count: number }[] = [];\n for (const run of runs) {\n for (const value of valuesOf(run, axis)) rows.push({ value, count: 1 });\n }\n return mergeRunValueFacetRows(rows, opts);\n}\n","import type {\n EngineEvent,\n GroupHealth,\n RunFacetQuery,\n RunFacetRow,\n RunQuery,\n RunResult,\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n RunWaiting,\n StepCheckpoint,\n WorkflowRun,\n} from './interfaces';\n\n/** A run as returned by the gateway's list — the durable run plus an optional {@link RunWaiting}\n * descriptor the control plane resolves (what a suspended run is parked on), so the dashboard can\n * name the wait in a list row without fetching each run's timeline. Additive: `waiting` is absent\n * on a non-parked run and on gateways/versions that don't compute it. */\nexport type RunListItem = WorkflowRun & { waiting?: RunWaiting | undefined };\n\n/** Which durable topology a gateway speaks for — surfaced in the dashboard so an operator can tell a\n * control plane from a tenant at a glance (the store-backed gateway is the operator; the proxy is a\n * tenant). Cheap, synchronous, local knowledge — no round-trip. */\nexport interface DurableTopology {\n role: 'control-plane' | 'tenant';\n /** The tenant's isolation partition name; set only when `role` is 'tenant'. */\n tenant?: string;\n}\n\n/** A run + its timeline + child ids — the detail view. Single source of truth: the dashboard server\n * re-exports this instead of re-declaring it, and the dashboard client derives its wire mirror from\n * it via {@link WireDates} instead of hand-mirroring field by field. */\nexport interface RunDetail {\n run: WorkflowRun;\n /** Steps in execution order (local + remote). */\n timeline: StepCheckpoint[];\n /** Ids of runs this run spawned (parent→children tree). */\n children: string[];\n}\n\n/**\n * Maps every `Date` (and `Date | undefined`) field of `T` to its ISO-string wire form — the shape a\n * JSON response actually carries once dates cross the wire (`JSON.stringify` already does this\n * coercion; this just types it). Homomorphic: each field keeps its own optional modifier, so a\n * required `Date` becomes a required `string` and an optional one stays optional. Lets a consumer\n * derive its own wire-facing client type from a core server type (e.g. the dashboard's SPA `WorkflowRun`/\n * `StepCheckpoint`/`RunDetail`) instead of hand-mirroring it field by field and drifting.\n */\nexport type WireDates<T> = {\n [K in keyof T]: T[K] extends Date\n ? string\n : T[K] extends Date | undefined\n ? string | undefined\n : T[K];\n};\n\n/**\n * The bounded read/control/stream surface a consumer (e.g. a controller) needs, satisfied by BOTH\n * topologies: the control plane binds a store-backed impl (reuses `DashboardService`); a tenant binds\n * a `ProxyRunGateway` that round-trips over the transport. Deliberately smaller than the full dashboard\n * (no metrics/bulk/update/signal) — those stay control-plane-only. `workerHealth` IS on the port: the\n * operator answers it scoped to the requester's own groups, so a tenant's Workers panel works too.\n *\n * Declared as an **abstract class** rather than an interface so it doubles as its own NestJS DI token\n * (the idiomatic inject-by-type pattern): providers bind `{ provide: RunGateway, useClass/useFactory }`\n * and consumers inject `constructor(private readonly gateway: RunGateway)` with no string/symbol token.\n * `StoreRunGateway`/`ProxyRunGateway` `implements RunGateway`; abstract methods carry no body, so the\n * emitted runtime class is an empty, non-instantiable shell used only as the token.\n */\nexport abstract class RunGateway {\n /** This deployment's durable role (control plane vs tenant) — synchronous local metadata. */\n abstract topology(): DurableTopology;\n abstract getRunDetail(runId: string): Promise<RunDetail | null>;\n /** List runs, each optionally carrying a {@link RunWaiting} descriptor (what a suspended run is\n * parked on). The store-backed gateway resolves `waiting`; a proxy relays whatever the control\n * plane sent. */\n abstract listRuns(query: RunQuery): Promise<RunListItem[]>;\n /**\n * Counts of the runs matching `query`, grouped by `(status, origin)` — what a console's status and\n * origin chips display. Separate from {@link listRuns} precisely so the list can be PAGINATED: the\n * page bounds what is rendered, these counts stay whole-set exact. Zero-count cells are absent.\n */\n abstract runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;\n /**\n * The distinct values of one filter axis over the runs matching `query`, with counts — what fills a\n * console's tenant/tag/attribute pickers. On the port (not control-plane-only) because the pickers\n * belong to the same panel as {@link listRuns}: a tenant that can list its runs has to be able to\n * see what it may filter them by, or its console offers a blank dropdown.\n *\n * Returns `[]` when the underlying store does not implement the enumeration — an empty picker with\n * free-text entry still standing, not an error.\n */\n abstract runValueFacets(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]>;\n /**\n * Bulk-resolve {@link RunWaiting} for an arbitrary set of run ids — for a consumer with its OWN\n * filtered/paginated run listing (so it isn't just `listRuns` under another name) that needs to know\n * which of ITS runs are parked on a breakpoint (or any other event wait) without re-deriving the bulk\n * waiter scan itself or reaching for raw SQL against `durable_step_checkpoints`. A `Record` (not a\n * `Map`) because `ProxyRunGateway` serialises the reply over the transport as plain JSON. Entries are\n * present ONLY for runs currently waiting — an unknown id, a non-suspended id, and a suspended id\n * parked on something non-event (a bare `ctx.sleep`, an in-flight step) are simply absent, same as a\n * `listRuns` row with no `waiting`.\n */\n abstract waitingFor(runIds: string[]): Promise<Record<string, RunWaiting>>;\n /** Per-group worker health (queue backlog + live worker heartbeats). On the control plane this is\n * every group; over a tenant proxy the operator scopes it to the tenant's own groups. */\n abstract workerHealth(): Promise<GroupHealth[]>;\n abstract cancel(runId: string, opts?: { compensate?: boolean }): Promise<RunResult | null>;\n abstract retry(runId: string): Promise<RunResult | null>;\n abstract continue(runId: string): Promise<RunResult | null>;\n /** Re-dispatch every remote step of a run stuck `pending` — the operator recovery for a LOST step\n * dispatch (crashed worker / dropped job) that no automatic path re-drives. Returns the run's status\n * plus how many steps were re-dispatched, or null if the run is unknown. */\n abstract redispatchPending(runId: string): Promise<(RunResult & { redispatched: number }) | null>;\n abstract retryWithInput(runId: string, input: unknown): Promise<{ runId: string } | null>;\n /** Live lifecycle events for one run; returns an unsubscribe fn. Framework-agnostic (no rxjs). */\n abstract subscribe(runId: string, onEvent: (event: EngineEvent) => void): () => void;\n}\n","import type {\n ChildWait,\n RetentionPolicy,\n RunFacetQuery,\n RunFacetRow,\n RunQuery,\n RunValueAxis,\n RunValueFacetOptions,\n RunValueFacetRow,\n ScheduleQuery,\n ScheduleRecord,\n SignalWaiter,\n StateStore,\n StepCheckpoint,\n WorkflowRun,\n} from './interfaces';\n\n/**\n * Transforms a payload value as it crosses the store boundary — e.g. encrypt-at-rest, compress, or\n * redact PII. `decode` must be the exact inverse of `encode`. Both are synchronous (use a local\n * cipher / codec); wrap an async KMS yourself if you need one.\n */\nexport interface PayloadCodec {\n encode(value: unknown): unknown;\n decode(value: unknown): unknown;\n}\n\n/**\n * A `StateStore` decorator that runs run/step **payloads** (input + output) through a\n * {@link PayloadCodec} — encoded on write, decoded on read — so they're never stored in the clear.\n * Adapter-agnostic: wrap any store. Searchable metadata (id, status, workflow, tags, timestamps) and\n * the structured `error` are left untouched so the dashboard, queries, and recovery still work.\n *\n * ```ts\n * const store = new CodecStateStore(new TypeOrmStateStore(ds), aesCodec);\n * ```\n */\nexport class CodecStateStore implements StateStore {\n /** Atomic claims touch only searchable metadata and bypass payload encoding. */\n readonly tryAdmitSingleton?: (\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ) => Promise<boolean>;\n\n /**\n * Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches\n * (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store\n * actually aggregates, so `store.runFacets?.()` still reports absence through the wrapper instead\n * of resolving to a silently wrong empty result.\n */\n readonly runFacets?: (query: RunFacetQuery) => Promise<RunFacetRow[]>;\n\n /**\n * Forwarded verbatim, and safe to: the axes a value facet enumerates are searchable metadata\n * (workflow, status, origin, namespace, tags, search attributes), none of which the codec encodes.\n * Bound the same conditional way as {@link runFacets} so absence is reported, not faked.\n */\n readonly runValueFacets?: (\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ) => Promise<RunValueFacetRow[]>;\n\n /** Forwarded verbatim (deletes touch no payload). Bound only when the inner store has it, so the\n * engine's per-run fallback still kicks in through the wrapper. */\n readonly deleteRuns?: (runIds: string[]) => Promise<void>;\n\n /** Forwarded verbatim — retention selects by status/updatedAt/scope, never by payload. Bound only\n * when the inner store prunes, so the retention poller still sees (and warns about) its absence. */\n readonly pruneTerminalRuns?: (\n policy: RetentionPolicy,\n nowMs: number,\n limit: number,\n ) => Promise<number>;\n\n /** Forwarded verbatim — a count reads no payload. Bound only when the inner store counts, so the\n * engine's facet/listing fallback still applies through the wrapper. */\n readonly countRuns?: (query: Omit<RunQuery, 'limit' | 'offset'>) => Promise<number>;\n /** The placeholder checkpoints are encoded like any other checkpoint. */\n readonly registerChildWaits?: (entries: ChildWait[]) => Promise<void>;\n /** The folded checkpoint carries the children's outputs, so it is encoded. */\n readonly compactCheckpoints?: (\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ) => Promise<void>;\n /** Forwarded verbatim — a waiter carries no payload. */\n readonly listSignalWaitersByRun?: (runIds: string[]) => Promise<SignalWaiter[]>;\n /** Forwarded verbatim — a waiter carries no payload. */\n readonly hasSignalWaiter?: (runId: string, tokenPrefix: string) => Promise<boolean>;\n\n /** Schedules persist their run `input` inside `spec` — encoded like any other payload. Bound only\n * when the inner store persists schedules, so `engine.schedules` reports absence faithfully. */\n readonly saveSchedule?: (record: ScheduleRecord) => Promise<void>;\n readonly getSchedule?: (id: string) => Promise<ScheduleRecord | null>;\n readonly updateSchedule?: (\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ) => Promise<boolean>;\n readonly deleteSchedule?: (id: string) => Promise<boolean>;\n readonly listSchedules?: (query: ScheduleQuery) => Promise<ScheduleRecord[]>;\n\n constructor(\n private readonly inner: StateStore,\n private readonly codec: PayloadCodec,\n ) {\n if (inner.tryAdmitSingleton) this.tryAdmitSingleton = inner.tryAdmitSingleton.bind(inner);\n const deleteRuns = inner.deleteRuns;\n if (deleteRuns) this.deleteRuns = (ids) => deleteRuns.call(inner, ids);\n const prune = inner.pruneTerminalRuns;\n if (prune)\n this.pruneTerminalRuns = (policy, now, limit) => prune.call(inner, policy, now, limit);\n const count = inner.countRuns;\n if (count) this.countRuns = (query) => count.call(inner, query);\n const registerChildWaits = inner.registerChildWaits;\n if (registerChildWaits)\n this.registerChildWaits = (entries) =>\n registerChildWaits.call(\n inner,\n entries.map((e) => ({ waiter: e.waiter, checkpoint: this.encCp(e.checkpoint) })),\n );\n const compact = inner.compactCheckpoints;\n if (compact)\n this.compactCheckpoints = (runId, fromSeq, toSeq, into) =>\n compact.call(inner, runId, fromSeq, toSeq, this.encCp(into));\n const byRun = inner.listSignalWaitersByRun;\n if (byRun) this.listSignalWaitersByRun = (runIds) => byRun.call(inner, runIds);\n const hasWaiter = inner.hasSignalWaiter;\n if (hasWaiter)\n this.hasSignalWaiter = (runId, tokenPrefix) => hasWaiter.call(inner, runId, tokenPrefix);\n\n const { saveSchedule, getSchedule, updateSchedule, deleteSchedule, listSchedules } = inner;\n if (saveSchedule && getSchedule && updateSchedule && deleteSchedule && listSchedules) {\n this.saveSchedule = (r) => saveSchedule.call(inner, this.encSchedule(r));\n this.getSchedule = async (id) => this.decSchedule(await getSchedule.call(inner, id));\n this.updateSchedule = (id, patch, expected) =>\n updateSchedule.call(\n inner,\n id,\n patch.spec ? { ...patch, spec: this.encSpec(patch.spec) } : patch,\n expected,\n );\n this.deleteSchedule = (id) => deleteSchedule.call(inner, id);\n this.listSchedules = async (q) =>\n (await listSchedules.call(inner, q)).map((r) => this.decSchedule(r) as ScheduleRecord);\n }\n const facets = inner.runFacets;\n if (facets) this.runFacets = (query) => facets.call(inner, query);\n const valueFacets = inner.runValueFacets;\n if (valueFacets) {\n this.runValueFacets = (axis, query, opts) => valueFacets.call(inner, axis, query, opts);\n }\n }\n\n private enc(v: unknown): unknown {\n return v === undefined ? undefined : this.codec.encode(v);\n }\n private dec(v: unknown): unknown {\n return v === undefined ? undefined : this.codec.decode(v);\n }\n\n private encRun(run: WorkflowRun): WorkflowRun {\n return { ...run, input: this.enc(run.input), output: this.enc(run.output) };\n }\n private decRun<T extends WorkflowRun | null>(run: T): T {\n return (run && { ...run, input: this.dec(run.input), output: this.dec(run.output) }) as T;\n }\n private encCp(cp: StepCheckpoint): StepCheckpoint {\n return { ...cp, input: this.enc(cp.input), output: this.enc(cp.output) };\n }\n private decCp<T extends StepCheckpoint | null>(cp: T): T {\n return (cp && { ...cp, input: this.dec(cp.input), output: this.dec(cp.output) }) as T;\n }\n\n private encSpec(spec: Record<string, unknown>): Record<string, unknown> {\n return 'input' in spec ? { ...spec, input: this.enc(spec.input) } : spec;\n }\n private encSchedule(r: ScheduleRecord): ScheduleRecord {\n return { ...r, spec: this.encSpec(r.spec) };\n }\n private decSchedule(r: ScheduleRecord | null): ScheduleRecord | null {\n if (!r || !('input' in r.spec)) return r;\n return { ...r, spec: { ...r.spec, input: this.dec(r.spec.input) } };\n }\n\n ensureSchema(): Promise<void> {\n return this.inner.ensureSchema?.() ?? Promise.resolve();\n }\n\n createRun(run: WorkflowRun): Promise<void> {\n return this.inner.createRun(this.encRun(run));\n }\n updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const next = { ...patch };\n if ('input' in patch) next.input = this.enc(patch.input);\n if ('output' in patch) next.output = this.enc(patch.output);\n return this.inner.updateRun(runId, next);\n }\n async getRun(runId: string): Promise<WorkflowRun | null> {\n return this.decRun(await this.inner.getRun(runId));\n }\n deleteRun(runId: string): Promise<void> {\n return this.inner.deleteRun(runId);\n }\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n return this.decCp(await this.inner.getCheckpoint(runId, seq));\n }\n saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n return this.inner.saveCheckpoint(this.encCp(checkpoint));\n }\n transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n if (!this.inner.transaction) {\n throw new Error('the wrapped store does not support transactions');\n }\n // Encode the checkpoint inside the tx, so payloads stay encoded at rest like the normal path.\n return this.inner.transaction((tx) =>\n work({ raw: tx.raw, saveCheckpoint: (cp) => tx.saveCheckpoint(this.encCp(cp)) }),\n );\n }\n async listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listIncompleteRuns(namespace)).map((r) => this.decRun(r));\n }\n async listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listPendingRuns(limit, namespace)).map((r) => this.decRun(r));\n }\n async listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]> {\n return (await this.inner.listDueTimers(nowMs, namespace)).map((r) => this.decRun(r));\n }\n tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean> {\n return this.inner.tryLockRun(runId, owner, leaseUntilMs, nowMs);\n }\n releaseRunLock(runId: string): Promise<void> {\n return this.inner.releaseRunLock(runId);\n }\n renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n return this.inner.renewRunLock(runId, owner, leaseUntilMs);\n }\n putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n return this.inner.putSignalWaiter(waiter);\n }\n takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n return this.inner.takeSignalWaiter(token);\n }\n listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n return this.inner.listSignalWaiters(prefix);\n }\n removeSignalWaiter(waiter: SignalWaiter): Promise<void> {\n return this.inner.removeSignalWaiter(waiter);\n }\n bufferSignal(token: string, payload: unknown): Promise<void> {\n return this.inner.bufferSignal(token, this.enc(payload));\n }\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const buffered = await this.inner.takeBufferedSignal(token);\n return buffered && { payload: this.dec(buffered.payload) };\n }\n bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void> {\n return this.inner.bufferEvent({ ...input, payload: this.enc(input.payload) });\n }\n async listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>> {\n const events = await this.inner.listBufferedEvents(name, limit);\n return events.map((e) => ({ ...e, payload: this.dec(e.payload) }));\n }\n removeBufferedEvent(id: string): Promise<boolean> {\n return this.inner.removeBufferedEvent(id);\n }\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n return (await this.inner.listRuns(query)).map((r) => this.decRun(r));\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n return (await this.inner.listCheckpoints(runId)).map((c) => this.decCp(c));\n }\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n // Forward the targeted read when the inner store implements it; otherwise fall back to the\n // (always-present) listCheckpoints scan so wrapping a legacy custom store keeps working.\n if (this.inner.getLatestCheckpointByName) {\n const cp = await this.inner.getLatestCheckpointByName(runId, name);\n return cp ? this.decCp(cp) : undefined;\n }\n let latest: StepCheckpoint | undefined;\n for (const cp of await this.inner.listCheckpoints(runId)) if (cp.name === name) latest = cp;\n return latest ? this.decCp(latest) : undefined;\n }\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n const matches = this.inner.listCheckpointsByNamePrefix\n ? await this.inner.listCheckpointsByNamePrefix(runId, prefixes)\n : (await this.inner.listCheckpoints(runId)).filter((cp) =>\n prefixes.some((p) => cp.name.startsWith(p)),\n );\n return matches.map((c) => this.decCp(c));\n }\n}\n","import type { EngineEvent } from './interfaces';\n\nexport interface MetricsSnapshot {\n runs: { started: number; completed: number; failed: number; suspended: number };\n steps: { started: number; completed: number; failed: number };\n /** Per-workflow run counters, keyed by workflow name. */\n byWorkflow: Record<string, { started: number; completed: number; failed: number }>;\n /** Sum + count of recorded step durations (ms), for an average. */\n stepDuration: { sumMs: number; count: number };\n}\n\nexport interface MetricsCollector {\n snapshot(): MetricsSnapshot;\n /** Prometheus text exposition of the counters — serve this from a `/metrics` endpoint. */\n prometheus(): string;\n /** Unsubscribe from the engine. */\n stop(): void;\n}\n\ntype Subscribable = { subscribe(listener: (event: EngineEvent) => void): () => void };\n\n/**\n * Subscribe to an engine's lifecycle events and accumulate Prometheus-style counters (runs + steps by\n * outcome, per-workflow run counts, step-duration sum/count). Dependency-free — call `.prometheus()`\n * from your metrics endpoint, or `.snapshot()` for the raw numbers. Counters are per process; scrape\n * each instance.\n */\nexport function collectMetrics(engine: Subscribable): MetricsCollector {\n const m: MetricsSnapshot = {\n runs: { started: 0, completed: 0, failed: 0, suspended: 0 },\n steps: { started: 0, completed: 0, failed: 0 },\n byWorkflow: {},\n stepDuration: { sumMs: 0, count: 0 },\n };\n const wf = (name?: string) => {\n const k = name ?? 'unknown';\n let entry = m.byWorkflow[k];\n if (!entry) {\n entry = { started: 0, completed: 0, failed: 0 };\n m.byWorkflow[k] = entry;\n }\n return entry;\n };\n\n const stop = engine.subscribe((e) => {\n switch (e.type) {\n case 'run.started':\n m.runs.started += 1;\n wf(e.workflow).started += 1;\n break;\n case 'run.completed':\n m.runs.completed += 1;\n wf(e.workflow).completed += 1;\n break;\n case 'run.failed':\n m.runs.failed += 1;\n wf(e.workflow).failed += 1;\n break;\n case 'run.suspended':\n m.runs.suspended += 1;\n break;\n case 'step.started':\n m.steps.started += 1;\n break;\n case 'step.completed':\n m.steps.completed += 1;\n if (e.durationMs != null) {\n m.stepDuration.sumMs += e.durationMs;\n m.stepDuration.count += 1;\n }\n break;\n case 'step.failed':\n m.steps.failed += 1;\n break;\n }\n });\n\n return {\n snapshot: () => structuredClone(m),\n stop,\n prometheus: () => {\n const lines: string[] = [];\n lines.push('# TYPE durable_runs_total counter');\n for (const [k, v] of Object.entries(m.runs))\n lines.push(`durable_runs_total{event=\"${k}\"} ${v}`);\n lines.push('# TYPE durable_steps_total counter');\n for (const [k, v] of Object.entries(m.steps))\n lines.push(`durable_steps_total{event=\"${k}\"} ${v}`);\n lines.push('# TYPE durable_runs_by_workflow_total counter');\n for (const [name, v] of Object.entries(m.byWorkflow))\n for (const [event, n] of Object.entries(v))\n lines.push(`durable_runs_by_workflow_total{workflow=\"${name}\",event=\"${event}\"} ${n}`);\n lines.push('# TYPE durable_step_duration_ms_sum counter');\n lines.push(`durable_step_duration_ms_sum ${m.stepDuration.sumMs}`);\n lines.push('# TYPE durable_step_duration_count counter');\n lines.push(`durable_step_duration_count ${m.stepDuration.count}`);\n return `${lines.join('\\n')}\\n`;\n },\n };\n}\n","import type {\n AttributeFilter,\n AttributeOp,\n RunQuery,\n ScalarAttributeFilter,\n WorkflowRun,\n} from './interfaces';\nimport type { SearchAttributes } from './interfaces';\n\n/** Compare one attribute value against a predicate. Range ops need both sides comparable; `in` is an\n * OR over its operand set, so an empty set matches nothing. */\nfunction compare(actual: unknown, filter: AttributeFilter): boolean {\n if (filter.op === 'in') return filter.values.some((v) => actual === v);\n const expected = filter.value;\n switch (filter.op) {\n case 'eq':\n return actual === expected;\n case 'ne':\n return actual !== expected;\n case 'gt':\n return actual != null && actual > expected;\n case 'gte':\n return actual != null && actual >= expected;\n case 'lt':\n return actual != null && actual < expected;\n case 'lte':\n return actual != null && actual <= expected;\n }\n}\n\n/**\n * Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`\n * on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined\n * filters match everything. Shared by every store so typed/range queries behave identically across\n * adapters (applied in-process after the coarse workflow/status/tag filters).\n */\nexport function matchesAttributes(\n attributes: SearchAttributes | undefined,\n filters: AttributeFilter[] | undefined,\n): boolean {\n if (!filters?.length) return true;\n if (!attributes) return false;\n return filters.every((f) => f.key in attributes && compare(attributes[f.key], f));\n}\n\n/**\n * Apply a query's attribute predicates then its `offset`/`limit`, in-process — for store adapters\n * that can't express typed/range predicates in SQL. Pass rows already coarse-filtered (workflow /\n * status / tag) and sorted newest-first; this filters by `attributes` and paginates. Only call it\n * when `query.attributes` is set (otherwise let the DB do `LIMIT`/`OFFSET`).\n */\nexport function applyAttributeQuery(rows: WorkflowRun[], query: RunQuery): WorkflowRun[] {\n const filtered = rows.filter((r) => matchesAttributes(r.searchAttributes, query.attributes));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? filtered.length;\n return filtered.slice(offset, offset + limit);\n}\n\n/**\n * One normalized row of the `durable_run_attributes` side-table: a single (key → value) pair of a\n * run's search attributes, split into typed columns so SQL can index/range-scan it. Exactly one of\n * `strValue`/`numValue` is set per row (booleans normalize to a string `\"true\"`/`\"false\"` so `eq`/`ne`\n * still match). NULL for the column that doesn't apply, which keeps `(key, numValue)` /\n * `(key, strValue)` indexes selective.\n */\nexport interface RunAttributeRow {\n runId: string;\n key: string;\n strValue: string | null;\n numValue: number | null;\n}\n\n/**\n * Explode a run's search attributes into normalized side-table rows (one per key). Used by SQL stores\n * to maintain `durable_run_attributes` on every create/update and by the in-memory store's index, so\n * attribute predicates can be pushed DOWN into a join/EXISTS instead of scanned in-process. Numbers go\n * to `numValue`; strings to `strValue`; booleans to `strValue` as `\"true\"`/`\"false\"` (matching how the\n * in-process `compare` treats `eq`/`ne` on booleans). Returns `[]` for a run with no attributes.\n */\nexport function normalizeAttributeRows(\n runId: string,\n attributes: SearchAttributes | undefined,\n): RunAttributeRow[] {\n if (!attributes) return [];\n const out: RunAttributeRow[] = [];\n for (const [key, value] of Object.entries(attributes)) {\n if (typeof value === 'number') {\n out.push({ runId, key, strValue: null, numValue: value });\n } else if (typeof value === 'boolean') {\n out.push({ runId, key, strValue: value ? 'true' : 'false', numValue: null });\n } else {\n out.push({ runId, key, strValue: value, numValue: null });\n }\n }\n return out;\n}\n\n/**\n * SQL comparison operator for a single-operand {@link AttributeOp} (used to build pushdown\n * predicates). `in` is absent by construction: it compares against a SET, which a store emits as an\n * OR of equalities over {@link attributePredicateOperands} rather than as one comparator.\n */\nexport function sqlComparator(op: Exclude<AttributeOp, 'in'>): string {\n switch (op) {\n case 'eq':\n return '=';\n case 'ne':\n return '<>';\n case 'gt':\n return '>';\n case 'gte':\n return '>=';\n case 'lt':\n return '<';\n case 'lte':\n return '<=';\n }\n}\n\n/**\n * Which side-table column an attribute filter compares against: numeric operands (and range ops on\n * numbers) hit `numValue`; everything else hits `strValue` (booleans are stored as `\"true\"`/`\"false\"`).\n * Keeping this in core means every SQL adapter pushes predicates down identically.\n */\nexport function attributeColumnFor(filter: ScalarAttributeFilter): 'numValue' | 'strValue' {\n return typeof filter.value === 'number' ? 'numValue' : 'strValue';\n}\n\n/** The literal a side-table predicate compares against (booleans → `\"true\"`/`\"false\"` strings). */\nexport function attributeOperand(filter: ScalarAttributeFilter): string | number {\n if (typeof filter.value === 'boolean') return filter.value ? 'true' : 'false';\n return filter.value;\n}\n\n/** One comparison a side-table predicate makes: which typed column, with which operator, against\n * which literal. */\nexport interface AttributePredicateOperand {\n column: 'numValue' | 'strValue';\n comparator: string;\n operand: string | number;\n}\n\n/**\n * The comparisons one {@link AttributeFilter} makes, for a store to OR together inside its\n * `EXISTS`/join on the normalized attribute side-table. A scalar op yields exactly ONE comparison\n * (the same column/operator/literal {@link attributeColumnFor} and {@link attributeOperand} give);\n * `in` yields one per member, each an equality, since its operands may be of mixed types and so land\n * in different typed columns.\n *\n * An EMPTY list is a real answer, not a missing one: `in` over no values can match no run. A caller\n * that ORs an empty list must emit a false predicate rather than dropping the filter, or the query\n * silently widens to every run.\n */\nexport function attributePredicateOperands(filter: AttributeFilter): AttributePredicateOperand[] {\n if (filter.op === 'in') {\n return filter.values.map((value) => {\n const scalar = { key: filter.key, op: 'eq', value } as ScalarAttributeFilter;\n return {\n column: attributeColumnFor(scalar),\n comparator: '=',\n operand: attributeOperand(scalar),\n };\n });\n }\n return [\n {\n column: attributeColumnFor(filter),\n comparator: sqlComparator(filter.op),\n operand: attributeOperand(filter),\n },\n ];\n}\n","import type { InferSearchAttributes, SearchAttributes, SearchAttributesSchema } from './interfaces';\n\n/**\n * Read a run's `searchAttributes` through a {@link SearchAttributesSchema}, typed to the schema's\n * inferred output. **Safe-parse semantics, deliberately lenient** — unlike\n * `ctx.upsertSearchAttributes` (which is strict: an invalid merge throws), a failed validation here\n * returns `{}` rather than throwing. This is intentional: `run.searchAttributes` may predate the\n * schema (an older deploy wrote it under a looser or absent schema, or a run started before this\n * workflow ever declared one), and a dashboard/read path crashing on old history is worse than it\n * quietly reporting no typed attributes for that run. Write-time enforcement is what keeps NEW writes\n * conformant; this is the read-side counterpart for consuming them.\n *\n * The schema's `validate` must be synchronous (matching the write-side constraint in\n * `ctx.upsertSearchAttributes`) — one returning a `Promise` throws with a clear error rather than\n * being silently awaited or silently treated as a failure.\n *\n * @example\n * ```ts\n * import { z } from 'zod';\n * import { readSearchAttributes } from '@dudousxd/nestjs-durable-core';\n *\n * const orderAttrs = z.object({ tier: z.enum(['free', 'pro']), amount: z.number() });\n *\n * const run = await store.getRun(runId);\n * const attrs = readSearchAttributes(orderAttrs, run ?? {}); // { tier: 'pro', amount: 42 } | {}\n * ```\n */\nexport function readSearchAttributes<S extends SearchAttributesSchema>(\n schema: S,\n // `| null` because ORM store entities (MikroORM/TypeORM/Prisma) type the JSON column as\n // nullable — the entity row is the argument every real consumer passes.\n run: { searchAttributes?: SearchAttributes | null | undefined },\n): InferSearchAttributes<S> {\n const result = schema['~standard'].validate(run.searchAttributes ?? {});\n if (result instanceof Promise) {\n throw new Error(\n \"readSearchAttributes: schema validation must be synchronous (the searchAttributes schema's \" +\n '`~standard.validate` returned a Promise) — async Standard Schema validators are not supported.',\n );\n }\n if (result.issues) {\n // Lenient by design (see doc comment) — old/foreign runs shouldn't crash a read path. The `{}`\n // is cast, not `Partial<InferSearchAttributes<S>>`, to keep the common case (destructuring known\n // keys straight off the result) ergonomic; callers reading untrusted history should still treat\n // every field as possibly absent.\n return {} as InferSearchAttributes<S>;\n }\n return result.value as InferSearchAttributes<S>;\n}\n","/**\n * Dependency-injection tokens. Adapters bind their implementations to these so `core` and\n * `@dudousxd/nestjs-durable` depend only on the interfaces in `./interfaces`.\n *\n * These use `Symbol.for(key)` (the global symbol registry), NOT `Symbol(key)`, so the token is the\n * SAME instance no matter how many times `core` is evaluated in a process. A consumer can hold more\n * than one physical copy of `core` at runtime — pnpm peer-dependency multiplexing installs a\n * separate virtual copy per distinct peer set, and the dual ESM/CJS build can be loaded once as\n * `import` (`index.js`) and once as `require` (`index.cjs`). A plain `Symbol()` would mint a\n * DISTINCT token per copy, so `DurableModule` (provider) and `DashboardService` / a store adapter\n * (injector) could resolve different symbols → Nest can't satisfy the dependency\n * (`STATE_STORE is not available in the DurableApiModule context`). A registered symbol collapses\n * them to one. Mirrors the `CONTEXT_ACCESSOR` token in `@dudousxd/nestjs-durable`'s `tokens.ts`.\n */\n\n/**\n * @deprecated Use {@link STATE_STORE_CANONICAL} (`@dudousxd/nestjs-durable:state-store`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const STATE_STORE = Symbol.for('nestjs-durable:STATE_STORE');\n/**\n * @deprecated Use {@link TRANSPORT_CANONICAL} (`@dudousxd/nestjs-durable:transport`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const TRANSPORT = Symbol.for('nestjs-durable:TRANSPORT');\n/**\n * @deprecated Use {@link DURABLE_OPTIONS_CANONICAL} (`@dudousxd/nestjs-durable:options`). The legacy\n * token stays bound as a back-compat alias and still resolves; it will be removed in a future major.\n */\nexport const DURABLE_OPTIONS = Symbol.for('nestjs-durable:DURABLE_OPTIONS');\n\n/**\n * Canonical, cross-lib-discoverable aliases of the durable DI tokens, following the ecosystem\n * capability naming `@dudousxd/nestjs-durable:<name>` (identical to `capability('durable', <name>)`).\n * `DurableModule` binds these alongside the legacy tokens (dual-bind), so an external library can\n * resolve durable's store/transport/options by the canonical name without importing durable\n * internals. Bare `Symbol.for` (same cross-copy-stability rationale as the legacy tokens above)\n * keeps `core` free of any `@dudousxd/nestjs-diagnostics` runtime dependency.\n */\nexport const STATE_STORE_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:state-store');\nexport const TRANSPORT_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:transport');\nexport const DURABLE_OPTIONS_CANONICAL = Symbol.for('@dudousxd/nestjs-durable:options');\n","import { parseDuration } from '../duration';\nimport {\n type ChildWait,\n type RetentionPolicy,\n type RunFacetQuery,\n type RunFacetRow,\n type RunQuery,\n type RunValueAxis,\n type RunValueFacetOptions,\n type RunValueFacetRow,\n type ScheduleQuery,\n type ScheduleRecord,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n TERMINAL_RUN_STATUSES,\n type WorkflowRun,\n} from '../interfaces';\nimport type { AttributeFilter } from '../interfaces';\nimport { mergeRunFacetRows } from '../run-facets';\nimport { RUN_VALUE_FACET_SCAN, runValueFacetsFromRuns } from '../run-value-facets';\nimport {\n type RunAttributeRow,\n attributePredicateOperands,\n normalizeAttributeRows,\n} from '../search-attributes';\nimport {\n SINGLETON_ADMITTED_TAG,\n singletonAdmissionDenialPatch,\n singletonAdmissionTags,\n} from '../singleton-admission';\n\n/**\n * A non-durable, in-process `StateStore` for tests and local development.\n * The shipped `@dudousxd/nestjs-durable-store` package re-exports an equivalent.\n */\nexport class InMemoryStateStore implements StateStore {\n private readonly runs = new Map<string, WorkflowRun>();\n private readonly checkpoints = new Map<string, StepCheckpoint>();\n private readonly signalWaiters = new Map<string, SignalWaiter>();\n\n /**\n * Normalized search-attribute side-table, the in-memory analog of the SQL stores'\n * `durable_run_attributes`: `key -> (runId -> row)`. Maintained on every create/update so an\n * attribute query can be pushed DOWN to a key-indexed candidate set instead of scanning every run\n * and comparing in-process. Mirrors {@link normalizeAttributeRows} so behavior matches the SQL path.\n */\n private readonly attributeIndex = new Map<string, Map<string, RunAttributeRow>>();\n /** Test/observability hook: how many candidate runs the last attribute query's index produced. */\n lastAttributeCandidates = 0;\n /**\n * Test/observability hook: how many checkpoint rows the LAST checkpoint read materialized (the rows\n * actually returned to the caller). `listCheckpoints` returns all rows for the run; the targeted\n * {@link getLatestCheckpointByName} / {@link listCheckpointsByNamePrefix} return only the matches —\n * so this lets the benchmark contrast \"fetch N, scan in JS\" against \"fetch the k that match\".\n */\n lastCheckpointRowsRead = 0;\n\n private key(runId: string, seq: number): string {\n return `${runId}:${seq}`;\n }\n\n /** Drop then re-add a run's normalized attribute rows so the index tracks its current attributes. */\n private reindexAttributes(runId: string, attributes: WorkflowRun['searchAttributes']): void {\n for (const byRun of this.attributeIndex.values()) byRun.delete(runId);\n for (const row of normalizeAttributeRows(runId, attributes)) {\n let byRun = this.attributeIndex.get(row.key);\n if (!byRun) {\n byRun = new Map();\n this.attributeIndex.set(row.key, byRun);\n }\n byRun.set(runId, row);\n }\n }\n\n async tryAdmitSingleton(\n runId: string,\n tag: string,\n workflow: string,\n limit: number,\n retryWakeAt?: number,\n ): Promise<boolean> {\n // No await between snapshot and claim: JavaScript's synchronous turn is the critical section.\n const runs = [...this.runs.values()];\n const tags = singletonAdmissionTags(runs, runId, tag, workflow, limit);\n if (!tags) {\n const patch = singletonAdmissionDenialPatch(runs, runId, tag, workflow, retryWakeAt);\n const candidate = this.runs.get(runId);\n if (patch && candidate) this.runs.set(runId, { ...candidate, ...patch });\n return false;\n }\n const run = this.runs.get(runId);\n if (!run) return false;\n this.runs.set(runId, { ...run, tags });\n return true;\n }\n\n async createRun(run: WorkflowRun): Promise<void> {\n // Normalize undefined namespace to 'default', matching the SQL stores' column DEFAULT 'default'\n // (interfaces.ts: \"the store persists it as 'default'\"). This ensures legacy runs (created without\n // a namespace, e.g. in tests that bypass the engine) are reachable via a namespace='default' filter.\n this.runs.set(run.id, { ...run, namespace: run.namespace ?? 'default' });\n this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, inputPatch: Partial<WorkflowRun>): Promise<void> {\n const patch =\n inputPatch.status && TERMINAL_RUN_STATUSES.includes(inputPatch.status)\n ? {\n ...inputPatch,\n tags: ('tags' in inputPatch ? inputPatch.tags : this.runs.get(runId)?.tags)?.filter(\n (tag) => tag !== SINGLETON_ADMITTED_TAG,\n ),\n }\n : inputPatch;\n const existing = this.runs.get(runId);\n if (!existing) throw new Error(`run ${runId} not found`);\n const next = { ...existing, ...patch };\n this.runs.set(runId, next);\n if ('searchAttributes' in patch) this.reindexAttributes(runId, next.searchAttributes);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const run = this.runs.get(runId);\n return run ? { ...run } : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n this.runs.delete(runId);\n for (const [key, cp] of this.checkpoints) {\n if (cp.runId === runId) this.checkpoints.delete(key);\n }\n for (const [token, waiter] of this.signalWaiters) {\n if (waiter.runId === runId) this.signalWaiters.delete(token);\n }\n // Drop the run's normalized attribute rows (reindex with no attributes clears them).\n this.reindexAttributes(runId, undefined);\n }\n\n async deleteRuns(runIds: string[]): Promise<void> {\n for (const runId of runIds) await this.deleteRun(runId);\n }\n\n async pruneTerminalRuns(policy: RetentionPolicy, nowMs: number, limit: number): Promise<number> {\n // Only terminal statuses are ever eligible — a policy naming a live status would race the engine.\n const statuses = policy.statuses.filter((s) => TERMINAL_RUN_STATUSES.includes(s));\n if (statuses.length === 0 || limit <= 0) return 0;\n if (policy.maxAge == null && policy.maxCount == null) return 0;\n const inScope = this.matching({ ...(policy.scope ?? {}), statuses });\n const ids = new Set<string>();\n if (policy.maxAge != null) {\n const cutoff = nowMs - parseDuration(policy.maxAge);\n const expired = inScope\n .filter((r) => r.updatedAt.getTime() < cutoff)\n .sort((a, b) => a.updatedAt.getTime() - b.updatedAt.getTime()) // oldest first\n .slice(0, limit);\n for (const r of expired) ids.add(r.id);\n }\n if (policy.maxCount != null && ids.size < limit) {\n // Everything past the newest `maxCount` runs of the (scoped) status set.\n const byRecency = [...inScope].sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime() || b.id.localeCompare(a.id),\n );\n for (const r of byRecency.slice(policy.maxCount)) {\n if (ids.size >= limit) break;\n ids.add(r.id);\n }\n }\n const doomed = [...ids].slice(0, limit);\n await this.deleteRuns(doomed);\n return doomed.length;\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const cp = this.checkpoints.get(this.key(runId, seq));\n return cp ? { ...cp } : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n this.checkpoints.set(this.key(checkpoint.runId, checkpoint.seq), { ...checkpoint });\n }\n\n async listIncompleteRuns(namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) =>\n (r.status === 'running' || r.status === 'cancelling') &&\n (namespace === undefined || r.namespace === namespace),\n )\n .map((r) => ({ ...r }));\n }\n\n async listPendingRuns(limit: number, namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) => r.status === 'pending' && (namespace === undefined || r.namespace === namespace),\n )\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id))\n .slice(0, limit)\n .map((r) => ({ ...r }));\n }\n\n async listDueTimers(nowMs: number, namespace?: string): Promise<WorkflowRun[]> {\n return [...this.runs.values()]\n .filter(\n (r) =>\n r.status === 'suspended' &&\n r.wakeAt !== undefined &&\n r.wakeAt <= nowMs &&\n (namespace === undefined || r.namespace === namespace),\n )\n .map((r) => ({ ...r }));\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const run = this.runs.get(runId);\n if (!run) return false;\n if (run.lockedUntil !== undefined && run.lockedUntil > nowMs) return false;\n run.lockedBy = owner;\n run.lockedUntil = leaseUntilMs;\n return true;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n const run = this.runs.get(runId);\n if (run) {\n run.lockedBy = undefined;\n run.lockedUntil = undefined;\n }\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const run = this.runs.get(runId);\n if (!run || run.lockedBy !== owner) return false;\n run.lockedUntil = leaseUntilMs;\n return true;\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n this.signalWaiters.set(waiter.token, { ...waiter });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const waiter = this.signalWaiters.get(token);\n if (!waiter) return null;\n this.signalWaiters.delete(token);\n return { ...waiter };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n return [...this.signalWaiters.values()]\n .filter((w) => w.token.startsWith(prefix))\n .map((w) => ({ ...w }));\n }\n\n async registerChildWaits(entries: ChildWait[]): Promise<void> {\n for (const { waiter } of entries) this.signalWaiters.set(waiter.token, { ...waiter });\n for (const { checkpoint } of entries) await this.saveCheckpoint(checkpoint);\n }\n\n async compactCheckpoints(\n runId: string,\n fromSeq: number,\n toSeq: number,\n into: StepCheckpoint,\n ): Promise<void> {\n for (let seq = fromSeq; seq <= toSeq; seq += 1) this.checkpoints.delete(this.key(runId, seq));\n this.checkpoints.set(this.key(runId, into.seq), { ...into, runId });\n }\n\n async listSignalWaitersByRun(runIds: string[]): Promise<SignalWaiter[]> {\n const ids = new Set(runIds);\n return [...this.signalWaiters.values()].filter((w) => ids.has(w.runId)).map((w) => ({ ...w }));\n }\n\n async hasSignalWaiter(runId: string, tokenPrefix: string): Promise<boolean> {\n for (const w of this.signalWaiters.values()) {\n if (w.runId === runId && w.token.startsWith(tokenPrefix)) return true;\n }\n return false;\n }\n\n async removeSignalWaiter(waiter: SignalWaiter): Promise<void> {\n // Keyed by token only (one row per token) — only delete if the CURRENT row still matches this\n // exact (runId, seq); a later putSignalWaiter for the same token may have already replaced it\n // with a different run's row, which must be left alone.\n const current = this.signalWaiters.get(waiter.token);\n if (current && current.runId === waiter.runId && current.seq === waiter.seq) {\n this.signalWaiters.delete(waiter.token);\n }\n }\n\n // No real DB transaction (there's no DB) — run the work and save the checkpoint. Exactly-once\n // across a crash needs a SQL store; this keeps `ctx.transaction` usable in tests / local dev.\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return work({ raw: this, saveCheckpoint: (cp) => this.saveCheckpoint(cp) });\n }\n\n private readonly bufferedSignals = new Map<string, unknown[]>();\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n const queue = this.bufferedSignals.get(token) ?? [];\n queue.push(payload);\n this.bufferedSignals.set(token, queue);\n }\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const queue = this.bufferedSignals.get(token);\n if (!queue || queue.length === 0) return null;\n const payload = queue.shift();\n if (queue.length === 0) this.bufferedSignals.delete(token);\n return { payload };\n }\n\n /** `id -> row`, so {@link removeBufferedEvent} can delete an exact row regardless of iteration\n * order — mirrors the SQL stores' PK-by-id delete. */\n private readonly bufferedEvents = new Map<\n string,\n { name: string; payload: unknown; publishedAt: number }\n >();\n async bufferEvent(input: {\n name: string;\n payload: unknown;\n id: string;\n publishedAt: number;\n }): Promise<void> {\n this.bufferedEvents.set(input.id, {\n name: input.name,\n payload: input.payload,\n publishedAt: input.publishedAt,\n });\n }\n async listBufferedEvents(\n name: string,\n limit: number,\n ): Promise<Array<{ id: string; payload: unknown; publishedAt: number }>> {\n return [...this.bufferedEvents.entries()]\n .filter(([, e]) => e.name === name)\n .sort((a, b) => a[1].publishedAt - b[1].publishedAt) // oldest first\n .slice(0, limit)\n .map(([id, e]) => ({ id, payload: e.payload, publishedAt: e.publishedAt }));\n }\n async removeBufferedEvent(id: string): Promise<boolean> {\n return this.bufferedEvents.delete(id);\n }\n\n /**\n * Candidate run ids satisfying ONE attribute predicate, served from {@link attributeIndex} — the\n * pushdown step. Numeric predicates scan only `numValue` rows under the key; string/boolean ones\n * scan `strValue` rows. This is the in-memory analog of the SQL EXISTS on `durable_run_attributes`.\n */\n private candidatesForFilter(f: AttributeFilter): Set<string> {\n const byRun = this.attributeIndex.get(f.key);\n const out = new Set<string>();\n if (!byRun) return out;\n // One comparison per operand — a scalar op has exactly one, `in` has one per member — ORed, the\n // same shape the SQL stores emit inside their EXISTS. An `in` over no values compares nothing and\n // so matches nothing, which is why this ORs a possibly-empty list instead of skipping the filter.\n const comparisons = attributePredicateOperands(f);\n for (const row of byRun.values()) {\n const matched = comparisons.some(({ column, comparator, operand }) => {\n const actual = column === 'numValue' ? row.numValue : row.strValue;\n if (actual == null) return false;\n switch (comparator) {\n case '=':\n return actual === operand;\n case '<>':\n return actual !== operand;\n case '>':\n return actual > operand;\n case '>=':\n return actual >= operand;\n case '<':\n return actual < operand;\n default:\n return actual <= operand;\n }\n });\n if (matched) out.add(row.runId);\n }\n return out;\n }\n\n /** Every run satisfying `query`'s predicates, unsorted and unpaged — the shared body of\n * {@link listRuns} (which then sorts + pages it) and {@link runFacets} (which groups it). */\n private matching(query: RunQuery): WorkflowRun[] {\n let runs = [...this.runs.values()];\n if (query.workflow) runs = runs.filter((r) => r.workflow === query.workflow);\n if (query.workflows) runs = runs.filter((r) => query.workflows?.includes(r.workflow));\n if (query.status) runs = runs.filter((r) => r.status === query.status);\n if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));\n if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag as string));\n // ANY of the tags, against a run that carries a SET of them — see `RunQuery.tags`.\n if (query.tags) runs = runs.filter((r) => r.tags?.some((t) => query.tags?.includes(t)));\n if (query.namespace !== undefined) runs = runs.filter((r) => r.namespace === query.namespace);\n if (query.namespaces) {\n runs = runs.filter(\n (r) => r.namespace !== undefined && query.namespaces?.includes(r.namespace),\n );\n }\n // Exact match on a value; `null` selects the runs carrying NO origin — see `RunQuery.origin`.\n if (query.origin === null) runs = runs.filter((r) => r.origin == null);\n else if (query.origin !== undefined) runs = runs.filter((r) => r.origin === query.origin);\n // `null` is a member like any other here, so a set can ask for named origins AND the\n // unattributed bucket in one predicate.\n if (query.origins) {\n runs = runs.filter((r) => query.origins?.includes(r.origin ?? null));\n }\n if (query.attributes?.length) {\n // Pushdown: intersect per-predicate candidate sets from the key-indexed side-table, so we only\n // ever materialize the runs that already satisfy EVERY attribute filter (no full per-run scan).\n let candidates: Set<string> | null = null;\n for (const f of query.attributes) {\n const next = this.candidatesForFilter(f);\n if (candidates == null) {\n candidates = next;\n } else {\n const prev: Set<string> = candidates;\n candidates = new Set([...prev].filter((id) => next.has(id)));\n }\n if (candidates.size === 0) break;\n }\n const ids = candidates ?? new Set<string>();\n this.lastAttributeCandidates = ids.size;\n runs = runs.filter((r) => ids.has(r.id));\n }\n return runs;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const runs = this.matching(query);\n // Newest first (matches the store adapters' `createdAt DESC`) — recent runs on top in the dashboard.\n runs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n const offset = query.offset ?? 0;\n const limit = query.limit ?? runs.length;\n return runs.slice(offset, offset + limit).map((r) => ({ ...r }));\n }\n\n async countRuns(query: Omit<RunQuery, 'limit' | 'offset'>): Promise<number> {\n return this.matching(query).length;\n }\n\n async runFacets(query: RunFacetQuery): Promise<RunFacetRow[]> {\n return mergeRunFacetRows(\n this.matching(query).map((run) => ({ status: run.status, origin: run.origin, count: 1 })),\n );\n }\n\n /** Counted over the newest `scan` matching runs for EVERY axis, not just `tag`: this store holds\n * its runs in a Map with no index to group by, so the bound that the SQL stores need only for tags\n * is the honest one to apply here throughout. */\n async runValueFacets(\n axis: RunValueAxis,\n query: RunFacetQuery,\n opts?: RunValueFacetOptions,\n ): Promise<RunValueFacetRow[]> {\n const runs = await this.listRuns({ ...query, limit: opts?.scan ?? RUN_VALUE_FACET_SCAN });\n return runValueFacetsFromRuns(runs, axis, opts);\n }\n\n private readonly schedules = new Map<string, ScheduleRecord>();\n\n async saveSchedule(record: ScheduleRecord): Promise<void> {\n this.schedules.set(record.id, structuredClone(record));\n }\n\n async getSchedule(id: string): Promise<ScheduleRecord | null> {\n const record = this.schedules.get(id);\n return record ? structuredClone(record) : null;\n }\n\n async updateSchedule(\n id: string,\n patch: Partial<Omit<ScheduleRecord, 'id' | 'createdAt'>>,\n expectedNextFireAt?: number | null,\n ): Promise<boolean> {\n const record = this.schedules.get(id);\n if (!record) return false;\n if (expectedNextFireAt !== undefined && record.nextFireAt !== expectedNextFireAt) return false;\n this.schedules.set(id, { ...record, ...structuredClone(patch) });\n return true;\n }\n\n async deleteSchedule(id: string): Promise<boolean> {\n return this.schedules.delete(id);\n }\n\n async listSchedules(query: ScheduleQuery): Promise<ScheduleRecord[]> {\n const rows = [...this.schedules.values()]\n .filter((s) => query.namespace === undefined || s.namespace === query.namespace)\n .filter((s) => query.workflow === undefined || s.workflow === query.workflow)\n .filter((s) => query.tag === undefined || (s.tags ?? []).includes(query.tag))\n .filter((s) => query.paused === undefined || s.paused === query.paused)\n .filter(\n (s) =>\n query.dueBy === undefined ||\n (!s.paused && s.nextFireAt !== null && s.nextFireAt <= query.dueBy),\n )\n .sort(\n (a, b) =>\n (a.nextFireAt ?? Number.POSITIVE_INFINITY) - (b.nextFireAt ?? Number.POSITIVE_INFINITY) ||\n a.id.localeCompare(b.id),\n );\n const offset = query.offset ?? 0;\n return rows\n .slice(offset, query.limit != null ? offset + query.limit : undefined)\n .map((s) => structuredClone(s));\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = [...this.checkpoints.values()]\n .filter((cp) => cp.runId === runId)\n .sort((a, b) => a.seq - b.seq)\n .map((cp) => ({ ...cp }));\n this.lastCheckpointRowsRead = rows.length;\n return rows;\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n let latest: StepCheckpoint | undefined;\n for (const cp of this.checkpoints.values()) {\n if (cp.runId !== runId || cp.name !== name) continue;\n if (!latest || cp.seq > latest.seq) latest = cp;\n }\n this.lastCheckpointRowsRead = latest ? 1 : 0;\n return latest ? { ...latest } : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n const rows = [...this.checkpoints.values()]\n .filter((cp) => cp.runId === runId && prefixes.some((p) => cp.name.startsWith(p)))\n .sort((a, b) => a.seq - b.seq)\n .map((cp) => ({ ...cp }));\n this.lastCheckpointRowsRead = rows.length;\n return rows;\n }\n}\n","import type {\n ControlMessage,\n ControlPlane,\n Heartbeat,\n RemoteTask,\n StepResult,\n Transport,\n WorkflowStepEvent,\n} from '../interfaces';\nimport { type StepHandler, runStepHandler } from '../protocol';\n\n/**\n * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered\n * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,\n * and control messages broadcast locally. Pass the same instance as both `transport` and\n * `controlPlane`.\n */\nexport class InMemoryTransport implements Transport, ControlPlane {\n private readonly handlers = new Map<string, StepHandler>();\n private resultHandler?: (result: StepResult) => Promise<void>;\n private heartbeatHandler?: (beat: Heartbeat) => Promise<void>;\n private stepEventHandler?: (event: WorkflowStepEvent) => Promise<void>;\n private readonly controlHandlers = new Set<(msg: ControlMessage) => void>();\n\n /** Register a fake worker handler for a step name. */\n handle(name: string, fn: StepHandler): void {\n this.handlers.set(name, fn);\n }\n\n async dispatch(task: RemoteTask): Promise<void> {\n if (!this.resultHandler) throw new Error('no result handler registered');\n const result = await runStepHandler(task, this.handlers.get(task.name));\n // Deliver the result ASYNCHRONOUSLY, not inline: a durable `ctx.call` suspends the run right\n // after dispatch, so the result must land AFTER that unwinds (else the resume re-enters\n // mid-suspend). Real brokers are async; this mirrors them.\n setImmediate(() => void this.resultHandler?.(result));\n }\n\n onResult(handler: (result: StepResult) => Promise<void>): void {\n this.resultHandler = handler;\n }\n\n onHeartbeat(handler: (beat: Heartbeat) => Promise<void>): void {\n // In-process step handlers run synchronously (no step liveness to track), but a test can drive a\n // RUN-scoped beat via `emitHeartbeat` to exercise the engine's heartbeat-rearmed advance deadline.\n this.heartbeatHandler = handler;\n }\n\n /** Test hook: deliver a liveness heartbeat to the engine, as a real broker would on its channel. */\n async emitHeartbeat(beat: Heartbeat): Promise<void> {\n await this.heartbeatHandler?.(beat);\n }\n\n /** Workflow step lifecycle: deliver to the engine's handler (async, mirroring a real broker). */\n async dispatchStepEvent(event: WorkflowStepEvent): Promise<void> {\n await this.stepEventHandler?.(event);\n }\n\n onStepEvent(handler: (event: WorkflowStepEvent) => Promise<void>): void {\n this.stepEventHandler = handler;\n }\n\n // Control plane: broadcast to every registered handler (including the publisher's own — the\n // engine dedupes by `from`), mirroring how a real broker echoes a publish to all subscribers.\n async publishControl(msg: ControlMessage): Promise<void> {\n for (const handler of this.controlHandlers) handler(msg);\n }\n\n onControl(handler: (msg: ControlMessage) => void): void {\n this.controlHandlers.add(handler);\n }\n}\n"],"mappings":"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","names":["QueueController","inFlight","windowStart","windowCount","waiters","Map","waiterSeq","keyServed","servedTick","config","clock","ordered","fairness","order","tryAdmit","item","now","rl","rateLimit","periodMs","limit","ok","retryAt","usingOrder","priority","waiterId","full","concurrency","register","retryMs","size","isNext","delete","key","set","release","existing","get","seq","self","undefined","Number","POSITIVE_INFINITY","best","w","values","better","a","b","sa","servedOf","sb","InMemoryAdmissionBackend","controllers","Map","clock","register","config","set","name","QueueController","handles","queue","has","tryAdmit","item","controller","get","ok","release","_slotId","AsyncLocalStorage","STORAGE_KEY","Symbol","for","globalRef","globalThis","AsyncLocalStorage","storage","runInWorkflowCtx","ctx","fn","run","currentWorkflowCtx","getStore","STEP_SCOPE_KEY","stepScopeRef","stepScopeStorage","runInStepScope","owner","step","currentStepScope","runOutsideWorkflowCtx","exit","AsyncLocalStorage","STORAGE_KEY","Symbol","for","globalRef","globalThis","AsyncLocalStorage","storage","runInStepLogger","logger","fn","run","currentStep","getStore","log","level","message","data","debug","info","warn","error","sub","name","status","subEvent","e","noopSubProcessHandle","phase","skip","fail","subProcess","body","opts","Promise","resolve","CONTROL_FLOW_SIGNAL","Symbol","for","isWorkflowControlFlowSignal","error","FatalError","Error","code","message","name","ConcurrencyLimitError","workflow","key","limit","active","SingletonQueueFullError","maxQueueDepth","SignalTimeoutError","token","timeoutMs","RemoteStepTimeout","stepId","RemoteWorkflowTimeout","taskId","NonDeterminismError","runId","seq","expected","recorded","NestedWorkflowCallError","primitive","step","GatherError","failures","total","ids","map","f","id","join","denom","length","WorkflowSuspended","wakeAt","fan","CONTROL_FLOW_SIGNAL","ContinueAsNew","input","WORKFLOW_NAME_KEY","Symbol","for","workflowName","ref","name","Error","BINDINGS_KEY","Symbol","for","globalRef","globalThis","WeakMap","bindings","bindWorkflowClass","ctor","client","set","clientOf","get","Error","workflowName","DurableWorkflow","start","input","opts","cls","ctx","currentWorkflowCtx","runId","startChild","id","status","crypto","randomUUID","execute","child","waitForRun","FatalError","settled","timeoutMs","until","output","detail","error","message","code","UNIT_MS","ms","s","sec","second","seconds","m","min","minute","minutes","h","hr","hour","hours","d","day","days","w","week","weeks","parseDuration","duration","match","trim","Error","value","Number","unit","toLowerCase","factor","undefined","backoffDelay","attempt","options","base","backoffMs","raw","backoff","capped","backoffMaxMs","Math","min","jitter","round","random","wrappers","useDurableExecution","wrapper","push","i","indexOf","splice","clearDurableExecutionWrappers","length","hasDurableExecutionWrappers","runDurableExecution","execution","body","outcome","inner","value","ok","error","chain","reduceRight","next","undefined","Error","withDuration","start","now","data","base","durationMs","createStepLogger","events","currentSub","push","level","message","at","subId","id","undefined","subEvent","e","status","phase","name","group","subProcess","body","opts","globalThis","crypto","randomUUID","prevSub","terminal","emit","handle","skip","reason","fail","result","err","Error","String","debug","m","d","info","warn","error","sub","stepId","runId","seq","breakpointToken","runStepHandler","task","handler","base","startedAt","Date","now","status","error","message","name","retryable","events","withEvents","result","length","logger","createStepLogger","output","runDurableExecution","unit","workflow","undefined","attempt","runOutsideWorkflowCtx","runInStepLogger","input","err","e","Error","String","code","REDISPATCHED_STEP_EVENT","LOST_STEP_EVENT","lostStepEvent","at","attempts","outcome","level","name","message","nonEmptyEvents","events","length","undefined","stepCheckpoint","p","runId","seq","kind","stepId","status","input","output","error","workerGroup","wakeAt","parallelGroup","enqueuedAt","startedAt","finishedAt","instantCheckpoint","Date","isFailedCompletion","payload","c","ok","unwrapCompletion","label","FatalError","error","value","DEFAULT_CONCURRENCY_STATUSES","concurrencyTag","key","resolveConcurrency","override","config","input","undefined","limit","countStatuses","countRuns","store","query","runFacets","status","statuses","origin","cells","reduce","sum","c","count","rest","filter","includes","listRuns","length","assertConcurrency","workflow","quota","active","tag","ConcurrencyLimitError","ENTITY_WORKFLOW","entityRunId","name","key","Entities","configs","Map","host","register","ctx","input","run","config","set","dispatch","op","arg","reply","runId","signalWithStart","token","payload","signal","getState","getEvent","get","FatalError","state","initialState","i","msg","waitForSignal","out","localStep","handler","handlers","result","setEvent","accToken","target","EventAccumulators","host","register","ctx","input","debounce","batch","route","config","payload","workflow","mode","windowMs","maxSize","signalWithStart","token","last","waitForSignal","timeoutMs","e","SignalTimeoutError","startChild","continueAsNew","events","deadline","now","length","remaining","push","enc","s","Buffer","from","toString","dec","EVENT_BUFFER_SCAN_LIMIT","EVENT_TOKEN_PREFIX","eventPrefix","name","isEventToken","token","startsWith","eventToken","match","runId","seq","JSON","stringify","eventNameOf","split","eventMatchOf","parse","eventMatches","payload","keys","Object","length","p","every","k","allChildId","runId","firstSeq","index","wave","allBase","allGroup","mode","allWait","base","waiterPrefix","checkpointPrefix","fanJoin","waits","FOLDED_PREFIX","allFoldedName","foldedChildIds","checkpoint","name","slice","length","from","values","output","map","_","j","undefined","allWaves","size","concurrency","Number","isInteger","Error","waveSize","maxWaves","Math","floor","ENGINE_CHILD_ID","parentRunIdOf","exec","GROUP","REST","fanOfWaiter","waiter","group","parallelGroup","token","startsWith","rest","failFast","CURRENT_PROTOCOL_VERSION","LEGACY_V1_PROTOCOL","version","range","LEGACY_V1_CAPABILITIES","Object","freeze","isLegacyDescriptor","raw","protocol","undefined","normalizeDescriptor","instanceId","runtime","sdk","name","capabilities","workflows","steps","registrations","partition","namespace","startedAt","canonicalizeRegistrations","regs","canonical","map","r","group","requires","Set","sort","origin","byJson","Map","entry","set","JSON","stringify","keys","k","get","canonicalizeForHash","d","xs","fnv1a64Hex","input","OFFSET","PRIME","MASK","hash","i","length","BigInt","charCodeAt","toString","padStart","descriptorHash","descriptor","heartbeatStatus","opts","ts","Date","now","status","describeWorker","a","b","localeCompare","announcementsOf","raw","d","normalizeDescriptor","identity","instanceId","runtime","announcements","registrations","map","reg","covered","Set","a","name","workflows","has","push","announcementKey","version","undefined","stated","values","filter","v","sort","aggregateAnnouncements","descriptors","byKey","Map","descriptor","announcement","key","bucket","get","set","out","groups","group","origins","origin","requiresByJson","requires","canonical","JSON","stringify","x","y","join","localeCompare","disagreements","length","axis","r","first","evidence","runtimes","instances","b","observedAnnouncements","heartbeats","byToken","beat","add","entries","coveredTokens","announced","sanitize","tokens","entry","step","steps","token","partition","DEFAULT_PARTITION","partitionOfToken","token","at","lastIndexOf","slice","buildWorkflowDirectory","input","descriptors","heartbeats","namespace","supported","sanitize","workflows","otherPartitions","detail","mine","undefined","ownDescriptors","filter","d","ownBeats","foreign","Map","beat","group","partition","push","seen","get","groups","add","instances","instanceId","set","Set","declared","aggregateAnnouncements","observed","observedAnnouncements","coveredTokens","sort","a","b","key","localeCompare","entries","map","describeDirectory","summarize","names","limit","length","join","here","elsewhere","p","w","evidence","declaredNote","rangesOverlap","a","b","Math","max","min","difference","bset","Set","filter","x","has","sort","intersection","negotiate","localRaw","remoteRaw","opts","local","normalizeDescriptor","remote","localRange","protocol","range","remoteRange","shared","capabilities","missingOnRemote","missingOnLocal","outcome","negotiatedProtocol","reason","code","message","detail","required","missingRequired","length","join","parts","push","requiredCapabilities","handler","list","Array","isArray","requires","Set","canRoute","worker","required","length","advertised","normalizeDescriptor","capabilities","every","cap","has","missingCapabilities","filter","capableWorkers","workers","w","resolveRouting","capable","map","status","suffix","join","reason","controlPlaneDescriptor","opts","version","CURRENT_PROTOCOL_VERSION","instanceId","runtime","sdk","name","String","protocol","range","capabilities","workflows","steps","partition","undefined","namespace","startedAt","WorkflowBlocked","Error","plan","reason","planDispatch","requires","liveDescriptors","cp","token","required","requiredCapabilities","workers","map","normalizeDescriptor","capable","filter","w","canRoute","compatible","negotiate","outcome","length","status","workerRanges","code","join","diagnostics","liveWorkers","controlPlaneRange","controlPlane","advertised","Set","flatMap","missingCapabilities","cap","has","TERMINAL_RUN_STATUSES","isNonEmptyRunScope","scope","workflow","undefined","workflows","tag","tags","namespace","namespaces","attributes","length","tenantGroup","baseGroup","tenant","undefined","sanitizeQueueToken","name","replace","RemoteWorkflowExecutor","transport","name","partition","_opts","dispatch","run","history","taskId","pendingSignals","dispatchWorkflowTask","Error","task","runId","id","workflow","workflowVersion","input","group","tenantGroup","sanitizeQueueToken","priority","attempt","WEBHOOK_PREFIX","CHILD_PREFIX","BREAKPOINT_PREFIX","EVENT_PREFIX","EVENT_TOKEN_PREFIX","classifyWaiterToken","token","startsWith","on","name","slice","length","eventNameOf","resolveRunWaiting","run","waiterByRun","status","undefined","waiter","get","id","RUN_ID_BATCH","listSignalWaitersOfRuns","store","runIds","unique","Set","listSignalWaitersByRun","ids","listSignalWaiters","filter","w","has","runId","out","at","push","indexWaitersByRun","waiters","byRun","Map","set","createRequire","isIndexable","value","unwrapDefault","module_","Reflect","get","undefined","inner","v4Entry","parse","expr","options","call","v5Entry","parser","resolveCronParse","resolved","nodeRequire","createRequire","url","defaultSleep","ms","Promise","r","setTimeout","scheduledRunId","key","everyMs","nowMs","Math","floor","cronParser","loadCronParser","undefined","Error","prevCronFireMs","expr","timezone","parse","resolveCronParse","currentDate","Date","tz","prev","toDate","getTime","nextCronFireMs","afterMs","next","scheduleRunIdAt","s","cron","scheduleRunIdsAt","current","backfill","maxCatchup","ids","bucket","oldest","max","b","push","prior","cursor","i","before","reverse","runSchedules","engine","schedules","opts","random","sleep","paused","overlap","prevBucket","getRun","status","jitter","runId","start","workflow","input","ScheduleAlreadyExistsError","Error","scheduleId","name","ScheduleNotFoundError","DEFAULT_NAMESPACE","ON_TIME_GRACE_MS","TICK_BATCH","ScheduleClient","store","host","options","now","clock","Date","supported","s","saveSchedule","getSchedule","updateSchedule","deleteSchedule","listSchedules","requireStore","r","call","id","patch","expected","q","create","opts","write","upsert","get","record","describe","list","query","map","delete","pause","note","mustGet","spec","undefined","paused","updatedAt","resume","window","nextWindowAfter","nextFireAt","jitterFor","state","trigger","runId","start","workflow","specOf","input","startOptions","tick","nowMs","started","round","isDraining","due","dueBy","namespace","limit","fire","push","length","latest","next","latestWindowAtOrBefore","error","lastError","errorMessage","jitter","jitterMs","onTime","fired","skipMissed","catchup","beforeWindow","overlapping","getRun","nextState","lastFireAt","lastRunId","fires","stripUndefined","overlap","prev","TERMINAL_RUN_STATUSES","includes","status","existing","toSpec","workflowName","tags","createdAt","cron","every","everyMs","parseDuration","v","timezone","searchAttributes","priority","concurrency","atMs","prevCronFireMs","Math","floor","afterMs","nextCronFireMs","max","h","ch","charCodeAt","imul","o","Object","fromEntries","entries","filter","message","String","SINGLETON_ADMITTED_TAG","SINGLETON_ACTIVE_STATUSES","singletonAdmissionTags","runs","runId","tag","workflow","limit","Number","isInteger","Error","active","filter","run","includes","status","tags","candidate","find","id","holders","remaining","length","waiters","sort","a","b","createdAt","getTime","localeCompare","slice","some","clearTerminalSingletonAdmission","patch","getRun","TERMINAL_RUN_STATUSES","singletonAdmissionDenialPatch","retryWakeAt","undefined","wakeAt","updatedAt","Date","SINGLETON_RETRY_MS","SINGLETON_RETRY_JITTER_MS","SingletonGate","deps","tag","cfg","input","store","tryAdmitSingleton","Error","key","retryWakeAt","clock","Math","floor","random","assertCapacity","workflow","maxQueueDepth","cap","limit","queued","listRuns","statuses","SINGLETON_ACTIVE_STATUSES","length","SingletonQueueFullError","admit","run","admitted","id","tags","includes","SINGLETON_ADMITTED_TAG","wakeNext","settled","configFor","find","t","startsWith","gated","sort","a","b","createdAt","getTime","localeCompare","next","slice","updateRun","wakeAt","updatedAt","Date","catch","undefined","dispatch","TransportPool","transports","size","length","primary","first","Error","transport","bind","onResult","onHeartbeat","onStepEvent","onDecision","dispatch","task","preferId","lastErr","id","ordered","err","groupHealth","group","reports","push","undefined","depth","reduce","sum","r","liveWorkers","flatMap","onStartRun","handler","readWorkerDescriptors","descriptors","readAllWorkerDescriptors","byInstance","Map","descriptor","has","instanceId","set","values","readAllWorkerHeartbeats","seen","beat","key","introspectsFleet","some","listWorkerGroups","groups","Set","g","add","transportWithLiveGroup","includes","pref","filter","t","DURABLE_STEP_NAME","Symbol","for","DURABLE_STEP_CONFIG","isStepConfig","value","stepNameOf","ref","undefined","stamped","stepConfigOf","FAN_CHUNK","FOLD_MIN_FAN","normalizeChildOptions","options","childId","formatIssuePath","path","length","map","segment","String","key","join","resolveStepPolicy","config","opts","policy","retries","undefined","backoff","backoffMs","backoffMaxMs","jitter","timeoutMs","requires","Position","seq","next","rewind","peek","createWorkflowCtx","host","runId","compensations","workflow","searchAttributesSchema","store","replay","pos","scopeOwner","readCheckpoint","hit","get","getCheckpoint","writeCheckpoint","cp","saveCheckpoint","set","localStep","name","fn","current","existing","NonDeterminismError","status","compensate","push","output","maxAttempts","Math","max","startedAt","Date","startStep","kind","attempts","enqueuedAt","attempt","events","invocation","stepName","body","logger","createStepLogger","clock","runInStepScope","runInStepLogger","interceptStep","completeStep","err","FatalError","failStep","error","message","Error","stack","wait","backoffDelay","Promise","resolve","setTimeout","transaction","tx","raw","instantCheckpoint","suspendUntil","wakeAt","now","WorkflowSuspended","at","sleep","duration","parseDuration","sleepUntil","when","getTime","continueAsNew","input","ContinueAsNew","consumeBuffered","token","buffered","takeBufferedSignal","payload","value","consumeBufferedEvent","match","candidates","listBufferedEvents","EVENT_BUFFER_SCAN_LIMIT","candidate","eventMatches","removeBufferedEvent","id","removeSignalWaiter","stampDeadline","deadlineSeq","label","recorded","deadline","waitForSignal","putSignalWaiter","lateBuffered","waitSeq","waited","catch","SignalTimeoutError","waitForEvent","eventToken","bufferedHit","task","dispatch","unwrapCompletion","child","priority","version","getRun","startChild","workflowName","fanJoin","waiterPrefix","checkpointPrefix","all","inputs","mode","waves","allWaves","concurrency","positions","firstSeq","group","allGroup","waveOf","i","floor","waveSize","allChildId","checkpoints","folded","readFan","allWait","allFoldedName","waveCount","ceil","waveItems","k","_","from","slice","c","ok","j","cancelChild","GatherError","index","compactCheckpoints","items","first","last","values","into","parallelGroup","delete","sent","some","settled","every","active","unsettled","maxWaves","toRegister","toEnsure","chunk","entries","waiter","checkpoint","registerChildWaits","outputs","failures","prefixes","expand","startsWith","FOLDED_PREFIX","fold","Array","isArray","forEach","missing","filter","listCheckpointsByNamePrefix","bySeq","Map","e","callEntity","op","arg","reply","signalEntity","breakpoint","breakpointToken","patched","marker","onUpdate","setEvent","webhook","takeSignalWaiter","url","webhookUrl","sideEffect","upsertSearchAttributes","attrs","run","merged","searchAttributes","result","validate","issues","offendingKeys","Set","issue","details","resolveCompensateDef","stepNameOf","stepConfigOf","step","handlerOrName","def","callRemote","queue","transport","fairnessKey","then","args","nestedStep","scope","currentStepScope","owner","guard","primitive","NestedWorkflowCallError","guardedWebhook","mergeTags","staticTags","runTags","length","undefined","Set","BREAKPOINT","isBreakpoint","cp","status","name","startsWith","VERSION_UNDECLARED_TAG","versionKey","version","stepGroup","step","runNamespace","tenantGroup","sanitizeQueueToken","partition","nextContinuationId","runId","m","match","Number","isNewerVersion","a","b","na","nb","isNaN","localeCompare","numeric","NamespaceMismatch","Error","WorkflowEngine","store","pool","controlPlane","clock","instanceId","namespace","leaseMs","maxRecoveryAttempts","remoteAdvanceSilenceMs","reconcileMs","eventBufferTtlMs","remoteRedispatchMs","remoteRedispatchMax","blockedPollMs","cpDescriptor","webhookUrl","traceparent","context","rehydrate","compensationRetries","trackStepStart","runDispatcher","singletons","schedules","workflows","Map","latest","eventTriggers","entities","accumulators","pending","heartbeatResets","listeners","interceptors","cancelListeners","enqueuedListeners","deadListeners","updateValidators","cancelRequested","admission","queueWaiters","stepQueue","inflight","draining","drainSpentMs","drainRearms","deps","TransportPool","transports","transport","id","Date","now","InMemoryAdmissionBackend","onFreed","queue","wakeQueueWaiters","globalThis","crypto","randomUUID","Math","max","controlPlaneDescriptor","_carrier","fn","dispatch","queueMicrotask","runOne","catch","SingletonGate","configFor","run","get","workflow","workflowVersion","singleton","ScheduleClient","start","input","opts","getRun","isDraining","bind","result","waiter","stepId","delete","resolve","output","startedAt","events","reject","RemoteStepError","error","completeRemoteResult","beat","reset","rearmDecisionDeadline","rearmStepLease","seq","event","persistStepEvent","decision","completeRemoteDecision","onStartRun","message","tenant","tags","searchAttributes","onControl","msg","from","kind","deliver","at","notifyCancelled","EventAccumulators","Entities","registerEntity","config","register","signalEntity","key","op","arg","signal","getEntityState","getState","onEnqueued","listener","add","group","executor","registered","concurrency","executionTimeoutMs","executionTimeout","parseDuration","validateInput","searchAttributesSchema","onEvent","eventBatch","requires","origin","hasBody","remote","set","current","subscribers","workflowBody","reg","registeredVersions","versions","values","filter","w","map","join","registerRemote","rest","RemoteWorkflowExecutor","primary","registerQueue","subscribe","use","interceptor","push","i","indexOf","splice","interceptStep","invocation","body","carrier","chain","reduceRight","next","onCancel","onDead","notifyDead","emit","full","publishControl","workflowName","pinned","ancestor","findRemoteAncestor","synthesizeRemoteChild","conventionRun","createdAt","updatedAt","resolveRemoteByConvention","askFleetForVersion","prior","quota","resolveConcurrency","assertConcurrency","stampedTags","tag","concurrencyTag","versionDeclared","SINGLETON_ADMITTED_TAG","assertCapacity","priority","createRun","resume","resumeRun","resumeImplicit","allowFailed","releaseRunLock","includes","updateRun","findInheritedRegistration","track","execute","liveTransport","transportWithLiveGroup","declared","declaredVersion","readWorkerDescriptors","descriptors","announced","aggregateAnnouncements","only","childRunId","visited","has","parentRunId","findParentRunId","parent","parentReg","token","waiters","listSignalWaiters","find","p","done","then","beginDrain","spentMs","isFinite","rearm","drain","timeoutMs","size","timeout","timer","Promise","clearTimeout","remaining","setTimeout","unref","race","allSettled","sweepTimeouts","deadline","listRuns","getTime","code","type","cancelChildren","recoverIncomplete","nowMs","results","listed","listIncompleteRuns","acquired","tryLockRun","dispatched","inFlightRemoteStep","wakeAt","reconcileWakeAt","settled","countRecovery","checkpoints","listCheckpoints","attempts","recoveryAttempts","resumeDueTimers","due","listDueTimers","blocked","dueBlockedRuns","waiterByRun","indexWaitersByRun","listSignalWaitersOfRuns","resumeLeased","reconcileSignalWaiter","isEventToken","reconcileBufferedEvent","buffered","takeBufferedSignal","removeSignalWaiter","deliverSignal","payload","eventNameOf","eventMatchOf","candidates","listBufferedEvents","EVENT_BUFFER_SCAN_LIMIT","candidate","publishedAt","removeBufferedEvent","eventMatches","err","requeue","_seen","seen","resurrecting","isFailureCompletion","v","ok","saveCheckpoint","retryable","childId","slice","parked","successAt","findIndex","success","bufferSignal","bufferedSuccess","putSignalWaiter","parallelGroup","child","redispatchPending","redispatched","reAttempt","reEnqueuedAt","enqueuedAt","finishedAt","dispatchRemoteTask","workerGroup","attempt","retryWithInput","newRunId","runPending","listPendingRuns","waitForRun","TERMINAL","isSettled","until","awaitingDecisionTaskId","toResult","off","poller","clearInterval","finish","fail","check","interval","setInterval","ev","runs","onLocked","console","publishEvent","touched","eventPrefix","eventId","batch","route","buffer","bufferedId","bufferEvent","lateWaiters","lateWaiter","takeSignalWaiter","instantCheckpoint","fanStillWaiting","hasSignalWaiter","fan","fanOfWaiter","failFast","isFailedCompletion","waiterPrefix","redriveSettledChildren","wait","waits","listCheckpointsByNamePrefix","checkpointPrefix","every","reclaimed","signalWithStart","completeTask","value","failTask","notifyParent","completion","lastIndexOf","startChildDeferred","String","cancel","TERMINAL_RUN_STATUSES","compensate","wakeNext","cancelWhere","r","deleteRun","deleted","getRunChildren","purgeRuns","scope","isNonEmptyRunScope","batchSize","cancelLive","withChildren","children","statuses","previous","limit","fingerprint","known","ids","collectSubtrees","doomed","deleteRunIds","purgeNamespace","rootIds","prefixes","CHILD_EDGE_PREFIXES","childrenOf","awaitedChildIds","cps","some","childIdsOf","ordered","visit","deleteRuns","childIds","childCheckpoints","knownGroups","extra","groups","def","workerHealth","listWorkerGroups","inflightStepGroups","workflowTokens","out","health","groupHealth","baseToken","announcedWorkflows","workflowDirectory","buildWorkflowDirectory","readAllWorkerDescriptors","heartbeats","readAllWorkerHeartbeats","supported","introspectsFleet","sanitize","phase","stepCheckpoint","failed","startStep","completeStep","queueMs","durationMs","failStep","singletonWaitResult","lockNow","lockedBy","lockedUntil","renew","renewRunLock","floor","runRemoteExecution","runExecution","settleRun","outcome","parkBlocked","admit","wfPlan","planRoute","history","remoteHistory","taskId","silenceMs","advanceExecutor","advance","call","awaitWithLivenessDeadline","RemoteWorkflowTimeout","stack","applyDecision","applyCommands","commands","fresh","suspended","redriveIfTurnSawStaleHistory","blocking","cmd","checkpoint","getCheckpoint","redriveLostCall","lease","stepLeaseWakeAt","lostStepEvent","reconcile","min","stepLeaseRearms","lookAgainAt","halfWindow","ceil","renewed","clear","kindOf","local","sleep","sort","redriveLost","existing","leaseAt","leaseWake","ms","deliverBuffered","lateBuffered","compensateAndCancel","compensations","replay","unwindCompensations","runDurableExecution","unit","runExecutionTurn","snapshot","suspendedOnFan","ctx","createWorkflowCtx","ctxHostFor","runInWorkflowCtx","ContinueAsNew","nextId","WorkflowBlocked","plan","WorkflowSuspended","comp","runCompensation","dispatchCompensation","args","maxAttempts","retries","backoffDelay","withWakeAt","dispatchCompensationAttempt","parentNamespace","s","callRemote","startChild","cancelChild","upsertSearchAttributes","attrs","reply","continue","bp","breakpointToken","getEvent","getLatestCheckpointByName","registerUpdateValidator","validate","update","accepted","reason","planDispatch","ensureRoutable","diagnostics","routing","NonDeterminismError","callRemoteInMemory","nextDeadline","handles","tryAdmit","fairnessKey","waiterId","retryAt","task","releaseQueueSlot","decisionDeadlineRearms","runIds","release","validInput","parse","resultPromise","resolution","awaitWithHeartbeat","RemoteStepTimeout","onTimeout","cleanup","arm","stepError","FOLDED_PREFIX","foldedChildIds","facetOrigin","origin","trim","mergeRunFacetRows","rows","cells","Map","row","key","JSON","stringify","status","cell","get","count","set","values","RUN_VALUE_FACET_LIMIT","RUN_VALUE_FACET_SCAN","ENGINE_MINTED_TAG_PREFIXES","isEngineMintedTag","value","some","prefix","startsWith","axisIsRunColumn","axis","field","valuesOf","run","workflow","status","facetOrigin","origin","namespace","undefined","tags","Object","keys","searchAttributes","key","String","mergeRunValueFacetRows","rows","opts","counts","Map","row","set","get","Number","count","needle","search","trim","toLowerCase","merged","map","filter","includes","sort","a","b","engineA","engineB","localeCompare","offset","slice","limit","runValueFacetsFromRuns","runs","push","RunGateway","CodecStateStore","tryAdmitSingleton","runFacets","runValueFacets","deleteRuns","pruneTerminalRuns","countRuns","registerChildWaits","compactCheckpoints","listSignalWaitersByRun","hasSignalWaiter","saveSchedule","getSchedule","updateSchedule","deleteSchedule","listSchedules","inner","codec","bind","ids","call","prune","policy","now","limit","count","query","entries","map","e","waiter","checkpoint","encCp","compact","runId","fromSeq","toSeq","into","byRun","runIds","hasWaiter","tokenPrefix","r","encSchedule","id","decSchedule","patch","expected","spec","encSpec","q","facets","valueFacets","axis","opts","enc","v","undefined","encode","dec","decode","encRun","run","input","output","decRun","cp","decCp","ensureSchema","Promise","resolve","createRun","updateRun","next","getRun","deleteRun","getCheckpoint","seq","saveCheckpoint","transaction","work","Error","tx","raw","listIncompleteRuns","namespace","listPendingRuns","listDueTimers","nowMs","tryLockRun","owner","leaseUntilMs","releaseRunLock","renewRunLock","putSignalWaiter","takeSignalWaiter","token","listSignalWaiters","prefix","removeSignalWaiter","bufferSignal","payload","takeBufferedSignal","buffered","bufferEvent","listBufferedEvents","name","events","removeBufferedEvent","listRuns","listCheckpoints","c","getLatestCheckpointByName","latest","listCheckpointsByNamePrefix","prefixes","matches","filter","some","p","startsWith","collectMetrics","engine","m","runs","started","completed","failed","suspended","steps","byWorkflow","stepDuration","sumMs","count","wf","name","k","entry","stop","subscribe","e","type","workflow","durationMs","snapshot","structuredClone","prometheus","lines","push","v","Object","entries","event","n","join","compare","actual","filter","op","values","some","v","expected","value","matchesAttributes","attributes","filters","length","every","f","key","applyAttributeQuery","rows","query","filtered","r","searchAttributes","offset","limit","slice","normalizeAttributeRows","runId","out","Object","entries","push","strValue","numValue","sqlComparator","attributeColumnFor","attributeOperand","attributePredicateOperands","map","scalar","column","comparator","operand","readSearchAttributes","schema","run","result","validate","searchAttributes","Promise","Error","issues","value","STATE_STORE","Symbol","for","TRANSPORT","DURABLE_OPTIONS","STATE_STORE_CANONICAL","TRANSPORT_CANONICAL","DURABLE_OPTIONS_CANONICAL","InMemoryStateStore","runs","Map","checkpoints","signalWaiters","attributeIndex","lastAttributeCandidates","lastCheckpointRowsRead","key","runId","seq","reindexAttributes","attributes","byRun","values","delete","row","normalizeAttributeRows","get","set","tryAdmitSingleton","tag","workflow","limit","retryWakeAt","tags","singletonAdmissionTags","patch","singletonAdmissionDenialPatch","candidate","run","createRun","id","namespace","searchAttributes","updateRun","inputPatch","status","TERMINAL_RUN_STATUSES","includes","filter","SINGLETON_ADMITTED_TAG","existing","Error","next","getRun","deleteRun","cp","token","waiter","undefined","deleteRuns","runIds","pruneTerminalRuns","policy","nowMs","statuses","s","length","maxAge","maxCount","inScope","matching","scope","ids","Set","cutoff","parseDuration","expired","r","updatedAt","getTime","sort","a","b","slice","add","size","byRecency","localeCompare","doomed","getCheckpoint","saveCheckpoint","checkpoint","listIncompleteRuns","map","listPendingRuns","createdAt","listDueTimers","wakeAt","tryLockRun","owner","leaseUntilMs","lockedUntil","lockedBy","releaseRunLock","renewRunLock","putSignalWaiter","takeSignalWaiter","listSignalWaiters","prefix","w","startsWith","registerChildWaits","entries","compactCheckpoints","fromSeq","toSeq","into","listSignalWaitersByRun","has","hasSignalWaiter","tokenPrefix","removeSignalWaiter","current","transaction","work","raw","bufferedSignals","bufferSignal","payload","queue","push","takeBufferedSignal","shift","bufferedEvents","bufferEvent","input","name","publishedAt","listBufferedEvents","e","removeBufferedEvent","candidatesForFilter","f","out","comparisons","attributePredicateOperands","matched","some","column","comparator","operand","actual","numValue","strValue","query","workflows","t","namespaces","origin","origins","candidates","prev","listRuns","offset","countRuns","runFacets","mergeRunFacetRows","count","runValueFacets","axis","opts","scan","RUN_VALUE_FACET_SCAN","runValueFacetsFromRuns","schedules","saveSchedule","record","structuredClone","getSchedule","updateSchedule","expectedNextFireAt","nextFireAt","deleteSchedule","listSchedules","rows","paused","dueBy","Number","POSITIVE_INFINITY","listCheckpoints","getLatestCheckpointByName","latest","listCheckpointsByNamePrefix","prefixes","p","InMemoryTransport","handlers","Map","resultHandler","heartbeatHandler","stepEventHandler","controlHandlers","Set","handle","name","fn","set","dispatch","task","Error","result","runStepHandler","get","setImmediate","onResult","handler","onHeartbeat","emitHeartbeat","beat","dispatchStepEvent","event","onStepEvent","publishControl","msg","onControl","add"]}
|