@sanity/workflow-engine 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/api/validate.ts","../src/core/refs.ts","../src/core/params.ts","../src/keys.ts","../src/core/eval.ts","../src/core/snapshot.ts","../src/snapshot.ts","../src/core/path.ts","../src/core/slot-validation.ts","../src/state-resolution.ts","../src/engine/context.ts","../src/core/state-read.ts","../src/core/source.ts","../src/core/bindings.ts","../src/instance.ts","../src/core/guards.ts","../src/guard-bindings.ts","../src/guards-lifecycle.ts","../src/discover.ts","../src/engine/spawn.ts","../src/engine/tasks.ts","../src/engine/stages.ts","../src/engine/cascade.ts","../src/engine/mutation.ts","../src/engine/effects.ts","../src/engine/results.ts","../src/engine/ops.ts","../src/engine/actions.ts","../src/permissions.ts","../src/access.ts","../src/tags.ts","../src/evaluate.ts","../src/types/evaluation.ts","../src/api/deploy.ts","../src/api/operations.ts","../src/api/workflow.ts","../src/api/drain.ts","../src/api/engine-factory.ts","../src/types/authorization.ts","../src/display.ts"],"sourcesContent":["import {parse as parseGroq} from 'groq-js'\n\nimport type {Stage, StateSlot, Task, WorkflowDefinition} from '../define/schema.ts'\n\n/**\n * Parse-validate every GROQ string in a definition before deploy.\n * Surfaces malformed predicate queries, filters, bindings, and\n * `task.completeWhen`/`failWhen` expressions early — long before any\n * instance runs.\n *\n * Throws an `Error` with all problems aggregated. Doesn't try to\n * type-check semantics (just syntax). Reserved params don't need to be\n * declared here — groq-js's parser doesn't know about runtime params,\n * just syntax.\n */\nexport function validateDefinition(definition: WorkflowDefinition): void {\n const v = createDefinitionValidator()\n\n for (const slot of (definition as WorkflowDefinition & {state?: StateSlot[]}).state ?? []) {\n v.checkSlot(slot, `workflow.state`, `workflow.state \"${slot.id}\"`)\n }\n\n for (const p of definition.predicates ?? []) {\n if (p.groq) v.checkFilter(p.groq, `predicate \"${p.id}\"`)\n }\n\n for (const stage of definition.stages) {\n validateStage(v, stage)\n }\n\n if (v.errors.length > 0) {\n throw new Error(\n `defineWorkflow(\"${definition.workflowId}\", v${definition.version}): ` +\n `${v.errors.length} validation error${v.errors.length === 1 ? '' : 's'}:\\n` +\n v.errors.join('\\n'),\n )\n }\n}\n\ninterface DefinitionValidator {\n errors: string[]\n /** Parse-check raw GROQ; records a syntax error under `where`. */\n tryParse: (groq: string, where: string) => void\n /** Parse-check a filter AND reject `_type` discovery scans in it. */\n checkFilter: (groq: string, where: string) => void\n /** Reject `computed` slots and parse-check a `query`-sourced slot. */\n checkSlot: (slot: StateSlot, scopeLabel: string, slotLabel: string) => void\n}\n\nfunction createDefinitionValidator(): DefinitionValidator {\n const errors: string[] = []\n const tryParse = (groq: string, where: string) => {\n try {\n parseGroq(groq)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n errors.push(` · ${where}: ${message}`)\n }\n }\n // Reject filters that scan by `_type` — those are discovery queries,\n // not predicates. Filters evaluate against the in-memory snapshot\n // (instance + subject + ancestors + state-declared docs), which never\n // contains \"all docs of type X\", so a type scan returns empty and the\n // workflow appears stuck. Regex-based: `*[` followed by `_type`. False\n // negatives slip through harmlessly (runtime still returns empty).\n const rejectTypeScan = (groq: string, where: string) => {\n if (/\\*\\s*\\[\\s*_type\\b/.test(groq)) {\n errors.push(\n ` · ${where}: filter scans by \\`_type\\` — that's a discovery query, not a predicate. ` +\n `Filters evaluate against the in-memory snapshot (instance + ancestors + ` +\n `state-declared docs). To bring extra docs in scope, declare a \\`workflow.state.doc.ref\\` ` +\n `(or \\`doc.refs\\`) slot on the workflow or this stage. For lake scans like ` +\n `\"all articles in this release\", use spawn \\`forEach.groq\\` instead.`,\n )\n }\n }\n const checkFilter = (groq: string, where: string) => {\n tryParse(groq, where)\n rejectTypeScan(groq, where)\n }\n const checkSlot = (slot: StateSlot, scopeLabel: string, slotLabel: string) => {\n if (slot.source.kind === 'computed') {\n errors.push(\n ` · ${scopeLabel} slot \"${slot.id}\": source.kind=\"computed\" is reserved (not implemented in v0.1)`,\n )\n }\n if (slot.source.kind === 'query') tryParse(slot.source.query, `${slotLabel}.query`)\n }\n return {errors, tryParse, checkFilter, checkSlot}\n}\n\nfunction validateStage(v: DefinitionValidator, stage: Stage): void {\n for (const slot of stage.state ?? []) {\n v.checkSlot(slot, `stage \"${stage.id}\".state`, `stage \"${stage.id}\".state \"${slot.id}\"`)\n }\n if (typeof stage.completion === 'string') {\n v.tryParse(stage.completion, `stage \"${stage.id}\".completion`)\n }\n for (const t of stage.transitions ?? []) {\n // Effect bindings are typed Source values now — no GROQ to parse.\n if (typeof t.filter === 'string')\n v.checkFilter(t.filter, `transition ${stage.id} → ${t.to} filter`)\n }\n for (const task of stage.tasks ?? []) {\n validateTask(v, stage.id, task)\n }\n}\n\nfunction validateTask(v: DefinitionValidator, stageId: string, task: Task): void {\n const where = `stage \"${stageId}\" task \"${task.id}\"`\n for (const slot of task.state ?? []) {\n v.checkSlot(slot, `${where}.state`, `${where}.state \"${slot.id}\"`)\n }\n if (typeof task.filter === 'string') v.checkFilter(task.filter, `${where}.filter`)\n if (typeof task.completeWhen === 'string')\n v.checkFilter(task.completeWhen, `${where}.completeWhen`)\n for (const a of task.actions ?? []) {\n if (typeof a.filter === 'string')\n v.checkFilter(a.filter, `task \"${task.id}\" action \"${a.id}\".filter`)\n }\n // spawn.forEach.groq is intentionally NOT type-scan-checked — it's\n // discovery, not a filter.\n if (task.spawns?.forEach?.groq) {\n v.tryParse(task.spawns.forEach.groq, `task \"${task.id}\".spawns.forEach.groq`)\n }\n}\n","/**\n * Global Document References (GDR).\n *\n * Every cross-document reference in the engine API uses this shape so\n * workflow state can live in one Sanity resource while subjects /\n * ancestors / effect-binding refs point at docs in *different* resources.\n *\n * Resource schemes mirror `@sanity/client`'s `ClientConfigResource`\n * discriminator. A GDR id is a typed URI:\n *\n * dataset:<projectId>:<dataset>:<documentId>\n * canvas:<resourceId>:<documentId>\n * media-library:<resourceId>:<documentId>\n * dashboard:<resourceId>:<documentId>\n *\n * The `type` field carries the doc's schema `_type` so consumers don't\n * need a separate lookup to know what they're pointing at.\n */\n\nexport type GdrScheme = 'dataset' | 'canvas' | 'media-library' | 'dashboard'\n\n/**\n * Typed GDR URI string. The compiler rejects bare doc ids (`\"doc-1\"`)\n * — only `<scheme>:<...id-parts>` values typecheck. Construct one via\n * `gdrUri()` / `gdrFromResource()` / `refDataset()` etc., or by hand\n * with the scheme prefix baked in (`` `dataset:proj:ds:${docId}` `` ).\n *\n * Combined with Zod validation at the API boundary, this is the\n * type + runtime guarantee that no bare-string id reaches the\n * snapshot, slot, or filter layer.\n */\nexport type GdrUri = `${GdrScheme}:${string}`\n\nexport interface GlobalDocumentReference {\n /** URI: `<scheme>:<...id-parts>` */\n id: GdrUri\n /** Document `_type` (schema name) */\n type: string\n}\n\nexport interface ParsedGdr {\n scheme: GdrScheme\n /** For `dataset`: `<projectId>` */\n projectId?: string\n /** For `dataset`: `<dataset>` */\n dataset?: string\n /** For `canvas` / `media-library` / `dashboard`: `<resourceId>` */\n resourceId?: string\n /** The trailing `<documentId>` part — what `_id` of the target doc is */\n documentId: string\n}\n\nconst KNOWN_SCHEMES = new Set<string>(['dataset', 'canvas', 'media-library', 'dashboard'])\n\n/**\n * Parse a GDR URI into its scheme + addressing parts. Throws on\n * unknown scheme or malformed shape.\n */\nexport function parseGdr(uri: string): ParsedGdr {\n const colon = uri.indexOf(':')\n if (colon < 0) {\n throw new Error(\n `Invalid GDR \"${uri}\": must be a URI of form \"<scheme>:<...id-parts>\". Known schemes: dataset, canvas, media-library, dashboard.`,\n )\n }\n const scheme = uri.slice(0, colon)\n const rest = uri.slice(colon + 1)\n if (!KNOWN_SCHEMES.has(scheme)) {\n throw new Error(\n `Invalid GDR \"${uri}\": unknown scheme \"${scheme}\". Known: dataset, canvas, media-library, dashboard.`,\n )\n }\n const parts = rest.split(':')\n if (parts.some((part) => part.length === 0)) {\n throw new Error(\n `Invalid GDR \"${uri}\": id parts must be non-empty (no leading, trailing, or doubled \":\").`,\n )\n }\n if (scheme === 'dataset') {\n if (parts.length !== 3) {\n throw new Error(\n `Invalid GDR \"${uri}\": dataset scheme requires <projectId>:<dataset>:<documentId> (3 parts after scheme); got ${parts.length}.`,\n )\n }\n return {\n scheme: 'dataset',\n projectId: parts[0]!,\n dataset: parts[1]!,\n documentId: parts[2]!,\n }\n }\n // canvas / media-library / dashboard share <resourceId>:<documentId>\n if (parts.length !== 2) {\n throw new Error(\n `Invalid GDR \"${uri}\": ${scheme} scheme requires <resourceId>:<documentId> (2 parts after scheme); got ${parts.length}.`,\n )\n }\n return {\n scheme: scheme as GdrScheme,\n resourceId: parts[0]!,\n documentId: parts[1]!,\n }\n}\n\n/** Compose a GDR URI from parts. Inverse of `parseGdr`. */\nexport function gdrUri(\n parts:\n | {scheme: 'dataset'; projectId: string; dataset: string; documentId: string}\n | {\n scheme: 'canvas' | 'media-library' | 'dashboard'\n resourceId: string\n documentId: string\n },\n): GdrUri {\n if (parts.scheme === 'dataset') {\n return `dataset:${parts.projectId}:${parts.dataset}:${parts.documentId}` as GdrUri\n }\n return `${parts.scheme}:${parts.resourceId}:${parts.documentId}` as GdrUri\n}\n\n/**\n * Extract the bare document `_id` from a GDR URI — what\n * `*[_id == $docId]` in GROQ needs.\n */\nexport function extractDocumentId(gdrUriString: string): string {\n return parseGdr(gdrUriString).documentId\n}\n\n/** Make a GDR pointer to a project-dataset doc. */\nexport function refDataset(\n projectId: string,\n dataset: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'dataset', projectId, dataset, documentId}), type}\n}\n\n/** Make a GDR pointer to a Canvas-resource doc. */\nexport function refCanvas(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'canvas', resourceId, documentId}), type}\n}\n\n/** Make a GDR pointer to a Media-Library-resource doc. */\nexport function refMediaLibrary(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'media-library', resourceId, documentId}), type}\n}\n\n/** Make a GDR pointer to a Dashboard-resource doc. */\nexport function refDashboard(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'dashboard', resourceId, documentId}), type}\n}\n\n/**\n * The resource a Sanity client is configured against — mirrors\n * `@sanity/client`'s `ClientConfigResource` discriminator. For\n * `dataset`, `id` is `<projectId>.<dataset>`. For the others, `id` is\n * the resource id.\n */\nexport type WorkflowResource =\n | {type: 'dataset'; id: string}\n | {type: 'canvas'; id: string}\n | {type: 'media-library'; id: string}\n | {type: 'dashboard'; id: string}\n\n/**\n * Build a GDR URI from a workflow resource config + a document id\n * within that resource. This is how the engine mints `_id`s for\n * definitions / instances / ancestor refs into its own resource.\n */\nexport function gdrFromResource(res: WorkflowResource, documentId: string): GdrUri {\n if (res.type === 'dataset') {\n const dot = res.id.indexOf('.')\n if (dot < 0) {\n throw new Error(`Invalid dataset resource id \"${res.id}\": expected \"<projectId>.<dataset>\".`)\n }\n const projectId = res.id.slice(0, dot)\n const dataset = res.id.slice(dot + 1)\n return gdrUri({scheme: 'dataset', projectId, dataset, documentId})\n }\n return gdrUri({scheme: res.type, resourceId: res.id, documentId})\n}\n\n/**\n * Type-narrowing predicate — `true` when `value` looks like a GDR URI\n * (has a known scheme prefix). Use at boundaries that receive\n * stringified ids and need to refuse bare doc ids.\n */\nexport function isGdrUri(value: unknown): value is GdrUri {\n if (typeof value !== 'string') return false\n try {\n parseGdr(value)\n return true\n } catch {\n return false\n }\n}\n\n/** Build a GDR (id + type) pointing at a document within a workflow resource. */\nexport function gdrRef(\n res: WorkflowResource,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrFromResource(res, documentId), type}\n}\n\n/** Type filter for GDR shape. */\nexport function isGdr(value: unknown): value is GlobalDocumentReference {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as {id?: unknown}).id === 'string' &&\n typeof (value as {type?: unknown}).type === 'string'\n )\n}\n","/**\n * Pure param transforms.\n *\n * `buildParams(instance, extra?)` — assemble the reserved param bag\n * a filter sees: `$self`, `$state`, `$parent`, `$ancestors`,\n * `$stage`, `$now`. All ids are GDR URIs so they match the\n * snapshot's keying.\n *\n * `paramsForLake(params)` — strip GDR URIs back to bare ids on the\n * reserved id params, for the shell when it needs to fall through\n * to a lake fetch (spawn discovery scans). Pure transform;\n * doesn't touch the network itself.\n *\n * No client. No I/O. The shell builds these and passes them to\n * `evaluateFilter` (also pure).\n */\n\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {extractDocumentId, gdrFromResource, isGdrUri} from './refs.ts'\n\n/**\n * Reserved params available to every filter. `$now` is set at call time\n * so multiple predicates fired in the same eval pass agree on the time.\n *\n * `$state` is a map keyed by slot id — filters read state via\n * `$state.<slotId>.value.id` for doc.refs, `$state.<slotId>.value`\n * for scalar slots, etc. There is no privileged slot name; the\n * engine doesn't care that you happened to name one \"subject\" or\n * \"article\". The author owns the naming.\n */\nexport function buildParams(\n instance: WorkflowInstance,\n extra?: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n self: gdrFromResource(instance.workflowResource, instance._id),\n state: stateMap(instance.state ?? []),\n parent: instance.ancestors.at(-1)?.id ?? null,\n ancestors: instance.ancestors.map((a) => a.id),\n /** Current stage id — bind for filters that scope to the current stage. */\n stage: instance.currentStageId,\n now: new Date().toISOString(),\n ...extra,\n }\n}\n\n/**\n * Project the instance's workflow-scope state into a `slotId → slot`\n * map so filters can write `$state.article.value.id`. The slot envelope\n * (id, _type, title?, description?, value, resolvedAt?) is exposed —\n * not just the `value` — so filters that want to distinguish \"slot\n * absent\" from \"slot present with null value\" can do so via\n * `defined($state.article)` vs `defined($state.article.value)`.\n *\n * Stage-scope and task-scope state are NOT in `$state`. They live on\n * `instance.stages[id == $stage && !defined(exitedAt)][0].state[]`\n * and the parallel task path, addressable via GROQ traversal.\n */\nfunction stateMap(slots: ResolvedStateSlot[]): Record<string, ResolvedStateSlot> {\n const out: Record<string, ResolvedStateSlot> = {}\n for (const s of slots) out[s.id] = s\n return out\n}\n\n/**\n * Strip GDR URIs back to bare `_id`s on the reserved id params before\n * a lake fetch (discovery scans). Sanity refs are stored bare on disk,\n * so `releaseRef._ref == $state.release.value.id` only matches when\n * the id is bare in the lake query.\n *\n * Pure transform. Doesn't fetch. The shell decides when to call it.\n *\n * The `$state` map is walked recursively because slot values can\n * carry GDRs (doc.ref / doc.refs) that need stripping for lake match\n * predicates.\n */\nexport function paramsForLake(params: Record<string, unknown>): Record<string, unknown> {\n return {\n ...params,\n self: typeof params.self === 'string' ? bareId(params.self) : params.self,\n parent: typeof params.parent === 'string' ? bareId(params.parent) : params.parent,\n ancestors: Array.isArray(params.ancestors)\n ? params.ancestors.map((a) => (typeof a === 'string' ? bareId(a) : a))\n : params.ancestors,\n state: stripStateForLake(params.state),\n }\n}\n\nfunction stripStateForLake(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return bareId(value)\n if (Array.isArray(value)) return value.map(stripStateForLake)\n if (typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = stripStateForLake(v)\n }\n return out\n }\n return value\n}\n\nfunction bareId(id: string): string {\n return isGdrUri(id) ? extractDocumentId(id) : id\n}\n","/** Hex-encoded random key, sliced to {@link length} chars. Used for every\n * Sanity array `_key` and document id suffix the engine mints. */\nexport function randomKey(length = 12): string {\n const bytes = new Uint8Array(length)\n globalThis.crypto.getRandomValues(bytes)\n return [...bytes]\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, length)\n}\n","/**\n * Pure filter evaluation.\n *\n * Takes a filter (inline GROQ or named-predicate ref), a definition\n * (for predicate lookup + arg validation), a hydrated snapshot, and a\n * param bag. Runs groq-js against the snapshot. Returns boolean.\n *\n * NO CLIENT. NO I/O. NO LAKE FALLBACK.\n *\n * Filters evaluate against whatever the shell handed us — never against\n * the network. Purity is what lets the evaluator compose reactively: an\n * observable's snapshot updates can pipe straight into this function,\n * which a client-taking evaluator could not. If a filter references a\n * doc the shell didn't hydrate, groq-js sees a hole and the predicate\n * evaluates accordingly (usually false / null). Hydration completeness\n * is the shell's responsibility, not the core's.\n *\n * Discovery queries (`*[_type == 'X' && ...]` — spawn `forEach.groq`,\n * cross-doc lake scans) are NOT filters. They live in a separate shell\n * primitive (`discoverItems`) and never come through here.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport type {Filter, Predicate, WorkflowDefinition} from '../define/schema.ts'\nimport {isGdr} from './refs.ts'\nimport type {HydratedSnapshot} from './snapshot.ts'\n\nexport interface EvaluateFilterArgs {\n filter: Filter | undefined\n definition: WorkflowDefinition\n snapshot: HydratedSnapshot\n params: Record<string, unknown>\n}\n\n/**\n * Evaluate a filter against the supplied snapshot. Returns true when no\n * filter is set (vacuous truth). Throws on a malformed named ref or\n * invalid predicate args — those are author bugs, not runtime\n * conditions.\n */\nexport async function evaluateFilter(args: EvaluateFilterArgs): Promise<boolean> {\n const {filter, definition, snapshot, params} = args\n if (filter === undefined) return true\n\n if (typeof filter === 'string') {\n return runGroqAgainstSnapshot(filter, params, snapshot)\n }\n\n const predicate = (definition.predicates ?? []).find((p) => p.id === filter.ref)\n if (predicate === undefined) {\n throw new Error(`Unknown predicate ref: ${filter.ref}`)\n }\n validatePredicateArgs(predicate, filter.args ?? {})\n\n const merged = {...params, ...filter.args}\n return runGroqAgainstSnapshot(predicate.groq, merged, snapshot)\n}\n\nasync function runGroqAgainstSnapshot(\n groq: string,\n params: Record<string, unknown>,\n snapshot: HydratedSnapshot,\n): Promise<boolean> {\n // No `*`? Pure-param query. Empty dataset is fine.\n if (!groq.includes('*')) {\n const tree = parse(groq, {params})\n const value = await evaluate(tree, {params})\n return Boolean(await value.get())\n }\n // `*`-touching query. Evaluate against the in-memory snapshot.\n const tree = parse(groq, {params})\n const value = await evaluate(tree, {dataset: snapshot.docs, params})\n return Boolean(await value.get())\n}\n\nfunction validatePredicateArgs(predicate: Predicate, args: Record<string, unknown>): void {\n for (const param of predicate.params ?? []) {\n validatePredicateParam(predicate.id, param, args)\n }\n}\n\ntype PredicateParam = NonNullable<Predicate['params']>[number]\n\nfunction validatePredicateParam(\n predicateId: string,\n param: PredicateParam,\n args: Record<string, unknown>,\n): void {\n if (!(param.id in args)) {\n throw new Error(`Predicate \"${predicateId}\" requires param \"${param.id}\"`)\n }\n const value = args[param.id]\n if (!matchesParamType(param.type, value)) {\n throw new Error(\n `Predicate \"${predicateId}\" param \"${param.id}\" must be of type ${param.type}; got ${describeValue(value)}`,\n )\n }\n if (param.enum && !param.enum.includes(value as string)) {\n throw new Error(\n `Predicate \"${predicateId}\" param \"${param.id}\" must be one of ${param.enum.join(', ')}; got \"${String(value)}\"`,\n )\n }\n}\n\nfunction matchesParamType(type: PredicateParam['type'], value: unknown): boolean {\n switch (type) {\n case 'string':\n return typeof value === 'string'\n case 'number':\n return typeof value === 'number'\n case 'boolean':\n return typeof value === 'boolean'\n case 'string[]':\n return Array.isArray(value) && value.every((v) => typeof v === 'string')\n case 'reference':\n return isGdr(value)\n }\n}\n\nfunction describeValue(value: unknown): string {\n if (Array.isArray(value)) return 'array'\n if (value === null) return 'null'\n return typeof value\n}\n","/**\n * Pure snapshot construction.\n *\n * A `HydratedSnapshot` is an in-memory groq-js dataset of docs the\n * engine evaluator can query without touching the network. Inside it,\n * **every identity is a GDR URI** — `_id` on each top-level doc AND\n * every nested `_ref` value. That uniformity is what lets the snapshot\n * behave like a real groq-js store: `*[_id == $subject][0].team->name`\n * deref works because `_ref` URIs and `_id` URIs are in the same form;\n * `*[_id in $ancestors]...` joins work because both ends speak URI.\n *\n * The CORE rule: ids are rewritten in the snapshot, NEVER in the\n * underlying storage. Persistence stays bare. Sanity rejects `:` in\n * `_id`s, and `_ref` values inside stored docs are the bare ids Sanity\n * validated on write. The URI form is a runtime concept; the bench /\n * shell loads docs in their storage form and hands them to the core,\n * which restamps them for snapshot keying.\n *\n * **A `_ref` inside a doc is always assumed to point at a doc in the\n * same resource as its containing doc** — that's how Sanity\n * references work (same dataset, validated on write). The rewriter\n * uses the parent doc's resource to construct the GDR URI for each\n * nested `_ref`. Cross-resource refs would need an explicit envelope\n * (out of scope for now).\n */\n\nimport type {SanityDocument} from '@sanity/types'\n\nimport {gdrFromResource, type WorkflowResource} from './refs.ts'\n\n/**\n * The in-memory groq-js dataset filters evaluate against. Built once\n * per cascade entry (in the shell), passed through to `evaluateFilter`\n * (in the core) for every filter check.\n */\nexport interface HydratedSnapshot {\n /** All hydrated docs, keyed by GDR URI as `_id`. */\n docs: SanityDocument[]\n /**\n * The set of GDR URIs present in `docs`. Helpful for tests and shells\n * that want to assert \"is this doc in scope?\" — the core eval pipeline\n * itself doesn't read it.\n */\n knownIds: Set<string>\n}\n\n/**\n * One loaded doc plus the resource it came from. The shell builds\n * this list by routing reads to the right client for each doc, then\n * hands it to `buildSnapshot`.\n */\nexport interface LoadedDoc {\n doc: SanityDocument\n resource: WorkflowResource\n}\n\n/**\n * Build a snapshot from a set of loaded docs. Pure transform.\n *\n * For each `LoadedDoc { doc, resource }`:\n * - The doc's `_id` is rewritten to `gdrFromResource(resource, _id)`.\n * - Every nested `_ref` value (recursively, through objects and arrays)\n * is rewritten the same way: bare ref → URI in the parent's resource.\n * Already-qualified `_ref` URIs (containing `:`) are left alone.\n *\n * Plain string fields, numbers, booleans — anything that isn't an\n * object with a `_ref` field — pass through untouched. The rewriter is\n * structural, not schema-aware: only the `_ref` field on an object is\n * treated as a Sanity reference. Everything else is user data.\n */\nexport function buildSnapshot(args: {docs: LoadedDoc[]}): HydratedSnapshot {\n const docs: SanityDocument[] = []\n const knownIds = new Set<string>()\n for (const {doc, resource} of args.docs) {\n const uri = gdrFromResource(resource, doc._id)\n const restamped = restampForSnapshot(doc, uri, resource)\n docs.push(restamped)\n knownIds.add(uri)\n }\n return {docs, knownIds}\n}\n\n/**\n * Restamp a single doc for the snapshot — rewrite `_id` to the given\n * GDR URI, recursively rewrite every nested `_ref` to a GDR URI in the\n * doc's own resource. Pure; doesn't mutate the input.\n */\nfunction restampForSnapshot<T extends SanityDocument>(\n doc: T,\n gdrUri: string,\n resource: WorkflowResource,\n): T {\n const rewritten = rewriteRefsRecursive(doc, resource) as T\n return {...rewritten, _id: gdrUri}\n}\n\n/**\n * Walk an arbitrary JSON-ish value and rewrite every `_ref` field on\n * an object to its GDR URI form (in `resource`). Other fields and\n * non-object values pass through unchanged.\n */\nfunction rewriteRefsRecursive(value: unknown, resource: WorkflowResource): unknown {\n if (Array.isArray(value)) {\n return value.map((v) => rewriteRefsRecursive(v, resource))\n }\n if (value === null || typeof value !== 'object') return value\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (k === '_ref' && typeof v === 'string') {\n // Already-qualified URIs (cross-resource refs) pass through.\n out[k] = v.includes(':') ? v : gdrFromResource(resource, v)\n } else {\n out[k] = rewriteRefsRecursive(v, resource)\n }\n }\n return out\n}\n","/**\n * Shell-side snapshot hydration.\n *\n * The core defines `HydratedSnapshot`, `LoadedDoc`, and the pure\n * `buildSnapshot` transform (recursive `_ref` + `_id` rewriting to\n * GDR URIs). This module does the I/O: route each read to the right\n * resource client, gather loaded docs with their resource attribution,\n * hand the list to `buildSnapshot`.\n *\n * **Scope rule (the contract):** a doc is in the snapshot iff it is\n * - the workflow instance itself,\n * - any ancestor doc (from `instance.ancestors[].id`),\n * - or a doc declared by a `workflow.state.doc.ref` / `.doc.refs`\n * slot on the workflow OR the current stage.\n *\n * Authors who want their filters to read a referenced doc via `->`\n * deref MUST declare a doc.ref / doc.refs slot pointing at it. The\n * shell loads exactly what's declared; the core rewrites refs purely\n * over that set. No transitive crawling; no surprise hops.\n */\n\nimport type {SanityDocument} from '@sanity/types'\n\nimport {gdrFromResource, parseGdr, type ParsedGdr, type WorkflowResource} from './core/refs.ts'\nimport {buildSnapshot, type HydratedSnapshot, type LoadedDoc} from './core/snapshot.ts'\nimport type {WorkflowDefinition} from './define/schema.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\n/**\n * Build the in-memory snapshot for filter evaluation on the instance's\n * current stage. Routed reads, then pure construction.\n *\n * Failures (ACL denied, doc missing, routed client throws) are\n * swallowed — the doc just isn't in the snapshot. Predicates\n * referencing it will see `null` / empty results.\n */\nexport async function hydrateSnapshot(args: {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n /**\n * Optional — if supplied, the shell uses this to find the current\n * stage's declared `doc.ref` / `doc.refs` slots and pulls those docs\n * into scope. When omitted, only instance + subject + ancestors\n * are loaded (e.g. `workflow.evaluate` callers that just want the\n * basic three).\n */\n definition?: WorkflowDefinition\n}): Promise<HydratedSnapshot> {\n const {client, clientForGdr, instance, definition} = args\n const loaded: LoadedDoc[] = []\n const visited = new Set<string>()\n\n const loadInto = async (uri: string): Promise<void> => {\n if (visited.has(uri)) return\n const fetched = await loadByGdr(client, clientForGdr, instance.workflowResource, uri)\n if (fetched) {\n loaded.push(fetched)\n visited.add(uri)\n }\n }\n\n // 1. The instance itself. Resource = its own workflowResource. Key it\n // with the same GDR-URI form `buildSnapshot` uses, so a self-\n // referential ancestor/slot dedups against it.\n loaded.push({doc: instance, resource: instance.workflowResource})\n visited.add(gdrFromResource(instance.workflowResource, instance._id))\n\n // 2. Ancestors.\n for (const ancestor of instance.ancestors) {\n await loadInto(ancestor.id)\n }\n\n // 3. Workflow-level state slots — every `doc.ref` / `doc.refs` slot\n // pulled into scope. No slot is privileged; the engine doesn't\n // care what they're named.\n for (const uri of collectSlotDocUris(instance.state)) {\n await loadInto(uri)\n }\n\n // 4. Stage-declared `doc.ref` / `doc.refs` slots — only the current\n // stage's entry. These are the docs the author declared as \"in\n // scope for filters on THIS stage.\"\n if (definition) {\n const stageEntry = instance.stages.find(\n (s) => s.id === instance.currentStageId && s.exitedAt === undefined,\n )\n for (const uri of collectSlotDocUris(stageEntry?.state)) {\n await loadInto(uri)\n }\n }\n\n return buildSnapshot({docs: loaded})\n}\n\nasync function loadByGdr(\n defaultClient: WorkflowClient,\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient,\n defaultResource: WorkflowResource,\n uri: string,\n): Promise<LoadedDoc | null> {\n let parsed: ParsedGdr\n try {\n parsed = parseGdr(uri)\n } catch {\n // Not a GDR URI — load the value directly against the default\n // client. Without a parsed GDR we can't know the resource, so we\n // attribute the doc to the default client's own resource.\n const doc = await defaultClient.getDocument<SanityDocument>(uri)\n if (!doc) return null\n return {doc, resource: defaultResource}\n }\n const routed = clientForGdr(parsed)\n const doc = await routed.getDocument<SanityDocument>(parsed.documentId)\n if (!doc) return null\n return {doc, resource: resourceFromParsed(parsed)}\n}\n\nfunction resourceFromParsed(parsed: ParsedGdr): WorkflowResource {\n if (parsed.scheme === 'dataset') {\n return {type: 'dataset', id: `${parsed.projectId}.${parsed.dataset}`}\n }\n return {type: parsed.scheme, id: parsed.resourceId ?? ''}\n}\n\n/**\n * Walk resolved state slots and collect every GDR URI mentioned by a\n * `doc.ref` or `doc.refs` slot's value. These are the docs the author\n * declared should be in scope for filters.\n */\nfunction collectSlotDocUris(resolvedStateSlots: unknown): string[] {\n if (!Array.isArray(resolvedStateSlots)) return []\n return resolvedStateSlots.flatMap(slotDocUris)\n}\n\nfunction slotDocUris(slot: unknown): string[] {\n if (!slot || typeof slot !== 'object') return []\n const s = slot as {_type?: string; value?: unknown}\n if (s._type === 'workflow.state.doc.ref') {\n const v = s.value as {id?: string} | null | undefined\n const id = refId(v)\n return id !== undefined ? [id] : []\n }\n if (s._type === 'workflow.state.doc.refs') {\n const v = s.value as {id?: string}[] | null | undefined\n if (!Array.isArray(v)) return []\n return v.map(refId).filter((id): id is string => id !== undefined)\n }\n return []\n}\n\nfunction refId(ref: {id?: string} | null | undefined): string | undefined {\n return ref && typeof ref.id === 'string' ? ref.id : undefined\n}\n","/**\n * Walk a dot-separated property path into a value, returning `undefined` at\n * the first non-object link. Pure; shared by binding resolution, state-slot\n * path dives, and op-predicate field reads.\n */\nexport function getPath(value: unknown, path: string): unknown {\n let current: unknown = value\n for (const part of path.split('.')) {\n if (current === undefined || current === null || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n","/**\n * Per-slot-type value validation.\n *\n * Every write into a typed slot must match the slot's declared shape.\n * The validator is called at three boundaries:\n *\n * 1. `workflow.op.state.set` — full-value replace on any slot\n * 2. `workflow.op.state.append` — one-item push on array slots\n * 3. `resolveDeclaredState` — init / literal / stateRead / query\n *\n * `validateSlotValue` checks a complete slot value against the slot\n * type's shape (scalar or array-of-items, depending on the kind).\n *\n * `validateSlotAppendItem` checks a single item against the slot's\n * row shape (only array slots support append).\n *\n * Both throw `SlotValueShapeError` with the slot id, slot type and a\n * brief description of the observed shape — so the cause is obvious\n * in test output, drive-script stdout, and the workflow history.\n *\n * Notes stays permissive (any object with optional `_key`) pending a\n * dedicated row-shape design.\n */\n\nimport {z} from 'zod'\n\nimport {isGdrUri} from './refs.ts'\n\nclass SlotValueShapeError extends Error {\n readonly slotType: string\n readonly slotId: string\n readonly issues: string[]\n\n constructor(args: {slotType: string; slotId: string; issues: string[]; mode: 'value' | 'item'}) {\n const issueText = args.issues.join('; ')\n super(`Slot ${args.mode} shape invalid for \"${args.slotId}\" (${args.slotType}): ${issueText}`)\n this.name = 'SlotValueShapeError'\n this.slotType = args.slotType\n this.slotId = args.slotId\n this.issues = args.issues\n }\n}\n\n// Per-shape schemas — used both for whole-value and per-item validation.\n\nconst GdrShape = z\n .object({\n id: z.string().refine((s) => isGdrUri(s), {message: 'must be a GDR URI'}),\n type: z.string().min(1),\n })\n .passthrough()\n\n// Release ref: a GDR to the `_.releases.<name>` system doc, plus the\n// bare release name the engine reads to derive perspective.\nconst ReleaseRefShape = z\n .object({\n id: z.string().refine((s) => isGdrUri(s), {message: 'must be a GDR URI'}),\n type: z.literal('system.release'),\n releaseName: z.string().min(1),\n })\n .passthrough()\n\nconst ActorShape = z\n .object({\n kind: z.enum(['user', 'ai', 'system']),\n id: z.string().min(1),\n roles: z.array(z.string()).optional(),\n onBehalfOf: z.string().optional(),\n })\n .passthrough()\n\nconst AssigneeShape = z.union([\n z.object({kind: z.literal('user'), id: z.string().min(1)}).passthrough(),\n z.object({kind: z.literal('role'), role: z.string().min(1)}).passthrough(),\n])\n\nconst ChecklistItemShape = z\n .object({\n label: z.string().min(1),\n done: z.boolean(),\n doneBy: z.string().optional(),\n doneAt: z.string().optional(),\n _key: z.string().min(1).optional(),\n })\n .passthrough()\n\n// Notes are intentionally loose pending the row-shape design.\nconst NoteItemShape = z\n .object({\n _key: z.string().min(1).optional(),\n })\n .passthrough()\n .refine((v) => typeof v === 'object' && v !== null && !Array.isArray(v), {\n message: 'must be an object',\n })\n\n// Scalars that allow null (write-sourced slots default to null until written).\nconst NullableString = z.union([z.null(), z.string()])\nconst NullableNumber = z.union([z.null(), z.number()])\nconst NullableBoolean = z.union([z.null(), z.boolean()])\n\n// dateTime: stricter than plain string — must parse as ISO-8601.\nconst NullableDateTime = z.union([\n z.null(),\n z.string().refine((s) => !Number.isNaN(Date.parse(s)), {\n message: 'must be an ISO-8601 datetime string',\n }),\n])\n\n// URL: loose — accept any non-empty string. Tightening later is easy;\n// loosening would break already-stored values.\nconst NullableUrl = NullableString\n\n// Whole-value schemas, keyed by slot type.\n\nconst valueSchemas = {\n 'workflow.state.doc.ref': z.union([z.null(), GdrShape]),\n 'workflow.state.doc.refs': z.array(GdrShape),\n 'workflow.state.release.ref': z.union([z.null(), ReleaseRefShape]),\n 'workflow.state.query': z.any(),\n 'workflow.state.value.string': NullableString,\n 'workflow.state.value.url': NullableUrl,\n 'workflow.state.value.number': NullableNumber,\n 'workflow.state.value.boolean': NullableBoolean,\n 'workflow.state.value.dateTime': NullableDateTime,\n 'workflow.state.value.actor': z.union([z.null(), ActorShape]),\n 'workflow.state.checklist': z.array(ChecklistItemShape),\n 'workflow.state.notes': z.array(NoteItemShape),\n 'workflow.state.assignees': z.array(AssigneeShape),\n} as const\n\n// Per-item schemas for `workflow.op.state.append`. Scalar slot types\n// don't support append — callers asking for them get an error.\n\nconst itemSchemas = {\n 'workflow.state.doc.refs': GdrShape,\n 'workflow.state.checklist': ChecklistItemShape,\n 'workflow.state.notes': NoteItemShape,\n 'workflow.state.assignees': AssigneeShape,\n} as const\n\ntype AppendableSlotType = keyof typeof itemSchemas\n\nfunction isAppendable(slotType: string): slotType is AppendableSlotType {\n return slotType in itemSchemas\n}\n\n// Public API.\n\nexport function validateSlotValue(args: {slotType: string; slotId: string; value: unknown}): void {\n const schema = (valueSchemas as Record<string, z.ZodTypeAny>)[args.slotType]\n if (schema === undefined) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: [`unknown slot type ${args.slotType}`],\n mode: 'value',\n })\n }\n const result = schema.safeParse(args.value)\n if (!result.success) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: formatIssues(result.error.issues),\n mode: 'value',\n })\n }\n}\n\nexport function validateSlotAppendItem(args: {\n slotType: string\n slotId: string\n item: unknown\n}): void {\n if (!isAppendable(args.slotType)) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: [`slot type ${args.slotType} does not support append`],\n mode: 'item',\n })\n }\n const schema = itemSchemas[args.slotType]\n const result = schema.safeParse(args.item)\n if (!result.success) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: formatIssues(result.error.issues),\n mode: 'item',\n })\n }\n}\n\nfunction formatIssues(issues: readonly z.ZodIssue[]): string[] {\n return issues.map((i) => {\n const path = i.path.length > 0 ? `at ${i.path.join('.')}: ` : ''\n return `${path}${i.message}`\n })\n}\n","/**\n * Resolve a definition's `state[]` declarations into `ResolvedStateSlot`s.\n *\n * Shared by:\n * - `workflow.startInstance` (workflow-scope state)\n * - engine stage entry (stage-scope state on StageEntry)\n * - engine task activation (task-scope state on TaskEntry)\n *\n * Source-kind semantics:\n * - `kind: \"init\"` reads from caller-supplied `initialState`.\n * - `kind: \"query\"` runs the slot's GROQ against the lake via the\n * supplied client; result lands as the slot value with `resolvedAt`\n * stamped on `workflow.state.query` slots.\n * - `kind: \"write\"` defaults to null (scalars) or `[]` (array kinds);\n * ops fill it later.\n * - `kind: \"computed\"` — reserved; defaults like \"write\".\n */\n\nimport {paramsForLake} from './core/params.ts'\nimport {getPath} from './core/path.ts'\nimport {gdrFromResource, isGdrUri, type WorkflowResource} from './core/refs.ts'\nimport {validateSlotValue} from './core/slot-validation.ts'\nimport type {StateSlot} from './define/schema.ts'\nimport type {WorkflowClient, WorkflowPerspective} from './types/client.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from './types/state-slots.ts'\n\nexport interface ResolveStateContext {\n /** Lake client for `kind: \"query\"` slot evaluation. Omitted → query\n * slots fall back to their default value. */\n client?: WorkflowClient\n selfId?: string\n tags?: string[]\n /** Bound to `$stage` inside stage/task-scope query slots. */\n stageId?: string\n /** Bound to `$task` inside task-scope query slots. */\n taskId?: string\n /**\n * Already-resolved state slots in the SAME scope being resolved\n * right now. Exposed to subsequent query-sourced slots as\n * `$state.<slotId>`; also the lookup target for\n * `source: { kind: \"stateRead\", scope: \"stage\" }` on a sibling\n * stage-scope slot. Sequential resolution means slot N's source can\n * read slots 0..N-1 by id but not later ones.\n */\n resolvedState?: ResolvedStateSlot[]\n /**\n * Already-resolved workflow-scope state. Available when resolving\n * stage- or task-scope slots so a `source: { kind: \"stateRead\",\n * scope: \"workflow\" }` can read durable workflow-scope slots that\n * were resolved at `startInstance` time.\n */\n workflowState?: ResolvedStateSlot[]\n /**\n * Resource of the workflow itself. Used to canonicalize raw Sanity\n * reference shapes (`{_ref, _type}`) returned by `kind: \"query\"`\n * slots into GDR `{id, type}` form. Without this, a query-sourced\n * doc.ref slot would leave its value in the lake shape and the\n * snapshot hydrator wouldn't know to pull the referenced doc into\n * scope.\n */\n workflowResource?: WorkflowResource\n /**\n * Perspective for `kind: \"query\"` slot evaluation. Threaded through\n * to `client.fetch(..., { perspective })`. Lets a slot that runs\n * GROQ against the lake see a release-stacked view rather than the\n * published shadow. Unset → reads run under the client's default\n * perspective (which is `\"raw\"` on the test client and whatever the\n * caller configured on `@sanity/client`).\n */\n perspective?: WorkflowPerspective\n}\n\n/**\n * Derive a read perspective from resolved workflow-scope state: if any\n * `workflow.state.release.ref` slot has a value, return a single-release\n * stack `[releaseName]`. Returns `undefined` when no release slot is\n * populated, so callers can fall back to an explicit perspective or\n * the engine default.\n *\n * The first populated release slot wins (workflows targeting more than\n * one release aren't modelled — a single release-ref slot is the\n * canonical shape). Pure: operates on already-resolved slots.\n */\nexport function derivePerspectiveFromState(\n slots: ResolvedStateSlot[] | undefined,\n): WorkflowPerspective | undefined {\n if (slots === undefined) return undefined\n for (const slot of slots) {\n if (slot._type === 'workflow.state.release.ref' && slot.value !== null) {\n const releaseName = slot.value.releaseName\n if (typeof releaseName === 'string' && releaseName.length > 0) {\n return [releaseName]\n }\n }\n }\n return undefined\n}\n\nexport async function resolveDeclaredState(args: {\n slotDefs: StateSlot[] | undefined\n initialState: InitialStateValue[]\n ctx: ResolveStateContext\n randomKey: () => string\n}): Promise<ResolvedStateSlot[]> {\n const {slotDefs, initialState, ctx, randomKey} = args\n if (slotDefs === undefined || slotDefs.length === 0) return []\n const out: ResolvedStateSlot[] = []\n for (const slot of slotDefs) {\n // Each slot sees the already-resolved ones via `$state.<slotId>`.\n const scopedCtx: ResolveStateContext = {...ctx, resolvedState: out}\n out.push(await resolveOneSlot(slot, initialState, scopedCtx, randomKey))\n }\n return out\n}\n\nconst ARRAY_SLOT_TYPES = new Set<StateSlot['type']>([\n 'workflow.state.doc.refs',\n 'workflow.state.checklist',\n 'workflow.state.notes',\n 'workflow.state.assignees',\n])\n\n/** Default for an unfilled slot: `[]` for array kinds, `null` otherwise. */\nfunction defaultSlotValue(slotType: StateSlot['type']): unknown {\n return ARRAY_SLOT_TYPES.has(slotType) ? [] : null\n}\n\n/**\n * Read a caller-supplied `init` value. Rejects bare doc ids at the\n * boundary: the engine stores GDR URIs throughout — callers MUST\n * construct full URIs (via `gdrFromResource` / `refDataset` / etc.)\n * before passing them into `initialState`. Silent canonicalisation\n * would mask the shape gap and let bare-id refs leak into snapshots,\n * where they mismatch every GDR-keyed lookup and break filters.\n */\nfunction resolveInitValue(\n slot: StateSlot,\n initialState: InitialStateValue[],\n defaultValue: unknown,\n): unknown {\n const initMatch = initialState.find((s) => s.id === slot.id && s.type === slot.type)\n if (initMatch === undefined) return defaultValue\n assertInitValueShape(slot, initMatch.value)\n return initMatch.value\n}\n\nfunction resolveStateReadValue(\n source: Extract<StateSlot['source'], {kind: 'stateRead'}>,\n ctx: ResolveStateContext,\n defaultValue: unknown,\n): unknown {\n const slotsForScope =\n source.scope === 'workflow' ? (ctx.workflowState ?? []) : (ctx.resolvedState ?? [])\n const target = slotsForScope.find((s) => s.id === source.slotId)\n const targetValue = target === undefined ? undefined : (target as {value?: unknown}).value\n const resolved = source.path !== undefined ? getPath(targetValue, source.path) : targetValue\n return resolved === undefined || resolved === null ? defaultValue : resolved\n}\n\n/**\n * Run a `query` slot's GROQ against the lake. Params carry GDR URIs\n * (snapshot form) but are stripped to bare for the fetch — same pattern\n * as filter evaluation's lake fallback: the lake stores bare `_id`s, so\n * `$state.<slot>.value.id` etc. must be bare too.\n *\n * `$state` exposes slots already resolved before this one (sequential\n * resolution). Cyclic references to later slots produce `undefined` in\n * GROQ and the slot falls through to its default.\n */\nasync function resolveQueryValue(\n slot: StateSlot,\n source: Extract<StateSlot['source'], {kind: 'query'}>,\n ctx: ResolveStateContext,\n client: WorkflowClient,\n defaultValue: unknown,\n): Promise<unknown> {\n const params = paramsForLake({\n self: ctx.selfId ?? null,\n state: stateMapFromResolved(ctx.resolvedState ?? []),\n stage: ctx.stageId ?? null,\n task: ctx.taskId ?? null,\n now: new Date().toISOString(),\n engineTags: ctx.tags ?? [],\n })\n try {\n const fetchOptions = ctx.perspective !== undefined ? {perspective: ctx.perspective} : undefined\n const result = await client.fetch<unknown>(source.query, params, fetchOptions)\n return normalizeQueryResult(slot.type, result, ctx.workflowResource) ?? defaultValue\n } catch (err) {\n throw new Error(\n `Failed to resolve query slot \"${slot.id}\" (${slot.type}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n {cause: err},\n )\n }\n}\n\nasync function resolveSlotValue(\n slot: StateSlot,\n initialState: InitialStateValue[],\n ctx: ResolveStateContext,\n defaultValue: unknown,\n): Promise<unknown> {\n const source = slot.source\n if (source.kind === 'init') return resolveInitValue(slot, initialState, defaultValue)\n if (source.kind === 'literal') return source.value ?? defaultValue\n if (source.kind === 'stateRead') return resolveStateReadValue(source, ctx, defaultValue)\n if (source.kind === 'query' && ctx.client !== undefined) {\n return resolveQueryValue(slot, source, ctx, ctx.client, defaultValue)\n }\n // \"write\" / \"computed\" (and \"query\" without a client) use defaults.\n return defaultValue\n}\n\n/** Build the persisted slot envelope; `query` slots carry `resolvedAt`. */\nfunction buildResolvedSlot(slot: StateSlot, value: unknown, _key: string): ResolvedStateSlot {\n const titleProp = slot.title !== undefined ? {title: slot.title} : {}\n const descriptionProp = slot.description !== undefined ? {description: slot.description} : {}\n if (slot.type === 'workflow.state.query') {\n return {\n _key,\n _type: 'workflow.state.query',\n id: slot.id,\n ...titleProp,\n ...descriptionProp,\n value,\n resolvedAt: new Date().toISOString(),\n }\n }\n return {\n _key,\n _type: slot.type,\n id: slot.id,\n ...titleProp,\n ...descriptionProp,\n value,\n } as ResolvedStateSlot\n}\n\nasync function resolveOneSlot(\n slot: StateSlot,\n initialState: InitialStateValue[],\n ctx: ResolveStateContext,\n randomKey: () => string,\n): Promise<ResolvedStateSlot> {\n const defaultValue = defaultSlotValue(slot.type)\n const value = await resolveSlotValue(slot, initialState, ctx, defaultValue)\n\n // Validate the resolved value against the slot's declared shape.\n // The `value.query` slot type is permissive (escape hatch). Default\n // values (null / []) are always shape-valid; init/literal/stateRead/\n // query may have produced something else — catch shape mismatches\n // here before they leak into the persisted snapshot.\n validateSlotValue({slotType: slot.type, slotId: slot.id, value})\n\n return buildResolvedSlot(slot, value, randomKey())\n}\n\n/** Project resolved slots into the `$state` shape (slotId → slot envelope). */\nfunction stateMapFromResolved(slots: ResolvedStateSlot[]): Record<string, ResolvedStateSlot> {\n const out: Record<string, ResolvedStateSlot> = {}\n for (const s of slots) out[s.id] = s\n return out\n}\n\n/**\n * Validate caller-supplied `initialState` values for shape correctness\n * BEFORE they hit the persisted instance. Init-sourced doc.ref /\n * doc.refs slots reject bare-string `id`s — the engine stores GDR\n * URIs everywhere and a bare id silently mismatches snapshots later.\n * Throws a clear error pointing at the slot id + bad value.\n *\n * Query-sourced values are NOT validated here; the lake returns\n * various shapes and {@link normalizeQueryResult} is the only path that\n * gets to canonicalise them.\n */\nfunction assertInitValueShape(slot: StateSlot, value: unknown): void {\n if (slot.type === 'workflow.state.doc.ref') {\n assertGdrShape(value, `state slot \"${slot.id}\" (workflow.state.doc.ref)`)\n return\n }\n if (slot.type === 'workflow.state.release.ref') {\n assertGdrShape(value, `state slot \"${slot.id}\" (workflow.state.release.ref)`)\n const v = value as {releaseName?: unknown}\n if (typeof v.releaseName !== 'string' || v.releaseName.length === 0) {\n throw new Error(\n `Invalid init value for state slot \"${slot.id}\" (workflow.state.release.ref): ` +\n `\\`releaseName\\` must be a non-empty string. Got ${JSON.stringify(v.releaseName)}.`,\n )\n }\n return\n }\n if (slot.type === 'workflow.state.doc.refs') {\n if (!Array.isArray(value)) {\n throw new Error(\n `Invalid init value for state slot \"${slot.id}\" (workflow.state.doc.refs): expected an array of GDRs, got ${typeof value}.`,\n )\n }\n for (const [i, item] of value.entries()) {\n assertGdrShape(item, `state slot \"${slot.id}\" (workflow.state.doc.refs) item [${i}]`)\n }\n }\n}\n\nfunction assertGdrShape(value: unknown, context: string): void {\n if (typeof value !== 'object' || value === null) {\n throw new Error(\n `Invalid GDR for ${context}: expected { id: \"<scheme>:...\", type: \"<schema>\" }, got ${typeof value}.`,\n )\n }\n const v = value as {id?: unknown; type?: unknown}\n if (typeof v.id !== 'string' || !isGdrUri(v.id)) {\n throw new Error(\n `Invalid GDR for ${context}: \\`id\\` must be a GDR URI (\"<scheme>:<...id-parts>\" with scheme dataset|canvas|media-library|dashboard). ` +\n `Got ${JSON.stringify(v.id)}. Construct via \\`gdrFromResource\\` / \\`refDataset\\` / \\`refCanvas\\` etc. — bare document ids are not accepted.`,\n )\n }\n if (typeof v.type !== 'string' || v.type.length === 0) {\n throw new Error(\n `Invalid GDR for ${context}: \\`type\\` (schema name) must be a non-empty string. Got ${JSON.stringify(v.type)}.`,\n )\n }\n}\n\n/**\n * Convert a raw GROQ result into the slot's expected value shape.\n *\n * For `doc.ref` / `doc.refs` slots, the engine's internal contract is\n * a GDR `{id, type}` object. But a natural query like\n * `*[_id == $subject][0].primaryTeam` returns the Sanity reference\n * shape `{_ref, _type: \"reference\"}` — bare `_ref`, generic `_type`.\n * Convert it: GDR id = `gdrFromResource(workflowResource, _ref)`,\n * GDR type = \"document\" (the target doc's real schema type isn't\n * carried by the ref envelope; consumers shouldn't depend on it for\n * the slot value's `type` field).\n *\n * Already-GDR-shaped values (with `id` + `type`) pass through. Bare\n * strings are treated as doc ids and wrapped. Arrays are walked for\n * the refs case. Other slot kinds pass through unchanged.\n */\nfunction normalizeQueryResult(\n slotType: StateSlot['type'],\n raw: unknown,\n workflowResource: WorkflowResource | undefined,\n): unknown {\n if (raw === null || raw === undefined) return raw\n if (slotType === 'workflow.state.doc.ref') {\n return coerceToGdr(raw, workflowResource)\n }\n if (slotType === 'workflow.state.doc.refs') {\n if (!Array.isArray(raw)) return []\n return raw.map((item) => coerceToGdr(item, workflowResource)).filter((v) => v !== null)\n }\n return raw\n}\n\ntype Gdr = {id: import('./core/refs.ts').GdrUri; type: string}\n\n/** Resolve a doc id (bare or already-URI) to a GDR URI via the resource. */\nfunction toGdrUri(\n docId: string,\n workflowResource: WorkflowResource,\n): import('./core/refs.ts').GdrUri {\n return isGdrUri(docId) ? docId : gdrFromResource(workflowResource, docId)\n}\n\n/**\n * Coerce an already-GDR-shaped `{id, type}` value. The id must be a\n * known-scheme URI to pass through; otherwise it's a bare id from a\n * non-canonical source and we re-derive it via the resource. Returns\n * null when the shape doesn't match so callers fall through.\n */\nfunction coerceGdrShape(raw: object, workflowResource: WorkflowResource | undefined): Gdr | null {\n if (!('id' in raw) || !('type' in raw)) return null\n const r = raw as {id: unknown; type: unknown}\n if (typeof r.id !== 'string' || typeof r.type !== 'string') return null\n if (isGdrUri(r.id)) return {id: r.id, type: r.type}\n if (workflowResource) return {id: gdrFromResource(workflowResource, r.id), type: r.type}\n return null\n}\n\n/**\n * Coerce a Sanity reference envelope `{_ref, _type: \"reference\"}` to a\n * GDR. Without `workflowResource` there's no way to construct the URI;\n * returns null and lets the snapshot hydrator skip the slot.\n */\nfunction coerceRefEnvelope(\n raw: object,\n workflowResource: WorkflowResource | undefined,\n): Gdr | null {\n if (!('_ref' in raw)) return null\n const r = raw as {_ref: unknown}\n if (typeof r._ref !== 'string' || !workflowResource) return null\n return {id: toGdrUri(r._ref, workflowResource), type: 'document'}\n}\n\nfunction coerceToGdr(raw: unknown, workflowResource: WorkflowResource | undefined): Gdr | null {\n if (raw === null || raw === undefined) return null\n if (typeof raw === 'object') {\n return coerceGdrShape(raw, workflowResource) ?? coerceRefEnvelope(raw, workflowResource)\n }\n // Bare string — assume doc id in the workflow resource.\n if (typeof raw === 'string' && workflowResource) {\n return {id: toGdrUri(raw, workflowResource), type: 'document'}\n }\n return null\n}\n","import {evaluateFilter} from '../core/eval.ts'\nimport {buildParams} from '../core/params.ts'\nimport {extractDocumentId, type ParsedGdr} from '../core/refs.ts'\nimport type {HydratedSnapshot} from '../core/snapshot.ts'\nimport type {Filter, Stage, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport {resolveDeclaredState} from '../state-resolution.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {StageId} from '../types/ids.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from '../types/state-slots.ts'\n\n/**\n * Convert a GDR URI back to a bare document id. The engine's\n * cross-resource reference fields (`ancestors[].id`,\n * `spawnedInstances[].id`) carry full GDR URIs; the persistent `_id`\n * on disk is bare. Use this when fetching a referenced doc from Sanity.\n */\nexport function gdrToBareId(uri: string): string {\n return uri.includes(':') ? extractDocumentId(uri) : uri\n}\n\n// Internal — context load\n\nexport interface EngineContext {\n /** Engine's own client — bound to the workflow resource. */\n client: WorkflowClient\n /**\n * Route a cross-resource read by parsed GDR. Returns the engine's\n * own client when the resolver doesn't have an entry. The cascade\n * uses this for subject + ancestor loads.\n */\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n /**\n * GDR-keyed snapshot of docs hydrated at cascade entry — instance,\n * subject (if cross-resource and reachable), ancestors. Always\n * present: `loadContext` builds it via `hydrateSnapshot`. Filters\n * evaluate against this snapshot (pure, no lake fallback). The shell\n * is responsible for completeness — anything not hydrated is invisible\n * to the filter.\n */\n snapshot: HydratedSnapshot\n}\n\nexport async function loadContext(\n client: WorkflowClient,\n instanceId: string,\n options?: {clientForGdr?: (parsed: ParsedGdr) => WorkflowClient},\n): Promise<EngineContext> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) {\n throw new Error(`Workflow instance ${instanceId} not found`)\n }\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const clientForGdr = options?.clientForGdr ?? (() => client)\n const snapshot = await hydrateSnapshot({client, clientForGdr, instance, definition})\n return {client, clientForGdr, instance, definition, snapshot}\n}\n\n/** Evaluate a filter against the context's definition + hydrated\n * snapshot, with the instance's reserved params bound. An undefined\n * filter is vacuously true (see {@link evaluateFilter}). */\nexport function ctxEvaluateFilter(\n ctx: EngineContext,\n filter: Filter | undefined,\n): Promise<boolean> {\n return evaluateFilter({\n filter,\n definition: ctx.definition,\n snapshot: ctx.snapshot,\n params: buildParams(ctx.instance),\n })\n}\n\n/** Assemble an {@link EngineContext} for an already-loaded instance,\n * hydrating its snapshot. Used by the post-prime + propagation paths\n * that re-read the instance mid-cascade. */\nexport async function buildEngineContext(args: {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n}): Promise<EngineContext> {\n const {client, clientForGdr, instance, definition} = args\n return {\n client,\n clientForGdr,\n instance,\n definition,\n snapshot: await hydrateSnapshot({client, clientForGdr, instance, definition}),\n }\n}\n\nexport function findStage(definition: WorkflowDefinition, stageId: StageId): Stage {\n const stage = definition.stages.find((s) => s.id === stageId)\n if (stage === undefined) {\n throw new Error(`Stage \"${stageId}\" not found in definition ${definition.workflowId}`)\n }\n return stage\n}\n\n/**\n * Build the per-stage resolved state[] from the stage definition + an\n * optional `initialState` (e.g. supplied to `setStage`). Bound to the\n * instance's subject and to `$stage = stage.id`.\n */\nexport async function resolveStageStateSlots(args: {\n client: WorkflowClient\n instance: WorkflowInstance\n stage: Stage\n initialState?: InitialStateValue[]\n}): Promise<ResolvedStateSlot[]> {\n const {client, instance, stage, initialState} = args\n return resolveDeclaredState({\n slotDefs: stage.state,\n initialState: initialState ?? [],\n ctx: {\n client,\n selfId: instance._id,\n tags: instance.tags ?? [],\n stageId: stage.id,\n workflowResource: instance.workflowResource,\n // Allow stage-scope slots' `source: { kind: \"stateRead\", scope:\n // \"workflow\", ... }` to see the already-resolved workflow-scope\n // state.\n workflowState: instance.state ?? [],\n ...(instance.perspective !== undefined ? {perspective: instance.perspective} : {}),\n },\n randomKey,\n })\n}\n\n/** Same shape as `resolveStageStateSlots` but scoped to a task. */\nexport async function resolveTaskStateSlots(args: {\n client: WorkflowClient\n instance: WorkflowInstance\n stage: Stage\n task: Task\n}): Promise<ResolvedStateSlot[]> {\n const {client, instance, stage, task} = args\n return resolveDeclaredState({\n slotDefs: task.state,\n initialState: [],\n ctx: {\n client,\n selfId: instance._id,\n tags: instance.tags ?? [],\n stageId: stage.id,\n workflowResource: instance.workflowResource,\n taskId: task.id,\n workflowState: instance.state ?? [],\n ...(instance.perspective !== undefined ? {perspective: instance.perspective} : {}),\n },\n randomKey,\n })\n}\n","/**\n * Pure state-slot reads.\n *\n * Given an instance and a `(scope, slotId)` address, return the resolved\n * slot's `value`. Workflow-scope reads hit `instance.state`; stage/task\n * reads resolve against the current (un-exited) stage entry and, for task\n * scope, the named task entry. No I/O.\n */\n\nimport type {StateScope} from '../types/enums.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\n\nexport function readStateSlot(\n instance: WorkflowInstance,\n scope: StateScope,\n slotId: string,\n stageId: string | undefined,\n taskId: string | undefined,\n): unknown {\n if (scope === 'workflow') {\n return slotValue(instance.state?.find((s) => s.id === slotId))\n }\n const stageEntry = instance.stages.find(\n (s) => s.id === (stageId ?? instance.currentStageId) && s.exitedAt === undefined,\n )\n if (stageEntry === undefined) return undefined\n if (scope === 'stage') {\n return slotValue(stageEntry.state?.find((s) => s.id === slotId))\n }\n const taskEntry = stageEntry.tasks.find((t) => t.id === taskId)\n return slotValue(taskEntry?.state?.find((s) => s.id === slotId))\n}\n\nfunction slotValue(slot: unknown): unknown {\n if (slot === undefined || slot === null) return undefined\n if (typeof slot !== 'object') return undefined\n return (slot as {value?: unknown}).value\n}\n","/**\n * Pure `Source` resolution.\n *\n * A `Source` value declared on effects, ops, and state-slot resolvers is\n * evaluated into a concrete value here. No GROQ, no client, no I/O — just\n * structural lookups against the instance + actor + caller params.\n *\n * `new Date()` is the one impurity (used by `source: \"now\"`). Treated as a\n * documented escape hatch; the shell could thread an explicit `now` param if\n * we ever need stricter purity.\n */\n\nimport type {Source} from '../define/schema.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {getPath} from './path.ts'\nimport {readStateSlot} from './state-read.ts'\n\nexport interface ResolveSourceContext {\n instance: WorkflowInstance\n params?: Record<string, unknown>\n actor?: Actor\n /**\n * When the Source is being evaluated in the scope of a specific stage\n * or task, provide their ids so `scope: \"stage\" | \"task\"` reads land\n * on the right state[].\n */\n stageId?: string\n taskId?: string\n}\n\nexport function resolveSource(src: Source, ctx: ResolveSourceContext): unknown {\n switch (src.source) {\n case 'literal':\n return src.value\n case 'param':\n return ctx.params?.[src.paramId]\n case 'actor':\n return ctx.actor\n case 'now':\n return new Date().toISOString()\n case 'self':\n return ctx.instance._id\n case 'stageId':\n return ctx.stageId ?? ctx.instance.currentStageId\n case 'stateRead':\n return resolveStateRead(src, ctx)\n case 'effectOutput':\n return resolveEffectOutput(src, ctx)\n case 'object':\n return resolveObject(src, ctx)\n }\n}\n\ntype StateReadSource = Extract<Source, {source: 'stateRead'}>\ntype EffectOutputSource = Extract<Source, {source: 'effectOutput'}>\ntype ObjectSource = Extract<Source, {source: 'object'}>\n\nfunction resolveStateRead(src: StateReadSource, ctx: ResolveSourceContext): unknown {\n const value = readStateSlot(ctx.instance, src.scope, src.slotId, ctx.stageId, ctx.taskId)\n return src.path !== undefined ? getPath(value, src.path) : value\n}\n\nfunction resolveEffectOutput(src: EffectOutputSource, ctx: ResolveSourceContext): unknown {\n const entry = ctx.instance.effectsContext.find((e) => e.id === src.contextId)\n if (entry === undefined) return null\n const value = src.path !== undefined ? getPath(entry.value, src.path) : entry.value\n return value === undefined ? null : value\n}\n\nfunction resolveObject(src: ObjectSource, ctx: ResolveSourceContext): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [field, fieldSrc] of Object.entries(src.fields)) {\n out[field] = resolveSource(fieldSrc, ctx)\n }\n return out\n}\n","/**\n * Pure effect-binding resolution.\n *\n * An effect's `bindings` is a `Record<string, Source>`. This resolves each\n * binding to a concrete value (via {@link resolveSource}) and merges the\n * result with the effect's static input to form the params object the\n * handler is called with. No GROQ, no client, no I/O.\n */\n\nimport type {Source} from '../define/schema.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {resolveSource, type ResolveSourceContext} from './source.ts'\n\n/**\n * Resolve effect bindings against an instance. Each binding is a typed\n * `Source`; the resolved values are merged with the static input. The\n * result is the params object the handler will be called with.\n */\nexport async function resolveBindings(args: {\n bindings: Record<string, Source> | undefined\n staticInput: Record<string, unknown> | undefined\n instance: WorkflowInstance\n params?: Record<string, unknown>\n actor?: Actor\n}): Promise<Record<string, unknown>> {\n const {bindings, staticInput, instance, params, actor} = args\n const resolved: Record<string, unknown> = {}\n if (bindings) {\n const ctx: ResolveSourceContext = {\n instance,\n ...(params !== undefined ? {params} : {}),\n ...(actor !== undefined ? {actor} : {}),\n }\n for (const [key, src] of Object.entries(bindings)) {\n resolved[key] = resolveSource(src, ctx)\n }\n }\n return {...resolved, ...staticInput}\n}\n","import type {GlobalDocumentReference, WorkflowResource} from './core/refs.ts'\nimport type {WorkflowDefinition} from './define/schema.ts'\nimport {randomKey} from './keys.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {WorkflowPerspective} from './types/client.ts'\nimport type {EffectsContextEntry} from './types/effects.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\nimport type {ResolvedStateSlot} from './types/state-slots.ts'\n\n/** Wrap a scalar or GDR value in its typed {@link EffectsContextEntry}\n * envelope, minting a fresh `_key`. */\nexport function effectsContextEntry(\n id: string,\n value: string | number | boolean | GlobalDocumentReference,\n): EffectsContextEntry {\n const _key = randomKey()\n if (typeof value === 'string') return {_key, _type: 'effectsContext.string', id, value}\n if (typeof value === 'number') return {_key, _type: 'effectsContext.number', id, value}\n if (typeof value === 'boolean') return {_key, _type: 'effectsContext.boolean', id, value}\n return {_key, _type: 'effectsContext.ref', id, value}\n}\n\n/**\n * Build a fresh {@link WorkflowInstance} document for `create`. Shared by\n * `startInstance` (root instances) and the spawn path (child instances):\n * both pin the definition snapshot, seed state + effectsContext, enter\n * the initial stage with a single `stageEntered` history entry, and stamp\n * `_createdAt`/`startedAt`/`lastChangedAt` to the same `now`.\n */\nexport function buildInstanceBase(args: {\n id: string\n now: string\n tags: string[]\n workflowResource: WorkflowResource\n workflowId: string\n pinnedVersion: number\n definition: WorkflowDefinition\n state: ResolvedStateSlot[]\n effectsContext: EffectsContextEntry[]\n ancestors: GlobalDocumentReference[]\n perspective: WorkflowPerspective | undefined\n initialStageId: string\n actor: Actor | undefined\n}): WorkflowInstance {\n const {id, now, actor, perspective} = args\n return {\n _id: id,\n _type: 'workflow.instance',\n _rev: '',\n _createdAt: now,\n _updatedAt: now,\n tags: args.tags,\n workflowResource: args.workflowResource,\n workflowId: args.workflowId,\n pinnedVersion: args.pinnedVersion,\n definitionSnapshot: JSON.stringify(args.definition),\n state: args.state,\n effectsContext: args.effectsContext,\n ancestors: args.ancestors,\n ...(perspective !== undefined ? {perspective} : {}),\n currentStageId: args.initialStageId,\n stages: [],\n pendingEffects: [],\n effectHistory: [],\n history: [\n {\n _key: randomKey(),\n _type: 'workflow.history.stageEntered',\n at: now,\n stageId: args.initialStageId,\n ...(actor !== undefined ? {actor} : {}),\n },\n ],\n startedAt: now,\n lastChangedAt: now,\n }\n}\n","/**\n * Pure compilation and evaluation of lake mutation guards.\n *\n * NO CLIENT. NO I/O. The shell resolves a stage `Guard`'s `match.idRefs`\n * Sources to bare ids + a resource and its `metadata` Sources to values, then\n * hands the resolved pieces here to assemble a `temp.system.guard` doc and to\n * evaluate predicates against a `before`/`after` mutation image via groq-js.\n *\n * Guard semantics:\n * - empty predicate ⇒ unconditional deny;\n * - fail-closed — a compile/eval error or non-`true` result denies;\n * - evaluation context = document before/after + mutation + guard + identity().\n *\n * Enforcement is OPTIMISTIC: the lake does not enforce `temp.system.guard`\n * yet, so a pass here is an engine *preview*, not proof. The predicate dialect\n * is groq-js delta-mode; the guard doc is referenced as the `$guard` param and\n * `identity()` resolves to the authenticated caller, the same way `permissions.ts`\n * feeds grant filters.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport type {MutationContext, MutationGuardDoc, MutationGuardMatch} from '../types/authorization.ts'\nimport type {MutationGuardAction} from '../types/enums.ts'\n\n/** Deterministic id so deploy/retract are query-free and idempotent. */\nexport function lakeGuardId(args: {instanceDocId: string; stageId: string; index: number}): string {\n return `temp.system.guard.${args.instanceDocId}.${args.stageId}.${args.index}`\n}\n\nexport interface CompileGuardArgs {\n id: string\n resourceType: string\n resourceId: string\n owner: string\n name?: string\n description?: string\n /** Already-resolved match — bare ids, no GDRs. */\n match: MutationGuardMatch\n /** Lake GROQ; \"\" = unconditional deny. */\n predicate: string\n /** Already-resolved projected metadata values. */\n metadata: Record<string, unknown>\n}\n\n/** Assemble a persisted guard doc from resolved pieces. */\nexport function compileGuard(args: CompileGuardArgs): MutationGuardDoc {\n return {\n _id: args.id,\n _type: 'temp.system.guard',\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n owner: args.owner,\n ...(args.name !== undefined ? {name: args.name} : {}),\n ...(args.description !== undefined ? {description: args.description} : {}),\n match: args.match,\n predicate: args.predicate,\n metadata: args.metadata,\n } satisfies MutationGuardDoc\n}\n\n/**\n * Translate a lake-wire predicate to groq-js for optimistic POC evaluation.\n * The wire dialect binds `guard` and `mutation` as predicate identifiers;\n * groq-js has no such globals, so we expose them as `$params` and rewrite the\n * references.\n * `identity()`, `delta::*`, and `before`/`after` are native to groq-js and pass\n * through. The STORED predicate stays in wire form (bare `guard`/`mutation`) so\n * it is correct when handed to the real lake; this rewrite is eval-time only.\n */\nfunction toGroqJsPredicate(predicate: string): string {\n return predicate\n .replace(/(?<!\\$)\\bguard\\./g, '$guard.')\n .replace(/(?<!\\$)\\bmutation\\./g, '$mutation.')\n}\n\n/** Glob match supporting a single `*` wildcard per pattern. */\nfunction globMatch(pattern: string, value: string): boolean {\n if (!pattern.includes('*')) return pattern === value\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*')\n return new RegExp(`^${escaped}$`).test(value)\n}\n\n/**\n * Does this guard's `match` apply to a mutation on the given document?\n * `types` and id facets are ANDed; an unspecified facet does not constrain.\n */\nexport function guardMatches(\n guard: MutationGuardDoc,\n doc: {id: string; type?: string},\n action: MutationGuardAction,\n): boolean {\n const m = guard.match\n if (!m.actions.includes(action)) return false\n if (m.types && m.types.length > 0 && !(doc.type !== undefined && m.types.includes(doc.type))) {\n return false\n }\n const hasIdFacet = (m.idRefs && m.idRefs.length > 0) || (m.idPatterns && m.idPatterns.length > 0)\n if (hasIdFacet) {\n const byRef = m.idRefs?.includes(doc.id) ?? false\n const byPattern = m.idPatterns?.some((p) => globMatch(p, doc.id)) ?? false\n if (!byRef && !byPattern) return false\n }\n return true\n}\n\n/**\n * Evaluate a guard predicate against a mutation. Returns `true` only when the\n * predicate is strictly `true` (ALLOW). Empty predicate denies. Fail-closed:\n * any thrown error or non-`true` result denies.\n */\nexport async function evaluateMutationGuard(args: {\n guard: MutationGuardDoc\n context: MutationContext\n}): Promise<boolean> {\n const {guard, context} = args\n if (guard.predicate === '') return false // alwaysDeny\n const params = {guard, mutation: {action: context.action}}\n try {\n const tree = parse(toGroqJsPredicate(guard.predicate), {mode: 'delta', params})\n const value = await evaluate(tree, {\n before: context.before,\n after: context.after,\n params,\n ...(context.identity !== undefined ? {identity: context.identity} : {}),\n })\n return (await value.get()) === true\n } catch {\n return false\n }\n}\n\n/**\n * Run every guard whose `match` applies and collect those that DENY. Empty\n * result ⇒ allowed (optimistically).\n */\nexport async function denyingGuards(args: {\n guards: MutationGuardDoc[]\n doc: {id: string; type?: string}\n context: MutationContext\n}): Promise<MutationGuardDoc[]> {\n const {guards, doc, context} = args\n const denied: MutationGuardDoc[] = []\n for (const guard of guards) {\n if (!guardMatches(guard, doc, context.action)) continue\n if (!(await evaluateMutationGuard({guard, context}))) denied.push(guard)\n }\n return denied\n}\n","import {isGdrUri, parseGdr} from './core/refs.ts'\nimport type {ParsedGdr} from './core/refs.ts'\nimport {resolveSource} from './core/source.ts'\nimport type {Source} from './define/schema.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nexport interface Resource {\n type: string\n id: string\n}\n\nfunction resourceOf(p: ParsedGdr): Resource {\n if (p.scheme === 'dataset') return {type: 'dataset', id: `${p.projectId}.${p.dataset}`}\n return {type: p.scheme, id: p.resourceId ?? ''}\n}\n\ninterface GdrTarget {\n parsed: ParsedGdr\n type?: string\n}\n\nexport interface BindingContext {\n instance: WorkflowInstance\n stageId: string\n}\n\n/**\n * Resolve a single `idRefs` Source to a GDR URI + an optional author type.\n * Returns null for unresolvable / non-GDR targets (e.g. `self`).\n */\nfunction resolveIdRefTarget(src: Source, ctx: BindingContext): GdrTarget | null {\n const value = resolveSource(src, ctx)\n if (typeof value === 'string' && isGdrUri(value)) {\n return {parsed: parseGdr(value)}\n }\n if (value && typeof value === 'object') {\n const v = value as {id?: unknown; type?: unknown}\n if (typeof v.id === 'string' && isGdrUri(v.id)) {\n return typeof v.type === 'string'\n ? {parsed: parseGdr(v.id), type: v.type}\n : {parsed: parseGdr(v.id)}\n }\n }\n return null\n}\n\n/**\n * Resolve every `idRefs` Source. Returns null if any target is unresolvable\n * (the whole guard is then deferred) or if no targets are declared.\n */\nexport function resolveIdRefTargets(\n idRefs: readonly Source[] | undefined,\n ctx: BindingContext,\n): GdrTarget[] | null {\n const targets: GdrTarget[] = []\n for (const src of idRefs ?? []) {\n const target = resolveIdRefTarget(src, ctx)\n if (target === null) return null\n targets.push(target)\n }\n return targets.length === 0 ? null : targets\n}\n\n/**\n * Enforce the single-resource invariant: every target must live in the same\n * datasource. Returns that shared resource, or throws on a span.\n */\nexport function assertSingleResource(targets: readonly GdrTarget[]): Resource {\n const resource = resourceOf(targets[0]!.parsed)\n for (const g of targets) {\n const r = resourceOf(g.parsed)\n if (r.type !== resource.type || r.id !== resource.id) {\n throw new Error(\n `Guard targets span multiple resources (${resource.type}:${resource.id} vs ${r.type}:${r.id}); a guard is single-resource.`,\n )\n }\n }\n return resource\n}\n\n/** Bare ids in both published + draft forms for each target. */\nexport function bareIdRefs(targets: readonly GdrTarget[]): string[] {\n return targets.flatMap((g) => [g.parsed.documentId, `drafts.${g.parsed.documentId}`])\n}\n\n/**\n * Effective `match.types`: author-specified wins; otherwise the distinct\n * inferred types across targets, or undefined when none were inferred.\n */\nexport function resolveMatchTypes(\n targets: readonly GdrTarget[],\n authorTypes: string[] | undefined,\n): string[] | undefined {\n if (authorTypes !== undefined) return authorTypes\n const inferred = [...new Set(targets.map((g) => g.type).filter((t): t is string => !!t))]\n return inferred.length > 0 ? inferred : undefined\n}\n\n/** Project each metadata Source to its resolved value. */\nexport function resolveMetadata(\n metadata: Record<string, Source> | undefined,\n ctx: BindingContext,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [k, src] of Object.entries(metadata ?? {})) {\n out[k] = resolveSource(src, ctx)\n }\n return out\n}\n","/**\n * Shell-side lake-guard lifecycle: deploy and retract `temp.system.guard`\n * documents as a workflow enters and exits stages. NOT pure — resolves each\n * stage `Guard`'s `match.idRefs` / `metadata` Sources against the instance,\n * splits the resolved GDR into the guard's resource (resourceType/resourceId)\n * + bare ids, and writes via `clientForGdr` into that resource.\n *\n * Single-resource is enforced here: all idRefs of one guard must resolve to\n * the same datasource (the guard lives in and references only that one).\n *\n * \"Retract\" lifts the predicate to `\"true\"` (unconditionally allow) rather\n * than deleting — the `WorkflowClient` contract has no delete, and a loop-back\n * re-enters the stage and re-deploys the real predicate. POC simplification;\n * orphan accumulation + cross-dataset non-atomicity are documented seams.\n *\n * Enforcement is OPTIMISTIC: deploying a guard does not make the lake enforce\n * it. The engine evaluates guards itself (core/guards.ts); the bench throws.\n */\n\nimport {compileGuard, lakeGuardId} from './core/guards.ts'\nimport type {ParsedGdr} from './core/refs.ts'\nimport type {Guard, WorkflowDefinition} from './define/schema.ts'\nimport {\n assertSingleResource,\n bareIdRefs,\n resolveIdRefTargets,\n resolveMatchTypes,\n resolveMetadata,\n} from './guard-bindings.ts'\nimport type {MutationGuardDoc} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nexport const GUARD_OWNER = 'robot:workflow-engine'\n/** Retracted predicate — unconditionally allows, lifting the guard. */\nexport const GUARD_LIFTED_PREDICATE = 'true'\n\ninterface ResolvedGuard {\n doc: MutationGuardDoc\n routeGdr: ParsedGdr\n}\n\n/**\n * Resolve a stage `Guard` into a persisted doc + the GDR to route the write.\n * Returns null when no target resolves to a GDR (e.g. `self` — instance-side\n * guards are deferred), or when targets span resources (rejected).\n */\nfunction resolveGuard(\n guard: Guard,\n index: number,\n instance: WorkflowInstance,\n stageId: string,\n): ResolvedGuard | null {\n const ctx = {instance, stageId}\n\n const targets = resolveIdRefTargets(guard.match.idRefs, ctx)\n if (targets === null) return null\n\n const resource = assertSingleResource(targets)\n const types = resolveMatchTypes(targets, guard.match.types)\n\n const doc = compileGuard({\n id: lakeGuardId({instanceDocId: instance._id, stageId, index}),\n resourceType: resource.type,\n resourceId: resource.id,\n owner: GUARD_OWNER,\n ...(guard.name !== undefined ? {name: guard.name} : {}),\n ...(guard.description !== undefined ? {description: guard.description} : {}),\n match: {\n ...(types !== undefined ? {types} : {}),\n idRefs: bareIdRefs(targets),\n ...(guard.match.idPatterns !== undefined ? {idPatterns: guard.match.idPatterns} : {}),\n actions: guard.match.actions,\n },\n predicate: guard.predicate ?? '',\n metadata: resolveMetadata(guard.metadata, ctx),\n })\n\n return {doc, routeGdr: targets[0]!.parsed}\n}\n\nasync function upsertGuard(client: WorkflowClient, doc: MutationGuardDoc): Promise<void> {\n const existing = await client.getDocument(doc._id)\n const set: Record<string, unknown> = {\n resourceType: doc.resourceType,\n resourceId: doc.resourceId,\n owner: doc.owner,\n match: doc.match,\n predicate: doc.predicate,\n metadata: doc.metadata,\n }\n if (doc.name !== undefined) set.name = doc.name\n if (doc.description !== undefined) set.description = doc.description\n if (existing) {\n await client.patch(doc._id).set(set).commit()\n } else {\n await client.create(doc)\n }\n}\n\nexport interface StageGuardArgs {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n stageId: string\n}\n\n/** Resolve a stage's guards to their routed client + guard doc, skipping any that don't resolve. */\nfunction resolvedStageGuards(\n args: StageGuardArgs,\n): Array<{client: WorkflowClient; doc: MutationGuardDoc}> {\n const stage = args.definition.stages.find((s) => s.id === args.stageId)\n const out: Array<{client: WorkflowClient; doc: MutationGuardDoc}> = []\n for (const [index, guard] of (stage?.guards ?? []).entries()) {\n const resolved = resolveGuard(guard, index, args.instance, args.stageId)\n if (resolved === null) continue\n out.push({client: args.clientForGdr(resolved.routeGdr), doc: resolved.doc})\n }\n return out\n}\n\n/** Deploy every guard for a stage being entered (idempotent upsert). */\nexport async function deployStageGuards(args: StageGuardArgs): Promise<void> {\n for (const {client, doc} of resolvedStageGuards(args)) {\n await upsertGuard(client, doc)\n }\n}\n\n/** Retract every guard for a stage being exited (lift predicate to allow). */\nexport async function retractStageGuards(args: StageGuardArgs): Promise<void> {\n for (const {client, doc} of resolvedStageGuards(args)) {\n const existing = await client.getDocument<MutationGuardDoc>(doc._id)\n if (!existing) continue\n await client.patch(doc._id).set({predicate: GUARD_LIFTED_PREDICATE}).commit()\n }\n}\n\n/** Retract the exited stage's guards, then deploy the entered stage's. */\nexport async function reconcileStageGuards(args: {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n exitedStageId?: string\n enteredStageId?: string\n}): Promise<void> {\n const {client, clientForGdr, instance, definition, exitedStageId, enteredStageId} = args\n if (exitedStageId !== undefined) {\n await retractStageGuards({\n client,\n clientForGdr,\n instance,\n definition,\n stageId: exitedStageId,\n })\n }\n if (enteredStageId !== undefined) {\n await deployStageGuards({\n client,\n clientForGdr,\n instance,\n definition,\n stageId: enteredStageId,\n })\n }\n}\n","/**\n * Shell-side discovery query.\n *\n * Spawn `forEach.groq` scans the lake for rows to spawn child\n * workflows over. These are NOT filters — they look at content that\n * isn't in the snapshot (typically every doc of a given type that\n * references a doc the workflow already knows about). Different\n * semantics, different primitive, different code path from\n * `evaluateFilter`.\n *\n * Keeping discovery out of the filter pipeline is what lets the core\n * stay pure. Filters eval against pre-hydrated data; discovery hits the\n * lake by design.\n */\n\nimport {paramsForLake} from './core/params.ts'\nimport {parseGdr} from './core/refs.ts'\nimport type {WorkflowClient, WorkflowPerspective} from './types/client.ts'\n\n/**\n * Run a discovery GROQ against the appropriate client.\n *\n * The query receives params with GDR IDs stripped back to bare form\n * (via `paramsForLake`) because lake refs are bare. Caller decides\n * which client to use — typically the resource client of the first\n * `doc.ref` state slot, since discovery scans look for items related\n * to docs the workflow already references.\n */\nexport async function discoverItems(args: {\n client: WorkflowClient\n groq: string\n params: Record<string, unknown>\n /**\n * Read-side perspective. When set, the engine threads the instance's\n * `perspective` field through so spawn `forEach.groq` sees a\n * release-stacked view of the lake. Unset → client default.\n */\n perspective?: WorkflowPerspective\n}): Promise<unknown> {\n const {client, groq, params, perspective} = args\n const fetchOptions = perspective !== undefined ? {perspective} : undefined\n return client.fetch(groq, paramsForLake(params), fetchOptions)\n}\n\n/**\n * Convenience: pick the right client for a discovery scan given the\n * subject's GDR URI. Bare ids (no `:`) → default client. Anything\n * parseable → routed client.\n */\nexport function clientForDiscovery(\n defaultClient: WorkflowClient,\n clientForGdr: (parsed: import('./core/refs.ts').ParsedGdr) => WorkflowClient,\n subjectGdrUri: string | undefined,\n): WorkflowClient {\n if (!subjectGdrUri || !subjectGdrUri.includes(':')) return defaultClient\n try {\n return clientForGdr(parseGdr(subjectGdrUri))\n } catch {\n return defaultClient\n }\n}\n","import type {SanityDocument} from '@sanity/types'\nimport {evaluate, parse} from 'groq-js'\n\nimport {buildParams} from '../core/params.ts'\nimport {getPath} from '../core/path.ts'\nimport {gdrFromResource, isGdrUri, type GlobalDocumentReference} from '../core/refs.ts'\nimport type {Source, Spawn, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {clientForDiscovery, discoverItems} from '../discover.ts'\nimport {buildInstanceBase, effectsContextEntry} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport {derivePerspectiveFromState, resolveDeclaredState} from '../state-resolution.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectsContextEntry} from '../types/effects.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from '../types/state-slots.ts'\nimport {type EngineContext, gdrToBareId} from './context.ts'\nimport type {MutableInstance} from './mutation.ts'\n\n/**\n * Maximum depth of the spawn ancestor chain. A child's depth is\n * `ancestors.length`. With this limit a spawned chain can reach\n * `root → 1 → 2 → 3 → 4 → 5 → 6` (six levels of nesting below root);\n * a spawn that would create a seventh level is rejected.\n *\n * Backstop against runtime spawn recursion that the deploy-time cycle\n * detector cannot see — definitions whose spawn fires conditionally on\n * subject state can produce dynamic recursion without a static cycle\n * in the definition graph.\n */\nconst MAX_SPAWN_DEPTH = 6\n\n/**\n * Resolve a spawn declaration's `forEach` against the parent instance,\n * create one child workflow instance per result row, prime each child's\n * initial stage, cascade auto-transitions on each, and return the refs.\n *\n * `spawn.forEach.groq` is the discovery query (lake fetch) — runs with\n * the parent's reserved params (`$self`, `$state`, `$parent`,\n * `$ancestors`, `$stage`, `$now`) stripped to bare for the lake.\n *\n * `spawn.forEach.as.initialState` is a typed projection from each row\n * to the child's `initialState` array. Two spawn-only Sources:\n * - `{ source: \"row\", path? }` reads from the iteration row.\n * - `{ source: \"parentState\", slotId, path? }` reads from the\n * parent's resolved workflow-scope state.\n *\n * The child receives no auto-stamped state — only what the projection\n * produces. The child's workflow definition declares which slots it\n * expects; this projection feeds them.\n */\nexport async function spawnChildren(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n spawn: Spawn,\n actor: Actor | undefined,\n): Promise<GlobalDocumentReference[]> {\n // Depth backstop. Parent's `ancestors.length` is its own depth; a\n // child would be at `parent.ancestors.length + 1`. Reject before any\n // lake work or item resolution — the mutation has not been persisted\n // yet, so throwing here is safe.\n if (ctx.instance.ancestors.length + 1 > MAX_SPAWN_DEPTH) {\n const chain = [\n ...ctx.instance.ancestors.map((a) => a.id),\n gdrFromResource(ctx.instance.workflowResource, ctx.instance._id),\n ].join(' → ')\n throw new Error(\n `Spawn depth limit (${MAX_SPAWN_DEPTH}) exceeded on task \"${task.id}\" of ${ctx.instance._id}. ` +\n `Ancestor chain: ${chain}`,\n )\n }\n\n const rows = await resolveSpawnRows(ctx, spawn)\n const refs: GlobalDocumentReference[] = []\n\n for (const row of rows) {\n const projected = projectSpawnRow(ctx.instance, spawn, row)\n const {ref, body} = await prepareChildInstance({\n client: ctx.client,\n parent: ctx.instance,\n task,\n spawn,\n initialState: projected.initialState,\n effectsContext: projected.effectsContext,\n actor,\n })\n refs.push(ref)\n // Defer the write — `persist` drains `pendingCreates` into one\n // transaction with the parent's patch.\n mutation.pendingCreates.push(body)\n }\n\n return refs\n}\n\n/**\n * Run `spawn.forEach.groq` against the lake and return the rows. The\n * groq runs through the discovery client (resourceClients-aware) with\n * reserved params stripped to bare ids.\n */\nasync function resolveSpawnRows(ctx: EngineContext, spawn: Spawn): Promise<unknown[]> {\n const params = buildParams(ctx.instance)\n const groq = spawn.forEach.groq\n\n let value: unknown\n if (groq.includes('*')) {\n // Lake discovery — route through resourceClients in case the\n // spawn's GROQ targets a different Sanity resource than the\n // parent. We pick the resource by the first workflow-scope\n // `doc.ref` slot's GDR — typically the natural \"subject\" of the\n // workflow. Authors declaring a different routing target should\n // put that doc.ref slot first.\n const routingUri = firstDocRefGdrUri(ctx.instance.state)\n const client = clientForDiscovery(ctx.client, ctx.clientForGdr, routingUri)\n value = await discoverItems({\n client,\n groq,\n params,\n ...(ctx.instance.perspective !== undefined ? {perspective: ctx.instance.perspective} : {}),\n })\n } else {\n // Pure-param GROQ — evaluate in-process against an empty dataset.\n const tree = parse(groq, {params})\n const result = await evaluate(tree, {dataset: [ctx.instance], params, root: ctx.instance})\n value = await result.get()\n }\n\n if (Array.isArray(value)) return value\n if (value === null || value === undefined) return []\n return [value]\n}\n\n/** First workflow-scope `doc.ref` slot GDR URI, if any. Used to pick\n * the discovery client for spawn `forEach.groq`. */\nfunction firstDocRefGdrUri(slots: ResolvedStateSlot[] | undefined): string | undefined {\n if (!slots) return undefined\n for (const s of slots) {\n if (s._type === 'workflow.state.doc.ref' && s.value !== null) return s.value.id\n }\n return undefined\n}\n\n/**\n * Resolve a Source against the spawn-time context: row + parent state.\n * Returns the resolved value. Bare doc ids in `row` are NOT canonicalised\n * — the projection author is responsible for spelling out the GDR type\n * via a nested object or by using `Source.parentState` for ids that\n * already live in canonical form.\n */\nfunction resolveSpawnSource(source: Source, parent: WorkflowInstance, row: unknown): unknown {\n switch (source.source) {\n case 'literal':\n return source.value\n case 'row':\n return source.path !== undefined ? getPath(row, source.path) : row\n case 'parentState': {\n const slot = parent.state?.find((s) => s.id === source.slotId)\n if (slot === undefined) return null\n return source.path !== undefined ? getPath(slot, source.path) : slot\n }\n case 'self':\n return gdrFromResource(parent.workflowResource, parent._id)\n case 'stageId':\n return parent.currentStageId\n case 'now':\n return new Date().toISOString()\n case 'object': {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(source.fields)) {\n out[k] = resolveSpawnSource(v, parent, row)\n }\n return out\n }\n case 'actor':\n case 'param':\n case 'stateRead':\n case 'effectOutput':\n // These don't make sense at spawn time — no firing actor, no\n // action params, no in-progress mutation, no effect outputs.\n // Return null to fail loud rather than silently producing\n // misleading data.\n return null\n }\n}\n\n/**\n * Project a spawn's `forEach.as` against one row → the child's\n * `initialState` array + the seed map for the child's `effectsContext`.\n */\nfunction projectSpawnRow(\n parent: WorkflowInstance,\n spawn: Spawn,\n row: unknown,\n): {\n initialState: InitialStateValue[]\n effectsContext: Record<string, string | number | boolean | GlobalDocumentReference>\n} {\n const initialState: InitialStateValue[] = []\n for (const entry of spawn.forEach.as.initialState ?? []) {\n const raw = resolveSpawnSource(entry.value, parent, row)\n const value = canonicaliseSpawnValue(entry.type, raw, parent.workflowResource)\n initialState.push({\n type: entry.type as InitialStateValue['type'],\n id: entry.id,\n value: value as InitialStateValue['value'],\n } as InitialStateValue)\n }\n\n const effectsContext: Record<string, string | number | boolean | GlobalDocumentReference> = {}\n for (const [k, src] of Object.entries(spawn.forEach.as.effectsContext ?? {})) {\n const v = resolveSpawnSource(src, parent, row)\n if (v === undefined || v === null) continue\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n effectsContext[k] = v\n } else if (typeof v === 'object' && 'id' in v && 'type' in v) {\n // GDR shape — Zod-validate at create time; engine here just\n // trusts the projection author's typing.\n effectsContext[k] = v as GlobalDocumentReference\n }\n }\n return {initialState, effectsContext}\n}\n\n/**\n * Canonicalise a spawn-projected slot value for `doc.ref` / `doc.refs`\n * slots. Spawn projections naturally produce raw row data: bare doc\n * ids, `{ _ref, _type }` envelopes, or `{ id, type }` pairs where `id`\n * may be bare. The engine knows the spawning parent's resource, so it\n * canonicalises bare ids into GDR URIs rooted at that resource.\n *\n * Cross-resource spawns must spell the URI out in GROQ (or build a\n * `{ id: \"<full-uri>\", type: ... }` object via the `object` Source)\n * — the engine doesn't infer foreign resources.\n *\n * Non doc.ref / doc.refs slots pass through unchanged.\n */\nfunction canonicaliseSpawnValue(\n slotType: string,\n value: unknown,\n workflowResource: import('../core/refs.ts').WorkflowResource,\n): unknown {\n if (slotType === 'workflow.state.doc.ref') {\n return coerceSpawnGdr(value, workflowResource)\n }\n if (slotType === 'workflow.state.doc.refs') {\n if (!Array.isArray(value)) return value\n return value.map((v) => coerceSpawnGdr(v, workflowResource)).filter((v) => v !== null)\n }\n return value\n}\n\nfunction coerceSpawnGdr(\n raw: unknown,\n workflowResource: import('../core/refs.ts').WorkflowResource,\n): GlobalDocumentReference | null {\n // Canonicalise a bare doc id into a GDR URI rooted at this resource;\n // leave already-canonical URIs untouched.\n const toUri = (id: string) => (isGdrUri(id) ? id : gdrFromResource(workflowResource, id))\n\n if (raw === null || raw === undefined) return null\n if (typeof raw === 'object' && 'id' in raw && 'type' in raw) {\n const r = raw as {id: unknown; type: unknown}\n if (typeof r.id === 'string' && typeof r.type === 'string') {\n return {id: toUri(r.id), type: r.type}\n }\n }\n if (typeof raw === 'object' && '_ref' in raw) {\n const r = raw as {_ref: unknown}\n if (typeof r._ref === 'string') return {id: toUri(r._ref), type: 'document'}\n }\n if (typeof raw === 'string' && raw.length > 0) return {id: toUri(raw), type: 'document'}\n return null\n}\n\n/**\n * Resolve a logical (workflowId, version?) ref to a deployed\n * `workflow.definition` doc. Scopes the lookup to definitions sharing\n * at least one tag with the caller. Picks the highest `version` when\n * `version` is omitted or `\"latest\"`; otherwise the explicit version.\n *\n * Returns null when no matching definition exists.\n */\nasync function resolveLogicalDefinition(\n client: WorkflowClient,\n ref: {workflowId: string; version?: number | 'latest' | undefined},\n tags: string[],\n): Promise<(WorkflowDefinition & SanityDocument) | null> {\n const wantsExplicit = typeof ref.version === 'number'\n const params: Record<string, unknown> = {workflowId: ref.workflowId, tags}\n if (wantsExplicit) params.version = ref.version\n const groq = wantsExplicit\n ? `*[_type == \"workflow.definition\" && workflowId == $workflowId && version == $version && count(tags[@ in $tags]) > 0][0]`\n : `*[_type == \"workflow.definition\" && workflowId == $workflowId && count(tags[@ in $tags]) > 0] | order(version desc)[0]`\n const result = await client.fetch<(WorkflowDefinition & SanityDocument) | null>(groq, params)\n return result ?? null\n}\n\nasync function prepareChildInstance(args: {\n client: WorkflowClient\n parent: WorkflowInstance\n task: Task\n spawn: Spawn\n initialState: InitialStateValue[]\n effectsContext: Record<string, string | number | boolean | GlobalDocumentReference>\n actor: Actor | undefined\n}): Promise<{ref: GlobalDocumentReference; body: WorkflowInstance}> {\n const {client, parent, task, spawn, initialState, effectsContext, actor} = args\n\n const definition = await resolveLogicalDefinition(client, spawn.definitionRef, parent.tags ?? [])\n if (definition === null) {\n const versionLabel =\n spawn.definitionRef.version === undefined || spawn.definitionRef.version === 'latest'\n ? 'latest'\n : `v${spawn.definitionRef.version}`\n throw new Error(\n `Spawn target workflowId=\"${spawn.definitionRef.workflowId}\" ${versionLabel} not deployed (parent ${parent._id}, task ${task.id})`,\n )\n }\n\n // Child inherits the parent's tags + workflow resource so it stays\n // visible to whichever engine spawned the parent.\n const childTags = parent.tags ?? []\n const childPrefix = childTags[0] ?? 'wf'\n const workflowResource = parent.workflowResource\n // Bare `_id` — Sanity rejects `:` in document IDs. The GDR URI form\n // (`childUri`) is what the parent's `taskEntry.spawnedInstances[]`\n // and the child's own `ancestors[]` reference.\n const childDocId = `${childPrefix}.wf-instance.${randomKey()}`\n const childUri = gdrFromResource(workflowResource, childDocId)\n const childRef: GlobalDocumentReference = {id: childUri, type: 'workflow.instance'}\n const ancestors = [\n ...parent.ancestors,\n {\n id: gdrFromResource(parent.workflowResource, parent._id),\n type: 'workflow.instance',\n } as GlobalDocumentReference,\n ]\n\n // Resolve the child's workflow-scope state declarations against the\n // caller-supplied `initialState`. The child's own state[] schema\n // dictates which slot ids/types exist; the spawn projection just\n // fills the \"init\"-sourced ones. Query/write/computed slots resolve\n // per their own source kind.\n // Child instances inherit the parent's perspective by default — if\n // the parent reads under a release stack, child filters / spawn\n // discovery should see the same stacked view of the lake.\n const inheritedPerspective = parent.perspective\n const childState = await resolveDeclaredState({\n slotDefs: definition.state,\n initialState,\n ctx: {\n client,\n selfId: childDocId,\n tags: childTags,\n workflowResource,\n ...(inheritedPerspective !== undefined ? {perspective: inheritedPerspective} : {}),\n },\n randomKey,\n })\n // A child may carry its own `release.ref` slot (projected from the\n // spawn forEach) — that takes precedence over inheritance. Otherwise\n // it inherits the parent's perspective.\n const childPerspective = derivePerspectiveFromState(childState) ?? inheritedPerspective\n\n const effectsContextEntries: EffectsContextEntry[] = Object.entries(effectsContext).map(\n ([key, value]) => {\n if (typeof value === 'object' && value !== null && 'id' in value && 'type' in value) {\n if (!isGdrUri(value.id)) {\n throw new Error(\n `spawn.forEach.as.effectsContext[\"${key}\"]: GDR id must be a \"<scheme>:...\" URI, got ${JSON.stringify(value.id)}.`,\n )\n }\n return effectsContextEntry(key, {id: value.id, type: value.type})\n }\n return effectsContextEntry(key, value)\n },\n )\n\n const base = buildInstanceBase({\n id: childDocId,\n now: new Date().toISOString(),\n tags: childTags,\n workflowResource,\n workflowId: definition.workflowId,\n pinnedVersion: definition.version,\n definition,\n state: childState,\n effectsContext: effectsContextEntries,\n ancestors,\n perspective: childPerspective,\n initialStageId: definition.initialStageId,\n actor,\n })\n // Body is returned to the caller; the actual `client.create` happens\n // inside the parent's persist transaction so the parent's\n // `spawnedInstances` patch and this child create commit atomically.\n // Priming + cascade run after the transaction (per-child, single-doc).\n return {ref: childRef, body: base}\n}\n\nexport async function checkSpawnCompletion(\n client: WorkflowClient,\n entry: TaskEntry,\n spawn: Spawn,\n): Promise<boolean> {\n const refs = entry.spawnedInstances ?? []\n if (refs.length === 0) {\n // Vacuous: 0/0 children done satisfies \"all\" / \"count: 0\"; \"any\" / \"count: N>0\" fails.\n const policy = spawn.completionPolicy ?? {kind: 'all'}\n return policy.kind === 'all' || (policy.kind === 'count' && policy.n === 0)\n }\n\n // Single GROQ — fetches every child's stage info in one roundtrip\n // instead of N serial `getDocument` calls. (Previously this was the\n // engine's most expensive cascade hot path for fan-out spawns.)\n // `ref.id` is the child's GDR URI; the persistent `_id` is bare.\n const ids = refs.map((r) => (r.id.includes(':') ? gdrToBareId(r.id) : r.id))\n const children = await client.fetch<\n {_id: string; currentStageId: string; definitionSnapshot: string}[]\n >(`*[_id in $ids]{_id, currentStageId, definitionSnapshot}`, {ids})\n\n let terminalCount = 0\n for (const child of children) {\n const childDef = JSON.parse(child.definitionSnapshot) as WorkflowDefinition\n const childStage = childDef.stages.find((s) => s.id === child.currentStageId)\n if (childStage?.kind === 'terminal') terminalCount++\n }\n\n const policy = spawn.completionPolicy ?? {kind: 'all'}\n switch (policy.kind) {\n case 'all':\n // refs.length here is non-zero (handled above).\n return terminalCount === refs.length\n case 'any':\n return terminalCount >= 1\n case 'count':\n return terminalCount >= policy.n\n }\n}\n","import type {Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {TaskId} from '../types/ids.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport {\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n loadContext,\n resolveTaskStateSlots,\n} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {\n findCurrentTasks,\n findTaskInCurrentStage,\n type MutableInstance,\n persist,\n requireMutationTaskEntry,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport type {EngineCallOptions, InvokeResult} from './results.ts'\nimport {checkSpawnCompletion, spawnChildren} from './spawn.ts'\n\n/**\n * Flip a task from `pending` to `active` and queue its declared effects.\n * No-op if the task is already active or done.\n */\nexport async function invokeTask(args: {\n client: WorkflowClient\n instanceId: string\n taskId: TaskId\n options?: EngineCallOptions\n}): Promise<InvokeResult> {\n const {client, instanceId, taskId, options} = args\n const ctx = await loadContext(client, instanceId)\n return commitInvoke(ctx, taskId, options?.actor)\n}\n\nasync function commitInvoke(\n ctx: EngineContext,\n taskId: TaskId,\n actor: Actor | undefined,\n): Promise<InvokeResult> {\n const {task} = findTaskInCurrentStage(ctx, taskId)\n const entry = findCurrentTasks(ctx.instance).find((t) => t.id === taskId)\n if (entry === undefined) {\n throw new Error(`Task \"${taskId}\" has no status entry on instance ${ctx.instance._id}`)\n }\n if (entry.status !== 'pending') {\n return {invoked: false, taskId}\n }\n\n const mutation = startMutation(ctx.instance)\n const mutEntry = requireMutationTaskEntry(mutation, taskId)\n await activateTask(ctx, mutation, task, mutEntry, actor)\n await persist(ctx, mutation)\n return {invoked: true, taskId}\n}\n\n/**\n * On activation, evaluate the task's `failWhen` then `completeWhen`\n * predicates against the current snapshot. The first truthy one\n * immediately resolves the task (failure dominates), recording a\n * system-actor status change. Returns true when the task resolved so\n * the caller short-circuits the normal active path.\n */\nasync function autoResolveOnActivate(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n entry: TaskEntry,\n): Promise<boolean> {\n const checks: {filter: Task['failWhen']; outcome: 'failed' | 'done'; systemId: string}[] = [\n {filter: task.failWhen, outcome: 'failed', systemId: 'engine.failWhen'},\n {filter: task.completeWhen, outcome: 'done', systemId: 'engine.completeWhen'},\n ]\n for (const {filter, outcome, systemId} of checks) {\n if (filter === undefined) continue\n if (!(await ctxEvaluateFilter(ctx, filter))) continue\n const completedAt = new Date().toISOString()\n entry.status = outcome\n entry.completedAt = completedAt\n entry.completedBy = systemId\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: mutation.currentStageId,\n taskId: task.id,\n from: 'active',\n to: outcome,\n actor: {kind: 'system', id: systemId},\n at: completedAt,\n }),\n )\n return true\n }\n return false\n}\n\nexport async function activateTask(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n entry: TaskEntry,\n actor: Actor | undefined,\n): Promise<void> {\n entry.status = 'active'\n entry.startedAt = new Date().toISOString()\n // Resolve task-scoped state slots declared on the task definition.\n // Skipped if the task declares none — keeps the entry shape clean.\n if (task.state !== undefined && task.state.length > 0) {\n const stage = findStage(ctx.definition, mutation.currentStageId)\n entry.state = await resolveTaskStateSlots({\n client: ctx.client,\n instance: ctx.instance,\n stage,\n task,\n })\n }\n // Auto-failure dominates auto-completion: if both predicates would\n // fire, evaluate failWhen first so the more notable signal wins.\n if (await autoResolveOnActivate(ctx, mutation, task, entry)) return\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.taskActivated',\n at: new Date().toISOString(),\n stageId: mutation.currentStageId,\n taskId: task.id,\n ...(actor !== undefined ? {actor} : {}),\n })\n await queueEffects(\n ctx,\n mutation,\n task.effects,\n {\n kind: 'taskInvoke',\n id: task.id,\n },\n actor,\n )\n\n // If the task has a `spawns` declaration, fan out child workflow\n // instances now. The task stays `active` — propagation will flip it\n // to `done` once the spawn's completion policy is satisfied as\n // children transition.\n if (task.spawns !== undefined) {\n const refs = await spawnChildren(ctx, mutation, task, task.spawns, actor)\n entry.spawnedInstances = refs\n for (const ref of refs) {\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.spawned',\n at: new Date().toISOString(),\n taskId: task.id,\n instanceRef: ref,\n })\n }\n\n // Vacuous-truth case: if the spawn yielded zero items and the\n // policy is satisfied without any children (`{ kind: \"all\" }` over\n // an empty set is true; `{ kind: \"count\", n: 0 }` likewise), mark\n // the task done immediately. Otherwise propagation would never fire\n // (no child transitions to ride on), and the task would be stuck.\n if (await checkSpawnCompletion(ctx.client, entry, task.spawns)) {\n const previousStatus = entry.status\n entry.status = 'done'\n entry.completedAt = new Date().toISOString()\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: mutation.currentStageId,\n taskId: task.id,\n from: previousStatus,\n to: 'done',\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n }\n }\n}\n\n// Internal — task status & effects\n\nexport async function buildStageTasks(ctx: EngineContext, stage: Stage): Promise<TaskEntry[]> {\n const entries: TaskEntry[] = []\n for (const task of stage.tasks ?? []) {\n const inScope = await ctxEvaluateFilter(ctx, task.filter)\n entries.push({\n _key: randomKey(),\n id: task.id,\n status: inScope ? 'pending' : 'skipped',\n ...(task.filter !== undefined\n ? {\n filterEvaluation: {\n at: new Date().toISOString(),\n truthy: inScope,\n },\n }\n : {}),\n })\n }\n return entries\n}\n\n/** Tasks that implicitly activate when their stage is entered. */\nexport function activatesOnStageEnter(task: Task): boolean {\n return (\n task.invokeOn === 'stageEnter' ||\n task.spawns !== undefined ||\n task.completeWhen !== undefined ||\n task.failWhen !== undefined\n )\n}\n","import type {Stage, Transition} from '../define/schema.ts'\nimport {reconcileStageGuards} from '../guards-lifecycle.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {StageId} from '../types/ids.ts'\nimport type {StageEntry} from '../types/instance-state.ts'\nimport {\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n loadContext,\n resolveStageStateSlots,\n} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {\n findOpenStageEntry,\n type MutableInstance,\n persist,\n stageTransitionHistory,\n startMutation,\n} from './mutation.ts'\nimport type {EngineCallOptions, TransitionResult} from './results.ts'\nimport {activatesOnStageEnter, activateTask, buildStageTasks} from './tasks.ts'\n\n/**\n * Admin override — force the instance into `targetStageId` regardless\n * of filters or declared transitions. Use cases: Kanban-style UI where\n * each column is a stage; migration scripts; manual recovery from a\n * stuck workflow. ACL gating is enforced at the API layer.\n *\n * Behaviour mirrors a successful transition: exit current stage,\n * append a fresh StageEntry for the target, fire onExit + onEnter\n * effects, auto-activate stageEnter / spawn / completeWhen tasks,\n * cascade. The history entries carry `via: \"setStage\"` so audits can\n * distinguish filtered transitions from admin overrides.\n */\nexport async function setStage(args: {\n client: WorkflowClient\n instanceId: string\n targetStageId: StageId\n reason?: string\n options?: EngineCallOptions\n}): Promise<TransitionResult> {\n const {client, instanceId, targetStageId, reason, options} = args\n const ctx = await loadContext(client, instanceId)\n return commitSetStage(ctx, targetStageId, reason, options?.actor)\n}\n\n/**\n * Append a fresh {@link StageEntry} for `nextStage` and run the on-entry\n * lifecycle: queue `onEnter` effects, auto-activate tasks that must run on\n * stage entry (`invokeOn: \"stageEnter\"`, or those declaring `spawns` /\n * `completeWhen` / `failWhen`), and mark the instance complete if the stage is\n * terminal. The caller owns history, prior-stage exit, persistence, and guard\n * reconciliation. `at` is the single timestamp stamped on the entry.\n */\nasync function enterStage(\n ctx: EngineContext,\n mutation: MutableInstance,\n nextStage: Stage,\n actor: Actor | undefined,\n at: string,\n): Promise<void> {\n mutation.currentStageId = nextStage.id\n const nextStageEntry: StageEntry = {\n _key: randomKey(),\n id: nextStage.id,\n enteredAt: at,\n state: await resolveStageStateSlots({\n client: ctx.client,\n instance: ctx.instance,\n stage: nextStage,\n }),\n tasks: await buildStageTasks(ctx, nextStage),\n }\n mutation.stages.push(nextStageEntry)\n\n await queueEffects(\n ctx,\n mutation,\n nextStage.onEnter,\n {kind: 'stageEnter', id: nextStage.id},\n actor,\n )\n\n for (const task of nextStage.tasks ?? []) {\n if (!activatesOnStageEnter(task)) continue\n const entry = nextStageEntry.tasks.find((t) => t.id === task.id)\n if (entry && entry.status === 'pending') {\n await activateTask(ctx, mutation, task, entry, actor)\n }\n }\n\n if (nextStage.kind === 'terminal') {\n mutation.completedAt = at\n }\n}\n\n/**\n * Begin a stage move: snapshot the instance into a mutation, stamp one `at`\n * timestamp for the whole move, and queue the current stage's onExit effects.\n * Shared by the setStage and transition commit paths.\n */\nasync function beginStageMove(\n ctx: EngineContext,\n currentStage: Stage,\n actor: Actor | undefined,\n): Promise<{mutation: MutableInstance; at: string}> {\n const mutation = startMutation(ctx.instance)\n const at = new Date().toISOString()\n await queueEffects(\n ctx,\n mutation,\n currentStage.onExit,\n {kind: 'stageExit', id: currentStage.id},\n actor,\n )\n return {mutation, at}\n}\n\nasync function commitSetStage(\n ctx: EngineContext,\n targetStageId: StageId,\n reason: string | undefined,\n actor: Actor | undefined,\n): Promise<TransitionResult> {\n const currentStage = findStage(ctx.definition, ctx.instance.currentStageId)\n const nextStage = findStage(ctx.definition, targetStageId)\n if (currentStage.id === nextStage.id) {\n return {fired: false}\n }\n\n const {mutation, at} = await beginStageMove(ctx, currentStage, actor)\n\n const transitionId = `setStage:${currentStage.id}->${nextStage.id}`\n mutation.history.push(\n ...stageTransitionHistory({\n fromStageId: currentStage.id,\n toStageId: nextStage.id,\n at,\n transitionId,\n via: 'setStage',\n ...(actor !== undefined ? {actor} : {}),\n ...(reason !== undefined ? {reason} : {}),\n }),\n )\n\n const priorEntry = findOpenStageEntry(mutation)\n if (priorEntry !== undefined) priorEntry.exitedAt = at\n\n await enterStage(ctx, mutation, nextStage, actor, at)\n\n await persistStageMove(ctx, mutation, currentStage.id, nextStage.id)\n\n return {\n fired: true,\n fromStageId: currentStage.id,\n toStageId: nextStage.id,\n transitionId,\n }\n}\n\n/** Persist the mutation, then reconcile lake guards for the stage move —\n * retract the exited stage's guards, deploy the entered stage's.\n * Cross-dataset, runs post-persist. */\nasync function persistStageMove(\n ctx: EngineContext,\n mutation: MutableInstance,\n exitedStageId: StageId,\n enteredStageId: StageId,\n): Promise<void> {\n await persist(ctx, mutation)\n await reconcileStageGuards({\n client: ctx.client,\n clientForGdr: ctx.clientForGdr,\n instance: ctx.instance,\n definition: ctx.definition,\n exitedStageId,\n enteredStageId,\n })\n}\n\nexport async function commitTransition(\n ctx: EngineContext,\n action: string | undefined,\n actor: Actor | undefined,\n): Promise<TransitionResult> {\n const currentStage = findStage(ctx.definition, ctx.instance.currentStageId)\n const transition = await pickTransition(ctx, currentStage, action)\n if (transition === undefined) {\n return {fired: false}\n }\n\n const {mutation, at} = await beginStageMove(ctx, currentStage, actor)\n\n // Fire transition effects.\n await queueEffects(\n ctx,\n mutation,\n transition.effects,\n {\n kind: 'transition',\n id: transition.id ?? `${currentStage.id}->${transition.to}`,\n },\n actor,\n )\n\n // Append history.\n mutation.history.push(\n ...stageTransitionHistory({\n fromStageId: currentStage.id,\n toStageId: transition.to,\n at,\n ...(transition.id !== undefined ? {transitionId: transition.id} : {}),\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n\n // Mark the prior stage exited. There can be multiple entries with\n // the same id from loop-backs — the current one is the one without\n // exitedAt set.\n const priorEntry = findOpenStageEntry(mutation)\n if (priorEntry !== undefined) priorEntry.exitedAt = at\n\n // Move to new stage and append a fresh StageEntry with its tasks.\n const nextStage = findStage(ctx.definition, transition.to)\n await enterStage(ctx, mutation, nextStage, actor, at)\n\n await persistStageMove(ctx, mutation, currentStage.id, nextStage.id)\n\n return {\n fired: true,\n fromStageId: currentStage.id,\n toStageId: transition.to,\n ...(transition.id !== undefined ? {transitionId: transition.id} : {}),\n }\n}\n\nasync function pickTransition(\n ctx: EngineContext,\n stage: Stage,\n action: string | undefined,\n): Promise<Transition | undefined> {\n const candidates = (stage.transitions ?? []).filter((t) => {\n if (action === undefined) return t.on === undefined\n return t.on === action\n })\n for (const candidate of candidates) {\n if (await ctxEvaluateFilter(ctx, candidate.filter)) return candidate\n }\n return undefined\n}\n","// Essential commit⇄cascade mutual recursion: `mutation.persist` is the single\n// transactional commit chokepoint, and committing a parent that spawned\n// children must drive those children's lifecycle (prime → cascade → propagate)\n// inline, which itself commits through `persist`. Children are primed *within*\n// the parent's commit so the parent's spawn-completion gate observes them in the\n// same pass — deferring the drive to a higher layer would break that synchronous\n// nested-workflow semantics. Resolved at call time; module init is unaffected.\n// fallow-ignore-file circular-dependencies\nimport {resolveBindings} from '../core/bindings.ts'\nimport {evaluateFilter} from '../core/eval.ts'\nimport {buildParams} from '../core/params.ts'\nimport type {ParsedGdr} from '../core/refs.ts'\nimport type {Stage, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {deployStageGuards} from '../guards-lifecycle.ts'\nimport {randomKey} from '../keys.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {StageEntry, TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {\n buildEngineContext,\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n gdrToBareId,\n loadContext,\n resolveStageStateSlots,\n} from './context.ts'\nimport {buildQueuedEffect} from './effects.ts'\nimport {\n currentTasks,\n findCurrentTasks,\n persist,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport type {EngineCallOptions, TransitionResult} from './results.ts'\nimport {checkSpawnCompletion} from './spawn.ts'\nimport {commitTransition} from './stages.ts'\nimport {activatesOnStageEnter, activateTask} from './tasks.ts'\n\n/**\n * Re-evaluate auto-transitions. Use after any change that might unblock\n * one (e.g. after a fireAction commits).\n */\nasync function evaluateAutoTransitions(args: {\n client: WorkflowClient\n instanceId: string\n options?: EngineCallOptions\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient\n}): Promise<TransitionResult> {\n const {client, instanceId, options, clientForGdr} = args\n const ctx = await loadContext(client, instanceId, clientForGdr ? {clientForGdr} : undefined)\n return commitTransition(ctx, undefined, options?.actor)\n}\n\n// Initial-stage priming, cascade, propagation — used by both api.ts (for\n// fresh instances and after-call cascading) and the spawn path inside\n// activateTask. Exported so api.ts doesn't reimplement them.\n\n/**\n * Build taskStatus + queue onEnter effects + auto-activate stageEnter\n * tasks for a freshly-created instance's initial stage. Called by both\n * `workflow.startInstance` and the spawn path.\n */\nexport async function primeInitialStage(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<void> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) return\n // Idempotency: if the initial stage entry is already on the instance,\n // skip. New instances arrive here with `stages: []`.\n if (instance.stages.length > 0 || instance.pendingEffects.length > 0) return\n\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const stage = definition.stages.find((s) => s.id === instance.currentStageId)\n if (stage === undefined) return\n\n // Build a snapshot up-front so any `filter` on a stage-tasks entry\n // can evaluate in-memory. Same shape the cascade uses.\n const snapshot = await hydrateSnapshot({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance,\n definition,\n })\n const tasks: TaskEntry[] = []\n for (const task of stage.tasks ?? []) {\n const inScope = await evaluateFilter({\n filter: task.filter,\n definition,\n snapshot,\n params: buildParams(instance),\n })\n tasks.push({\n _key: randomKey(),\n id: task.id,\n status: inScope ? 'pending' : 'skipped',\n })\n }\n const initialStageEntry: StageEntry = {\n _key: randomKey(),\n id: stage.id,\n enteredAt: new Date().toISOString(),\n state: await resolveStageStateSlots({client, instance, stage}),\n tasks,\n }\n\n const pendingEffects: PendingEffect[] = []\n const newHistory = [...instance.history]\n for (const effect of stage.onEnter ?? []) {\n const params = await resolveBindings({\n bindings: effect.bindings,\n staticInput: effect.input,\n instance,\n ...(actor !== undefined ? {actor} : {}),\n })\n const {pending, history} = buildQueuedEffect(\n effect,\n {kind: 'stageEnter', id: stage.id},\n params,\n actor,\n )\n pendingEffects.push(pending)\n newHistory.push(history)\n }\n\n // Patch — fails fast if the instance was deleted between the\n // `create` above and this prime call. `ifRevisionId` rejects concurrent\n // priming attempts (e.g. a retried startInstance).\n await client\n .patch(instance._id)\n .set({\n stages: [initialStageEntry],\n pendingEffects,\n history: newHistory,\n lastChangedAt: new Date().toISOString(),\n })\n .ifRevisionId(instance._rev)\n .commit()\n\n // Deploy lake guards for the initial stage (no exit to retract).\n await deployStageGuards({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance,\n definition,\n stageId: stage.id,\n })\n\n await autoActivatePrimedTasks(client, instanceId, definition, stage, actor, clientForGdr)\n}\n\n/**\n * After the initial stage entry is persisted, re-load and auto-activate\n * the tasks that implicitly run on stage-entry (`invokeOn: \"stageEnter\"`,\n * spawn-bearing, or carrying a `completeWhen`/`failWhen` predicate). Each\n * activation reloads + persists independently so spawns + auto-resolution\n * see committed state.\n */\nasync function autoActivatePrimedTasks(\n client: WorkflowClient,\n instanceId: string,\n definition: WorkflowDefinition,\n stage: Stage,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<void> {\n const resolvedClientForGdr = clientForGdr ?? (() => client)\n for (const task of stage.tasks ?? []) {\n if (!activatesOnStageEnter(task)) continue\n const updated = await client.getDocument<WorkflowInstance>(instanceId)\n if (!updated) continue\n const updatedCtx = await buildEngineContext({\n client,\n clientForGdr: resolvedClientForGdr,\n instance: updated,\n definition,\n })\n const mutation = startMutation(updated)\n const mutEntry = currentTasks(mutation).find((t) => t.id === task.id)\n if (mutEntry && mutEntry.status === 'pending') {\n await activateTask(updatedCtx, mutation, task, mutEntry, actor)\n await persist(updatedCtx, mutation)\n }\n }\n}\n\nconst CASCADE_LIMIT = 100\n\n/**\n * Walk active task entries whose authoring definition declares a\n * `completeWhen` and/or `failWhen` filter; evaluate the filters against\n * the current snapshot and flip any matching task accordingly. Returns\n * the count flipped.\n *\n * Both predicates are evaluated on the same pass. If a single task has\n * both and both are truthy, `failWhen` wins — failure dominates so the\n * more notable signal is not silently swallowed.\n *\n * The engine never runs a clock — this only fires if something else\n * (a `tick`, a `fireAction`, a `completeEffect`, or `startInstance`)\n * has already kicked the cascade. External schedulers can index\n * `dueAt` for the wall-clock fast-path; state-based predicates rely on\n * the caller invoking `tick` when relevant state changes.\n */\ntype AutoResolveCandidate = {task: Task; outcome: 'done' | 'failed'}\n\n/** For each active task carrying an auto-predicate, evaluate `failWhen`\n * then `completeWhen` (failure dominates) and collect the outcome. */\nasync function gatherAutoResolveCandidates(\n ctx: EngineContext,\n tasks: Task[],\n): Promise<AutoResolveCandidate[]> {\n const currentTasksList = findCurrentTasks(ctx.instance)\n const candidates: AutoResolveCandidate[] = []\n for (const task of tasks) {\n const entry = currentTasksList.find((e) => e.id === task.id)\n if (entry?.status !== 'active') continue\n // failWhen first — failure dominates if both fire.\n if (task.failWhen !== undefined && (await ctxEvaluateFilter(ctx, task.failWhen))) {\n candidates.push({task, outcome: 'failed'})\n continue\n }\n if (task.completeWhen !== undefined && (await ctxEvaluateFilter(ctx, task.completeWhen))) {\n candidates.push({task, outcome: 'done'})\n }\n }\n return candidates\n}\n\nasync function resolveCompleteWhen(\n client: WorkflowClient,\n instanceId: string,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<number> {\n const ctx = await loadContext(client, instanceId, clientForGdr ? {clientForGdr} : undefined)\n const stage = findStage(ctx.definition, ctx.instance.currentStageId)\n const tasksWithAutoPredicate = (stage.tasks ?? []).filter(\n (t) => t.completeWhen !== undefined || t.failWhen !== undefined,\n )\n if (tasksWithAutoPredicate.length === 0) return 0\n\n const candidates = await gatherAutoResolveCandidates(ctx, tasksWithAutoPredicate)\n if (candidates.length === 0) return 0\n\n const mutation = startMutation(ctx.instance)\n let count = 0\n for (const {task, outcome} of candidates) {\n const mutEntry = currentTasks(mutation).find((t) => t.id === task.id)\n if (mutEntry === undefined || mutEntry.status !== 'active') continue\n const previousStatus = mutEntry.status\n const actor: Actor = {\n kind: 'system',\n id: outcome === 'failed' ? 'engine.failWhen' : 'engine.completeWhen',\n }\n mutEntry.status = outcome\n mutEntry.completedAt = new Date().toISOString()\n mutEntry.completedBy = actor.id\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: stage.id,\n taskId: task.id,\n from: previousStatus,\n to: outcome,\n actor,\n }),\n )\n count++\n }\n if (count > 0) {\n await persist(ctx, mutation)\n }\n return count\n}\n\n/**\n * Cascade auto-transitions on the given instance until it lands stably.\n * Returns the count of transitions fired during the cascade. Resolves\n * any due waits before each transition pass so a wait that became due\n * can immediately unblock an `allTasksDone`-style filter.\n */\nexport async function cascadeAutoTransitions(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<number> {\n let count = 0\n while (true) {\n await resolveCompleteWhen(client, instanceId, clientForGdr)\n const result = await evaluateAutoTransitions({\n client,\n instanceId,\n ...(actor !== undefined ? {options: {actor}} : {}),\n ...(clientForGdr ? {clientForGdr} : {}),\n })\n if (!result.fired) return count\n count++\n if (count > CASCADE_LIMIT) {\n throw new Error(\n `Cascade did not stabilise after ${CASCADE_LIMIT} auto-transitions on ${instanceId} — possible infinite loop`,\n )\n }\n }\n}\n\n/**\n * Walk up an instance's ancestor chain, re-evaluating each ancestor's\n * spawn-bearing task in case its completion policy is now satisfied. If\n * a parent task flips done as a result, cascade auto-transitions on the\n * parent and recurse upward.\n *\n * This is the load-bearing primitive for nested workflows: child\n * transitions ripple up the tree, parent gates close, grand-parent\n * gates close, all the way to the root.\n */\nexport async function propagateToAncestors(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<void> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) return\n if (instance.ancestors.length === 0) return\n\n const parentRef = instance.ancestors[instance.ancestors.length - 1]\n if (parentRef === undefined) return\n // ancestors[].id is the GDR URI; the Sanity `_id` is bare.\n const parentId = gdrToBareId(parentRef.id)\n\n const parent = await client.getDocument<WorkflowInstance>(parentId)\n if (!parent) return\n // ancestors[] is supposed to carry GDR URIs of parent workflow\n // instances (built up via spawn). A misconfigured caller could put\n // arbitrary doc refs there — bail gracefully instead of crashing on\n // `JSON.parse(undefined)`.\n if (parent._type !== 'workflow.instance' || typeof parent.definitionSnapshot !== 'string') {\n return\n }\n\n const parentDefinition = JSON.parse(parent.definitionSnapshot) as WorkflowDefinition\n const parentStage = parentDefinition.stages.find((s) => s.id === parent.currentStageId)\n if (parentStage === undefined) return\n\n // Find the task on the parent's current stage that spawned this\n // child. `spawnedInstances[].id` is the GDR URI of the child; the\n // instance's persistent `_id` is bare — so compare via the bare id.\n const parentCurrentTasks = findCurrentTasks(parent)\n const parentTask = (parentStage.tasks ?? []).find((t) => {\n if (t.spawns === undefined) return false\n const entry = parentCurrentTasks.find((e) => e.id === t.id)\n return entry?.spawnedInstances?.some((r) => gdrToBareId(r.id) === instance._id) ?? false\n })\n if (parentTask === undefined) return\n\n const parentEntry = parentCurrentTasks.find((e) => e.id === parentTask.id)\n if (parentEntry === undefined || parentEntry.status === 'done') return\n\n // Re-evaluate the spawn's completion policy.\n const satisfied = await checkSpawnCompletion(client, parentEntry, parentTask.spawns!)\n if (!satisfied) return\n\n // Flip the parent's task to done and persist.\n const ctx = await buildEngineContext({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance: parent,\n definition: parentDefinition,\n })\n const mutation = startMutation(parent)\n const mutEntry = currentTasks(mutation).find((e) => e.id === parentTask.id)\n if (mutEntry === undefined) return\n const previousStatus = mutEntry.status\n mutEntry.status = 'done'\n mutEntry.completedAt = new Date().toISOString()\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: parentStage.id,\n taskId: parentTask.id,\n from: previousStatus,\n to: 'done',\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n await persist(ctx, mutation)\n\n // Cascade auto-transitions on the parent. This may transition it to\n // a new stage, which itself may unblock the grandparent's task.\n await cascadeAutoTransitions(client, parentId, actor, clientForGdr)\n\n // Recurse: propagate from the parent upward.\n await propagateToAncestors(client, parentId, actor, clientForGdr)\n}\n","import type {SanityDocument} from '@sanity/types'\n\nimport type {Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {EffectHistoryEntry, EffectsContextEntry, PendingEffect} from '../types/effects.ts'\nimport type {TaskStatus} from '../types/enums.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {StageEntry, TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {cascadeAutoTransitions, primeInitialStage, propagateToAncestors} from './cascade.ts'\nimport {type EngineContext, findStage} from './context.ts'\n\n// Internal — commits\n\nexport interface MutableInstance {\n currentStageId: StageId\n state: ResolvedStateSlot[]\n stages: StageEntry[]\n pendingEffects: PendingEffect[]\n effectHistory: EffectHistoryEntry[]\n effectsContext: EffectsContextEntry[]\n history: HistoryEntry[]\n lastChangedAt: string\n completedAt?: string\n /**\n * Net-new child workflow instances queued by `spawnChildren` during\n * this mutation. Drained at `persist` time into a single same-resource\n * transaction so the parent's `spawnedInstances` patch and the child\n * `create`s commit atomically.\n */\n pendingCreates: WorkflowInstance[]\n}\n\nexport function startMutation(instance: WorkflowInstance): MutableInstance {\n return {\n currentStageId: instance.currentStageId,\n // Deep-ish copy. Per-scope state slot arrays need their own copies\n // so ops can mutate without leaking into the source.\n state: (instance.state ?? []).map((s) => ({...s})),\n stages: instance.stages.map((s) => ({\n ...s,\n state: (s.state ?? []).map((slot) => ({...slot})),\n tasks: s.tasks.map((t) => ({\n ...t,\n ...(t.state !== undefined ? {state: t.state.map((slot) => ({...slot}))} : {}),\n })),\n })),\n pendingEffects: [...instance.pendingEffects],\n effectHistory: [...instance.effectHistory],\n effectsContext: [...instance.effectsContext],\n history: [...instance.history],\n lastChangedAt: instance.lastChangedAt,\n ...(instance.completedAt !== undefined ? {completedAt: instance.completedAt} : {}),\n pendingCreates: [],\n }\n}\n\n/** Build a `taskStatusChanged` history entry, stamping a fresh `_key`\n * and an `at` timestamp (defaulting to now). */\nexport function taskStatusChangedEntry(args: {\n stageId: StageId\n taskId: TaskId\n from: TaskStatus\n to: TaskStatus\n actor?: Actor\n at?: string\n}): HistoryEntry {\n return {\n _key: randomKey(),\n _type: 'workflow.history.taskStatusChanged',\n at: args.at ?? new Date().toISOString(),\n stageId: args.stageId,\n taskId: args.taskId,\n from: args.from,\n to: args.to,\n ...(args.actor !== undefined ? {actor: args.actor} : {}),\n }\n}\n\n/**\n * Build the three-entry history sequence for a stage move:\n * `stageExited` → `transitionFired` → `stageEntered`. All three share\n * `at`, the (optional) `transitionId`, `actor`, and the `via`/`reason`\n * discriminators that distinguish filtered transitions from admin\n * overrides.\n */\nexport function stageTransitionHistory(args: {\n fromStageId: StageId\n toStageId: StageId\n at: string\n transitionId?: string\n actor?: Actor\n via?: 'transition' | 'setStage'\n reason?: string\n}): HistoryEntry[] {\n const {fromStageId, toStageId, at, transitionId, actor, via, reason} = args\n const shared = {\n at,\n ...(transitionId !== undefined ? {transitionId} : {}),\n ...(actor !== undefined ? {actor} : {}),\n ...(via !== undefined ? {via} : {}),\n ...(reason !== undefined ? {reason} : {}),\n }\n return [\n {\n _key: randomKey(),\n _type: 'workflow.history.stageExited',\n stageId: fromStageId,\n toStageId,\n ...shared,\n },\n {\n _key: randomKey(),\n _type: 'workflow.history.transitionFired',\n fromStageId,\n toStageId,\n ...shared,\n },\n {\n _key: randomKey(),\n _type: 'workflow.history.stageEntered',\n stageId: toStageId,\n fromStageId,\n ...shared,\n },\n ]\n}\n\nexport async function persist(\n ctx: EngineContext,\n mutation: MutableInstance,\n): Promise<SanityDocument> {\n // Patch (not createOrReplace): patches require the doc to exist, so\n // a deleted instance mid-cascade fails fast instead of getting\n // silently resurrected. `ifRevisionId` adds optimistic concurrency —\n // if another writer raced us, the patch errors instead of clobbering.\n const set: Record<string, unknown> = {\n currentStageId: mutation.currentStageId,\n state: mutation.state,\n stages: mutation.stages,\n pendingEffects: mutation.pendingEffects,\n effectHistory: mutation.effectHistory,\n effectsContext: mutation.effectsContext,\n history: mutation.history,\n lastChangedAt: new Date().toISOString(),\n }\n if (mutation.completedAt !== undefined) set.completedAt = mutation.completedAt\n\n const pendingCreates = mutation.pendingCreates\n if (pendingCreates.length === 0) {\n return ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit()\n }\n\n // Multi-doc same-resource write: bundle the N child creates with the\n // parent's patch in one Sanity transaction. Children inherit the\n // parent's `workflowResource` so they are always provably same-resource.\n const tx = ctx.client.transaction()\n for (const body of pendingCreates) tx.create(body)\n tx.patch(ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev))\n await tx.commit()\n mutation.pendingCreates = []\n\n // Children are now durably in the lake with the parent's\n // `spawnedInstances` recorded atomically. Prime each child's initial\n // stage, cascade to whatever stage it lands on (possibly terminal),\n // then propagate up — a child that reached terminal needs to\n // re-evaluate its parent's spawn-completion gate. Pre-refactor,\n // `spawnChildren` ran per-child create+prime+cascade synchronously\n // and `activateTask`'s in-memory `checkSpawnCompletion` flipped the\n // parent's task done in the same mutation; deferring creates into\n // the transaction means we restore that effect via explicit\n // propagation here.\n const actorForPriming: Actor | undefined = undefined\n for (const body of pendingCreates) {\n await primeInitialStage(ctx.client, body._id, actorForPriming, ctx.clientForGdr)\n await cascadeAutoTransitions(ctx.client, body._id, actorForPriming, ctx.clientForGdr)\n await propagateToAncestors(ctx.client, body._id, actorForPriming, ctx.clientForGdr)\n }\n\n // Reload the parent so callers see the post-commit `_rev`. Persist's\n // historical return shape is the patched parent doc; preserve that.\n const reloaded = await ctx.client.getDocument<SanityDocument>(ctx.instance._id)\n if (!reloaded) {\n throw new Error(`Instance ${ctx.instance._id} disappeared after transaction commit`)\n }\n return reloaded\n}\n\n// Helpers for working with the per-stage task entries.\n//\n// \"Current\" means the StageEntry whose `exitedAt` is undefined AND whose\n// id matches `currentStageId`. On loop-backs (entering a stage that was\n// visited before), there are multiple entries with the same id — the\n// prior ones have `exitedAt` set, the current one does not.\n\n/** The open (un-exited) {@link StageEntry} matching `currentStageId`, or\n * undefined. Both {@link MutableInstance} and {@link WorkflowInstance}\n * share the `stages` + `currentStageId` shape this reads. */\nexport function findOpenStageEntry(host: {\n stages: StageEntry[]\n currentStageId: StageId\n}): StageEntry | undefined {\n return host.stages.find((s) => s.id === host.currentStageId && s.exitedAt === undefined)\n}\n\nfunction currentStageEntry(mutation: MutableInstance): StageEntry {\n const entry = findOpenStageEntry(mutation)\n if (entry === undefined) {\n throw new Error(\n `Mutation invariant broken: no current (un-exited) StageEntry for currentStageId \"${mutation.currentStageId}\"`,\n )\n }\n return entry\n}\n\nexport function currentTasks(mutation: MutableInstance): TaskEntry[] {\n return currentStageEntry(mutation).tasks\n}\n\n/** Find a task definition on the instance's current stage, throwing a\n * consistent error when it isn't declared there. */\nexport function findTaskInCurrentStage(\n ctx: EngineContext,\n taskId: TaskId,\n): {stage: Stage; task: Task} {\n const stage = findStage(ctx.definition, ctx.instance.currentStageId)\n const task = (stage.tasks ?? []).find((t) => t.id === taskId)\n if (task === undefined) {\n throw new Error(\n `Task \"${taskId}\" not found in current stage \"${stage.id}\" of ${ctx.definition.workflowId}`,\n )\n }\n return {stage, task}\n}\n\n/** The mutation copy's entry for `taskId`. Throws if it vanished — the\n * live instance and its mutation copy must agree on task identity. */\nexport function requireMutationTaskEntry(mutation: MutableInstance, taskId: TaskId): TaskEntry {\n const mutEntry = currentTasks(mutation).find((t) => t.id === taskId)\n if (mutEntry === undefined) {\n throw new Error(`Task \"${taskId}\" disappeared from mutation copy — invariant broken`)\n }\n return mutEntry\n}\n\nfunction findCurrentStageEntry(instance: WorkflowInstance): StageEntry | undefined {\n return findOpenStageEntry(instance)\n}\n\nexport function findCurrentTasks(instance: WorkflowInstance): TaskEntry[] {\n return findCurrentStageEntry(instance)?.tasks ?? []\n}\n","import {resolveBindings} from '../core/bindings.ts'\nimport type {GlobalDocumentReference} from '../core/refs.ts'\nimport type {Effect} from '../define/schema.ts'\nimport {effectsContextEntry} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectHistoryEntry, EffectOrigin, PendingEffect} from '../types/effects.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {type EngineContext, loadContext} from './context.ts'\nimport {type MutableInstance, persist, startMutation} from './mutation.ts'\nimport type {CompleteEffectResult, EngineCallOptions} from './results.ts'\n\n/**\n * Mark a queued effect as completed. Drains it from `pendingEffects`,\n * appends an `EffectHistoryEntry`, and (if `outputs` are supplied)\n * upserts those into `effectsContext` by key — making them available to\n * downstream effect bindings.\n *\n * This is the only path that mutates `effectsContext` after start.\n */\nexport async function completeEffect(args: {\n client: WorkflowClient\n instanceId: string\n effectKey: string\n status: 'done' | 'failed'\n outputs?: Record<string, string | number | boolean | GlobalDocumentReference>\n detail?: string\n error?: {message: string; stack?: string}\n durationMs?: number\n options?: EngineCallOptions\n}): Promise<CompleteEffectResult> {\n const {client, instanceId, effectKey, status, outputs, detail, error, durationMs, options} = args\n const ctx = await loadContext(client, instanceId)\n return commitCompleteEffect(\n ctx,\n effectKey,\n status,\n outputs,\n detail,\n error,\n durationMs,\n options?.actor,\n )\n}\n\n/** Build the {@link EffectHistoryEntry} recorded when a queued effect\n * completes, carrying the pending entry's identity forward and stamping\n * the run outcome. A supplied `actor` overrides the pending entry's. */\nfunction buildEffectHistoryEntry(\n pending: PendingEffect,\n outcome: {\n status: 'done' | 'failed'\n ranAt: string\n actor: Actor | undefined\n detail: string | undefined\n error: {message: string; stack?: string} | undefined\n durationMs: number | undefined\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined\n },\n): EffectHistoryEntry {\n const {status, ranAt, actor, detail, error, durationMs, outputs} = outcome\n return {\n _key: pending._key,\n effectId: pending.effectId,\n ...(pending.title !== undefined ? {title: pending.title} : {}),\n ...(pending.description !== undefined ? {description: pending.description} : {}),\n params: pending.params,\n origin: pending.origin,\n ...(actor !== undefined ? {actor} : pending.actor !== undefined ? {actor: pending.actor} : {}),\n ranAt,\n ...(durationMs !== undefined ? {durationMs} : {}),\n status,\n ...(detail !== undefined ? {detail} : {}),\n ...(error !== undefined ? {error} : {}),\n ...(outputs !== undefined ? {outputs} : {}),\n }\n}\n\n/** Upsert completed-effect outputs into the mutation's `effectsContext`,\n * replacing any existing entry with the same id. */\nfunction upsertEffectsContext(\n mutation: MutableInstance,\n outputs: Record<string, string | number | boolean | GlobalDocumentReference>,\n): void {\n for (const [id, value] of Object.entries(outputs)) {\n const existingIndex = mutation.effectsContext.findIndex((e) => e.id === id)\n const entry = effectsContextEntry(id, value)\n if (existingIndex >= 0) mutation.effectsContext[existingIndex] = entry\n else mutation.effectsContext.push(entry)\n }\n}\n\nasync function commitCompleteEffect(\n ctx: EngineContext,\n effectKey: string,\n status: 'done' | 'failed',\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined,\n detail: string | undefined,\n error: {message: string; stack?: string} | undefined,\n durationMs: number | undefined,\n actor: Actor | undefined,\n): Promise<CompleteEffectResult> {\n const pending = ctx.instance.pendingEffects.find((e) => e._key === effectKey)\n if (pending === undefined) {\n throw new Error(`Pending effect \"${effectKey}\" not found on instance ${ctx.instance._id}`)\n }\n\n const mutation = startMutation(ctx.instance)\n mutation.pendingEffects = mutation.pendingEffects.filter((e) => e._key !== effectKey)\n\n const ranAt = new Date().toISOString()\n mutation.effectHistory.push(\n buildEffectHistoryEntry(pending, {status, ranAt, actor, detail, error, durationMs, outputs}),\n )\n\n if (status === 'done' && outputs !== undefined) {\n upsertEffectsContext(mutation, outputs)\n }\n\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.effectCompleted',\n at: ranAt,\n effectKey,\n effectId: pending.effectId,\n status,\n ...(outputs !== undefined ? {outputs} : {}),\n ...(detail !== undefined ? {detail} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n\n await persist(ctx, mutation)\n return {effectKey, status}\n}\n\n/** Materialise one queued effect: its {@link PendingEffect} envelope and\n * the matching `effectQueued` history entry, sharing a freshly-minted\n * `_key`. Caller pushes each into the right array. */\nexport function buildQueuedEffect(\n effect: Effect,\n origin: EffectOrigin,\n params: Record<string, unknown>,\n actor: Actor | undefined,\n): {pending: PendingEffect; history: HistoryEntry} {\n const key = randomKey()\n const pending: PendingEffect = {\n _key: key,\n _type: 'workflow.pendingEffect',\n effectId: effect.id,\n ...(effect.title !== undefined ? {title: effect.title} : {}),\n ...(effect.description !== undefined ? {description: effect.description} : {}),\n ...(effect.bindings !== undefined ? {bindings: effect.bindings} : {}),\n params,\n origin,\n ...(actor !== undefined ? {actor} : {}),\n queuedAt: new Date().toISOString(),\n }\n const history: HistoryEntry = {\n _key: randomKey(),\n _type: 'workflow.history.effectQueued',\n at: new Date().toISOString(),\n effectKey: key,\n effectId: effect.id,\n origin,\n }\n return {pending, history}\n}\n\nexport async function queueEffects(\n ctx: EngineContext,\n mutation: MutableInstance,\n effects: Effect[] | undefined,\n origin: EffectOrigin,\n actor: Actor | undefined,\n callerParams?: Record<string, unknown>,\n): Promise<void> {\n if (!effects) return\n // Effect bindings see the FRESHEST state — read from the in-progress\n // mutation so an op that ran earlier in the same action commit is\n // visible to a bound effect on the same action.\n const liveInstance: WorkflowInstance = {\n ...ctx.instance,\n state: mutation.state,\n stages: mutation.stages,\n effectsContext: mutation.effectsContext,\n }\n for (const effect of effects) {\n const params = await resolveBindings({\n bindings: effect.bindings,\n staticInput: effect.input,\n instance: liveInstance,\n ...(callerParams !== undefined ? {params: callerParams} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n const {pending, history} = buildQueuedEffect(effect, origin, params, actor)\n mutation.pendingEffects.push(pending)\n mutation.history.push(history)\n }\n}\n","import type {Actor} from '../types/actor.ts'\nimport type {StateScope, TaskStatus} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\n\n// Public API\n\nexport interface EngineCallOptions {\n actor?: Actor\n}\n\nexport interface TransitionResult {\n fired: boolean\n fromStageId?: StageId\n toStageId?: StageId\n transitionId?: string\n}\n\nexport interface InvokeResult {\n invoked: boolean\n taskId: TaskId\n}\n\nexport interface OpAppliedSummary {\n opType: string\n target?: {scope: StateScope; slotId: string}\n resolved?: Record<string, unknown>\n}\n\nexport interface ActionResult {\n fired: boolean\n taskId: TaskId\n action: string\n newStatus?: TaskStatus\n /** Deterministic engine primitives that ran inline during the commit. */\n ranOps?: OpAppliedSummary[]\n}\n\n/**\n * Thrown when caller-supplied params don't satisfy the action's\n * declared `params[]` — missing required fields or wrong primitive\n * type. The action does not commit; the engine has not mutated state.\n */\nexport class ActionParamsInvalidError extends Error {\n readonly action: string\n readonly taskId: TaskId\n readonly issues: {paramId: string; reason: string}[]\n constructor(args: {action: string; taskId: TaskId; issues: {paramId: string; reason: string}[]}) {\n const lines = args.issues.map((i) => ` - ${i.paramId}: ${i.reason}`).join('\\n')\n super(`Action \"${args.action}\" on task \"${args.taskId}\" rejected: invalid params\\n${lines}`)\n this.name = 'ActionParamsInvalidError'\n this.action = args.action\n this.taskId = args.taskId\n this.issues = args.issues\n }\n}\n\nexport interface CompleteEffectResult {\n effectKey: string\n status: 'done' | 'failed'\n}\n","import {getPath} from '../core/path.ts'\nimport {validateSlotAppendItem, validateSlotValue} from '../core/slot-validation.ts'\nimport type {Action, ActionParam, Op, OpPredicate, Source} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {StateScope} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {findOpenStageEntry, type MutableInstance} from './mutation.ts'\nimport {ActionParamsInvalidError, type OpAppliedSummary} from './results.ts'\n\n// Action commit: param validation + op runner.\n\nexport function validateActionParams(\n action: Action,\n taskId: TaskId,\n callerParams: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const declared = action.params ?? []\n const params = callerParams ?? {}\n const issues: {paramId: string; reason: string}[] = []\n\n for (const decl of declared) {\n const value = params[decl.id]\n const present = decl.id in params && value !== undefined && value !== null\n if (decl.required === true && !present) {\n issues.push({paramId: decl.id, reason: 'required but missing'})\n continue\n }\n if (!present) continue\n const typeOk = checkParamType(value, decl)\n if (!typeOk) {\n issues.push({\n paramId: decl.id,\n reason: `expected paramType=${decl.paramType}, got ${typeof value}`,\n })\n }\n }\n if (issues.length > 0) {\n throw new ActionParamsInvalidError({action: action.id, taskId, issues})\n }\n return params\n}\n\n/** True when `value` is a non-null object carrying a string-typed `field`. */\nfunction hasStringField(value: unknown, field: string): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n field in value &&\n typeof (value as Record<string, unknown>)[field] === 'string'\n )\n}\n\nfunction checkParamType(value: unknown, decl: ActionParam): boolean {\n switch (decl.paramType) {\n case 'string':\n case 'url':\n case 'dateTime':\n return typeof value === 'string'\n case 'number':\n return typeof value === 'number' && Number.isFinite(value)\n case 'boolean':\n return typeof value === 'boolean'\n case 'actor':\n return hasStringField(value, 'kind')\n case 'doc.ref':\n return hasStringField(value, 'id')\n case 'doc.refs':\n return (\n Array.isArray(value) &&\n value.every((v) => checkParamType(v, {...decl, paramType: 'doc.ref'}))\n )\n case 'json':\n return true\n default:\n return false\n }\n}\n\ninterface RunOpsArgs {\n ops: Op[] | undefined\n mutation: MutableInstance\n stageId: StageId\n taskId: TaskId\n actionName: string\n params: Record<string, unknown>\n actor: Actor | undefined\n}\n\nexport async function runActionOps(args: RunOpsArgs): Promise<OpAppliedSummary[]> {\n const {ops, mutation, stageId, taskId, actionName, params, actor} = args\n if (ops === undefined || ops.length === 0) return []\n const summaries: OpAppliedSummary[] = []\n for (const op of ops) {\n const summary = applyOp(op, {mutation, stageId, taskId, params, actor})\n summaries.push(summary)\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.opApplied',\n at: new Date().toISOString(),\n stageId,\n taskId,\n actionId: actionName,\n opType: summary.opType,\n ...(summary.target !== undefined ? {target: summary.target} : {}),\n ...(summary.resolved !== undefined ? {resolved: summary.resolved} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n }\n return summaries\n}\n\ninterface OpContext {\n mutation: MutableInstance\n stageId: StageId\n taskId: TaskId\n params: Record<string, unknown>\n actor: Actor | undefined\n}\n\nfunction applyOp(op: Op, ctx: OpContext): OpAppliedSummary {\n switch (op.type) {\n case 'workflow.op.state.set':\n return applyStateSet(op, ctx)\n case 'workflow.op.state.append':\n return applyStateAppend(op, ctx)\n case 'workflow.op.state.updateWhere':\n return applyStateUpdateWhere(op, ctx)\n case 'workflow.op.state.removeWhere':\n return applyStateRemoveWhere(op, ctx)\n case 'workflow.op.status.set':\n return applyStatusSet(op, ctx)\n }\n}\n\nfunction applyStateSet(\n op: Extract<Op, {type: 'workflow.op.state.set'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const value = resolveOpSource(op.value, ctx)\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ true)\n if (slot !== undefined) {\n // Validate the resolved value against the slot's declared shape.\n // Wrong-shape writes throw `SlotValueShapeError` — the engine\n // aborts the action before persisting.\n validateSlotValue({slotType: slot._type, slotId: slot.id, value})\n slot.value = value as never\n }\n return {opType: op.type, target: op.target, resolved: {value}}\n}\n\nfunction applyStateAppend(\n op: Extract<Op, {type: 'workflow.op.state.append'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const item = resolveOpSource(op.item, ctx)\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ true)\n if (slot !== undefined) {\n validateSlotAppendItem({slotType: slot._type, slotId: slot.id, item})\n const current = Array.isArray(slot.value) ? slot.value : []\n slot.value = [...current, withRowKey(item)] as never\n }\n return {opType: op.type, target: op.target, resolved: {item}}\n}\n\n/** Stamp a `_key` onto a plain-object row that lacks one; scalars and\n * arrays pass through unchanged. */\nfunction withRowKey(item: unknown): unknown {\n if (typeof item === 'object' && item !== null && !Array.isArray(item) && !('_key' in item)) {\n return {_key: randomKey(), ...(item as Record<string, unknown>)}\n }\n return item\n}\n\nfunction applyStateUpdateWhere(\n op: Extract<Op, {type: 'workflow.op.state.updateWhere'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ false)\n const resolvedMerge: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(op.merge)) {\n resolvedMerge[k] = resolveOpSource(v, ctx)\n }\n if (slot !== undefined && Array.isArray(slot.value)) {\n slot.value = (slot.value as Record<string, unknown>[]).map((row) =>\n evalOpPredicate(op.where, row, ctx) ? {...row, ...resolvedMerge} : row,\n ) as never\n }\n return {opType: op.type, target: op.target, resolved: {merge: resolvedMerge}}\n}\n\nfunction applyStateRemoveWhere(\n op: Extract<Op, {type: 'workflow.op.state.removeWhere'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ false)\n if (slot !== undefined && Array.isArray(slot.value)) {\n slot.value = (slot.value as Record<string, unknown>[]).filter(\n (row) => !evalOpPredicate(op.where, row, ctx),\n ) as never\n }\n return {opType: op.type, target: op.target}\n}\n\nfunction applyStatusSet(\n op: Extract<Op, {type: 'workflow.op.status.set'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const entry = findOpenStageEntry(ctx.mutation)?.tasks.find((t) => t.id === op.taskId)\n if (entry !== undefined) entry.status = op.status\n return {opType: op.type, resolved: {taskId: op.taskId, status: op.status}}\n}\n\nfunction locateSlot(\n ctx: OpContext,\n target: {scope: StateScope; slotId: string},\n createIfMissing: boolean,\n): ResolvedStateSlot | undefined {\n let host: ResolvedStateSlot[] | undefined\n if (target.scope === 'workflow') {\n host = ctx.mutation.state\n } else if (target.scope === 'stage') {\n host = findOpenStageEntry(ctx.mutation)?.state\n } else {\n const task = findOpenStageEntry(ctx.mutation)?.tasks.find((t) => t.id === ctx.taskId)\n host = task?.state\n if (host === undefined && task !== undefined && createIfMissing) {\n task.state = []\n host = task.state\n }\n }\n if (host === undefined) {\n throw new Error(\n `Op target scope \"${target.scope}\" has no state container on this instance — declare the slot or check stage/task identity`,\n )\n }\n let slot = host.find((s) => s.id === target.slotId)\n if (slot === undefined && createIfMissing) {\n // No declared slot — synthesize a `value.string`-shaped entry as a\n // conservative default. Authors are expected to declare slots on\n // the definition; this fallback exists so ad-hoc tests don't have\n // to.\n slot = {\n _key: randomKey(),\n _type: 'workflow.state.value.string',\n id: target.slotId,\n value: null,\n } as ResolvedStateSlot\n host.push(slot)\n }\n return slot\n}\n\nfunction resolveOpSource(src: Source, ctx: OpContext): unknown {\n switch (src.source) {\n case 'literal':\n return src.value\n case 'param':\n return ctx.params[src.paramId]\n case 'actor':\n return ctx.actor\n case 'now':\n return new Date().toISOString()\n case 'self':\n return undefined // Not applicable inside ops; reserved for higher-level binding.\n case 'stageId':\n return ctx.stageId\n case 'stateRead': {\n const value = readSlotFromMutation(ctx, src.scope, src.slotId)\n return src.path !== undefined ? getPath(value, src.path) : value\n }\n case 'effectOutput': {\n const entry = ctx.mutation.effectsContext.find((e) => e.id === src.contextId)\n if (entry === undefined) return null\n const v = src.path !== undefined ? getPath(entry.value, src.path) : entry.value\n return v === undefined ? null : v\n }\n case 'object': {\n const out: Record<string, unknown> = {}\n for (const [field, fieldSrc] of Object.entries(src.fields)) {\n out[field] = resolveOpSource(fieldSrc, ctx)\n }\n return out\n }\n }\n}\n\nfunction slotValue(slots: ResolvedStateSlot[] | undefined, slotId: string): unknown {\n return slots?.find((s) => s.id === slotId)?.value\n}\n\nfunction readSlotFromMutation(ctx: OpContext, scope: StateScope, slotId: string): unknown {\n if (scope === 'workflow') return slotValue(ctx.mutation.state, slotId)\n const stageEntry = findOpenStageEntry(ctx.mutation)\n if (scope === 'stage') return slotValue(stageEntry?.state, slotId)\n const task = stageEntry?.tasks.find((t) => t.id === ctx.taskId)\n return slotValue(task?.state, slotId)\n}\n\nfunction evalOpPredicate(p: OpPredicate, row: Record<string, unknown>, ctx: OpContext): boolean {\n if ('all' in p) return p.all.every((sub) => evalOpPredicate(sub, row, ctx))\n if ('any' in p) return p.any.some((sub) => evalOpPredicate(sub, row, ctx))\n const target = resolveOpSource(p.equals, ctx)\n return row[p.field] === target\n}\n","import type {Action, Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {TaskStatus} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport {ctxEvaluateFilter, type EngineContext, loadContext} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {\n findCurrentTasks,\n findTaskInCurrentStage,\n type MutableInstance,\n persist,\n requireMutationTaskEntry,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport {runActionOps, validateActionParams} from './ops.ts'\nimport type {ActionResult, EngineCallOptions} from './results.ts'\n\n/**\n * Fire an action against an active task. The runtime applies the\n * declared `setStatus` flip and queues the action's effects.\n */\nexport async function fireAction(args: {\n client: WorkflowClient\n instanceId: string\n taskId: TaskId\n action: string\n /** Caller-supplied action params (validated against `Action.params[]`). */\n params?: Record<string, unknown>\n options?: EngineCallOptions\n}): Promise<ActionResult> {\n const {client, instanceId, taskId, action, params, options} = args\n const ctx = await loadContext(client, instanceId)\n return commitAction(ctx, taskId, action, params, options?.actor)\n}\n\n/**\n * Resolve and gate an action fire: locate the task + action in the\n * current stage, check the action filter, require the live task entry to\n * be `active`, and validate caller params. Throws on any failure so no\n * mutation begins. Returns the pieces the commit needs.\n */\nasync function resolveActionCommit(\n ctx: EngineContext,\n taskId: TaskId,\n actionName: string,\n callerParams: Record<string, unknown> | undefined,\n): Promise<{stage: Stage; task: Task; action: Action; params: Record<string, unknown>}> {\n const {stage, task} = findTaskInCurrentStage(ctx, taskId)\n const action = (task.actions ?? []).find((a) => a.id === actionName)\n if (action === undefined) {\n throw new Error(`Action \"${actionName}\" not declared on task \"${taskId}\"`)\n }\n\n const filterOk = await ctxEvaluateFilter(ctx, action.filter)\n if (!filterOk) {\n throw new Error(`Action \"${actionName}\" filter rejected on task \"${taskId}\"`)\n }\n\n const entry = findCurrentTasks(ctx.instance).find((t) => t.id === taskId)\n if (entry === undefined || entry.status !== 'active') {\n throw new Error(\n `Task \"${taskId}\" must be active to fire action \"${actionName}\"; status is ${entry?.status ?? 'missing'}`,\n )\n }\n\n // Validate caller params against `action.params[]` before any\n // mutation. The action does not commit if validation fails.\n const params = validateActionParams(action, taskId, callerParams)\n return {stage, task, action, params}\n}\n\n/** Apply an action's declared `setStatus` to the live task entry,\n * recording the status change. No-op (returns undefined) when the\n * action omits `setStatus` — e.g. claim/assign actions that keep the\n * task active. Returns the new status when applied. */\nfunction applyActionSetStatus(\n action: Action,\n mutation: MutableInstance,\n mutEntry: TaskEntry,\n stageId: StageId,\n taskId: TaskId,\n actor: Actor | undefined,\n): TaskStatus | undefined {\n if (action.setStatus === undefined) return undefined\n const initialStatus = mutEntry.status\n const newStatus = action.setStatus\n mutEntry.status = newStatus\n mutEntry.completedAt = new Date().toISOString()\n if (actor) mutEntry.completedBy = actor.id\n mutation.history.push(\n taskStatusChangedEntry({\n stageId,\n taskId,\n from: initialStatus,\n to: newStatus,\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n return newStatus\n}\n\nasync function commitAction(\n ctx: EngineContext,\n taskId: TaskId,\n actionName: string,\n callerParams: Record<string, unknown> | undefined,\n actor: Actor | undefined,\n): Promise<ActionResult> {\n const {stage, task, action, params} = await resolveActionCommit(\n ctx,\n taskId,\n actionName,\n callerParams,\n )\n\n const mutation = startMutation(ctx.instance)\n const mutEntry = requireMutationTaskEntry(mutation, taskId)\n\n // 1. Action commit: record the actionFired entry first so ops/effects\n // have a consistent audit trail order.\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.actionFired',\n at: new Date().toISOString(),\n stageId: stage.id,\n taskId,\n actionId: actionName,\n ...(actor !== undefined ? {actor} : {}),\n })\n\n // 2. Run ops inline. Sources resolve against the in-progress\n // mutation so a later op can read a value an earlier op wrote.\n // Ops can flip task status via `workflow.op.status.set`.\n const ranOps = await runActionOps({\n ops: action.ops,\n mutation,\n stageId: stage.id,\n taskId,\n actionName,\n params,\n actor,\n })\n\n // 3. Apply the action's declared `setStatus`, if any.\n const newStatus = applyActionSetStatus(action, mutation, mutEntry, stage.id, taskId, actor)\n\n // 4. Queue external effects with resolved Sources (caller params +\n // actor pinned for this commit).\n await queueEffects(\n ctx,\n mutation,\n action.effects,\n {\n kind: 'action',\n id: `${task.id}:${actionName}`,\n },\n actor,\n params,\n )\n\n await persist(ctx, mutation)\n return {\n fired: true,\n taskId,\n action: actionName,\n ...(newStatus !== undefined ? {newStatus} : {}),\n ...(ranOps.length > 0 ? {ranOps} : {}),\n }\n}\n","/**\n * Permissions — GROQ-filter-based grant evaluation.\n *\n * Sanity ACLs come back as `Grant[]`. Each grant has a GROQ `filter`\n * and a list of `permissions` it confers. Whether a permission is\n * allowed on a given document is \"does any grant whose filter matches\n * the document carry that permission?\". Most-permissive wins; multiple\n * grants compose.\n *\n * Filters are evaluated with groq-js (already a dependency for transition\n * filter evaluation) so the engine doesn't ship a second predicate engine.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport type {Grant} from './types/authorization.ts'\nimport type {DocumentValuePermission} from './types/enums.ts'\n\n// Parsed-filter cache, keyed by the filter string. AST is cheap to\n// reuse; the evaluation against a document is what we want to keep\n// uncached because the document changes much more often than the filter.\nconst parsedFilters = new Map<string, ReturnType<typeof parse>>()\n\n/**\n * Evaluate a grant's GROQ filter against a single document with the\n * supplied identity. Returns true iff the document survives the filter.\n *\n * The implementation parses `*[<filter>]` once per filter string,\n * evaluates against a singleton dataset, and asks the result for its\n * length — `length === 1` means the doc passed.\n */\nexport async function matchesFilter(args: {\n document: {_id?: string; _type?: string; [key: string]: unknown}\n filter: string\n userId?: string\n}): Promise<boolean> {\n const {document, filter, userId} = args\n if (!parsedFilters.has(filter)) {\n parsedFilters.set(filter, parse(`*[${filter}]`))\n }\n const ast = parsedFilters.get(filter)!\n const result = await evaluate(ast, {\n dataset: [document],\n ...(userId !== undefined ? {identity: userId} : {}),\n })\n const data = await result.get()\n return Array.isArray(data) && data.length === 1\n}\n\n/**\n * Does the supplied `grants` set grant `permission` on `document` for\n * the given user? Walks each grant; a grant counts iff its filter\n * matches AND it lists the permission. Most-permissive wins.\n */\nexport async function grantsPermissionOn(args: {\n document?: {_id?: string; _type?: string; [key: string]: unknown}\n grants: Grant[]\n permission: DocumentValuePermission\n userId?: string\n}): Promise<boolean> {\n const {document, grants, permission, userId} = args\n if (!document || grants.length === 0) return false\n\n for (const grant of grants) {\n if (!grant.permissions.includes(permission)) continue\n if (\n await matchesFilter({\n document,\n filter: grant.filter,\n ...(userId !== undefined ? {userId} : {}),\n })\n ) {\n return true\n }\n }\n return false\n}\n\n/**\n * Convenience: fetch the grants for a given resource via the supplied\n * client:\n *\n * GET <resourcePath> → Grant[]\n *\n * `resourcePath` is caller-supplied so the same helper works for\n * project ACLs (`/projects/<id>/datasets/<dataset>/acl`) and for a\n * dedicated workflow-collaboration resource. The client must support\n * the `request<T>({url})` method `@sanity/client` exposes.\n */\nexport async function fetchGrants(args: {\n client: {request: <T>(opts: {url: string; signal?: AbortSignal}) => Promise<T>}\n resourcePath: string\n signal?: AbortSignal\n}): Promise<Grant[]> {\n const {client, resourcePath, signal} = args\n return client.request<Grant[]>({url: resourcePath, ...(signal ? {signal} : {})})\n}\n","/**\n * Access state — the cohesive (actor + grants) pair the engine\n * relies on for every authorization decision: one provider, one\n * cached resolution.\n *\n * Resolution strategy:\n *\n * 1. **Override.** If the caller supplies an `access` object on the\n * verb (or the bench's `createBench({ access })`), it wins — no\n * network calls. This is the only path that fires for the test\n * bench, whose `TestClient` has no token-bearing `request` method.\n * 2. **Token.** Otherwise the engine resolves both halves from the\n * supplied `@sanity/client`:\n * - `actor` ← `client.request({ url: \"/users/me\" })`\n * - `grants` ← `client.request({ url: grantsFromPath })`\n * Run in parallel; cached per-client (and per-path for grants) via\n * WeakMap so concurrent verb calls share one fetch.\n * 3. **Refusal.** If the client can't make HTTP requests (`request`\n * undefined) and no override was supplied, the engine throws a\n * clear error pointing at the bench / explicit override.\n *\n * Grants-fetch failure degrades open (gate is skipped, real Sanity\n * write boundary still enforces). Actor-fetch failure is fatal — the\n * engine refuses to stamp history without an identity.\n */\n\nimport {fetchGrants} from './permissions.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {Grant} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\n\n/**\n * Sanity's `/users/me` response shape — subset of `@sanity/types`'s\n * `CurrentUser`. Declared locally so the engine doesn't take a\n * runtime dep on `@sanity/types` for a single type.\n */\ninterface SanityCurrentUser {\n id: string\n name?: string\n email?: string\n /** @deprecated singular `role` on legacy responses */\n role?: string\n roles?: {name: string; title?: string; description?: string}[]\n}\n\n/**\n * The engine's view of \"who am I, what can I do?\". `actor` is who\n * the engine stamps onto history / `completedBy` / `Source.actor`.\n * `grants` (when present) gates `permission-denied`; when absent the\n * gate is skipped and the real Sanity write boundary takes over.\n *\n * This is the RESOLVED shape — `actor` is guaranteed. For the\n * partial-override shape callers pass on verb args, see\n * `WorkflowAccessOverride`.\n */\nexport interface WorkflowAccess {\n actor: Actor\n grants?: Grant[]\n}\n\n/**\n * Partial override accepted by every public verb's `access?:`\n * argument. Any field present wins; missing halves token-resolve.\n *\n * `{ actor, grants }` — bench's all-access default; both halves\n * injected, no token round-trip.\n * `{ actor }` — \"act as another user\"; grants come from\n * `grantsFromPath` (or the gate is skipped).\n * `{ grants }` — \"preview with restricted permissions\"; actor\n * comes from `/users/me`.\n * omitted entirely — both halves token-resolved.\n */\nexport type WorkflowAccessOverride = Partial<WorkflowAccess>\n\nexport interface ResolveAccessArgs {\n /**\n * Partial override. Any field set here wins outright; any field\n * left unset falls through to token resolution.\n *\n * - `override.actor` set + `override.grants` set → returned as-is.\n * - `override.actor` set + `override.grants` unset → actor from\n * override; grants fetched from `grantsFromPath` (or undefined).\n * - `override.actor` unset + `override.grants` set → actor from\n * `/users/me`; grants from override.\n * - `override` undefined entirely → both halves fetched.\n *\n * The test bench passes a fully-populated `{ actor, grants }` so\n * the underlying TestClient (no `request` method) never hits the\n * token path. Admin/preview tooling passes one or the other.\n */\n override?: {actor?: Actor; grants?: Grant[]}\n /**\n * Where the engine should fetch grants from the supplied client\n * when `override.grants` isn't given, e.g. a Canvas resource at\n * `/canvases/<resourceId>/acl` or a dataset at\n * `/projects/<id>/datasets/<ds>/acl`.\n */\n grantsFromPath?: string\n}\n\n// Actor cache is per-client. /users/me doesn't vary by path; one\n// fetch per client lifetime suffices.\nconst actorCache = new WeakMap<object, Promise<Actor | undefined>>()\n\n// Grants cache is per-(client, path). Multiple consumers in one\n// process can share the same client across different resources.\nconst grantsCache = new WeakMap<object, Map<string, Promise<Grant[] | undefined>>>()\n\n/**\n * Resolve the engine's `WorkflowAccess` for a client. Override wins\n * outright; otherwise both halves are fetched in parallel and\n * cached. Throws if neither path yields an actor — the engine\n * refuses to operate without an identity.\n */\nexport async function resolveAccess(\n client: WorkflowClient,\n args: ResolveAccessArgs = {},\n): Promise<WorkflowAccess> {\n const overrideActor = args.override?.actor\n const overrideGrants = args.override?.grants\n\n // Fast path: bench supplies both halves; no token needed.\n if (overrideActor !== undefined && overrideGrants !== undefined) {\n return {actor: overrideActor, grants: overrideGrants}\n }\n\n // Reaching here, the fast path above ruled out \"both halves supplied\",\n // so at least one half needs the client. A client with no `request`\n // can't fetch either: throw if the missing half is the actor, otherwise\n // degrade open on grants (the production \"endpoint unreachable\" path).\n const requestFn = client.request\n if (requestFn === undefined) {\n if (overrideActor === undefined) {\n throw new Error(\n \"workflow: no actor available. The engine resolves the actor from the client's token \" +\n \"via `client.request({ url: '/users/me' })`. Supply a real `@sanity/client` configured \" +\n 'with a token, or pass an explicit `access.actor` override (the test bench provides ' +\n 'one by default).',\n )\n }\n return {actor: overrideActor}\n }\n\n const actorPromise =\n overrideActor !== undefined ? Promise.resolve(overrideActor) : cachedActor(client, requestFn)\n\n const grantsPromise =\n overrideGrants !== undefined\n ? Promise.resolve<Grant[] | undefined>(overrideGrants)\n : args.grantsFromPath !== undefined\n ? cachedGrants(client, requestFn, args.grantsFromPath)\n : Promise.resolve<Grant[] | undefined>(undefined)\n\n const [actor, grants] = await Promise.all([actorPromise, grantsPromise])\n if (actor === undefined) {\n throw new Error(\n 'workflow: failed to resolve actor from `/users/me`. The client is configured but the ' +\n 'endpoint returned no usable identity — check the token, or pass `access.actor` explicitly.',\n )\n }\n return {actor, ...(grants !== undefined ? {grants} : {})}\n}\n\nfunction cachedActor(\n client: WorkflowClient,\n requestFn: NonNullable<WorkflowClient['request']>,\n): Promise<Actor | undefined> {\n const cached = actorCache.get(client)\n if (cached !== undefined) return cached\n\n // Evict on failure so a transient `/users/me` error (401/503/network)\n // doesn't poison the per-client cache for its lifetime — the next call\n // retries instead of permanently throwing \"failed to resolve actor\".\n const pending = fetchActor(requestFn).catch((err) => {\n if (actorCache.get(client) === pending) actorCache.delete(client)\n throw err\n })\n actorCache.set(client, pending)\n return pending\n}\n\nfunction cachedGrants(\n client: WorkflowClient,\n requestFn: NonNullable<WorkflowClient['request']>,\n resourcePath: string,\n): Promise<Grant[] | undefined> {\n let byPath = grantsCache.get(client)\n if (byPath === undefined) {\n byPath = new Map()\n grantsCache.set(client, byPath)\n }\n let cached = byPath.get(resourcePath)\n if (cached === undefined) {\n cached = fetchGrantsCached(requestFn, resourcePath)\n byPath.set(resourcePath, cached)\n }\n return cached\n}\n\nasync function fetchActor(\n requestFn: <T>(opts: {\n url?: string\n uri?: string\n signal?: AbortSignal\n tag?: string\n }) => Promise<T>,\n): Promise<Actor | undefined> {\n // `@sanity/client.request` distinguishes `uri` (project-API path,\n // resolved against the apiHost — e.g. `https://api.sanity.io/v1/users/me`)\n // from `url` (raw URL). `/users/me` is a global endpoint accessed via\n // `uri`. Studio itself uses `uri: '/users/me'` in its authStore\n // (sanity-v3 `createAuthStore.ts`). Using `url` here makes the\n // request hit the project-scoped endpoint, which returns empty for\n // the global user — causing \"no usable identity\" errors in studio.\n let user: SanityCurrentUser\n try {\n user = await requestFn<SanityCurrentUser>({\n uri: '/users/me',\n tag: 'workflow.access.resolve-actor',\n })\n } catch (err) {\n // Surface the request failure with its cause intact so the eventual\n // throw is diagnosable — and let it propagate so the per-client cache\n // is evicted and the next call retries (transient 401/503/network).\n throw new Error(\n \"workflow: /users/me request failed. The engine resolves the actor from the client's token \" +\n 'via `client.request({ uri: \"/users/me\" })`. Check the token/connectivity, or pass an ' +\n 'explicit `access.actor` override.',\n {cause: err},\n )\n }\n // A well-formed response that carries no usable identity is NOT an\n // error worth retrying — return undefined so the caller throws its\n // \"no usable identity\" message.\n if (!user || typeof user.id !== 'string' || user.id.length === 0) return undefined\n const roleNames = user.roles?.map((r) => r.name).filter((n): n is string => Boolean(n)) ?? []\n return {\n kind: 'user',\n id: user.id,\n ...(roleNames.length > 0 ? {roles: roleNames} : {}),\n }\n}\n\nasync function fetchGrantsCached(\n requestFn: NonNullable<WorkflowClient['request']>,\n resourcePath: string,\n): Promise<Grant[] | undefined> {\n try {\n return await fetchGrants({client: {request: requestFn}, resourcePath})\n } catch (err) {\n console.warn(\n `workflow: failed to fetch grants from \"${resourcePath}\"; skipping permission gate. ` +\n `Original error: ${err instanceof Error ? err.message : String(err)}`,\n )\n return undefined\n }\n}\n","/**\n * Engine-scope tags — the multi-tenant isolation primitive.\n *\n * Every engine takes a required `tags: string[]` set at construction.\n * Tags must be Sanity-ID-compatible since they're joined into IDs with\n * `.` — ASCII lowercase + digits + dashes, no leading dash, no dots.\n *\n * The first tag in the array is the *canonical* tag, used as the ID\n * prefix when the engine writes new definitions or instances. The full\n * tag set goes onto every written doc and is the basis for read\n * filtering (tag intersection between engine and doc).\n */\n\nconst TAG_RE = /^[a-z0-9][a-z0-9-]*$/\n\nexport function validateTags(tags: string[]): void {\n if (tags.length === 0) {\n throw new Error('tags: must be a non-empty array')\n }\n for (const tag of tags) {\n if (!TAG_RE.test(tag)) {\n throw new Error(\n `tags: invalid tag \"${tag}\" — must match ${TAG_RE.source} (ASCII lowercase + digits + dashes, no leading dash, no dots)`,\n )\n }\n }\n}\n\nexport function canonicalTag(tags: string[]): string {\n return tags[0]!\n}\n","/**\n * `workflow.evaluate` — the third concept.\n *\n * Reads an instance and projects \"what can this actor do right now,\n * and why not the rest?\" as a structured `WorkflowEvaluation`. Pure\n * read; never writes. Different actors see different evaluations of\n * the same instance.\n *\n * Used internally by `fireAction` to gate writes and externally by\n * UIs to render disabled-with-reason buttons.\n */\n\nimport {resolveAccess, type WorkflowAccessOverride} from './access.ts'\nimport {evaluateFilter} from './core/eval.ts'\nimport {buildParams} from './core/params.ts'\nimport type {ParsedGdr, WorkflowResource} from './core/refs.ts'\nimport type {HydratedSnapshot} from './core/snapshot.ts'\nimport type {Action, Assignee, Task, WorkflowDefinition} from './define/schema.ts'\nimport {grantsPermissionOn} from './permissions.ts'\nimport {hydrateSnapshot} from './snapshot.ts'\nimport {validateTags} from './tags.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {Grant} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {TaskStatus} from './types/enums.ts'\nimport type {\n ActionEvaluation,\n DisabledReason,\n StageEvaluation,\n TaskEvaluation,\n TransitionEvaluation,\n WorkflowEvaluation,\n} from './types/evaluation.ts'\nimport type {TaskEntry} from './types/instance-state.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nconst WILDCARD_ROLE = '*'\n\nexport interface EvaluateArgs {\n client: WorkflowClient\n /** Engine-scope tags — required. */\n tags: string[]\n /** Engine workflow resource — required. */\n workflowResource: WorkflowResource\n instanceId: string\n /**\n * Optional access-state override. By default the engine resolves\n * `(actor, grants)` from the supplied client's token via\n * `/users/me` (+ `grantsFromPath`). The bench supplies its\n * `ALL_ACCESS` default here; admin tooling can use this for\n * \"view as another user\" or \"preview with restricted grants\" flows.\n */\n access?: WorkflowAccessOverride\n /**\n * URL path on the supplied client where the engine should fetch\n * grants when `access.grants` isn't supplied. Required for\n * production usage; omitting it means the engine skips the\n * `permission-denied` gate (graceful degradation — the real Sanity\n * write boundary still enforces).\n *\n * Canvas resource example: `/canvases/<resourceId>/acl`.\n * Project/dataset example: `/projects/<id>/datasets/<dataset>/acl`.\n *\n * Result is cached per `(client, path)` for the lifetime of the\n * process — grants don't change often, and tearing them down per\n * call would mean a network round-trip on every fireAction.\n */\n grantsFromPath?: string\n /**\n * Optional resource-aware client routing — see\n * `StartInstanceArgs.resourceClients`. When the workflow's subject\n * (or any ancestor) lives in a different resource than the engine's\n * client, this resolver decides which client to read it through.\n * The evaluation hydrates a GDR-keyed snapshot from those reads and\n * runs `_id`-scoped filters locally in groq-js — same model as the\n * cascade path.\n */\n resourceClients?: (parsed: ParsedGdr) => WorkflowClient | undefined\n}\n\nexport async function evaluateInstance(args: EvaluateArgs): Promise<WorkflowEvaluation> {\n const {client, tags, instanceId, resourceClients} = args\n validateTags(tags)\n // Resolve actor + grants together (one cached round-trip per client).\n // Caller can short-circuit by passing `access` (bench / impersonation\n // / preview). Caching lives in access.ts — same WeakMap pattern.\n const {actor, grants} = await resolveAccess(client, {\n ...(args.access !== undefined ? {override: args.access} : {}),\n ...(args.grantsFromPath !== undefined ? {grantsFromPath: args.grantsFromPath} : {}),\n })\n\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) {\n throw new Error(`Workflow instance \"${instanceId}\" not found`)\n }\n if (!tags.some((t) => instance.tags?.includes(t))) {\n throw new Error(`Workflow instance \"${instanceId}\" not visible to this engine (tag mismatch)`)\n }\n\n const definition = parseDefinitionSnapshot(instance)\n const stage = definition.stages.find((s) => s.id === instance.currentStageId)\n if (stage === undefined) {\n throw new Error(\n `Instance \"${instanceId}\" currentStageId \"${instance.currentStageId}\" not in definition`,\n )\n }\n\n // Build the GDR-keyed snapshot ONCE per evaluation call. Every\n // `evaluateFilter` below threads it through, so per-action/per-task\n // filter checks evaluate in-memory via groq-js with zero lake reads\n // (same model the cascade uses in engine.ts).\n const clientForGdr =\n resourceClients !== undefined\n ? (parsed: ParsedGdr) => resourceClients(parsed) ?? client\n : () => client\n const snapshot: HydratedSnapshot = await hydrateSnapshot({\n client,\n clientForGdr,\n instance,\n definition,\n })\n\n // \"Current\" stage entry: same id, no exitedAt — on loop-backs multiple\n // entries share an id, and the un-exited one is current.\n const currentStageEntry = instance.stages.find(\n (s) => s.id === instance.currentStageId && s.exitedAt === undefined,\n )\n const currentTaskEntries = currentStageEntry?.tasks ?? []\n\n const taskEvaluations: TaskEvaluation[] = []\n for (const task of stage.tasks ?? []) {\n taskEvaluations.push(\n await evaluateTask({\n task,\n statusEntry: currentTaskEntries.find((t) => t.id === task.id),\n instance,\n definition,\n actor,\n grants,\n snapshot,\n }),\n )\n }\n\n const transitionEvaluations: TransitionEvaluation[] = []\n for (const transition of stage.transitions ?? []) {\n transitionEvaluations.push({\n transition,\n filterSatisfied: await evaluateFilter({\n filter: transition.filter,\n definition,\n snapshot,\n params: buildParams(instance),\n }),\n })\n }\n\n const currentStage: StageEvaluation = {\n stage,\n tasks: taskEvaluations,\n transitions: transitionEvaluations,\n }\n\n const pendingOnYou = taskEvaluations.filter((t) => t.pendingOnActor)\n const canInteract = taskEvaluations.some((t) => t.actions.some((a) => a.allowed))\n\n return {\n instance,\n definition,\n actor,\n currentStage,\n pendingOnYou,\n canInteract,\n }\n}\n\ninterface EvaluateTaskArgs {\n task: Task\n statusEntry: TaskEntry | undefined\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n grants: Grant[] | undefined\n snapshot: HydratedSnapshot\n}\n\nasync function evaluateTask(args: EvaluateTaskArgs): Promise<TaskEvaluation> {\n const {task, statusEntry, instance, definition, actor, grants, snapshot} = args\n const status: TaskStatus = statusEntry?.status ?? 'pending'\n\n const actions: ActionEvaluation[] = []\n for (const action of task.actions ?? []) {\n actions.push(\n await evaluateAction({\n action,\n task,\n ...(statusEntry !== undefined ? {statusEntry} : {}),\n status,\n instance,\n definition,\n actor,\n ...(grants !== undefined ? {grants} : {}),\n snapshot,\n }),\n )\n }\n\n return {\n task,\n status,\n // \"pending on actor\" treats both `pending` and `active` as waiting on\n // the assignee — pending tasks just haven't been auto-invoked yet, but\n // they're still inbox items.\n pendingOnActor:\n (status === 'active' || status === 'pending') && actorIsAssignee(actor, task.assignees ?? []),\n actions,\n }\n}\n\n// Internal — per-action verdict\n\ninterface EvaluateActionArgs {\n action: Action\n task: Task\n statusEntry?: TaskEntry\n status: TaskStatus\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n grants?: Grant[]\n snapshot: HydratedSnapshot\n}\n\nasync function evaluateAction(args: EvaluateActionArgs): Promise<ActionEvaluation> {\n const {action, task, status, instance, definition, actor, grants, snapshot} = args\n\n // Gates are checked in order; the first failing one wins. Order is\n // chosen so the most informative reason surfaces first (instance-level\n // → stage-level → task-level → actor-level → permission-level →\n // filter-level).\n const syncReason =\n lifecycleReason(instance, definition, status) ?? actorReason(action, task, actor)\n if (syncReason !== undefined) return disabled(action, syncReason)\n\n const asyncReason =\n (await permissionReason(action, instance, actor, grants)) ??\n (await filterReason(action, instance, definition, snapshot))\n if (asyncReason !== undefined) return disabled(action, asyncReason)\n\n return {action, allowed: true}\n}\n\nfunction lifecycleReason(\n instance: WorkflowInstance,\n definition: WorkflowDefinition,\n status: TaskStatus,\n): DisabledReason | undefined {\n if (instance.completedAt !== undefined) {\n return {kind: 'instance-completed', completedAt: instance.completedAt}\n }\n if (definition.stages.find((s) => s.id === instance.currentStageId)?.kind === 'terminal') {\n return {kind: 'stage-terminal', stageId: instance.currentStageId}\n }\n if (status === 'done' || status === 'skipped' || status === 'failed') {\n return {kind: 'task-not-active', status}\n }\n return undefined\n}\n\nfunction actorReason(action: Action, task: Task, actor: Actor): DisabledReason | undefined {\n const actorRoles = actor.roles ?? []\n if (action.roles !== undefined && action.roles.length > 0) {\n const wildcard = actorRoles.includes(WILDCARD_ROLE)\n const match = wildcard || action.roles.some((r) => actorRoles.includes(r))\n if (!match) {\n return {kind: 'role-required', required: [...action.roles], actorRoles: [...actorRoles]}\n }\n }\n if (action.requireAssignment === true && !actorIsAssignee(actor, task.assignees ?? [])) {\n return {kind: 'not-assigned', assignees: [...(task.assignees ?? [])], actorId: actor.id}\n }\n return undefined\n}\n\nasync function permissionReason(\n action: Action,\n instance: WorkflowInstance,\n actor: Actor,\n grants: Grant[] | undefined,\n): Promise<DisabledReason | undefined> {\n if (grants === undefined) return undefined\n const permission = action.requiredPermission ?? 'update'\n const allowed = await grantsPermissionOn({\n document: instance,\n grants,\n permission,\n userId: actor.id,\n })\n if (allowed) return undefined\n return {kind: 'permission-denied', permission, matchingGrants: grants.length}\n}\n\nasync function filterReason(\n action: Action,\n instance: WorkflowInstance,\n definition: WorkflowDefinition,\n snapshot: HydratedSnapshot,\n): Promise<DisabledReason | undefined> {\n if (action.filter === undefined) return undefined\n const truthy = await evaluateFilter({\n filter: action.filter,\n definition,\n snapshot,\n params: buildParams(instance),\n })\n if (truthy) return undefined\n return {kind: 'filter-failed', filter: action.filter}\n}\n\nfunction disabled(action: Action, reason: DisabledReason): ActionEvaluation {\n return {action, allowed: false, disabledReason: reason}\n}\n\n// Internal — actor / assignee helpers\n\nfunction actorIsAssignee(actor: Actor, assignees: Assignee[]): boolean {\n if (assignees.length === 0) return false\n const actorRoles = actor.roles ?? []\n const wildcard = actorRoles.includes(WILDCARD_ROLE)\n for (const assignee of assignees) {\n if (assignee.kind === 'user' && assignee.id === actor.id) return true\n if (assignee.kind === 'role') {\n if (wildcard || actorRoles.includes(assignee.role)) return true\n }\n }\n return false\n}\n\nfunction parseDefinitionSnapshot(instance: WorkflowInstance): WorkflowDefinition {\n try {\n return JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n } catch (err) {\n throw new Error(\n `Failed to parse definitionSnapshot on instance \"${instance._id}\": ${\n err instanceof Error ? err.message : String(err)\n }`,\n {cause: err},\n )\n }\n}\n","// Workflow evaluation — the third concept. Derived projection of\n// (instance + definition + actor + grants + lake state) answering\n// \"what can this actor do right now, and why not the rest?\".\n//\n// Not stored. Computed by `workflow.evaluate`. Different actors see\n// different evaluations of the same instance.\n\nimport type {\n Action,\n Assignee,\n Filter,\n Stage,\n Task,\n Transition,\n WorkflowDefinition,\n} from '../define/schema.ts'\nimport type {Actor} from './actor.ts'\nimport type {DocumentValuePermission, TaskStatus} from './enums.ts'\nimport type {ActionName, StageId, TaskId} from './ids.ts'\nimport type {WorkflowInstance} from './instance.ts'\n\nexport type DisabledReason =\n | {\n kind: 'role-required'\n required: string[]\n actorRoles: string[]\n }\n | {\n kind: 'not-assigned'\n assignees: Assignee[]\n actorId: string\n }\n | {\n kind: 'permission-denied'\n permission: DocumentValuePermission\n matchingGrants: number\n }\n | {\n kind: 'filter-failed'\n filter: Filter\n detail?: string\n }\n | {\n kind: 'task-not-active'\n status: Exclude<TaskStatus, 'active' | 'pending'>\n }\n | {kind: 'stage-terminal'; stageId: StageId}\n | {kind: 'instance-completed'; completedAt: string}\n | {\n /**\n * A deployed lake mutation guard denied (or, in optimistic engine-side\n * preview, would deny) the write. Surfacing this is an engine *preview* —\n * not proof of lake enforcement.\n */\n kind: 'mutation-guard-denied'\n guardIds: string[]\n detail?: string\n }\n\nexport interface ActionEvaluation {\n action: Action\n allowed: boolean\n /** Present iff `allowed === false`. The first failing gate wins. */\n disabledReason?: DisabledReason\n}\n\nexport interface TaskEvaluation {\n task: Task\n status: TaskStatus\n /** Whether this task is the current actor's responsibility right now. */\n pendingOnActor: boolean\n actions: ActionEvaluation[]\n}\n\nexport interface TransitionEvaluation {\n transition: Transition\n /** Result of evaluating the transition's filter at read time. */\n filterSatisfied: boolean\n}\n\nexport interface StageEvaluation {\n stage: Stage\n tasks: TaskEvaluation[]\n transitions: TransitionEvaluation[]\n}\n\nexport interface WorkflowEvaluation {\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n currentStage: StageEvaluation\n /** Active tasks where the actor is in `task.assignees`. */\n pendingOnYou: TaskEvaluation[]\n /** True if at least one action on any active task is allowed. */\n canInteract: boolean\n}\n\n// Typed error thrown by fireAction when the requested action's verdict\n// is `allowed: false`. Carries the structured reason so UIs can render\n// a precise message instead of parsing a string.\n\nexport class ActionDisabledError extends Error {\n readonly reason: DisabledReason\n readonly taskId: TaskId\n readonly action: ActionName\n\n constructor(args: {taskId: TaskId; action: ActionName; reason: DisabledReason}) {\n super(formatDisabledReason(args.taskId, args.action, args.reason))\n this.name = 'ActionDisabledError'\n this.reason = args.reason\n this.taskId = args.taskId\n this.action = args.action\n }\n}\n\ntype DisabledReasonDetail = {\n [K in DisabledReason['kind']]: (reason: Extract<DisabledReason, {kind: K}>) => string\n}\n\nconst disabledReasonDetail: DisabledReasonDetail = {\n 'role-required': (r) =>\n `requires one of [${r.required.join(', ')}]; actor has [${r.actorRoles.join(', ') || '(none)'}]`,\n 'not-assigned': (r) => `actor \"${r.actorId}\" is not in the task assignees`,\n 'permission-denied': (r) => `actor lacks \"${r.permission}\" permission on the workflow instance`,\n 'filter-failed': (r) => `action filter returned false${r.detail ? ` (${r.detail})` : ''}`,\n 'task-not-active': (r) => `task status is \"${r.status}\"`,\n 'stage-terminal': (r) => `stage \"${r.stageId}\" is terminal`,\n 'instance-completed': (r) => `instance completed at ${r.completedAt}`,\n 'mutation-guard-denied': (r) =>\n `blocked by mutation guard(s) [${r.guardIds.join(', ')}]${r.detail ? ` (${r.detail})` : ''}`,\n}\n\nfunction formatDisabledReason(taskId: TaskId, action: ActionName, reason: DisabledReason): string {\n const detail = (disabledReasonDetail[reason.kind] as (r: DisabledReason) => string)(reason)\n return `Action \"${taskId}:${action}\" is not allowed: ${detail}`\n}\n","import type {SanityDocument} from '@sanity/types'\n\nimport type {WorkflowResource} from '../core/refs.ts'\nimport type {WorkflowDefinition} from '../define/schema.ts'\nimport {canonicalTag} from '../tags.ts'\nimport type {WorkflowClient} from '../types/client.ts'\n\n/**\n * Mint the Sanity document `_id` for a workflow.definition. Bare form\n * — no GDR scheme prefix — because Sanity rejects `:` in document\n * IDs. Cross-resource references can construct the full GDR URI from\n * `(workflowResource, _id)` on demand.\n */\nexport function definitionDocId(\n _workflowResource: WorkflowResource,\n prefix: string,\n workflowId: string,\n version: number,\n): string {\n return `${prefix}.${workflowId}.v${version}`\n}\n\n/**\n * Topologically sort definitions so spawn-children land before their\n * parents. Refs pointing outside the batch are validated against the\n * lake — if a ref points neither to a doc in the batch nor to an\n * already-deployed definition, throw before any write.\n *\n * Cycles error.\n */\nexport async function sortByDependencies(\n client: WorkflowClient,\n definitions: WorkflowDefinition[],\n tags: string[],\n workflowResource: WorkflowResource,\n): Promise<WorkflowDefinition[]> {\n const prefix = canonicalTag(tags)\n // Track every workflowId in this batch + the versions per id. Logical\n // refs match on workflowId alone (or workflowId + version when explicit).\n const byWorkflowId = new Map<string, WorkflowDefinition[]>()\n for (const def of definitions) {\n const list = byWorkflowId.get(def.workflowId) ?? []\n list.push(def)\n byWorkflowId.set(def.workflowId, list)\n }\n const findInBatch = (ref: LogicalRef) => findRefInBatch(byWorkflowId, ref)\n\n await assertCrossBatchRefsDeployed(client, definitions, {\n tags,\n workflowResource,\n prefix,\n findInBatch,\n })\n\n return topoSortDefinitions(definitions, {workflowResource, prefix, findInBatch})\n}\n\ninterface LogicalRef {\n workflowId: string\n version?: number | 'latest'\n}\n\n/** Find the definition in the batch satisfying a logical ref: an exact\n * version match, or the highest version when the ref omits one. */\nfunction findRefInBatch(\n byWorkflowId: Map<string, WorkflowDefinition[]>,\n ref: LogicalRef,\n): WorkflowDefinition | undefined {\n const candidates = byWorkflowId.get(ref.workflowId)\n if (candidates === undefined || candidates.length === 0) return undefined\n if (typeof ref.version === 'number') return candidates.find((c) => c.version === ref.version)\n return candidates.reduce<WorkflowDefinition | undefined>(\n (best, c) => (best === undefined || c.version > best.version ? c : best),\n undefined,\n )\n}\n\n/**\n * For every spawn ref not satisfied within the batch, confirm a matching\n * `workflow.definition` is already deployed and visible to this engine's\n * tags. Throws listing every unresolved ref. No-op when all resolve.\n */\nasync function assertCrossBatchRefsDeployed(\n client: WorkflowClient,\n definitions: WorkflowDefinition[],\n ctx: {\n tags: string[]\n workflowResource: WorkflowResource\n prefix: string\n findInBatch: (ref: LogicalRef) => WorkflowDefinition | undefined\n },\n): Promise<void> {\n const missing: {from: string; ref: string}[] = []\n for (const def of definitions) {\n const fromId = definitionDocId(ctx.workflowResource, ctx.prefix, def.workflowId, def.version)\n for (const ref of refsOf(def)) {\n if (ctx.findInBatch(ref) !== undefined) continue // satisfied within batch\n const label = await resolveDeployedRefLabel(client, ref, ctx.tags)\n if (label !== undefined) missing.push({from: fromId, ref: label})\n }\n }\n if (missing.length === 0) return\n const lines = missing.map((m) => ` - ${m.from} → ${m.ref} (neither in batch nor deployed)`)\n throw new Error(\n `workflow.deployDefinitions: ${missing.length} unresolved reference${missing.length === 1 ? '' : 's'}:\\n` +\n lines.join('\\n'),\n )\n}\n\n/** Look up a logical ref in the lake. Returns undefined when a matching\n * deployed definition is visible to `tags`, or a human-readable label\n * for the unresolved ref otherwise. */\nasync function resolveDeployedRefLabel(\n client: WorkflowClient,\n ref: LogicalRef,\n tags: string[],\n): Promise<string | undefined> {\n const wantsExplicit = typeof ref.version === 'number'\n const params: Record<string, unknown> = {workflowId: ref.workflowId, tags}\n if (wantsExplicit) params.version = ref.version\n const doc = await client.fetch<(SanityDocument & {tags?: string[]}) | null>(\n definitionLookupGroq(wantsExplicit),\n params,\n )\n if (doc) return undefined\n return wantsExplicit ? `${ref.workflowId} v${ref.version}` : ref.workflowId\n}\n\n/** Children-before-parents topological sort over in-batch spawn refs.\n * Throws on a dependency cycle. */\nfunction topoSortDefinitions(\n definitions: WorkflowDefinition[],\n ctx: {\n workflowResource: WorkflowResource\n prefix: string\n findInBatch: (ref: LogicalRef) => WorkflowDefinition | undefined\n },\n): WorkflowDefinition[] {\n const visited = new Set<string>()\n const visiting = new Set<string>()\n const ordered: WorkflowDefinition[] = []\n\n const visit = (def: WorkflowDefinition): void => {\n const id = definitionDocId(ctx.workflowResource, ctx.prefix, def.workflowId, def.version)\n if (visited.has(id)) return\n if (visiting.has(id)) {\n throw new Error(`workflow.deployDefinitions: dependency cycle involving \"${id}\"`)\n }\n visiting.add(id)\n for (const ref of refsOf(def)) {\n const child = ctx.findInBatch(ref)\n if (child !== undefined) visit(child)\n }\n visiting.delete(id)\n visited.add(id)\n ordered.push(def)\n }\n\n for (const def of definitions) visit(def)\n return ordered\n}\n\n/** GROQ to resolve a deployed `workflow.definition` visible to the\n * caller's tags — explicit version, or the highest deployed version. */\nfunction definitionLookupGroq(wantsExplicit: boolean): string {\n return wantsExplicit\n ? `*[_type == \"workflow.definition\" && workflowId == $workflowId && version == $version && count(tags[@ in $tags]) > 0][0]`\n : `*[_type == \"workflow.definition\" && workflowId == $workflowId && count(tags[@ in $tags]) > 0] | order(version desc)[0]`\n}\n\n// Collect every spawn ref a definition depends on as a logical\n// `{ workflowId, version? }` reference. Hoisted out of\n// sortByDependencies so it doesn't re-capture closure on each call.\nfunction refsOf(def: WorkflowDefinition): LogicalRef[] {\n const out: LogicalRef[] = []\n for (const stage of def.stages) {\n for (const task of stage.tasks ?? []) {\n const ref = task.spawns?.definitionRef\n if (ref !== undefined) {\n out.push({\n workflowId: ref.workflowId,\n ...(ref.version !== undefined ? {version: ref.version} : {}),\n })\n }\n }\n }\n return out\n}\n\n/**\n * Compare a deployed definition document to what we'd write next. Skip\n * Sanity-managed system fields (`_rev`, `_createdAt`, `_updatedAt`) —\n * those always differ. Everything else must match exactly for the\n * deploy to be a no-op.\n */\nexport function isDefinitionUnchanged(\n existing: SanityDocument & Record<string, unknown>,\n expected: Record<string, unknown>,\n): boolean {\n return (\n stableStringify(stripSystemFields(existing)) === stableStringify(stripSystemFields(expected))\n )\n}\n\nfunction stripSystemFields(doc: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(doc)) {\n if (k === '_rev' || k === '_createdAt' || k === '_updatedAt') continue\n out[k] = v\n }\n return out\n}\n\n/**\n * Stable JSON.stringify with sorted keys so object key order can't\n * cause a false \"changed\" diff.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`\n const entries = Object.entries(value as Record<string, unknown>).toSorted(([a], [b]) =>\n a.localeCompare(b),\n )\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(',')}}`\n}\n\nexport async function loadDefinition(\n client: WorkflowClient,\n workflowId: string,\n version: number | undefined,\n tags: string[],\n): Promise<WorkflowDefinition> {\n if (version !== undefined) {\n const doc = await client.fetch<(WorkflowDefinition & {tags?: string[]}) | null>(\n \"*[_type == 'workflow.definition' && workflowId == $id && version == $v && count(tags[@ in $engineTags]) > 0][0]\",\n {id: workflowId, v: version, engineTags: tags},\n )\n if (!doc) {\n throw new Error(`Workflow definition ${workflowId} v${version} not deployed`)\n }\n return doc\n }\n const latest = await client.fetch<WorkflowDefinition | null>(\n \"*[_type == 'workflow.definition' && workflowId == $id && count(tags[@ in $engineTags]) > 0] | order(version desc)[0]\",\n {id: workflowId, engineTags: tags},\n )\n if (!latest) {\n throw new Error(`No deployed definition for workflow ${workflowId}`)\n }\n return latest\n}\n","import {resolveAccess, type WorkflowAccessOverride} from '../access.ts'\nimport {extractDocumentId, type GlobalDocumentReference, type ParsedGdr} from '../core/refs.ts'\nimport {cascadeAutoTransitions, propagateToAncestors} from '../engine/cascade.ts'\nimport {effectsContextEntry} from '../instance.ts'\nimport {validateTags} from '../tags.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectsContextEntry} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResourceClientResolver} from './types.ts'\n\n// Internal helpers\n\n/**\n * Resolve a spawn `instanceRef.id` to the bare doc `_id` used by GROQ.\n * A misconfigured caller could write a malformed GDR URI into history;\n * {@link extractDocumentId} throws on those, so skip them (return no id)\n * instead of crashing the whole {@link workflow.children} call.\n */\nexport function bareIdFromSpawnRef(uri: string): string[] {\n if (!uri.includes(':')) return [uri]\n try {\n return [extractDocumentId(uri)]\n } catch {\n return []\n }\n}\n\n/**\n * Shared verb preamble: validate tags, resolve the calling actor from\n * the access override (or the client's token), and build the\n * cross-resource routing function. Every `workflow.*` verb opens this\n * way.\n */\nexport async function resolveOperationContext(args: {\n client: WorkflowClient\n tags: string[]\n resourceClients?: ResourceClientResolver\n access?: WorkflowAccessOverride\n grantsFromPath?: string\n}): Promise<{\n access: Awaited<ReturnType<typeof resolveAccess>>\n actor: Awaited<ReturnType<typeof resolveAccess>>['actor']\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n}> {\n validateTags(args.tags)\n const access = await resolveAccess(args.client, {\n ...(args.access !== undefined ? {override: args.access} : {}),\n ...(args.grantsFromPath !== undefined ? {grantsFromPath: args.grantsFromPath} : {}),\n })\n return {\n access,\n actor: access.actor,\n clientForGdr: buildClientForGdr(args.client, args.resourceClients),\n }\n}\n\nexport async function cascade(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n): Promise<number> {\n const count = await cascadeAutoTransitions(client, instanceId, actor, clientForGdr)\n await propagateToAncestors(client, instanceId, actor, clientForGdr)\n return count\n}\n\n/**\n * Build the routing function from a resolver. Falls back to using the\n * default client when the resolver is absent or returns undefined.\n */\nexport function buildClientForGdr(\n defaultClient: WorkflowClient,\n resolver: ResourceClientResolver | undefined,\n): (parsed: ParsedGdr) => WorkflowClient {\n if (resolver === undefined) return () => defaultClient\n return (parsed) => resolver(parsed) ?? defaultClient\n}\n\nexport async function reload(\n client: WorkflowClient,\n instanceId: string,\n tags: string[],\n): Promise<WorkflowInstance> {\n const doc = await client.getDocument<WorkflowInstance>(instanceId)\n if (!doc) throw new Error(`Workflow instance ${instanceId} not found`)\n if (!intersectsTags(doc.tags, tags)) {\n throw new Error(`Workflow instance ${instanceId} not visible to this engine (tag mismatch)`)\n }\n return doc\n}\n\nexport function intersectsTags(\n docTags: string[] | undefined | null,\n engineTags: string[],\n): boolean {\n if (!docTags || docTags.length === 0) return false\n return engineTags.some((t) => docTags.includes(t))\n}\n\nexport function toEffectsContextEntries(\n ctx: Record<string, string | number | boolean | GlobalDocumentReference>,\n): EffectsContextEntry[] {\n return Object.entries(ctx).map(([id, value]) => effectsContextEntry(id, value))\n}\n","/**\n * The workflow API — a single coherent SDK surface, five methods.\n *\n * The model:\n *\n * - **`deployDefinition`** — once at deploy time. Persists the definition.\n * - **`startInstance`** — once per workflow run. Pins a snapshot, seeds\n * `effectsContext` (stable params for effect handlers), enters the\n * initial stage. Cascades.\n * - **`fireAction`** — the universal \"something happened\" call. Editors\n * fire actions on tasks. Runtimes fire actions on tasks in response\n * to webhooks, timer firings, etc. External signals funnel through\n * this; nothing else.\n * - **`completeEffect`** — the runtime reports a queued effect's\n * outcome. Optionally carries `outputs` that get merged into\n * `effectsContext` so a downstream effect's bindings can reference\n * them (effect chains). The only path that mutates `effectsContext`\n * after start.\n * - **`tick`** — re-evaluate auto-transitions and resolve due waits.\n * Used after any change that might unblock a filter: a content\n * mutation in the lake, a timer crossing a `completeWhen` deadline,\n * a sibling workflow completing, etc. The runtime decides which\n * instances might need a tick; the engine just re-evaluates.\n *\n * What's NOT in the API:\n *\n * - No `requestTransition`. Workflow authors should not have a way to\n * \"force\" a stage transition outside of filters firing. If you want\n * \"cancel from anywhere,\" model cancellation as a task with an action\n * that flips it to `failed`, plus an auto-transition filtered on\n * `anyTaskFailed`. Same audit trail as everything else; same\n * mechanism.\n * - No `setContext`. `effectsContext` is set at start, then mutated\n * only by completed effects' `outputs`. External signals belong on\n * tasks (via `fireAction`) or in the lake (as document mutations\n * that filters can read).\n * - No `invokeTask`. Tasks auto-activate on stage entry. Editor's first\n * `fireAction` against a pending task auto-invokes it before\n * applying the action.\n *\n * What filters can read:\n *\n * - Task state on the instance (`*[_id == $self][0].stages[id == $stage && !defined(exitedAt)][0].tasks[...]`)\n * - Document content in the lake (`*[_type == \"...\" && ...]`)\n * - Reserved params: `$self`, `$subject`, `$parent`, `$ancestors`, `$now`\n *\n * What filters must NOT read:\n *\n * - `effectsContext`. That field is for effect handler params only.\n *\n * The boundary keeps each thing doing one job: tasks are workflow state,\n * the lake is content state, effectsContext is handler fuel.\n */\n\nimport type {SanityDocument} from '@sanity/types'\nimport {evaluate as evaluateGroq, parse as parseGroq} from 'groq-js'\n\nimport {buildParams} from '../core/params.ts'\nimport type {WorkflowResource} from '../core/refs.ts'\nimport type {StateSlot, WorkflowDefinition} from '../define/schema.ts'\nimport {fireAction as engineFireAction} from '../engine/actions.ts'\nimport {primeInitialStage} from '../engine/cascade.ts'\nimport {completeEffect as engineCompleteEffect} from '../engine/effects.ts'\nimport {setStage as engineSetStage} from '../engine/stages.ts'\nimport {invokeTask as engineInvokeTask} from '../engine/tasks.ts'\nimport {type EvaluateArgs, evaluateInstance} from '../evaluate.ts'\nimport {buildInstanceBase} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport {\n fetchGrants as permFetchGrants,\n grantsPermissionOn as permGrantsPermissionOn,\n matchesFilter as permMatchesFilter,\n} from '../permissions.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport {derivePerspectiveFromState, resolveDeclaredState} from '../state-resolution.ts'\nimport {canonicalTag, validateTags} from '../tags.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport {ActionDisabledError, type WorkflowEvaluation} from '../types/evaluation.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {\n definitionDocId,\n isDefinitionUnchanged,\n loadDefinition,\n sortByDependencies,\n} from './deploy.ts'\nimport {\n bareIdFromSpawnRef,\n buildClientForGdr,\n cascade,\n intersectsTags,\n reload,\n resolveOperationContext,\n toEffectsContextEntries,\n} from './operations.ts'\nimport type {\n CompleteEffectArgs,\n DeployDefinitionResult,\n DeployDefinitionsArgs,\n DeployDefinitionsResult,\n DispatchResult,\n FireActionArgs,\n OperationArgs,\n ResourceClientResolver,\n SetStageArgs,\n StartInstanceArgs,\n} from './types.ts'\nimport {validateDefinition} from './validate.ts'\n\n/**\n * The four-method workflow API.\n */\nexport const workflow = {\n /**\n * Persist a workflow definition to the lake. Stored as a\n * `workflow.definition` document with id\n * `workflow.definition.<workflowId>.v<version>`. Subsequent versions\n * are stored alongside earlier ones — `startInstance` picks the\n * highest version by default.\n */\n /**\n * Deploy a set of workflow definitions as one call. The SDK figures\n * out the dependency order itself (children before parents that spawn\n * them via `task.spawns.definitionRef`), idempotently writes any\n * definition whose content has changed, and reports a per-definition\n * outcome (`created` / `updated` / `unchanged`).\n *\n * Refs may point inside the batch OR at already-deployed definitions\n * in the lake — both are valid. A ref pointing at neither errors with\n * a clear message naming the missing target.\n *\n * Cycles in the dependency graph error before any write happens.\n */\n deployDefinitions: async (args: DeployDefinitionsArgs): Promise<DeployDefinitionsResult> => {\n const {client, tags, workflowResource, definitions} = args\n validateTags(tags)\n\n // 1. Validate each definition's GROQ + structural invariants\n // individually. Fail fast before we touch the lake.\n for (const def of definitions) {\n validateDefinition(def)\n }\n\n // 2. Build the dependency graph and topologically sort.\n // Children-before-parents; refs pointing outside the batch are\n // validated against the lake once.\n const ordered = await sortByDependencies(client, definitions, tags, workflowResource)\n\n // 3. Compare against the existing doc to skip unchanged definitions,\n // then write everything that DID change in a single same-resource\n // transaction. All-or-nothing — if one definition's rev check\n // fails, none of the batch lands.\n const results: DeployDefinitionResult[] = []\n const prefix = canonicalTag(tags)\n const tx = client.transaction()\n let hasWrites = false\n for (const def of ordered) {\n const id = definitionDocId(workflowResource, prefix, def.workflowId, def.version)\n const expected = {\n ...def,\n _id: id,\n _type: 'workflow.definition' as const,\n tags,\n }\n // `getDocument` returns the doc, or null/undefined when missing\n // (different clients return different falsy sentinels). Use a\n // truthy check rather than `=== null` to cover both.\n const existing = await client.getDocument<typeof expected & SanityDocument>(id)\n if (\n existing &&\n intersectsTags(existing.tags, tags) &&\n isDefinitionUnchanged(existing, expected)\n ) {\n results.push({workflowId: def.workflowId, version: def.version, status: 'unchanged'})\n continue\n }\n if (existing) {\n // Patch with rev check — fail fast if another deploy raced us.\n //\n // `set()` is a *partial* update: it overwrites the listed fields\n // but leaves any extra top-level fields untouched. That's wrong\n // for definition deploys, where a schema change can rename or\n // drop a field (e.g. `name` → `title`) and stale values would\n // otherwise linger on the deployed doc forever. Compute the\n // top-level keys that exist on `existing` but not on `expected`\n // and chain an `.unset()` so the deployed shape matches source.\n // Sanity-managed `_*` fields stay (we can't unset them anyway).\n const expectedKeys = new Set(Object.keys(expected))\n const toUnset = Object.keys(existing).filter(\n (k) => !k.startsWith('_') && !expectedKeys.has(k),\n )\n const patch = client.patch(id).set(expected).ifRevisionId(existing._rev)\n if (toUnset.length > 0) patch.unset(toUnset)\n tx.patch(patch)\n } else {\n // Net-new — `create` errors on collision instead of clobbering.\n tx.create(expected)\n }\n hasWrites = true\n results.push({\n workflowId: def.workflowId,\n version: def.version,\n status: existing ? 'updated' : 'created',\n })\n }\n if (hasWrites) await tx.commit()\n\n return {results}\n },\n\n /**\n * Spawn a new workflow instance from a deployed definition.\n *\n * Pins the snapshot at start-time, seeds `effectsContext`, enters\n * the initial stage (which builds taskStatus, queues onEnter\n * effects, auto-activates tasks). Then cascades auto-transitions\n * until stable. Returns the resulting instance.\n */\n startInstance: async (args: StartInstanceArgs): Promise<WorkflowInstance> => {\n const {\n client,\n tags,\n workflowResource,\n workflowId,\n version,\n initialState,\n ancestors,\n effectsContext,\n instanceId,\n perspective,\n } = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n\n const definition = await loadDefinition(client, workflowId, version, tags)\n // Bare `_id` — Sanity rejects `:` in document IDs, so we don't\n // use a GDR URI here. Cross-resource references build the GDR\n // URI from `(workflowResource, _id)` on demand.\n const id = instanceId ?? `${canonicalTag(tags)}.wf-instance.${randomKey()}`\n\n const initialStage = definition.stages.find((s) => s.id === definition.initialStageId)\n if (initialStage === undefined) {\n throw new Error(\n `Initial stage \"${definition.initialStageId}\" missing in ${workflowId} v${definition.version}`,\n )\n }\n\n const now = new Date().toISOString()\n const effectsContextEntries = effectsContext ? toEffectsContextEntries(effectsContext) : []\n // Workflow-scope state slots resolve in declaration order. Later\n // slots can read earlier ones via `$state.<slotId>` in their GROQ.\n // There's no privileged slot name — `$state` exposes every\n // declared slot keyed by its author-chosen id.\n const resolvedState = await resolveDeclaredState({\n slotDefs: (definition as WorkflowDefinition & {state?: StateSlot[]}).state ?? [],\n initialState: initialState ?? [],\n ctx: {\n client,\n selfId: id,\n tags,\n workflowResource,\n ...(perspective !== undefined ? {perspective} : {}),\n },\n randomKey,\n })\n\n // Perspective resolution: an explicit `perspective` arg wins;\n // otherwise derive it from a populated `release.ref` slot. This is\n // what makes a release-targeting workflow self-describing — the\n // caller fills the slot and the engine figures out the read\n // perspective, rather than every caller having to pass it.\n const effectivePerspective = perspective ?? derivePerspectiveFromState(resolvedState)\n\n const base = buildInstanceBase({\n id,\n now,\n tags,\n workflowResource,\n workflowId: definition.workflowId,\n pinnedVersion: definition.version,\n definition,\n state: resolvedState,\n effectsContext: effectsContextEntries,\n ancestors: ancestors ?? [],\n perspective: effectivePerspective,\n initialStageId: definition.initialStageId,\n actor,\n })\n // Net-new doc: `create` errors loud if `_id` collides instead of\n // silently wiping an existing instance. Use the caller-supplied\n // `instanceId` at your own risk — collisions surface here.\n await client.create(base)\n\n await primeInitialStage(client, id, actor, clientForGdr)\n await cascade(client, id, actor, clientForGdr)\n\n return reload(client, id, tags)\n },\n\n /**\n * Fire an action against a task. If the task is pending, it is\n * auto-invoked first (pending → active) so callers don't have to know\n * the lifecycle. Cascades auto-transitions and propagates to ancestors\n * after the action commits.\n *\n * This is the universal \"something happened\" call. Editors fire it.\n * Runtimes fire it in response to webhooks, effect completions, and\n * timer firings. External signals never bypass this.\n */\n fireAction: async (args: FireActionArgs): Promise<DispatchResult> => {\n const {\n client,\n tags,\n workflowResource,\n instanceId,\n taskId,\n action,\n params,\n idempotent,\n resourceClients,\n } = args\n const {access, actor, clientForGdr} = await resolveOperationContext(args)\n\n const before = await reload(client, instanceId, tags)\n const currentStageEntry = before.stages.find(\n (s) => s.id === before.currentStageId && s.exitedAt === undefined,\n )\n const taskEntry = currentStageEntry?.tasks.find((t) => t.id === taskId)\n if (taskEntry === undefined && idempotent === true) {\n return {instance: before, cascaded: 0, fired: false}\n }\n\n // Soft-gate via evaluation. We project the instance from the\n // actor's perspective and check the requested action's verdict\n // before invoking the engine. If denied, throw the structured\n // ActionDisabledError so callers can render `reason` directly.\n //\n // Reuse the already-resolved `access` (no second token/grant\n // round-trip) by passing it through as the override.\n const evaluation = await evaluateInstance({\n client,\n tags,\n workflowResource,\n instanceId,\n access,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n })\n const taskEval = evaluation.currentStage.tasks.find((t) => t.task.id === taskId)\n const actionEval = taskEval?.actions.find((a) => a.action.id === action)\n if (actionEval !== undefined && !actionEval.allowed && actionEval.disabledReason) {\n throw new ActionDisabledError({\n taskId,\n action,\n reason: actionEval.disabledReason,\n })\n }\n\n if (taskEntry?.status === 'pending') {\n await engineInvokeTask({\n client,\n instanceId,\n taskId,\n options: {actor},\n })\n }\n\n const actionResult = await engineFireAction({\n client,\n instanceId,\n taskId,\n action,\n ...(params !== undefined ? {params} : {}),\n options: {actor},\n })\n\n const cascaded = await cascade(client, instanceId, actor, clientForGdr)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: true,\n ...(actionResult.ranOps !== undefined ? {ranOps: actionResult.ranOps} : {}),\n }\n },\n\n /**\n * Report a queued effect's outcome. Drains it from `pendingEffects`,\n * appends an `effectHistory` entry, and (if `outputs` are supplied\n * and the effect succeeded) upserts those values into\n * `effectsContext` by key — so downstream effect bindings can\n * reference them. Cascades after.\n */\n completeEffect: async (args: CompleteEffectArgs): Promise<DispatchResult> => {\n const {client, tags, instanceId, effectKey, status, outputs, detail, error, durationMs} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n await engineCompleteEffect({\n client,\n instanceId,\n effectKey,\n status,\n ...(outputs !== undefined ? {outputs} : {}),\n ...(detail !== undefined ? {detail} : {}),\n ...(error !== undefined ? {error} : {}),\n ...(durationMs !== undefined ? {durationMs} : {}),\n ...(actor !== undefined ? {options: {actor}} : {}),\n })\n const cascaded = await cascade(client, instanceId, actor, clientForGdr)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: true,\n }\n },\n\n /**\n * Re-evaluate auto-transitions and resolve due waits until stable.\n *\n * Used by the runtime after any event that might affect the workflow\n * but isn't itself a task action: a subject doc was patched, a sibling\n * workflow completed, the clock crossed a `completeWhen` deadline, etc.\n * The runtime doesn't need to know what changed — it just nudges\n * affected instances and the engine re-evaluates.\n */\n tick: async (args: OperationArgs): Promise<DispatchResult> => {\n const {client, tags, instanceId} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n await reload(client, instanceId, tags)\n const cascaded = await cascade(client, instanceId, actor, clientForGdr)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: cascaded > 0,\n }\n },\n\n /**\n * Admin override — force the instance into `targetStageId` regardless\n * of filters or declared transitions. ACL gating should be enforced\n * upstream; this verb performs the mechanical move.\n */\n setStage: async (args: SetStageArgs): Promise<DispatchResult> => {\n const {client, tags, instanceId, targetStageId, reason} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n await reload(client, instanceId, tags)\n const result = await engineSetStage({\n client,\n instanceId,\n targetStageId,\n ...(reason !== undefined ? {reason} : {}),\n ...(actor !== undefined ? {options: {actor}} : {}),\n })\n const cascaded = result.fired ? await cascade(client, instanceId, actor, clientForGdr) : 0\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: result.fired,\n }\n },\n\n /**\n * Fetch a workflow instance by id, scoped to the engine's tags.\n * Throws when the instance doesn't exist or isn't visible to this\n * engine.\n */\n getInstance: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n }): Promise<WorkflowInstance> => {\n const {client, tags, instanceId} = args\n validateTags(tags)\n return reload(client, instanceId, tags)\n },\n\n /**\n * Run a caller-supplied GROQ query with the engine's tags bound as\n * `$engineTags`. This does NOT rewrite the query — arbitrary GROQ\n * can't be safely tag-scoped after the fact — so the CALLER MUST\n * filter on `$engineTags` (e.g.\n * `count(tags[@ in $engineTags]) > 0`). To guard against accidental\n * cross-tenant reads, a query that never references `$engineTags` is\n * rejected before it reaches the lake. Caller is responsible for type\n * narrowing the result.\n */\n query: async <T = unknown>(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n groq: string\n params?: Record<string, unknown>\n }): Promise<T> => {\n const {client, tags, groq, params} = args\n validateTags(tags)\n if (!groq.includes('$engineTags')) {\n throw new Error(\n `workflow.query: query must filter on $engineTags to stay tag-scoped (e.g. \"count(tags[@ in $engineTags]) > 0\"); got: ${groq}`,\n )\n }\n return client.fetch<T>(groq, {...params, engineTags: tags})\n },\n\n /**\n * Snapshot-aware GROQ — runs against the same in-memory view that\n * filters see for a given instance.\n *\n * Hydrates the instance's snapshot (instance + subject + ancestors\n * + every doc declared by a `doc.ref` / `doc.refs` slot in scope),\n * then evaluates the supplied GROQ in groq-js against that dataset.\n * Reserved params are auto-bound: `$self`, `$subject`, `$parent`,\n * `$ancestors`, `$stage`, `$now` — all in GDR URI form to match the\n * snapshot's keying.\n *\n * Use when an external consumer (a UI, a debug pane, a test) wants\n * to ask \"what does the engine see for this workflow right now?\"\n * without re-implementing hydration. Pure read — never writes.\n */\n queryInScope: async <T = unknown>(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n groq: string\n params?: Record<string, unknown>\n }): Promise<T> => {\n const {client, tags, instanceId, groq, params, resourceClients} = args\n validateTags(tags)\n const instance = await reload(client, instanceId, tags)\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const clientForGdr = buildClientForGdr(client, resourceClients)\n const snapshot = await hydrateSnapshot({client, clientForGdr, instance, definition})\n const reserved = buildParams(instance)\n const tree = parseGroq(groq, {params: {...reserved, ...params}})\n const evaluated = await evaluateGroq(tree, {\n dataset: snapshot.docs,\n params: {...reserved, ...params},\n })\n return (await evaluated.get()) as T\n },\n\n /**\n * List every pending effect on the instance. Returns the same entries\n * the runtime would see — claimed and unclaimed alike.\n */\n listPendingEffects: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n }): Promise<PendingEffect[]> => {\n const inst = await reload(args.client, args.instanceId, args.tags)\n return inst.pendingEffects\n },\n\n /**\n * Filter pending effects on the instance by criteria. `claimed`\n * filters on claim presence; `names` restricts to specific effect\n * names. Both filters compose (AND).\n */\n findPendingEffects: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n claimed?: boolean\n names?: string[]\n }): Promise<PendingEffect[]> => {\n const inst = await reload(args.client, args.instanceId, args.tags)\n return inst.pendingEffects.filter((e) => {\n if (args.claimed === true && e.claim === undefined) return false\n if (args.claimed === false && e.claim !== undefined) return false\n if (args.names !== undefined && !args.names.includes(e.effectId)) return false\n return true\n })\n },\n\n /**\n * Project the instance from a given actor's perspective. Returns a\n * `WorkflowEvaluation` with per-action verdicts (`allowed` + a\n * structured `disabledReason`). Pure read; never writes.\n *\n * Used by UIs to render disabled-with-reason buttons and by\n * `fireAction` to gate writes via the same logic.\n */\n evaluate: async (args: EvaluateArgs): Promise<WorkflowEvaluation> => {\n return evaluateInstance(args)\n },\n\n /**\n * Materialised spawned children of a parent instance.\n *\n * Walks `history` for `workflow.history.spawned` events — the durable\n * record. (The per-task `spawnedInstances` field on the active stage\n * only exists while that stage is current; history survives.) Strips\n * the GDR URI on each `instanceRef` to a bare `_id`, fetches the\n * instances, drops any that aren't visible to this engine's tags, and\n * returns them sorted by `startedAt` ascending.\n *\n * Pass `taskId` to restrict to a single spawning task on the parent.\n */\n children: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n taskId?: string\n }): Promise<WorkflowInstance[]> => {\n const {client, tags, instanceId, taskId} = args\n validateTags(tags)\n const parent = await reload(client, instanceId, tags)\n const isSpawned = (\n h: HistoryEntry,\n ): h is Extract<HistoryEntry, {_type: 'workflow.history.spawned'}> =>\n h._type === 'workflow.history.spawned'\n const ids = parent.history\n .filter(isSpawned)\n .filter((h) => taskId === undefined || h.taskId === taskId)\n .flatMap((h) => bareIdFromSpawnRef(h.instanceRef.id))\n if (ids.length === 0) return []\n // Single GROQ — server-side filters by id set + engine tags, sorts\n // by startedAt. Beats N `getDocument` roundtrips for fan-outs.\n //\n // Visibility: this assumes spawn writes were committed with default\n // `visibility: \"sync\"` (which is what @sanity/client does and what\n // the engine relies on everywhere else). If a write path ever opts\n // into `async`, this query will silently miss freshly-spawned\n // children — but every other GROQ in the engine has the same\n // assumption, so we're not making things worse here.\n return client.fetch<WorkflowInstance[]>(\n `*[_id in $ids && count(tags[@ in $engineTags]) > 0] | order(startedAt asc)`,\n {ids, engineTags: tags},\n )\n },\n\n /**\n * Permission helpers — Sanity ACL grants evaluated against documents\n * via GROQ. Used by `workflow.evaluate` to soft-gate actions when the\n * caller supplies grants.\n */\n permissions: {\n matchesFilter: permMatchesFilter,\n grantsPermissionOn: permGrantsPermissionOn,\n fetchGrants: permFetchGrants,\n },\n}\n","import type {WorkflowAccessOverride} from '../access.ts'\nimport type {GlobalDocumentReference, WorkflowResource} from '../core/refs.ts'\nimport type {Effect, WorkflowDefinition} from '../define/schema.ts'\nimport {validateTags} from '../tags.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {reload} from './operations.ts'\nimport type {\n DrainEffectsResult,\n EffectHandler,\n EngineLogger,\n LoggerFactory,\n MissingHandlerDeployInfo,\n MissingHandlerInfo,\n MissingHandlerPolicy,\n ResourceClientResolver,\n VerifyDeployedDefinitionsResult,\n} from './types.ts'\nimport {workflow} from './workflow.ts'\n\nexport async function verifyDeployedDefinitionsInternal(args: {\n client: WorkflowClient\n tags: string[]\n effectHandlers: Record<string, EffectHandler>\n missingHandler: MissingHandlerPolicy\n logger: LoggerFactory\n}): Promise<VerifyDeployedDefinitionsResult> {\n const {client, tags, effectHandlers, missingHandler, logger} = args\n validateTags(tags)\n const log = logger('verifyDeployedDefinitions')\n const definitions = await client.fetch<(WorkflowDefinition & {_id: string})[]>(\n '*[_type == \"workflow.definition\" && count(tags[@ in $engineTags]) > 0] | order(workflowId asc, version asc)',\n {engineTags: tags},\n )\n\n const seen: {workflowId: string; version: number; _id: string}[] = []\n const missingByName = new Map<string, {definitionId: string; locations: Set<string>}>()\n for (const def of definitions) {\n seen.push({workflowId: def.workflowId, version: def.version, _id: def._id})\n walkEffectNames(def, (name, location) => {\n if (effectHandlers[name] !== undefined) return\n const key = `${name}@@${def._id}`\n let bucket = missingByName.get(key)\n if (bucket === undefined) {\n bucket = {definitionId: def._id, locations: new Set()}\n missingByName.set(key, bucket)\n }\n bucket.locations.add(location)\n })\n }\n\n const missing: VerifyDeployedDefinitionsResult['missing'] = []\n for (const [key, bucket] of missingByName.entries()) {\n const name = key.split('@@')[0]!\n missing.push({\n name,\n definitionId: bucket.definitionId,\n locations: [...bucket.locations].toSorted(),\n })\n }\n\n for (const m of missing) {\n const info: MissingHandlerDeployInfo = {\n phase: 'deploy',\n name: m.name,\n locations: m.locations,\n definitionId: m.definitionId,\n }\n const verdict = await applyMissingHandler(missingHandler, info, log)\n if (verdict === 'fail') {\n throw new Error(\n `verifyDeployedDefinitions: missing handler for \"${m.name}\" referenced by ${m.definitionId} at ${m.locations.join(', ')}`,\n )\n }\n }\n\n return {definitions: seen, missing}\n}\n\n/** Walk every external effect reference in a definition, invoking the\n * visitor with each name + a structural location string. */\nfunction walkEffectNames(\n def: WorkflowDefinition & {_id?: string},\n visit: (id: string, location: string) => void,\n): void {\n const visitEffects = (effects: Effect[] | undefined, location: string) => {\n for (const e of effects ?? []) visit(e.id, location)\n }\n for (const stage of def.stages ?? []) {\n visitEffects(stage.onEnter, `stage[${stage.id}].onEnter`)\n visitEffects(stage.onExit, `stage[${stage.id}].onExit`)\n for (const t of stage.tasks ?? []) {\n visitEffects(t.effects, `stage[${stage.id}].task[${t.id}].effects`)\n for (const a of t.actions ?? []) {\n visitEffects(a.effects, `stage[${stage.id}].task[${t.id}].action[${a.id}].effects`)\n }\n }\n for (const tr of stage.transitions ?? []) {\n visitEffects(tr.effects, `stage[${stage.id}].transition[${tr.to}].effects`)\n }\n }\n}\n\n// drainEffects — three-write claim protocol per pending entry.\n//\n// 1. CLAIM: load instance (rev R0). Stamp `claim` on an unclaimed entry.\n// Persist via patch().set().ifRevisionId(R0). On rev mismatch\n// (someone else committed), restart and pick a different entry.\n// 2. DISPATCH: invoke the registered handler in a try/catch.\n// 3. COMPLETE: call `completeEffect` which moves the entry from\n// `pendingEffects[]` to `effectHistory[]` and cascades.\n//\n// Returns drained / failed / skipped buckets. Skipped means missing\n// handler (subject to the engine's missingHandler policy).\n\nexport async function drainEffectsInternal(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n effectHandlers: Record<string, EffectHandler>\n missingHandler: MissingHandlerPolicy\n logger: LoggerFactory\n /** Identity override for the drainer. Defaults to a system actor. */\n access?: WorkflowAccessOverride\n}): Promise<DrainEffectsResult> {\n const {\n client,\n tags,\n workflowResource,\n resourceClients,\n instanceId,\n effectHandlers,\n missingHandler,\n logger,\n } = args\n const drainerActor: Actor = args.access?.actor ?? {kind: 'system', id: 'engine.drainEffects'}\n // The completion call goes through workflow.completeEffect which\n // also accepts WorkflowAccessOverride; we hand it the drainer's\n // identity (override.actor or the system fallback) and pass any\n // explicit grants through verbatim.\n const completionAccess: WorkflowAccessOverride = {\n actor: drainerActor,\n ...(args.access?.grants !== undefined ? {grants: args.access.grants} : {}),\n }\n validateTags(tags)\n const log = logger('drainEffects')\n const drained: PendingEffect[] = []\n const failed: PendingEffect[] = []\n const skipped: PendingEffect[] = []\n // Keys of entries we've decided to skip (missing handler, policy\n // allows). We never claim them, so a plain `continue` would re-pick\n // the same entry forever — exclude them from the candidate search so\n // later entries that DO have handlers still drain.\n const skippedKeys = new Set<string>()\n\n while (true) {\n const before = await reload(client, instanceId, tags)\n const candidate = before.pendingEffects.find(\n (e) => e.claim === undefined && !skippedKeys.has(e._key),\n )\n if (candidate === undefined) break\n\n const handler = effectHandlers[candidate.effectId]\n if (handler === undefined) {\n await assertSkippableOrThrow(missingHandler, candidate, instanceId, log)\n skipped.push(candidate)\n skippedKeys.add(candidate._key)\n continue\n }\n\n const claimed = await claimPendingEffect(client, before, candidate._key, drainerActor)\n if (!claimed) continue // 409 — re-read and retry a fresh candidate.\n\n const {outputs, dispatchError} = await dispatchEffect(handler, candidate, {\n client,\n instanceId,\n logger,\n })\n\n await reportEffectOutcome({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n instanceId,\n effectKey: candidate._key,\n access: completionAccess,\n outputs,\n dispatchError,\n })\n\n if (dispatchError === undefined) drained.push(candidate)\n else failed.push(candidate)\n }\n\n return {drained, failed, skipped}\n}\n\n/** Report a dispatched effect's outcome through `workflow.completeEffect`,\n * translating the dispatch result into the `done`/`failed` status +\n * optional outputs/error the API expects. */\nasync function reportEffectOutcome(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n effectKey: string\n access: WorkflowAccessOverride\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined\n dispatchError: {message: string; stack?: string} | undefined\n}): Promise<void> {\n const {outputs, dispatchError, resourceClients, ...rest} = args\n await workflow.completeEffect({\n ...rest,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n status: dispatchError === undefined ? 'done' : 'failed',\n ...(outputs !== undefined ? {outputs} : {}),\n ...(dispatchError !== undefined ? {error: dispatchError} : {}),\n })\n}\n\n/** Apply the missing-handler policy to an unhandled candidate. Throws\n * when the policy resolves to `fail`; returns when the entry may be\n * skipped. */\nasync function assertSkippableOrThrow(\n missingHandler: MissingHandlerPolicy,\n candidate: PendingEffect,\n instanceId: string,\n log: EngineLogger,\n): Promise<void> {\n const policyResult = await applyMissingHandler(\n missingHandler,\n {phase: 'drain', name: candidate.effectId, effectKey: candidate._key, instanceId},\n log,\n )\n if (policyResult === 'fail') {\n throw new Error(\n `drainEffects: no handler registered for \"${candidate.effectId}\" (effectKey=${candidate._key}, instanceId=${instanceId})`,\n )\n }\n}\n\n/**\n * Claim a single pending entry by stamping `claim` conditional on the\n * instance's current `_rev`. Returns false on a 409 rev mismatch (a\n * concurrent writer raced us) so the caller re-reads and retries.\n */\nasync function claimPendingEffect(\n client: WorkflowClient,\n instance: WorkflowInstance,\n effectKey: string,\n drainerActor: Actor,\n): Promise<boolean> {\n const claim = {\n _type: 'workflow.pendingEffect.claim' as const,\n claimedAt: new Date().toISOString(),\n claimedBy: drainerActor,\n }\n try {\n await client\n .patch(instance._id)\n .ifRevisionId(instance._rev)\n .set({[`pendingEffects[_key==\"${effectKey}\"].claim`]: claim})\n .commit()\n return true\n } catch {\n return false\n }\n}\n\n/** Invoke a handler, capturing its `outputs` or shaping a thrown error\n * into the `{message, stack?}` envelope `completeEffect` expects. */\nasync function dispatchEffect(\n handler: EffectHandler,\n candidate: PendingEffect,\n ctx: {client: WorkflowClient; instanceId: string; logger: LoggerFactory},\n): Promise<{\n outputs?: Record<string, string | number | boolean | GlobalDocumentReference>\n dispatchError?: {message: string; stack?: string}\n}> {\n try {\n const result = await handler(candidate.params, {\n client: ctx.client,\n instanceId: ctx.instanceId,\n effectKey: candidate._key,\n log: (message, extra) => ctx.logger(`effect.${candidate.effectId}`).info(message, extra),\n })\n return result?.outputs !== undefined ? {outputs: result.outputs} : {}\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n const stack = err instanceof Error && err.stack !== undefined ? err.stack : undefined\n return {dispatchError: stack !== undefined ? {message, stack} : {message}}\n }\n}\n\nasync function applyMissingHandler(\n policy: MissingHandlerPolicy,\n info: MissingHandlerInfo,\n log: EngineLogger,\n): Promise<'fail' | 'skip'> {\n if (policy === 'fail') return 'fail'\n if (policy === 'skip') {\n log.warn(`Missing effect handler \"${info.name}\" — skipping`, {info})\n return 'skip'\n }\n try {\n await policy(info)\n return 'skip'\n } catch {\n return 'fail'\n }\n}\n","import type {WorkflowAccessOverride} from '../access.ts'\nimport type {WorkflowResource} from '../core/refs.ts'\nimport {type EvaluateArgs, evaluateInstance} from '../evaluate.ts'\nimport {validateTags} from '../tags.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {drainEffectsInternal, verifyDeployedDefinitionsInternal} from './drain.ts'\nimport type {\n CompleteEffectArgs,\n DeployDefinitionsArgs,\n DeployDefinitionsResult,\n DispatchResult,\n DrainEffectsResult,\n EffectHandler,\n EngineLogger,\n FireActionArgs,\n LoggerFactory,\n MissingHandlerPolicy,\n OperationArgs,\n ResourceClientResolver,\n SetStageArgs,\n StartInstanceArgs,\n VerifyDeployedDefinitionsResult,\n} from './types.ts'\nimport {workflow} from './workflow.ts'\n\n// createEngine factory.\n//\n// Pre-binds `client`, `tags`, `workflowResource` (and optional\n// `effectHandlers`, `missingHandler`, `loggerFactory`) so callers don't\n// repeat them on every call. Exposes the same verb surface as the\n// `workflow.*` namespace; the namespace stays for callers that want the\n// raw, unbound functions.\n\nexport interface CreateEngineArgs {\n client: WorkflowClient\n workflowResource: WorkflowResource\n tags: string[]\n /**\n * Optional routing for cross-resource reads. When the engine needs\n * a doc whose GDR points at a resource other than its own, it calls\n * the resolver; if the resolver returns a client, that one is used.\n * Otherwise the engine's default `client` is used (best for\n * single-resource setups — most demos).\n */\n resourceClients?: ResourceClientResolver\n effectHandlers?: Record<string, EffectHandler>\n missingHandler?: MissingHandlerPolicy\n loggerFactory?: LoggerFactory\n}\n\ntype Bound<\n Args extends {client: WorkflowClient; tags: string[]; workflowResource: WorkflowResource},\n> = Omit<Args, 'client' | 'tags' | 'workflowResource'>\n\nexport interface Engine {\n /** Engine-scoped bindings — exposed for the few advanced consumers\n * (e.g. test bench, drain workers) that need them; the verbs already\n * thread them through internally. */\n readonly client: WorkflowClient\n readonly tags: readonly string[]\n readonly workflowResource: WorkflowResource\n readonly effectHandlers: Readonly<Record<string, EffectHandler>>\n readonly missingHandler: MissingHandlerPolicy\n readonly logger: LoggerFactory\n\n deployDefinitions: (args: Bound<DeployDefinitionsArgs>) => Promise<DeployDefinitionsResult>\n startInstance: (args: Bound<StartInstanceArgs>) => Promise<WorkflowInstance>\n fireAction: (args: Bound<FireActionArgs>) => Promise<DispatchResult>\n completeEffect: (args: Bound<CompleteEffectArgs>) => Promise<DispatchResult>\n tick: (args: Bound<OperationArgs>) => Promise<DispatchResult>\n evaluateInstance: (args: Bound<EvaluateArgs>) => ReturnType<typeof evaluateInstance>\n\n /** Admin override — bypass filters/transitions and force the stage. */\n setStage: (args: Bound<SetStageArgs>) => Promise<DispatchResult>\n /** Fetch a workflow instance by id. */\n getInstance: (args: {instanceId: string}) => Promise<WorkflowInstance>\n /** Spawned children of a parent instance, optionally filtered by the\n * spawning task. Sorted by `startedAt` asc. */\n children: (args: {instanceId: string; taskId?: string}) => Promise<WorkflowInstance[]>\n /** GROQ query against the engine's workflow resource. `$engineTags`\n * is bound for tag-aware filtering. */\n query: <T = unknown>(args: {groq: string; params?: Record<string, unknown>}) => Promise<T>\n /** Snapshot-aware GROQ — runs against the same in-memory view the\n * engine's filters see for the supplied instance. Reserved params\n * (`$self`, `$subject`, `$ancestors`, `$now`, `$stage`) are bound\n * in GDR URI form to match the snapshot's keying. */\n queryInScope: <T = unknown>(args: {\n instanceId: string\n groq: string\n params?: Record<string, unknown>\n }) => Promise<T>\n /** List every pending effect on an instance. */\n listPendingEffects: (args: {instanceId: string}) => Promise<PendingEffect[]>\n /** Filter pending effects by claimed status and/or effect names. */\n findPendingEffects: (args: {\n instanceId: string\n claimed?: boolean\n names?: string[]\n }) => Promise<PendingEffect[]>\n /** Dispatch unclaimed effects through registered handlers. The\n * drainer's identity defaults to a `{ kind: \"system\", id: \"engine.drainEffects\" }`\n * actor; pass `access` to override (e.g. impersonate a real user\n * whose grants you want the dispatch to respect). */\n drainEffects: (args: {\n instanceId: string\n access?: WorkflowAccessOverride\n }) => Promise<DrainEffectsResult>\n /**\n * Inspect every workflow.definition in the engine's tags and apply\n * the configured missingHandler policy at `phase: \"deploy\"` for any\n * effect name without a registered handler. Catches \"definition\n * shipped, handler removed\" misconfigurations at startup instead of\n * three days later when the effect fires.\n *\n * Returns the list of (definitionId, name, locations) tuples it saw.\n * Throws if missingHandler resolved as \"fail\" for any of them.\n */\n verifyDeployedDefinitions: () => Promise<VerifyDeployedDefinitionsResult>\n}\n\n/**\n * Default LoggerFactory — writes through the global `console`. Exposed\n * so callers outside `createEngine` (drive scripts, the\n * drain-effects helper) can use the same logger shape the engine uses\n * internally. Returns a fresh `EngineLogger` per call; the `name`\n * shows up as a `[name]` prefix on every line.\n */\nexport const defaultLoggerFactory: LoggerFactory = (name) => ({\n // info/warn/error all go to stderr — these are diagnostic, not\n // program output. Keeps stdout reserved for the caller's own data\n // so progress markers (process.stdout.write) and logger lines\n // don't interleave on the same line.\n info: (message, extra) => console.error(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n warn: (message, extra) => console.warn(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n error: (message, extra) =>\n console.error(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n})\n\n/**\n * No-op logger. Default for library callers that don't want any\n * output unless explicitly opted in.\n */\nexport const silentLogger: EngineLogger = {\n info: () => {},\n warn: () => {},\n error: () => {},\n}\n\n/**\n * Construct an engine bound to a workflow resource + tags. The returned\n * object exposes the same verbs as the `workflow.*` namespace, minus\n * the boilerplate config arguments (client / tags / workflowResource)\n * which are pinned at construction.\n *\n * Effect handlers + missingHandler are stored for future drain wiring\n * (Step 10). They have no effect on `fireAction` / `tick` /\n * `completeEffect` today — those still expect the runtime to dispatch\n * effects and report back via `completeEffect`.\n */\nexport function createEngine(args: CreateEngineArgs): Engine {\n const {client, workflowResource, tags, resourceClients} = args\n validateTags(tags)\n const effectHandlers = args.effectHandlers ?? {}\n const missingHandler = args.missingHandler ?? 'fail'\n const logger = args.loggerFactory ?? defaultLoggerFactory\n\n const bind = <\n A extends {client: WorkflowClient; tags: string[]; workflowResource: WorkflowResource},\n >(\n rest: Omit<A, 'client' | 'tags' | 'workflowResource'>,\n ): A =>\n ({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n ...rest,\n }) as A\n\n return {\n client,\n tags,\n workflowResource,\n effectHandlers,\n missingHandler,\n logger,\n deployDefinitions: (rest) => workflow.deployDefinitions(bind<DeployDefinitionsArgs>(rest)),\n startInstance: (rest) => workflow.startInstance(bind<StartInstanceArgs>(rest)),\n fireAction: (rest) => workflow.fireAction(bind<FireActionArgs>(rest)),\n completeEffect: (rest) => workflow.completeEffect(bind<CompleteEffectArgs>(rest)),\n tick: (rest) => workflow.tick(bind<OperationArgs>(rest)),\n evaluateInstance: (rest) => evaluateInstance(bind<EvaluateArgs>(rest)),\n\n setStage: (rest) => workflow.setStage(bind<SetStageArgs>(rest)),\n getInstance: ({instanceId}) =>\n workflow.getInstance({client, tags, workflowResource, instanceId}),\n children: ({instanceId, taskId}) =>\n workflow.children({\n client,\n tags,\n workflowResource,\n instanceId,\n ...(taskId !== undefined ? {taskId} : {}),\n }),\n query: ({groq, params}) =>\n workflow.query({\n client,\n tags,\n workflowResource,\n groq,\n ...(params !== undefined ? {params} : {}),\n }),\n queryInScope: ({instanceId, groq, params}) =>\n workflow.queryInScope({\n client,\n tags,\n workflowResource,\n instanceId,\n groq,\n ...(params !== undefined ? {params} : {}),\n }),\n listPendingEffects: ({instanceId}) =>\n workflow.listPendingEffects({client, tags, workflowResource, instanceId}),\n findPendingEffects: ({instanceId, claimed, names}) =>\n workflow.findPendingEffects({\n client,\n tags,\n workflowResource,\n instanceId,\n ...(claimed !== undefined ? {claimed} : {}),\n ...(names !== undefined ? {names} : {}),\n }),\n drainEffects: ({instanceId, access}) =>\n drainEffectsInternal({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n instanceId,\n effectHandlers,\n missingHandler,\n logger,\n ...(access !== undefined ? {access} : {}),\n }),\n verifyDeployedDefinitions: () =>\n verifyDeployedDefinitionsInternal({\n client,\n tags,\n effectHandlers,\n missingHandler,\n logger,\n }),\n }\n}\n","/**\n * Authorization model — grants and mutation guards.\n *\n * Grants are most-permissive-wins value permissions. Mutation guards are\n * the compiled/persisted form of an authoring `Guard`: owner-registered,\n * scoped by `match`, gated by a GROQ `predicate`, enforced OPTIMISTICALLY\n * engine-side only.\n */\n\nimport type {DocumentValuePermission, MutationGuardAction} from './enums.ts'\n\n// Grants. Filters are GROQ strings evaluated through groq-js with the\n// document as the dataset and the actor id as `identity()`. Compose:\n// most-permissive wins.\n\nexport interface Grant {\n filter: string\n permissions: DocumentValuePermission[]\n}\n\n// Mutation guards — the compiled/persisted form of an authoring `Guard`. A\n// guard is owner-registered, scoped by `match`, gated by a GROQ `predicate`\n// (empty = unconditional deny), with an opaque `metadata` bag the predicate\n// can read. POC type is `temp.system.guard`; enforcement is OPTIMISTIC\n// engine-side only.\n//\n// `resourceType`/`resourceId` scope a guard to a single datasource: the engine\n// spans datasources and must record which one a guard belongs to (the content\n// lake is per-datasource and infers the resource from storage).\n\nexport interface MutationGuardMatch {\n types?: string[]\n /** Bare document ids (resource-local; both published and `drafts.` forms). */\n idRefs?: string[]\n idPatterns?: string[]\n actions: MutationGuardAction[]\n}\n\nexport interface MutationGuardDoc {\n _id: string\n _type: 'temp.system.guard'\n // System fields are assigned by the lake on write — never sent on create\n // (an empty-string `_createdAt`/`_updatedAt` fails datetime validation).\n _rev?: string\n _createdAt?: string\n _updatedAt?: string\n /** Engine-layer: the single datasource this guard belongs to. */\n resourceType: string\n resourceId: string\n /** Registering identity — the engine robot. Only owner/admin may modify. */\n owner: string\n name?: string\n description?: string\n match: MutationGuardMatch\n /** GROQ; empty string = unconditional deny. Bare ids/fields only — no GDRs. */\n predicate: string\n /** Caller-owned projected state the predicate reads as `guard.metadata.*`. */\n metadata: Record<string, unknown>\n}\n\n/**\n * Inputs to predicate evaluation: `document.before`/`after`, the `mutation`,\n * the `guard`, and `identity()`. `before` is null on create, `after` null on\n * delete.\n */\nexport interface MutationContext {\n before: ({_id: string; _type: string} & Record<string, unknown>) | null\n after: ({_id: string; _type: string} & Record<string, unknown>) | null\n action: MutationGuardAction\n /** Authenticated caller id, resolved as `identity()` in the predicate. */\n identity?: string\n}\n\n/**\n * Thrown when one or more guards deny a mutation. POC: raised by the engine /\n * bench enforcement layer; carries every denial. Fail-closed: a predicate that\n * errors or is non-true denies.\n */\nexport class MutationGuardDeniedError extends Error {\n readonly denied: Array<{guardId: string; name?: string}>\n readonly documentId: string\n readonly action: MutationGuardAction\n\n constructor(args: {\n documentId: string\n action: MutationGuardAction\n denied: Array<{guardId: string; name?: string}>\n }) {\n const ids = args.denied.map((d) => d.guardId).join(', ')\n super(`Mutation on \"${args.documentId}\" (${args.action}) denied by guard(s) [${ids}]`)\n this.name = 'MutationGuardDeniedError'\n this.denied = args.denied\n this.documentId = args.documentId\n this.action = args.action\n }\n}\n","/**\n * Display metadata for every `workflow.*` `_type` literal the engine\n * persists (history entries, state-slot kinds, ops, effects-context\n * entry kinds, authoring-shape discriminators). Each entry exposes\n *\n * - `title` — short label for chips, badges, headings\n * - `description` — longer prose for tooltips / inspector panes\n *\n * UIs that render a workflow.instance audit log should NEVER show\n * `workflow.history.transitionFired` raw — they look it up here and\n * render `\"Transition fired\"` instead.\n *\n * Stable, additive surface: adding a new `_type` to the engine must\n * also add an entry here.\n */\n\nexport interface DisplayMetadata {\n readonly title: string\n readonly description: string\n}\n\n/**\n * History-entry `_type` discriminators. Order roughly matches the\n * order a typical run produces them in a single fire-action commit.\n */\nexport const HISTORY_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.history.stageEntered': {\n title: 'Stage entered',\n description: 'The instance crossed into a new stage.',\n },\n 'workflow.history.stageExited': {\n title: 'Stage exited',\n description: 'The instance left a stage on the way to the next one.',\n },\n 'workflow.history.taskActivated': {\n title: 'Task activated',\n description: 'A task flipped from `pending` to `active` and its onEnter effects queued.',\n },\n 'workflow.history.taskStatusChanged': {\n title: 'Task status changed',\n description: \"An action or op flipped a task's status (active → done / skipped / failed).\",\n },\n 'workflow.history.actionFired': {\n title: 'Action fired',\n description:\n 'An action was invoked against a task — ops ran, status may have flipped, effects queued.',\n },\n 'workflow.history.transitionFired': {\n title: 'Transition fired',\n description: 'A transition committed and the instance moved to a new stage.',\n },\n 'workflow.history.effectQueued': {\n title: 'Effect queued',\n description: 'A pending effect was added to the queue, waiting for a drainer to dispatch it.',\n },\n 'workflow.history.effectCompleted': {\n title: 'Effect completed',\n description:\n 'A drainer ran an effect handler to completion (done or failed) and merged its outputs into effectsContext.',\n },\n 'workflow.history.spawned': {\n title: 'Spawned child',\n description: 'A `task.spawns` declaration spawned a child workflow instance.',\n },\n 'workflow.history.opApplied': {\n title: 'Op applied',\n description:\n 'An inline state-mutation op (state.set / state.append / status.set / etc.) ran during an action commit.',\n },\n}\n\n/**\n * State-slot `_type` discriminators. The slot's variant defines what\n * shape `value` takes (single GDR vs array, scalar vs notes log).\n */\nexport const STATE_SLOT_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.state.doc.ref': {\n title: 'Document reference',\n description: 'Single GDR pointer at a document in this or another resource.',\n },\n 'workflow.state.doc.refs': {\n title: 'Document references',\n description: 'Ordered list of GDR pointers — multi-doc selection.',\n },\n 'workflow.state.query': {\n title: 'Query result',\n description:\n 'Snapshot of a GROQ projection captured at slot-resolve time; resolvedAt is stamped on the value.',\n },\n 'workflow.state.value.string': {\n title: 'String value',\n description: 'Free-form string slot.',\n },\n 'workflow.state.value.url': {\n title: 'URL value',\n description: 'Validated URL slot.',\n },\n 'workflow.state.value.number': {\n title: 'Number value',\n description: 'Numeric slot.',\n },\n 'workflow.state.value.boolean': {\n title: 'Boolean value',\n description: 'True/false slot.',\n },\n 'workflow.state.value.dateTime': {\n title: 'Date / time value',\n description: 'ISO-timestamp slot.',\n },\n 'workflow.state.checklist': {\n title: 'Checklist',\n description: 'Append-only list of checkable items; ops add/update/remove entries.',\n },\n 'workflow.state.notes': {\n title: 'Notes log',\n description: 'Append-only structured-note log (signoffs, comments, audit rows).',\n },\n 'workflow.state.assignees': {\n title: 'Assignees',\n description: 'Ordered list of typed (user|role) assignees.',\n },\n}\n\n/**\n * Op `_type` discriminators.\n */\nexport const OP_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.op.state.set': {\n title: 'Set slot',\n description: \"Overwrite a state slot's value with a resolved Source.\",\n },\n 'workflow.op.state.append': {\n title: 'Append to slot',\n description:\n 'Push a resolved item onto an array-typed slot (notes, checklist, assignees, refs).',\n },\n 'workflow.op.state.updateWhere': {\n title: 'Update matching rows',\n description: 'Merge fields into rows of an array-typed slot that match the predicate.',\n },\n 'workflow.op.state.removeWhere': {\n title: 'Remove matching rows',\n description: 'Drop rows of an array-typed slot that match the predicate.',\n },\n 'workflow.op.status.set': {\n title: 'Set task status',\n description: \"Flip a task's status explicitly (action.setStatus is the more common path).\",\n },\n}\n\n/**\n * EffectsContext entry kinds.\n */\nexport const EFFECTS_CONTEXT_DISPLAY: Record<string, DisplayMetadata> = {\n 'effectsContext.string': {\n title: 'String',\n description: 'Stable string parameter for effect handlers.',\n },\n 'effectsContext.number': {\n title: 'Number',\n description: 'Stable numeric parameter for effect handlers.',\n },\n 'effectsContext.boolean': {\n title: 'Boolean',\n description: 'Stable boolean parameter for effect handlers.',\n },\n 'effectsContext.ref': {\n title: 'GDR reference',\n description: 'Stable GDR pointer parameter for effect handlers.',\n },\n 'effectsContext.json': {\n title: 'JSON',\n description: 'Stable JSON payload for effect handlers.',\n },\n}\n\n/**\n * Authoring-shape discriminators (used when declaring a workflow).\n */\nexport const AUTHORING_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.stage': {\n title: 'Stage',\n description: 'A bucket of tasks the workflow is currently in.',\n },\n 'workflow.task': {\n title: 'Task',\n description: 'A unit of work inside a stage; carries actions and may spawn children.',\n },\n 'workflow.action': {\n title: 'Action',\n description: 'An invocable transition on a task — runs ops, queues effects, may flip status.',\n },\n 'workflow.action.param': {\n title: 'Action param',\n description: 'Caller-supplied parameter on an action; validated before any commit.',\n },\n 'workflow.transition': {\n title: 'Transition',\n description: 'An edge between stages, gated by a filter.',\n },\n 'workflow.predicate': {\n title: 'Predicate',\n description: 'Named GROQ filter, reusable across transitions / tasks / actions.',\n },\n 'workflow.effect': {\n title: 'Effect',\n description:\n 'Externally-dispatched side effect; queued on commit, drained by a runtime, completed asynchronously.',\n },\n 'workflow.spawn': {\n title: 'Spawn',\n description: 'Declares a task that fans out one or more child workflow instances.',\n },\n 'workflow.pendingEffect': {\n title: 'Pending effect',\n description: 'An effect that has been queued but not yet dispatched.',\n },\n 'workflow.pendingEffect.claim': {\n title: 'Claim',\n description: \"A drainer's lock on a pending effect while it dispatches.\",\n },\n 'workflow.definition': {\n title: 'Workflow definition',\n description: 'An immutable workflow blueprint pinned by `workflowId` + `version`.',\n },\n 'workflow.instance': {\n title: 'Workflow instance',\n description: 'A running (or finished) workflow against a subject.',\n },\n}\n\n/**\n * Single combined map for callers that don't care which family the\n * key belongs to (e.g. an audit row showing any `_type`).\n */\nexport const DISPLAY: Record<string, DisplayMetadata> = {\n ...HISTORY_DISPLAY,\n ...STATE_SLOT_DISPLAY,\n ...OP_DISPLAY,\n ...EFFECTS_CONTEXT_DISPLAY,\n ...AUTHORING_DISPLAY,\n}\n\n/**\n * Lookup helper. Returns a friendly title for any known `_type`, or\n * the original key when unknown so UIs degrade gracefully.\n */\nexport function displayTitle(typeKey: string | undefined): string {\n if (!typeKey) return ''\n return DISPLAY[typeKey]?.title ?? typeKey\n}\n\n/**\n * Same idea but returns the description, or undefined when unknown.\n */\nexport function displayDescription(typeKey: string | undefined): string | undefined {\n if (!typeKey) return undefined\n return DISPLAY[typeKey]?.description\n}\n"],"names":["parseGroq","tree","parse","evaluate","gdrUri","doc","z","randomKey","slotValue","policy","engineInvokeTask","engineFireAction","engineCompleteEffect","engineSetStage","evaluateGroq"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/api/validate.ts","../src/clock.ts","../src/core/refs.ts","../src/core/params.ts","../src/keys.ts","../src/core/eval.ts","../src/core/snapshot.ts","../src/snapshot.ts","../src/core/path.ts","../src/core/slot-validation.ts","../src/state-resolution.ts","../src/engine/context.ts","../src/core/state-read.ts","../src/core/source.ts","../src/core/bindings.ts","../src/instance.ts","../src/types/authorization.ts","../src/core/guards.ts","../src/guard-bindings.ts","../src/guards-lifecycle.ts","../src/engine/results.ts","../src/engine/guard-commit.ts","../src/discover.ts","../src/engine/spawn.ts","../src/engine/tasks.ts","../src/engine/stages.ts","../src/engine/cascade.ts","../src/engine/mutation.ts","../src/engine/effects.ts","../src/engine/ops.ts","../src/engine/actions.ts","../src/permissions.ts","../src/access.ts","../src/tags.ts","../src/evaluate.ts","../src/guards-query.ts","../src/types/evaluation.ts","../src/api/deploy.ts","../src/api/operations.ts","../src/api/workflow.ts","../src/api/drain.ts","../src/api/engine-factory.ts","../src/display.ts"],"sourcesContent":["import {parse as parseGroq} from 'groq-js'\n\nimport type {Stage, StateSlot, Task, WorkflowDefinition} from '../define/schema.ts'\n\n/**\n * Parse-validate every GROQ string in a definition before deploy.\n * Surfaces malformed predicate queries, filters, bindings, and\n * `task.completeWhen`/`failWhen` expressions early — long before any\n * instance runs.\n *\n * Throws an `Error` with all problems aggregated. Doesn't try to\n * type-check semantics (just syntax). Reserved params don't need to be\n * declared here — groq-js's parser doesn't know about runtime params,\n * just syntax.\n */\nexport function validateDefinition(definition: WorkflowDefinition): void {\n const v = createDefinitionValidator()\n\n for (const slot of (definition as WorkflowDefinition & {state?: StateSlot[]}).state ?? []) {\n v.checkSlot(slot, `workflow.state \"${slot.id}\"`)\n }\n\n for (const p of definition.predicates ?? []) {\n if (p.groq) v.checkFilter(p.groq, `predicate \"${p.id}\"`)\n }\n\n for (const stage of definition.stages) {\n validateStage(v, stage)\n }\n\n if (v.errors.length > 0) {\n throw new Error(\n `defineWorkflow(\"${definition.workflowId}\", v${definition.version}): ` +\n `${v.errors.length} validation error${v.errors.length === 1 ? '' : 's'}:\\n` +\n v.errors.join('\\n'),\n )\n }\n}\n\ninterface DefinitionValidator {\n errors: string[]\n /** Parse-check raw GROQ; records a syntax error under `where`. */\n tryParse: (groq: string, where: string) => void\n /** Parse-check a filter AND reject `_type` discovery scans in it. */\n checkFilter: (groq: string, where: string) => void\n /** Parse-check a `query`-sourced slot's GROQ. */\n checkSlot: (slot: StateSlot, slotLabel: string) => void\n}\n\nfunction createDefinitionValidator(): DefinitionValidator {\n const errors: string[] = []\n const tryParse = (groq: string, where: string) => {\n try {\n parseGroq(groq)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n errors.push(` · ${where}: ${message}`)\n }\n }\n // Reject filters that scan by `_type` — those are discovery queries,\n // not predicates. Filters evaluate against the in-memory snapshot\n // (instance + subject + ancestors + state-declared docs), which never\n // contains \"all docs of type X\", so a type scan returns empty and the\n // workflow appears stuck. Regex-based: `*[` followed by `_type`. False\n // negatives slip through harmlessly (runtime still returns empty).\n const rejectTypeScan = (groq: string, where: string) => {\n if (/\\*\\s*\\[\\s*_type\\b/.test(groq)) {\n errors.push(\n ` · ${where}: filter scans by \\`_type\\` — that's a discovery query, not a predicate. ` +\n `Filters evaluate against the in-memory snapshot (instance + ancestors + ` +\n `state-declared docs). To bring extra docs in scope, declare a \\`workflow.state.doc.ref\\` ` +\n `(or \\`doc.refs\\`) slot on the workflow or this stage. For lake scans like ` +\n `\"all articles in this release\", use spawn \\`forEach.groq\\` instead.`,\n )\n }\n }\n const checkFilter = (groq: string, where: string) => {\n tryParse(groq, where)\n rejectTypeScan(groq, where)\n }\n const checkSlot = (slot: StateSlot, slotLabel: string) => {\n if (slot.source.kind === 'query') tryParse(slot.source.query, `${slotLabel}.query`)\n }\n return {errors, tryParse, checkFilter, checkSlot}\n}\n\nfunction validateStage(v: DefinitionValidator, stage: Stage): void {\n for (const slot of stage.state ?? []) {\n v.checkSlot(slot, `stage \"${stage.id}\".state \"${slot.id}\"`)\n }\n if (typeof stage.completion === 'string') {\n v.tryParse(stage.completion, `stage \"${stage.id}\".completion`)\n }\n for (const t of stage.transitions ?? []) {\n // Effect bindings are typed Source values now — no GROQ to parse.\n if (typeof t.filter === 'string')\n v.checkFilter(t.filter, `transition ${stage.id} → ${t.to} filter`)\n }\n for (const task of stage.tasks ?? []) {\n validateTask(v, stage.id, task)\n }\n}\n\nfunction validateTask(v: DefinitionValidator, stageId: string, task: Task): void {\n const where = `stage \"${stageId}\" task \"${task.id}\"`\n for (const slot of task.state ?? []) {\n v.checkSlot(slot, `${where}.state \"${slot.id}\"`)\n }\n if (typeof task.filter === 'string') v.checkFilter(task.filter, `${where}.filter`)\n if (typeof task.completeWhen === 'string')\n v.checkFilter(task.completeWhen, `${where}.completeWhen`)\n for (const a of task.actions ?? []) {\n if (typeof a.filter === 'string')\n v.checkFilter(a.filter, `task \"${task.id}\" action \"${a.id}\".filter`)\n }\n // spawn.forEach.groq is intentionally NOT type-scan-checked — it's\n // discovery, not a filter.\n if (task.spawns?.forEach?.groq) {\n v.tryParse(task.spawns.forEach.groq, `task \"${task.id}\".spawns.forEach.groq`)\n }\n}\n","/**\n * The engine's single source of \"now\".\n *\n * A {@link Clock} returns the current time as an ISO-8601 string. Each\n * verb-driven operation takes ONE reading and threads it everywhere —\n * `$now` in filters, the `now` op-source, every history `at` stamp,\n * `completedAt`, `enteredAt`, `lastChangedAt` — so an eval pass agrees on\n * the time and a frozen clock produces a deterministic instance.\n *\n * A clock is injected ONCE, never per call: production omits it entirely\n * (defaults to {@link wallClock}); deterministic harnesses pass\n * `createEngine({ clock })`, and tests use `@sanity/workflow-engine-test`'s\n * `setNow` / `advance` (the bench wraps the same seam). It is deliberately\n * NOT a field on the public per-verb `*Args` — the raw `workflow.*` verbs\n * accept it only through the internal {@link Clocked} seam, so prod code\n * can't trivially override engine time by accident.\n *\n * Out of scope: `drainEffects` (the external runtime worker claiming and\n * executing effects) still stamps `claimedAt` from wall-clock — it is not\n * a verb and the bench never drives it. Thread a clock there too if the\n * simulator ever needs deterministic drain timing.\n */\nexport type Clock = () => string\n\n/** The default clock: real wall-clock time as an ISO-8601 string. */\nexport const wallClock: Clock = () => new Date().toISOString()\n\n/**\n * Internal clock-injection seam for the raw `workflow.*` verbs. NOT part\n * of the public per-verb args (it is deliberately not re-exported from the\n * package root) — production injects a clock ONCE via\n * `createEngine({ clock })`, and the test bench via its `setNow` /\n * `advance`. This intersection just lets those two callers thread the\n * clock into a raw verb without `clock` cluttering every documented\n * `*Args` interface as if it were an everyday option.\n */\nexport type Clocked<T> = T & {clock?: Clock}\n","/**\n * Global Document References (GDR).\n *\n * Every cross-document reference in the engine API uses this shape so\n * workflow state can live in one Sanity resource while subjects /\n * ancestors / effect-binding refs point at docs in *different* resources.\n *\n * Resource schemes mirror `@sanity/client`'s `ClientConfigResource`\n * discriminator. A GDR id is a typed URI:\n *\n * dataset:<projectId>:<dataset>:<documentId>\n * canvas:<resourceId>:<documentId>\n * media-library:<resourceId>:<documentId>\n * dashboard:<resourceId>:<documentId>\n *\n * The `type` field carries the doc's schema `_type` so consumers don't\n * need a separate lookup to know what they're pointing at.\n */\n\nexport type GdrScheme = 'dataset' | 'canvas' | 'media-library' | 'dashboard'\n\n/**\n * Typed GDR URI string. The compiler rejects bare doc ids (`\"doc-1\"`)\n * — only `<scheme>:<...id-parts>` values typecheck. Construct one via\n * `gdrUri()` / `gdrFromResource()` / `refDataset()` etc., or by hand\n * with the scheme prefix baked in (`` `dataset:proj:ds:${docId}` `` ).\n *\n * Combined with schema validation at the API boundary, this is the\n * type + runtime guarantee that no bare-string id reaches the\n * snapshot, slot, or filter layer.\n */\nexport type GdrUri = `${GdrScheme}:${string}`\n\nexport interface GlobalDocumentReference {\n /** URI: `<scheme>:<...id-parts>` */\n id: GdrUri\n /** Document `_type` (schema name) */\n type: string\n}\n\nexport interface ParsedGdr {\n scheme: GdrScheme\n /** For `dataset`: `<projectId>` */\n projectId?: string\n /** For `dataset`: `<dataset>` */\n dataset?: string\n /** For `canvas` / `media-library` / `dashboard`: `<resourceId>` */\n resourceId?: string\n /** The trailing `<documentId>` part — what `_id` of the target doc is */\n documentId: string\n}\n\nconst KNOWN_SCHEMES = new Set<string>(['dataset', 'canvas', 'media-library', 'dashboard'])\n\n/**\n * Parse a GDR URI into its scheme + addressing parts. Throws on\n * unknown scheme or malformed shape.\n */\nexport function parseGdr(uri: string): ParsedGdr {\n const colon = uri.indexOf(':')\n if (colon < 0) {\n throw new Error(\n `Invalid GDR \"${uri}\": must be a URI of form \"<scheme>:<...id-parts>\". Known schemes: dataset, canvas, media-library, dashboard.`,\n )\n }\n const scheme = uri.slice(0, colon)\n const rest = uri.slice(colon + 1)\n if (!KNOWN_SCHEMES.has(scheme)) {\n throw new Error(\n `Invalid GDR \"${uri}\": unknown scheme \"${scheme}\". Known: dataset, canvas, media-library, dashboard.`,\n )\n }\n const parts = rest.split(':')\n if (parts.some((part) => part.length === 0)) {\n throw new Error(\n `Invalid GDR \"${uri}\": id parts must be non-empty (no leading, trailing, or doubled \":\").`,\n )\n }\n if (scheme === 'dataset') {\n if (parts.length !== 3) {\n throw new Error(\n `Invalid GDR \"${uri}\": dataset scheme requires <projectId>:<dataset>:<documentId> (3 parts after scheme); got ${parts.length}.`,\n )\n }\n return {\n scheme: 'dataset',\n projectId: parts[0]!,\n dataset: parts[1]!,\n documentId: parts[2]!,\n }\n }\n // canvas / media-library / dashboard share <resourceId>:<documentId>\n if (parts.length !== 2) {\n throw new Error(\n `Invalid GDR \"${uri}\": ${scheme} scheme requires <resourceId>:<documentId> (2 parts after scheme); got ${parts.length}.`,\n )\n }\n return {\n scheme: scheme as GdrScheme,\n resourceId: parts[0]!,\n documentId: parts[1]!,\n }\n}\n\n/** Compose a GDR URI from parts. Inverse of `parseGdr`. */\nexport function gdrUri(\n parts:\n | {scheme: 'dataset'; projectId: string; dataset: string; documentId: string}\n | {\n scheme: 'canvas' | 'media-library' | 'dashboard'\n resourceId: string\n documentId: string\n },\n): GdrUri {\n if (parts.scheme === 'dataset') {\n return `dataset:${parts.projectId}:${parts.dataset}:${parts.documentId}` as GdrUri\n }\n return `${parts.scheme}:${parts.resourceId}:${parts.documentId}` as GdrUri\n}\n\n/**\n * Extract the bare document `_id` from a GDR URI — what\n * `*[_id == $docId]` in GROQ needs.\n */\nexport function extractDocumentId(gdrUriString: string): string {\n return parseGdr(gdrUriString).documentId\n}\n\n/** Make a GDR pointer to a project-dataset doc. */\nexport function refDataset(\n projectId: string,\n dataset: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'dataset', projectId, dataset, documentId}), type}\n}\n\n/** Make a GDR pointer to a Canvas-resource doc. */\nexport function refCanvas(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'canvas', resourceId, documentId}), type}\n}\n\n/** Make a GDR pointer to a Media-Library-resource doc. */\nexport function refMediaLibrary(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'media-library', resourceId, documentId}), type}\n}\n\n/** Make a GDR pointer to a Dashboard-resource doc. */\nexport function refDashboard(\n resourceId: string,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrUri({scheme: 'dashboard', resourceId, documentId}), type}\n}\n\n/**\n * The resource a Sanity client is configured against — mirrors\n * `@sanity/client`'s `ClientConfigResource` discriminator. For\n * `dataset`, `id` is `<projectId>.<dataset>`. For the others, `id` is\n * the resource id.\n */\nexport type WorkflowResource =\n | {type: 'dataset'; id: string}\n | {type: 'canvas'; id: string}\n | {type: 'media-library'; id: string}\n | {type: 'dashboard'; id: string}\n\n/**\n * Build a GDR URI from a workflow resource config + a document id\n * within that resource. This is how the engine mints `_id`s for\n * definitions / instances / ancestor refs into its own resource.\n */\nexport function gdrFromResource(res: WorkflowResource, documentId: string): GdrUri {\n if (res.type === 'dataset') {\n const dot = res.id.indexOf('.')\n if (dot < 0) {\n throw new Error(`Invalid dataset resource id \"${res.id}\": expected \"<projectId>.<dataset>\".`)\n }\n const projectId = res.id.slice(0, dot)\n const dataset = res.id.slice(dot + 1)\n return gdrUri({scheme: 'dataset', projectId, dataset, documentId})\n }\n return gdrUri({scheme: res.type, resourceId: res.id, documentId})\n}\n\n/**\n * The GDR URI a document refers to itself by — its own `_id` minted into\n * its own `workflowResource`. This is the `$self` value filters see and\n * the form `Source.self` resolves to in ops and spawn.\n */\nexport function selfGdr(doc: {workflowResource: WorkflowResource; _id: string}): GdrUri {\n return gdrFromResource(doc.workflowResource, doc._id)\n}\n\n/**\n * Type-narrowing predicate — `true` when `value` looks like a GDR URI\n * (has a known scheme prefix). Use at boundaries that receive\n * stringified ids and need to refuse bare doc ids.\n */\nexport function isGdrUri(value: unknown): value is GdrUri {\n if (typeof value !== 'string') return false\n try {\n parseGdr(value)\n return true\n } catch {\n return false\n }\n}\n\n/** Build a GDR (id + type) pointing at a document within a workflow resource. */\nexport function gdrRef(\n res: WorkflowResource,\n documentId: string,\n type: string,\n): GlobalDocumentReference {\n return {id: gdrFromResource(res, documentId), type}\n}\n\n/** Type filter for GDR shape. */\nexport function isGdr(value: unknown): value is GlobalDocumentReference {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as {id?: unknown}).id === 'string' &&\n typeof (value as {type?: unknown}).type === 'string'\n )\n}\n","/**\n * Pure param transforms.\n *\n * `buildParams(instance, now, extra?)` — assemble the reserved param\n * bag a filter sees: `$self`, `$state`, `$parent`, `$ancestors`,\n * `$stage`, `$now`. All ids are GDR URIs so they match the\n * snapshot's keying. `now` is supplied by the shell (the engine's\n * {@link Clock}) — core never reads wall-clock itself.\n *\n * `paramsForLake(params)` — strip GDR URIs back to bare ids on the\n * reserved id params, for the shell when it needs to fall through\n * to a lake fetch (spawn discovery scans). Pure transform;\n * doesn't touch the network itself.\n *\n * No client. No I/O. The shell builds these and passes them to\n * `evaluateFilter` (also pure).\n */\n\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {extractDocumentId, isGdrUri, selfGdr} from './refs.ts'\n\n/**\n * Reserved params available to every filter. `$now` is the shell-supplied\n * clock reading, threaded so multiple predicates fired in the same eval\n * pass agree on the time (and a frozen clock makes the pass deterministic).\n *\n * `$state` is a map keyed by slot id — filters read state via\n * `$state.<slotId>.value.id` for doc.refs, `$state.<slotId>.value`\n * for scalar slots, etc. There is no privileged slot name; the\n * engine doesn't care that you happened to name one \"subject\" or\n * \"article\". The author owns the naming.\n */\nexport function buildParams(\n instance: WorkflowInstance,\n now: string,\n extra?: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n self: selfGdr(instance),\n state: stateMap(instance.state ?? []),\n parent: instance.ancestors.at(-1)?.id ?? null,\n ancestors: instance.ancestors.map((a) => a.id),\n /** Current stage id — bind for filters that scope to the current stage. */\n stage: instance.currentStageId,\n now,\n ...extra,\n }\n}\n\n/**\n * Project the instance's workflow-scope state into a `slotId → slot`\n * map so filters can write `$state.article.value.id`. The slot envelope\n * (id, _type, title?, description?, value, resolvedAt?) is exposed —\n * not just the `value` — so filters that want to distinguish \"slot\n * absent\" from \"slot present with null value\" can do so via\n * `defined($state.article)` vs `defined($state.article.value)`.\n *\n * Stage-scope and task-scope state are NOT in `$state`. They live on\n * `instance.stages[id == $stage && !defined(exitedAt)][0].state[]`\n * and the parallel task path, addressable via GROQ traversal.\n */\nfunction stateMap(slots: ResolvedStateSlot[]): Record<string, ResolvedStateSlot> {\n const out: Record<string, ResolvedStateSlot> = {}\n for (const s of slots) out[s.id] = s\n return out\n}\n\n/**\n * Strip GDR URIs back to bare `_id`s on the reserved id params before\n * a lake fetch (discovery scans). Sanity refs are stored bare on disk,\n * so `releaseRef._ref == $state.release.value.id` only matches when\n * the id is bare in the lake query.\n *\n * Pure transform. Doesn't fetch. The shell decides when to call it.\n *\n * The `$state` map is walked recursively because slot values can\n * carry GDRs (doc.ref / doc.refs) that need stripping for lake match\n * predicates.\n */\nexport function paramsForLake(params: Record<string, unknown>): Record<string, unknown> {\n return {\n ...params,\n self: typeof params.self === 'string' ? bareId(params.self) : params.self,\n parent: typeof params.parent === 'string' ? bareId(params.parent) : params.parent,\n ancestors: Array.isArray(params.ancestors)\n ? params.ancestors.map((a) => (typeof a === 'string' ? bareId(a) : a))\n : params.ancestors,\n state: stripStateForLake(params.state),\n }\n}\n\nfunction stripStateForLake(value: unknown): unknown {\n if (value === null || value === undefined) return value\n if (typeof value === 'string') return bareId(value)\n if (Array.isArray(value)) return value.map(stripStateForLake)\n if (typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = stripStateForLake(v)\n }\n return out\n }\n return value\n}\n\nfunction bareId(id: string): string {\n return isGdrUri(id) ? extractDocumentId(id) : id\n}\n","/** Hex-encoded random key, sliced to {@link length} chars. Used for every\n * Sanity array `_key` and document id suffix the engine mints. */\nexport function randomKey(length = 12): string {\n const bytes = new Uint8Array(length)\n globalThis.crypto.getRandomValues(bytes)\n return [...bytes]\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n .slice(0, length)\n}\n","/**\n * Pure filter evaluation.\n *\n * Takes a filter (inline GROQ or named-predicate ref), a definition\n * (for predicate lookup + arg validation), a hydrated snapshot, and a\n * param bag. Runs groq-js against the snapshot. Returns boolean.\n *\n * NO CLIENT. NO I/O. NO LAKE FALLBACK.\n *\n * Filters evaluate against whatever the shell handed us — never against\n * the network. Purity is what lets the evaluator compose reactively: an\n * observable's snapshot updates can pipe straight into this function,\n * which a client-taking evaluator could not. If a filter references a\n * doc the shell didn't hydrate, groq-js sees a hole and the predicate\n * evaluates accordingly (usually false / null). Hydration completeness\n * is the shell's responsibility, not the core's.\n *\n * Discovery queries (`*[_type == 'X' && ...]` — spawn `forEach.groq`,\n * cross-doc lake scans) are NOT filters. They live in a separate shell\n * primitive (`discoverItems`) and never come through here.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport type {Filter, Predicate, WorkflowDefinition} from '../define/schema.ts'\nimport {isGdr} from './refs.ts'\nimport type {HydratedSnapshot} from './snapshot.ts'\n\nexport interface EvaluateFilterArgs {\n filter: Filter | undefined\n definition: WorkflowDefinition\n snapshot: HydratedSnapshot\n params: Record<string, unknown>\n}\n\n/**\n * Evaluate a filter against the supplied snapshot. Returns true when no\n * filter is set (vacuous truth). Throws on a malformed named ref or\n * invalid predicate args — those are author bugs, not runtime\n * conditions.\n */\nexport async function evaluateFilter(args: EvaluateFilterArgs): Promise<boolean> {\n const {filter, definition, snapshot, params} = args\n if (filter === undefined) return true\n\n if (typeof filter === 'string') {\n return runGroqAgainstSnapshot(filter, params, snapshot)\n }\n\n const predicate = (definition.predicates ?? []).find((p) => p.id === filter.ref)\n if (predicate === undefined) {\n throw new Error(`Unknown predicate ref: ${filter.ref}`)\n }\n validatePredicateArgs(predicate, filter.args ?? {})\n\n const merged = {...params, ...filter.args}\n return runGroqAgainstSnapshot(predicate.groq, merged, snapshot)\n}\n\nasync function runGroqAgainstSnapshot(\n groq: string,\n params: Record<string, unknown>,\n snapshot: HydratedSnapshot,\n): Promise<boolean> {\n // No `*`? Pure-param query. Empty dataset is fine.\n if (!groq.includes('*')) {\n const tree = parse(groq, {params})\n const value = await evaluate(tree, {params})\n return Boolean(await value.get())\n }\n // `*`-touching query. Evaluate against the in-memory snapshot.\n const tree = parse(groq, {params})\n const value = await evaluate(tree, {dataset: snapshot.docs, params})\n return Boolean(await value.get())\n}\n\nfunction validatePredicateArgs(predicate: Predicate, args: Record<string, unknown>): void {\n for (const param of predicate.params ?? []) {\n validatePredicateParam(predicate.id, param, args)\n }\n}\n\ntype PredicateParam = NonNullable<Predicate['params']>[number]\n\nfunction validatePredicateParam(\n predicateId: string,\n param: PredicateParam,\n args: Record<string, unknown>,\n): void {\n if (!(param.id in args)) {\n throw new Error(`Predicate \"${predicateId}\" requires param \"${param.id}\"`)\n }\n const value = args[param.id]\n if (!matchesParamType(param.type, value)) {\n throw new Error(\n `Predicate \"${predicateId}\" param \"${param.id}\" must be of type ${param.type}; got ${describeValue(value)}`,\n )\n }\n if (param.enum && !param.enum.includes(value as string)) {\n throw new Error(\n `Predicate \"${predicateId}\" param \"${param.id}\" must be one of ${param.enum.join(', ')}; got \"${String(value)}\"`,\n )\n }\n}\n\nfunction matchesParamType(type: PredicateParam['type'], value: unknown): boolean {\n switch (type) {\n case 'string':\n return typeof value === 'string'\n case 'number':\n return typeof value === 'number'\n case 'boolean':\n return typeof value === 'boolean'\n case 'string[]':\n return Array.isArray(value) && value.every((v) => typeof v === 'string')\n case 'reference':\n return isGdr(value)\n }\n}\n\nfunction describeValue(value: unknown): string {\n if (Array.isArray(value)) return 'array'\n if (value === null) return 'null'\n return typeof value\n}\n","/**\n * Pure snapshot construction.\n *\n * A `HydratedSnapshot` is an in-memory groq-js dataset of docs the\n * engine evaluator can query without touching the network. Inside it,\n * **every identity is a GDR URI** — `_id` on each top-level doc AND\n * every nested `_ref` value. That uniformity is what lets the snapshot\n * behave like a real groq-js store: `*[_id == $subject][0].team->name`\n * deref works because `_ref` URIs and `_id` URIs are in the same form;\n * `*[_id in $ancestors]...` joins work because both ends speak URI.\n *\n * The CORE rule: ids are rewritten in the snapshot, NEVER in the\n * underlying storage. Persistence stays bare. Sanity rejects `:` in\n * `_id`s, and `_ref` values inside stored docs are the bare ids Sanity\n * validated on write. The URI form is a runtime concept; the bench /\n * shell loads docs in their storage form and hands them to the core,\n * which restamps them for snapshot keying.\n *\n * **A `_ref` inside a doc is always assumed to point at a doc in the\n * same resource as its containing doc** — that's how Sanity\n * references work (same dataset, validated on write). The rewriter\n * uses the parent doc's resource to construct the GDR URI for each\n * nested `_ref`. Cross-resource refs would need an explicit envelope\n * (out of scope for now).\n */\n\nimport type {SanityDocument} from '@sanity/types'\n\nimport {gdrFromResource, type WorkflowResource} from './refs.ts'\n\n/**\n * The in-memory groq-js dataset filters evaluate against. Built once\n * per cascade entry (in the shell), passed through to `evaluateFilter`\n * (in the core) for every filter check.\n */\nexport interface HydratedSnapshot {\n /** All hydrated docs, keyed by GDR URI as `_id`. */\n docs: SanityDocument[]\n /**\n * The set of GDR URIs present in `docs`. Helpful for tests and shells\n * that want to assert \"is this doc in scope?\" — the core eval pipeline\n * itself doesn't read it.\n */\n knownIds: Set<string>\n}\n\n/**\n * One loaded doc plus the resource it came from. The shell builds\n * this list by routing reads to the right client for each doc, then\n * hands it to `buildSnapshot`.\n */\nexport interface LoadedDoc {\n doc: SanityDocument\n resource: WorkflowResource\n}\n\n/**\n * Build a snapshot from a set of loaded docs. Pure transform.\n *\n * For each `LoadedDoc { doc, resource }`:\n * - The doc's `_id` is rewritten to `gdrFromResource(resource, _id)`.\n * - Every nested `_ref` value (recursively, through objects and arrays)\n * is rewritten the same way: bare ref → URI in the parent's resource.\n * Already-qualified `_ref` URIs (containing `:`) are left alone.\n *\n * Plain string fields, numbers, booleans — anything that isn't an\n * object with a `_ref` field — pass through untouched. The rewriter is\n * structural, not schema-aware: only the `_ref` field on an object is\n * treated as a Sanity reference. Everything else is user data.\n */\nexport function buildSnapshot(args: {docs: LoadedDoc[]}): HydratedSnapshot {\n const docs: SanityDocument[] = []\n const knownIds = new Set<string>()\n for (const {doc, resource} of args.docs) {\n const uri = gdrFromResource(resource, doc._id)\n const restamped = restampForSnapshot(doc, uri, resource)\n docs.push(restamped)\n knownIds.add(uri)\n }\n return {docs, knownIds}\n}\n\n/**\n * Restamp a single doc for the snapshot — rewrite `_id` to the given\n * GDR URI, recursively rewrite every nested `_ref` to a GDR URI in the\n * doc's own resource. Pure; doesn't mutate the input.\n */\nfunction restampForSnapshot<T extends SanityDocument>(\n doc: T,\n gdrUri: string,\n resource: WorkflowResource,\n): T {\n const rewritten = rewriteRefsRecursive(doc, resource) as T\n return {...rewritten, _id: gdrUri}\n}\n\n/**\n * Walk an arbitrary JSON-ish value and rewrite every `_ref` field on\n * an object to its GDR URI form (in `resource`). Other fields and\n * non-object values pass through unchanged.\n */\nfunction rewriteRefsRecursive(value: unknown, resource: WorkflowResource): unknown {\n if (Array.isArray(value)) {\n return value.map((v) => rewriteRefsRecursive(v, resource))\n }\n if (value === null || typeof value !== 'object') return value\n const obj = value as Record<string, unknown>\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (k === '_ref' && typeof v === 'string') {\n // Already-qualified URIs (cross-resource refs) pass through.\n out[k] = v.includes(':') ? v : gdrFromResource(resource, v)\n } else {\n out[k] = rewriteRefsRecursive(v, resource)\n }\n }\n return out\n}\n","/**\n * Shell-side snapshot hydration.\n *\n * The core defines `HydratedSnapshot`, `LoadedDoc`, and the pure\n * `buildSnapshot` transform (recursive `_ref` + `_id` rewriting to\n * GDR URIs). This module does the I/O: route each read to the right\n * resource client, gather loaded docs with their resource attribution,\n * hand the list to `buildSnapshot`.\n *\n * **Scope rule (the contract):** a doc is in the snapshot iff it is\n * - the workflow instance itself,\n * - any ancestor doc (from `instance.ancestors[].id`),\n * - or a doc declared by a `workflow.state.doc.ref` / `.doc.refs`\n * slot on the workflow OR the current stage.\n *\n * Authors who want their filters to read a referenced doc via `->`\n * deref MUST declare a doc.ref / doc.refs slot pointing at it. The\n * shell loads exactly what's declared; the core rewrites refs purely\n * over that set. No transitive crawling; no surprise hops.\n */\n\nimport type {SanityDocument} from '@sanity/types'\n\nimport {parseGdr, selfGdr, type ParsedGdr, type WorkflowResource} from './core/refs.ts'\nimport {buildSnapshot, type HydratedSnapshot, type LoadedDoc} from './core/snapshot.ts'\nimport type {WorkflowDefinition} from './define/schema.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\n/**\n * Build the in-memory snapshot for filter evaluation on the instance's\n * current stage. Routed reads, then pure construction.\n *\n * Failures (ACL denied, doc missing, routed client throws) are\n * swallowed — the doc just isn't in the snapshot. Predicates\n * referencing it will see `null` / empty results.\n */\nexport async function hydrateSnapshot(args: {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n /**\n * Optional — if supplied, the shell uses this to find the current\n * stage's declared `doc.ref` / `doc.refs` slots and pulls those docs\n * into scope. When omitted, only instance + subject + ancestors\n * are loaded (e.g. `workflow.evaluate` callers that just want the\n * basic three).\n */\n definition?: WorkflowDefinition\n}): Promise<HydratedSnapshot> {\n const {client, clientForGdr, instance, definition} = args\n const loaded: LoadedDoc[] = []\n const visited = new Set<string>()\n\n const loadInto = async (uri: string): Promise<void> => {\n if (visited.has(uri)) return\n const fetched = await loadByGdr(client, clientForGdr, instance.workflowResource, uri)\n if (fetched) {\n loaded.push(fetched)\n visited.add(uri)\n }\n }\n\n // 1. The instance itself. Resource = its own workflowResource. Key it\n // with the same GDR-URI form `buildSnapshot` uses, so a self-\n // referential ancestor/slot dedups against it.\n loaded.push({doc: instance, resource: instance.workflowResource})\n visited.add(selfGdr(instance))\n\n // 2. Ancestors.\n for (const ancestor of instance.ancestors) {\n await loadInto(ancestor.id)\n }\n\n // 3. Workflow-level state slots — every `doc.ref` / `doc.refs` slot\n // pulled into scope. No slot is privileged; the engine doesn't\n // care what they're named.\n for (const uri of collectSlotDocUris(instance.state)) {\n await loadInto(uri)\n }\n\n // 4. Stage-declared `doc.ref` / `doc.refs` slots — only the current\n // stage's entry. These are the docs the author declared as \"in\n // scope for filters on THIS stage.\"\n if (definition) {\n const stageEntry = instance.stages.find(\n (s) => s.id === instance.currentStageId && s.exitedAt === undefined,\n )\n for (const uri of collectSlotDocUris(stageEntry?.state)) {\n await loadInto(uri)\n }\n }\n\n return buildSnapshot({docs: loaded})\n}\n\nasync function loadByGdr(\n defaultClient: WorkflowClient,\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient,\n defaultResource: WorkflowResource,\n uri: string,\n): Promise<LoadedDoc | null> {\n let parsed: ParsedGdr\n try {\n parsed = parseGdr(uri)\n } catch {\n // Not a GDR URI — load the value directly against the default\n // client. Without a parsed GDR we can't know the resource, so we\n // attribute the doc to the default client's own resource.\n const doc = await defaultClient.getDocument<SanityDocument>(uri)\n if (!doc) return null\n return {doc, resource: defaultResource}\n }\n const routed = clientForGdr(parsed)\n const doc = await routed.getDocument<SanityDocument>(parsed.documentId)\n if (!doc) return null\n return {doc, resource: resourceFromParsed(parsed)}\n}\n\nexport function resourceFromParsed(parsed: ParsedGdr): WorkflowResource {\n if (parsed.scheme === 'dataset') {\n return {type: 'dataset', id: `${parsed.projectId}.${parsed.dataset}`}\n }\n return {type: parsed.scheme, id: parsed.resourceId ?? ''}\n}\n\n/**\n * Walk resolved state slots and collect every GDR URI mentioned by a\n * `doc.ref` or `doc.refs` slot's value. These are the docs the author\n * declared should be in scope for filters.\n */\nexport function collectSlotDocUris(resolvedStateSlots: unknown): string[] {\n if (!Array.isArray(resolvedStateSlots)) return []\n return resolvedStateSlots.flatMap(slotDocUris)\n}\n\nfunction slotDocUris(slot: unknown): string[] {\n if (!slot || typeof slot !== 'object') return []\n const s = slot as {_type?: string; value?: unknown}\n if (s._type === 'workflow.state.doc.ref') {\n const v = s.value as {id?: string} | null | undefined\n const id = refId(v)\n return id !== undefined ? [id] : []\n }\n if (s._type === 'workflow.state.doc.refs') {\n const v = s.value as {id?: string}[] | null | undefined\n if (!Array.isArray(v)) return []\n return v.map(refId).filter((id): id is string => id !== undefined)\n }\n return []\n}\n\nfunction refId(ref: {id?: string} | null | undefined): string | undefined {\n return ref && typeof ref.id === 'string' ? ref.id : undefined\n}\n","/**\n * Walk a dot-separated property path into a value, returning `undefined` at\n * the first non-object link. Pure; shared by binding resolution, state-slot\n * path dives, and op-predicate field reads.\n */\nexport function getPath(value: unknown, path: string): unknown {\n let current: unknown = value\n for (const part of path.split('.')) {\n if (current === undefined || current === null || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n","/**\n * Per-slot-type value validation.\n *\n * Every write into a typed slot must match the slot's declared shape.\n * The validator is called at three boundaries:\n *\n * 1. `workflow.op.state.set` — full-value replace on any slot\n * 2. `workflow.op.state.append` — one-item push on array slots\n * 3. `resolveDeclaredState` — init / literal / stateRead / query\n *\n * `validateSlotValue` checks a complete slot value against the slot\n * type's shape (scalar or array-of-items, depending on the kind).\n *\n * `validateSlotAppendItem` checks a single item against the slot's\n * row shape (only array slots support append).\n *\n * Both throw `SlotValueShapeError` with the slot id, slot type and a\n * brief description of the observed shape — so the cause is obvious\n * in test output, drive-script stdout, and the workflow history.\n *\n * Notes stays permissive (any object with optional `_key`) pending a\n * dedicated row-shape design.\n */\n\nimport * as v from 'valibot'\n\nimport {isGdrUri} from './refs.ts'\n\nclass SlotValueShapeError extends Error {\n readonly slotType: string\n readonly slotId: string\n readonly issues: string[]\n\n constructor(args: {slotType: string; slotId: string; issues: string[]; mode: 'value' | 'item'}) {\n const issueText = args.issues.join('; ')\n super(`Slot ${args.mode} shape invalid for \"${args.slotId}\" (${args.slotType}): ${issueText}`)\n this.name = 'SlotValueShapeError'\n this.slotType = args.slotType\n this.slotId = args.slotId\n this.issues = args.issues\n }\n}\n\n// Per-shape schemas — used both for whole-value and per-item validation.\n\nconst GdrShape = v.looseObject({\n id: v.pipe(\n v.string(),\n v.check((s) => isGdrUri(s), 'must be a GDR URI'),\n ),\n type: v.pipe(v.string(), v.minLength(1)),\n})\n\n// Release ref: a GDR to the `_.releases.<name>` system doc, plus the\n// bare release name the engine reads to derive perspective.\nconst ReleaseRefShape = v.looseObject({\n id: v.pipe(\n v.string(),\n v.check((s) => isGdrUri(s), 'must be a GDR URI'),\n ),\n type: v.literal('system.release'),\n releaseName: v.pipe(v.string(), v.minLength(1)),\n})\n\nconst ActorShape = v.looseObject({\n kind: v.picklist(['user', 'ai', 'system']),\n id: v.pipe(v.string(), v.minLength(1)),\n roles: v.optional(v.array(v.string())),\n onBehalfOf: v.optional(v.string()),\n})\n\nconst AssigneeShape = v.union([\n v.looseObject({kind: v.literal('user'), id: v.pipe(v.string(), v.minLength(1))}),\n v.looseObject({kind: v.literal('role'), role: v.pipe(v.string(), v.minLength(1))}),\n])\n\nconst ChecklistItemShape = v.looseObject({\n label: v.pipe(v.string(), v.minLength(1)),\n done: v.boolean(),\n doneBy: v.optional(v.string()),\n doneAt: v.optional(v.string()),\n _key: v.optional(v.pipe(v.string(), v.minLength(1))),\n})\n\n// Notes are intentionally loose pending the row-shape design.\nconst NoteItemShape = v.pipe(\n v.looseObject({\n _key: v.optional(v.pipe(v.string(), v.minLength(1))),\n }),\n v.check(\n (val) => typeof val === 'object' && val !== null && !Array.isArray(val),\n 'must be an object',\n ),\n)\n\n// Scalars that allow null (write-sourced slots default to null until written).\nconst NullableString = v.union([v.null(), v.string()])\nconst NullableNumber = v.union([v.null(), v.number()])\nconst NullableBoolean = v.union([v.null(), v.boolean()])\n\n// dateTime: stricter than plain string — must parse as ISO-8601.\nconst NullableDateTime = v.union([\n v.null(),\n v.pipe(\n v.string(),\n v.check((s) => !Number.isNaN(Date.parse(s)), 'must be an ISO-8601 datetime string'),\n ),\n])\n\n// URL: loose — accept any non-empty string. Tightening later is easy;\n// loosening would break already-stored values.\nconst NullableUrl = NullableString\n\n// Whole-value schemas, keyed by slot type.\n\nconst valueSchemas = {\n 'workflow.state.doc.ref': v.union([v.null(), GdrShape]),\n 'workflow.state.doc.refs': v.array(GdrShape),\n 'workflow.state.release.ref': v.union([v.null(), ReleaseRefShape]),\n 'workflow.state.query': v.any(),\n 'workflow.state.value.string': NullableString,\n 'workflow.state.value.url': NullableUrl,\n 'workflow.state.value.number': NullableNumber,\n 'workflow.state.value.boolean': NullableBoolean,\n 'workflow.state.value.dateTime': NullableDateTime,\n 'workflow.state.value.actor': v.union([v.null(), ActorShape]),\n 'workflow.state.checklist': v.array(ChecklistItemShape),\n 'workflow.state.notes': v.array(NoteItemShape),\n 'workflow.state.assignees': v.array(AssigneeShape),\n} as const\n\n// Per-item schemas for `workflow.op.state.append`. Scalar slot types\n// don't support append — callers asking for them get an error.\n\nconst itemSchemas = {\n 'workflow.state.doc.refs': GdrShape,\n 'workflow.state.checklist': ChecklistItemShape,\n 'workflow.state.notes': NoteItemShape,\n 'workflow.state.assignees': AssigneeShape,\n} as const\n\ntype AppendableSlotType = keyof typeof itemSchemas\n\nfunction isAppendable(slotType: string): slotType is AppendableSlotType {\n return slotType in itemSchemas\n}\n\n// Public API.\n\nexport function validateSlotValue(args: {slotType: string; slotId: string; value: unknown}): void {\n const schema = (valueSchemas as Record<string, v.GenericSchema>)[args.slotType]\n if (schema === undefined) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: [`unknown slot type ${args.slotType}`],\n mode: 'value',\n })\n }\n const result = v.safeParse(schema, args.value)\n if (!result.success) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: formatIssues(result.issues),\n mode: 'value',\n })\n }\n}\n\nexport function validateSlotAppendItem(args: {\n slotType: string\n slotId: string\n item: unknown\n}): void {\n if (!isAppendable(args.slotType)) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: [`slot type ${args.slotType} does not support append`],\n mode: 'item',\n })\n }\n const schema = itemSchemas[args.slotType]\n const result = v.safeParse(schema, args.item)\n if (!result.success) {\n throw new SlotValueShapeError({\n slotType: args.slotType,\n slotId: args.slotId,\n issues: formatIssues(result.issues),\n mode: 'item',\n })\n }\n}\n\nfunction formatIssues(issues: readonly v.BaseIssue<unknown>[]): string[] {\n return issues.map((i) => {\n const keys = i.path?.map((p) => p.key) ?? []\n const path = keys.length > 0 ? `at ${keys.join('.')}: ` : ''\n return `${path}${i.message}`\n })\n}\n","/**\n * Resolve a definition's `state[]` declarations into `ResolvedStateSlot`s.\n *\n * Shared by:\n * - `workflow.startInstance` (workflow-scope state)\n * - engine stage entry (stage-scope state on StageEntry)\n * - engine task activation (task-scope state on TaskEntry)\n *\n * Source-kind semantics:\n * - `kind: \"init\"` reads from caller-supplied `initialState`.\n * - `kind: \"query\"` runs the slot's GROQ against the lake via the\n * supplied client; result lands as the slot value with `resolvedAt`\n * stamped on `workflow.state.query` slots.\n * - `kind: \"write\"` defaults to null (scalars) or `[]` (array kinds);\n * ops fill it later.\n */\n\nimport {paramsForLake} from './core/params.ts'\nimport {getPath} from './core/path.ts'\nimport {gdrFromResource, isGdrUri, type WorkflowResource} from './core/refs.ts'\nimport {validateSlotValue} from './core/slot-validation.ts'\nimport type {StateSlot} from './define/schema.ts'\nimport type {WorkflowClient, WorkflowPerspective} from './types/client.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from './types/state-slots.ts'\n\nexport interface ResolveStateContext {\n /** Lake client for `kind: \"query\"` slot evaluation. Omitted → query\n * slots fall back to their default value. */\n client?: WorkflowClient\n /**\n * Shell-supplied clock reading (ISO). Bound as `$now` for query-slot\n * GROQ and stamped as `resolvedAt` on `workflow.state.query` slots, so\n * state resolution shares the engine's single {@link Clock}.\n */\n now: string\n selfId?: string\n tags?: string[]\n /** Bound to `$stage` inside stage/task-scope query slots. */\n stageId?: string\n /** Bound to `$task` inside task-scope query slots. */\n taskId?: string\n /**\n * Already-resolved state slots in the SAME scope being resolved\n * right now. Exposed to subsequent query-sourced slots as\n * `$state.<slotId>`; also the lookup target for\n * `source: { kind: \"stateRead\", scope: \"stage\" }` on a sibling\n * stage-scope slot. Sequential resolution means slot N's source can\n * read slots 0..N-1 by id but not later ones.\n */\n resolvedState?: ResolvedStateSlot[]\n /**\n * Already-resolved workflow-scope state. Available when resolving\n * stage- or task-scope slots so a `source: { kind: \"stateRead\",\n * scope: \"workflow\" }` can read durable workflow-scope slots that\n * were resolved at `startInstance` time.\n */\n workflowState?: ResolvedStateSlot[]\n /**\n * Resource of the workflow itself. Used to canonicalize raw Sanity\n * reference shapes (`{_ref, _type}`) returned by `kind: \"query\"`\n * slots into GDR `{id, type}` form. Without this, a query-sourced\n * doc.ref slot would leave its value in the lake shape and the\n * snapshot hydrator wouldn't know to pull the referenced doc into\n * scope.\n */\n workflowResource?: WorkflowResource\n /**\n * Perspective for `kind: \"query\"` slot evaluation. Threaded through\n * to `client.fetch(..., { perspective })`. Lets a slot that runs\n * GROQ against the lake see a release-stacked view rather than the\n * published shadow. Unset → reads run under the client's default\n * perspective (which is `\"raw\"` on the test client and whatever the\n * caller configured on `@sanity/client`).\n */\n perspective?: WorkflowPerspective\n}\n\n/**\n * Derive a read perspective from resolved workflow-scope state: if any\n * `workflow.state.release.ref` slot has a value, return a single-release\n * stack `[releaseName]`. Returns `undefined` when no release slot is\n * populated, so callers can fall back to an explicit perspective or\n * the engine default.\n *\n * The first populated release slot wins (workflows targeting more than\n * one release aren't modelled — a single release-ref slot is the\n * canonical shape). Pure: operates on already-resolved slots.\n */\nexport function derivePerspectiveFromState(\n slots: ResolvedStateSlot[] | undefined,\n): WorkflowPerspective | undefined {\n if (slots === undefined) return undefined\n for (const slot of slots) {\n if (slot._type === 'workflow.state.release.ref' && slot.value !== null) {\n const releaseName = slot.value.releaseName\n if (typeof releaseName === 'string' && releaseName.length > 0) {\n return [releaseName]\n }\n }\n }\n return undefined\n}\n\nexport async function resolveDeclaredState(args: {\n slotDefs: StateSlot[] | undefined\n initialState: InitialStateValue[]\n ctx: ResolveStateContext\n randomKey: () => string\n}): Promise<ResolvedStateSlot[]> {\n const {slotDefs, initialState, ctx, randomKey} = args\n if (slotDefs === undefined || slotDefs.length === 0) return []\n const out: ResolvedStateSlot[] = []\n for (const slot of slotDefs) {\n // Each slot sees the already-resolved ones via `$state.<slotId>`.\n const scopedCtx: ResolveStateContext = {...ctx, resolvedState: out}\n out.push(await resolveOneSlot(slot, initialState, scopedCtx, randomKey))\n }\n return out\n}\n\nconst ARRAY_SLOT_TYPES = new Set<StateSlot['type']>([\n 'workflow.state.doc.refs',\n 'workflow.state.checklist',\n 'workflow.state.notes',\n 'workflow.state.assignees',\n])\n\n/** Default for an unfilled slot: `[]` for array kinds, `null` otherwise. */\nfunction defaultSlotValue(slotType: StateSlot['type']): unknown {\n return ARRAY_SLOT_TYPES.has(slotType) ? [] : null\n}\n\n/**\n * Read a caller-supplied `init` value. Rejects bare doc ids at the\n * boundary: the engine stores GDR URIs throughout — callers MUST\n * construct full URIs (via `gdrFromResource` / `refDataset` / etc.)\n * before passing them into `initialState`. Silent canonicalisation\n * would mask the shape gap and let bare-id refs leak into snapshots,\n * where they mismatch every GDR-keyed lookup and break filters.\n */\nfunction resolveInitValue(\n slot: StateSlot,\n initialState: InitialStateValue[],\n defaultValue: unknown,\n): unknown {\n const initMatch = initialState.find((s) => s.id === slot.id && s.type === slot.type)\n if (initMatch === undefined) return defaultValue\n assertInitValueShape(slot, initMatch.value)\n return initMatch.value\n}\n\nfunction resolveStateReadValue(\n source: Extract<StateSlot['source'], {kind: 'stateRead'}>,\n ctx: ResolveStateContext,\n defaultValue: unknown,\n): unknown {\n const slotsForScope =\n source.scope === 'workflow' ? (ctx.workflowState ?? []) : (ctx.resolvedState ?? [])\n const target = slotsForScope.find((s) => s.id === source.slotId)\n const targetValue = target === undefined ? undefined : (target as {value?: unknown}).value\n const resolved = source.path !== undefined ? getPath(targetValue, source.path) : targetValue\n return resolved === undefined || resolved === null ? defaultValue : resolved\n}\n\n/**\n * Run a `query` slot's GROQ against the lake. Params carry GDR URIs\n * (snapshot form) but are stripped to bare for the fetch — same pattern\n * as filter evaluation's lake fallback: the lake stores bare `_id`s, so\n * `$state.<slot>.value.id` etc. must be bare too.\n *\n * `$state` exposes slots already resolved before this one (sequential\n * resolution). Cyclic references to later slots produce `undefined` in\n * GROQ and the slot falls through to its default.\n */\nasync function resolveQueryValue(\n slot: StateSlot,\n source: Extract<StateSlot['source'], {kind: 'query'}>,\n ctx: ResolveStateContext,\n client: WorkflowClient,\n defaultValue: unknown,\n): Promise<unknown> {\n const params = paramsForLake({\n self: ctx.selfId ?? null,\n state: stateMapFromResolved(ctx.resolvedState ?? []),\n stage: ctx.stageId ?? null,\n task: ctx.taskId ?? null,\n now: ctx.now,\n engineTags: ctx.tags ?? [],\n })\n try {\n const fetchOptions = ctx.perspective !== undefined ? {perspective: ctx.perspective} : undefined\n const result = await client.fetch<unknown>(source.query, params, fetchOptions)\n return normalizeQueryResult(slot.type, result, ctx.workflowResource) ?? defaultValue\n } catch (err) {\n throw new Error(\n `Failed to resolve query slot \"${slot.id}\" (${slot.type}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n {cause: err},\n )\n }\n}\n\nasync function resolveSlotValue(\n slot: StateSlot,\n initialState: InitialStateValue[],\n ctx: ResolveStateContext,\n defaultValue: unknown,\n): Promise<unknown> {\n const source = slot.source\n if (source.kind === 'init') return resolveInitValue(slot, initialState, defaultValue)\n if (source.kind === 'literal') return source.value ?? defaultValue\n if (source.kind === 'stateRead') return resolveStateReadValue(source, ctx, defaultValue)\n if (source.kind === 'query' && ctx.client !== undefined) {\n return resolveQueryValue(slot, source, ctx, ctx.client, defaultValue)\n }\n // \"write\" (and \"query\" without a client) use defaults.\n return defaultValue\n}\n\n/** Build the persisted slot envelope; `query` slots carry `resolvedAt`. */\nfunction buildResolvedSlot(\n slot: StateSlot,\n value: unknown,\n _key: string,\n now: string,\n): ResolvedStateSlot {\n const titleProp = slot.title !== undefined ? {title: slot.title} : {}\n const descriptionProp = slot.description !== undefined ? {description: slot.description} : {}\n if (slot.type === 'workflow.state.query') {\n return {\n _key,\n _type: 'workflow.state.query',\n id: slot.id,\n ...titleProp,\n ...descriptionProp,\n value,\n resolvedAt: now,\n }\n }\n return {\n _key,\n _type: slot.type,\n id: slot.id,\n ...titleProp,\n ...descriptionProp,\n value,\n } as ResolvedStateSlot\n}\n\nasync function resolveOneSlot(\n slot: StateSlot,\n initialState: InitialStateValue[],\n ctx: ResolveStateContext,\n randomKey: () => string,\n): Promise<ResolvedStateSlot> {\n const defaultValue = defaultSlotValue(slot.type)\n const value = await resolveSlotValue(slot, initialState, ctx, defaultValue)\n\n // Validate the resolved value against the slot's declared shape.\n // The `value.query` slot type is permissive (escape hatch). Default\n // values (null / []) are always shape-valid; init/literal/stateRead/\n // query may have produced something else — catch shape mismatches\n // here before they leak into the persisted snapshot.\n validateSlotValue({slotType: slot.type, slotId: slot.id, value})\n\n return buildResolvedSlot(slot, value, randomKey(), ctx.now)\n}\n\n/** Project resolved slots into the `$state` shape (slotId → slot envelope). */\nfunction stateMapFromResolved(slots: ResolvedStateSlot[]): Record<string, ResolvedStateSlot> {\n const out: Record<string, ResolvedStateSlot> = {}\n for (const s of slots) out[s.id] = s\n return out\n}\n\n/**\n * Validate caller-supplied `initialState` values for shape correctness\n * BEFORE they hit the persisted instance. Init-sourced doc.ref /\n * doc.refs slots reject bare-string `id`s — the engine stores GDR\n * URIs everywhere and a bare id silently mismatches snapshots later.\n * Throws a clear error pointing at the slot id + bad value.\n *\n * Query-sourced values are NOT validated here; the lake returns\n * various shapes and {@link normalizeQueryResult} is the only path that\n * gets to canonicalise them.\n */\nfunction assertInitValueShape(slot: StateSlot, value: unknown): void {\n if (slot.type === 'workflow.state.doc.ref') {\n assertGdrShape(value, `state slot \"${slot.id}\" (workflow.state.doc.ref)`)\n return\n }\n if (slot.type === 'workflow.state.release.ref') {\n assertGdrShape(value, `state slot \"${slot.id}\" (workflow.state.release.ref)`)\n const v = value as {releaseName?: unknown}\n if (typeof v.releaseName !== 'string' || v.releaseName.length === 0) {\n throw new Error(\n `Invalid init value for state slot \"${slot.id}\" (workflow.state.release.ref): ` +\n `\\`releaseName\\` must be a non-empty string. Got ${JSON.stringify(v.releaseName)}.`,\n )\n }\n return\n }\n if (slot.type === 'workflow.state.doc.refs') {\n if (!Array.isArray(value)) {\n throw new Error(\n `Invalid init value for state slot \"${slot.id}\" (workflow.state.doc.refs): expected an array of GDRs, got ${typeof value}.`,\n )\n }\n for (const [i, item] of value.entries()) {\n assertGdrShape(item, `state slot \"${slot.id}\" (workflow.state.doc.refs) item [${i}]`)\n }\n }\n}\n\nfunction assertGdrShape(value: unknown, context: string): void {\n if (typeof value !== 'object' || value === null) {\n throw new Error(\n `Invalid GDR for ${context}: expected { id: \"<scheme>:...\", type: \"<schema>\" }, got ${typeof value}.`,\n )\n }\n const v = value as {id?: unknown; type?: unknown}\n if (typeof v.id !== 'string' || !isGdrUri(v.id)) {\n throw new Error(\n `Invalid GDR for ${context}: \\`id\\` must be a GDR URI (\"<scheme>:<...id-parts>\" with scheme dataset|canvas|media-library|dashboard). ` +\n `Got ${JSON.stringify(v.id)}. Construct via \\`gdrFromResource\\` / \\`refDataset\\` / \\`refCanvas\\` etc. — bare document ids are not accepted.`,\n )\n }\n if (typeof v.type !== 'string' || v.type.length === 0) {\n throw new Error(\n `Invalid GDR for ${context}: \\`type\\` (schema name) must be a non-empty string. Got ${JSON.stringify(v.type)}.`,\n )\n }\n}\n\n/**\n * Convert a raw GROQ result into the slot's expected value shape.\n *\n * For `doc.ref` / `doc.refs` slots, the engine's internal contract is\n * a GDR `{id, type}` object. But a natural query like\n * `*[_id == $subject][0].primaryTeam` returns the Sanity reference\n * shape `{_ref, _type: \"reference\"}` — bare `_ref`, generic `_type`.\n * Convert it: GDR id = `gdrFromResource(workflowResource, _ref)`,\n * GDR type = \"document\" (the target doc's real schema type isn't\n * carried by the ref envelope; consumers shouldn't depend on it for\n * the slot value's `type` field).\n *\n * Already-GDR-shaped values (with `id` + `type`) pass through. Bare\n * strings are treated as doc ids and wrapped. Arrays are walked for\n * the refs case. Other slot kinds pass through unchanged.\n */\nfunction normalizeQueryResult(\n slotType: StateSlot['type'],\n raw: unknown,\n workflowResource: WorkflowResource | undefined,\n): unknown {\n if (raw === null || raw === undefined) return raw\n if (slotType === 'workflow.state.doc.ref') {\n return coerceToGdr(raw, workflowResource)\n }\n if (slotType === 'workflow.state.doc.refs') {\n if (!Array.isArray(raw)) return []\n return raw.map((item) => coerceToGdr(item, workflowResource)).filter((v) => v !== null)\n }\n return raw\n}\n\ntype Gdr = {id: import('./core/refs.ts').GdrUri; type: string}\n\n/** Resolve a doc id (bare or already-URI) to a GDR URI via the resource. */\nfunction toGdrUri(\n docId: string,\n workflowResource: WorkflowResource,\n): import('./core/refs.ts').GdrUri {\n return isGdrUri(docId) ? docId : gdrFromResource(workflowResource, docId)\n}\n\n/**\n * Coerce an already-GDR-shaped `{id, type}` value. The id must be a\n * known-scheme URI to pass through; otherwise it's a bare id from a\n * non-canonical source and we re-derive it via the resource. Returns\n * null when the shape doesn't match so callers fall through.\n */\nfunction coerceGdrShape(raw: object, workflowResource: WorkflowResource | undefined): Gdr | null {\n if (!('id' in raw) || !('type' in raw)) return null\n const r = raw as {id: unknown; type: unknown}\n if (typeof r.id !== 'string' || typeof r.type !== 'string') return null\n if (isGdrUri(r.id)) return {id: r.id, type: r.type}\n if (workflowResource) return {id: gdrFromResource(workflowResource, r.id), type: r.type}\n return null\n}\n\n/**\n * Coerce a Sanity reference envelope `{_ref, _type: \"reference\"}` to a\n * GDR. Without `workflowResource` there's no way to construct the URI;\n * returns null and lets the snapshot hydrator skip the slot.\n */\nfunction coerceRefEnvelope(\n raw: object,\n workflowResource: WorkflowResource | undefined,\n): Gdr | null {\n if (!('_ref' in raw)) return null\n const r = raw as {_ref: unknown}\n if (typeof r._ref !== 'string' || !workflowResource) return null\n return {id: toGdrUri(r._ref, workflowResource), type: 'document'}\n}\n\nfunction coerceToGdr(raw: unknown, workflowResource: WorkflowResource | undefined): Gdr | null {\n if (raw === null || raw === undefined) return null\n if (typeof raw === 'object') {\n return coerceGdrShape(raw, workflowResource) ?? coerceRefEnvelope(raw, workflowResource)\n }\n // Bare string — assume doc id in the workflow resource.\n if (typeof raw === 'string' && workflowResource) {\n return {id: toGdrUri(raw, workflowResource), type: 'document'}\n }\n return null\n}\n","import {type Clock, wallClock} from '../clock.ts'\nimport {evaluateFilter} from '../core/eval.ts'\nimport {buildParams} from '../core/params.ts'\nimport {extractDocumentId, type ParsedGdr} from '../core/refs.ts'\nimport type {HydratedSnapshot} from '../core/snapshot.ts'\nimport type {Filter, Stage, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport {resolveDeclaredState} from '../state-resolution.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {StageId} from '../types/ids.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from '../types/state-slots.ts'\n\n/**\n * Convert a GDR URI back to a bare document id. The engine's\n * cross-resource reference fields (`ancestors[].id`,\n * `spawnedInstances[].id`) carry full GDR URIs; the persistent `_id`\n * on disk is bare. Use this when fetching a referenced doc from Sanity.\n */\nexport function gdrToBareId(uri: string): string {\n return uri.includes(':') ? extractDocumentId(uri) : uri\n}\n\n// Internal — context load\n\nexport interface EngineContext {\n /** Engine's own client — bound to the workflow resource. */\n client: WorkflowClient\n /**\n * The single clock reading for this operation, taken once when the\n * context is built. EVERY \"now\" the engine stamps in this context —\n * `$now` in filters, the `now` op-source, all history `at`,\n * `completedAt`, `enteredAt`, `lastChangedAt` — reads {@link EngineContext.now},\n * so the whole operation shares one instant rather than drifting across\n * repeated wall-clock reads.\n */\n now: string\n /**\n * The {@link Clock} this context was built from, carried so nested\n * operations the context spawns (child priming + cascade inside\n * `persist`) read the SAME clock. Stamps use {@link EngineContext.now},\n * not this — call it only to seed a fresh context. Defaults to\n * {@link wallClock}.\n */\n clock: Clock\n /**\n * Route a cross-resource read by parsed GDR. Returns the engine's\n * own client when the resolver doesn't have an entry. The cascade\n * uses this for subject + ancestor loads.\n */\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n /**\n * GDR-keyed snapshot of docs hydrated at cascade entry — instance,\n * subject (if cross-resource and reachable), ancestors. Always\n * present: `loadContext` builds it via `hydrateSnapshot`. Filters\n * evaluate against this snapshot (pure, no lake fallback). The shell\n * is responsible for completeness — anything not hydrated is invisible\n * to the filter.\n */\n snapshot: HydratedSnapshot\n}\n\nexport async function loadContext(\n client: WorkflowClient,\n instanceId: string,\n options?: {clientForGdr?: (parsed: ParsedGdr) => WorkflowClient; clock?: Clock},\n): Promise<EngineContext> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) {\n throw new Error(`Workflow instance ${instanceId} not found`)\n }\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const clientForGdr = options?.clientForGdr ?? (() => client)\n const clock = options?.clock ?? wallClock\n const snapshot = await hydrateSnapshot({client, clientForGdr, instance, definition})\n return {client, clientForGdr, clock, now: clock(), instance, definition, snapshot}\n}\n\n/** Evaluate a filter against the context's definition + hydrated\n * snapshot, with the instance's reserved params bound. An undefined\n * filter is vacuously true (see {@link evaluateFilter}). */\nexport function ctxEvaluateFilter(\n ctx: EngineContext,\n filter: Filter | undefined,\n): Promise<boolean> {\n return evaluateFilter({\n filter,\n definition: ctx.definition,\n snapshot: ctx.snapshot,\n params: buildParams(ctx.instance, ctx.now),\n })\n}\n\n/** Assemble an {@link EngineContext} for an already-loaded instance,\n * hydrating its snapshot. Used by the post-prime + propagation paths\n * that re-read the instance mid-cascade. */\nexport async function buildEngineContext(args: {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n clock?: Clock\n}): Promise<EngineContext> {\n const {client, clientForGdr, instance, definition} = args\n const clock = args.clock ?? wallClock\n return {\n client,\n clientForGdr,\n clock,\n now: clock(),\n instance,\n definition,\n snapshot: await hydrateSnapshot({client, clientForGdr, instance, definition}),\n }\n}\n\nexport function findStage(definition: WorkflowDefinition, stageId: StageId): Stage {\n const stage = definition.stages.find((s) => s.id === stageId)\n if (stage === undefined) {\n throw new Error(`Stage \"${stageId}\" not found in definition ${definition.workflowId}`)\n }\n return stage\n}\n\n/**\n * Build the per-stage resolved state[] from the stage definition + an\n * optional `initialState` (e.g. supplied to `setStage`). Bound to the\n * instance's subject and to `$stage = stage.id`.\n */\nexport async function resolveStageStateSlots(args: {\n client: WorkflowClient\n instance: WorkflowInstance\n stage: Stage\n now: string\n initialState?: InitialStateValue[]\n}): Promise<ResolvedStateSlot[]> {\n const {client, instance, stage, now, initialState} = args\n return resolveDeclaredState({\n slotDefs: stage.state,\n initialState: initialState ?? [],\n ctx: {\n client,\n now,\n selfId: instance._id,\n tags: instance.tags ?? [],\n stageId: stage.id,\n workflowResource: instance.workflowResource,\n // Allow stage-scope slots' `source: { kind: \"stateRead\", scope:\n // \"workflow\", ... }` to see the already-resolved workflow-scope\n // state.\n workflowState: instance.state ?? [],\n ...(instance.perspective !== undefined ? {perspective: instance.perspective} : {}),\n },\n randomKey,\n })\n}\n\n/** Same shape as `resolveStageStateSlots` but scoped to a task. */\nexport async function resolveTaskStateSlots(args: {\n client: WorkflowClient\n instance: WorkflowInstance\n stage: Stage\n task: Task\n now: string\n}): Promise<ResolvedStateSlot[]> {\n const {client, instance, stage, task, now} = args\n return resolveDeclaredState({\n slotDefs: task.state,\n initialState: [],\n ctx: {\n client,\n now,\n selfId: instance._id,\n tags: instance.tags ?? [],\n stageId: stage.id,\n workflowResource: instance.workflowResource,\n taskId: task.id,\n workflowState: instance.state ?? [],\n ...(instance.perspective !== undefined ? {perspective: instance.perspective} : {}),\n },\n randomKey,\n })\n}\n","/**\n * Pure state-slot reads.\n *\n * Given an instance and a `(scope, slotId)` address, return the resolved\n * slot's `value`. Workflow-scope reads hit `instance.state`; stage/task\n * reads resolve against the current (un-exited) stage entry and, for task\n * scope, the named task entry. No I/O.\n */\n\nimport type {StateScope} from '../types/enums.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\n\nexport function readStateSlot(\n instance: WorkflowInstance,\n scope: StateScope,\n slotId: string,\n stageId: string | undefined,\n taskId: string | undefined,\n): unknown {\n if (scope === 'workflow') {\n return slotValue(instance.state?.find((s) => s.id === slotId))\n }\n const stageEntry = instance.stages.find(\n (s) => s.id === (stageId ?? instance.currentStageId) && s.exitedAt === undefined,\n )\n if (stageEntry === undefined) return undefined\n if (scope === 'stage') {\n return slotValue(stageEntry.state?.find((s) => s.id === slotId))\n }\n const taskEntry = stageEntry.tasks.find((t) => t.id === taskId)\n return slotValue(taskEntry?.state?.find((s) => s.id === slotId))\n}\n\nfunction slotValue(slot: unknown): unknown {\n if (slot === undefined || slot === null) return undefined\n if (typeof slot !== 'object') return undefined\n return (slot as {value?: unknown}).value\n}\n","/**\n * Pure `Source` resolution.\n *\n * A `Source` value declared on effects, ops, and state-slot resolvers is\n * evaluated into a concrete value here. No GROQ, no client, no I/O — just\n * structural lookups against the instance + actor + caller params.\n *\n * Pure: `source: \"now\"` reads the shell-supplied `now` (the engine's\n * {@link Clock}), never wall-clock — so an op's `now` agrees with `$now`\n * in the same eval pass and a frozen clock keeps it deterministic.\n */\n\nimport type {Source} from '../define/schema.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {getPath} from './path.ts'\nimport {readStateSlot} from './state-read.ts'\n\nexport interface ResolveSourceContext {\n instance: WorkflowInstance\n params?: Record<string, unknown>\n actor?: Actor\n /** Shell-supplied clock reading (ISO) backing `source: \"now\"`. */\n now: string\n /**\n * When the Source is being evaluated in the scope of a specific stage\n * or task, provide their ids so `scope: \"stage\" | \"task\"` reads land\n * on the right state[].\n */\n stageId?: string\n taskId?: string\n}\n\n/**\n * Resolve the context-free Source kinds (`literal` / `param` / `actor` /\n * `now`) shared by every Source resolver. Returns `{handled: false}` for\n * the kinds that need resolver-specific backing data (`self`, `stageId`,\n * `stateRead`, `effectOutput`, `object`), so the in-instance resolver\n * ({@link resolveSource}) and the in-mutation op resolver each keep their\n * own handling of those without duplicating these four.\n */\nexport function resolveStaticSource(\n src: Source,\n ctx: {params?: Record<string, unknown>; actor?: Actor | undefined; now: string},\n): {handled: true; value: unknown} | {handled: false} {\n switch (src.source) {\n case 'literal':\n return {handled: true, value: src.value}\n case 'param':\n return {handled: true, value: ctx.params?.[src.paramId]}\n case 'actor':\n return {handled: true, value: ctx.actor}\n case 'now':\n return {handled: true, value: ctx.now}\n default:\n return {handled: false}\n }\n}\n\nexport function resolveSource(src: Source, ctx: ResolveSourceContext): unknown {\n const staticValue = resolveStaticSource(src, ctx)\n if (staticValue.handled) return staticValue.value\n switch (src.source) {\n case 'self':\n return ctx.instance._id\n case 'stageId':\n return ctx.stageId ?? ctx.instance.currentStageId\n case 'stateRead':\n return resolveStateRead(src, ctx)\n case 'effectOutput':\n return resolveEffectOutput(src, ctx)\n case 'object':\n return resolveObject(src, ctx)\n case 'row':\n case 'parentState':\n // Spawn-only sources (resolved by resolveSpawnSource); not in scope here.\n return undefined\n default:\n // literal / param / actor / now resolved above by resolveStaticSource.\n return undefined\n }\n}\n\ntype StateReadSource = Extract<Source, {source: 'stateRead'}>\ntype EffectOutputSource = Extract<Source, {source: 'effectOutput'}>\ntype ObjectSource = Extract<Source, {source: 'object'}>\n\nfunction resolveStateRead(src: StateReadSource, ctx: ResolveSourceContext): unknown {\n const value = readStateSlot(ctx.instance, src.scope, src.slotId, ctx.stageId, ctx.taskId)\n return src.path !== undefined ? getPath(value, src.path) : value\n}\n\nfunction resolveEffectOutput(src: EffectOutputSource, ctx: ResolveSourceContext): unknown {\n const entry = ctx.instance.effectsContext.find((e) => e.id === src.contextId)\n if (entry === undefined) return null\n const value = src.path !== undefined ? getPath(entry.value, src.path) : entry.value\n return value === undefined ? null : value\n}\n\nfunction resolveObject(src: ObjectSource, ctx: ResolveSourceContext): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [field, fieldSrc] of Object.entries(src.fields)) {\n out[field] = resolveSource(fieldSrc, ctx)\n }\n return out\n}\n","/**\n * Pure effect-binding resolution.\n *\n * An effect's `bindings` is a `Record<string, Source>`. This resolves each\n * binding to a concrete value (via {@link resolveSource}) and merges the\n * result with the effect's static input to form the params object the\n * handler is called with. No GROQ, no client, no I/O.\n */\n\nimport type {Source} from '../define/schema.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {resolveSource, type ResolveSourceContext} from './source.ts'\n\n/**\n * Resolve effect bindings against an instance. Each binding is a typed\n * `Source`; the resolved values are merged with the static input. The\n * result is the params object the handler will be called with.\n */\nexport async function resolveBindings(args: {\n bindings: Record<string, Source> | undefined\n staticInput: Record<string, unknown> | undefined\n instance: WorkflowInstance\n /** Shell-supplied clock reading (ISO) backing `source: \"now\"`. */\n now: string\n params?: Record<string, unknown>\n actor?: Actor\n}): Promise<Record<string, unknown>> {\n const {bindings, staticInput, instance, now, params, actor} = args\n const resolved: Record<string, unknown> = {}\n if (bindings) {\n const ctx: ResolveSourceContext = {\n instance,\n now,\n ...(params !== undefined ? {params} : {}),\n ...(actor !== undefined ? {actor} : {}),\n }\n for (const [key, src] of Object.entries(bindings)) {\n resolved[key] = resolveSource(src, ctx)\n }\n }\n return {...resolved, ...staticInput}\n}\n","import type {GlobalDocumentReference, WorkflowResource} from './core/refs.ts'\nimport type {WorkflowDefinition} from './define/schema.ts'\nimport {randomKey} from './keys.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {WorkflowPerspective} from './types/client.ts'\nimport type {EffectsContextEntry} from './types/effects.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\nimport type {ResolvedStateSlot} from './types/state-slots.ts'\n\n/** Wrap a scalar or GDR value in its typed {@link EffectsContextEntry}\n * envelope, minting a fresh `_key`. */\nexport function effectsContextEntry(\n id: string,\n value: string | number | boolean | GlobalDocumentReference,\n): EffectsContextEntry {\n const _key = randomKey()\n if (typeof value === 'string') return {_key, _type: 'effectsContext.string', id, value}\n if (typeof value === 'number') return {_key, _type: 'effectsContext.number', id, value}\n if (typeof value === 'boolean') return {_key, _type: 'effectsContext.boolean', id, value}\n return {_key, _type: 'effectsContext.ref', id, value}\n}\n\n/**\n * Build a fresh {@link WorkflowInstance} document for `create`. Shared by\n * `startInstance` (root instances) and the spawn path (child instances):\n * both pin the definition snapshot, seed state + effectsContext, enter\n * the initial stage with a single `stageEntered` history entry, and stamp\n * `_createdAt`/`startedAt`/`lastChangedAt` to the same `now`.\n */\nexport function buildInstanceBase(args: {\n id: string\n now: string\n tags: string[]\n workflowResource: WorkflowResource\n workflowId: string\n pinnedVersion: number\n definition: WorkflowDefinition\n state: ResolvedStateSlot[]\n effectsContext: EffectsContextEntry[]\n ancestors: GlobalDocumentReference[]\n perspective: WorkflowPerspective | undefined\n initialStageId: string\n actor: Actor | undefined\n}): WorkflowInstance {\n const {id, now, actor, perspective} = args\n return {\n _id: id,\n _type: 'workflow.instance',\n _rev: '',\n _createdAt: now,\n _updatedAt: now,\n tags: args.tags,\n workflowResource: args.workflowResource,\n workflowId: args.workflowId,\n pinnedVersion: args.pinnedVersion,\n definitionSnapshot: JSON.stringify(args.definition),\n state: args.state,\n effectsContext: args.effectsContext,\n ancestors: args.ancestors,\n ...(perspective !== undefined ? {perspective} : {}),\n currentStageId: args.initialStageId,\n stages: [],\n pendingEffects: [],\n effectHistory: [],\n history: [\n {\n _key: randomKey(),\n _type: 'workflow.history.stageEntered',\n at: now,\n stageId: args.initialStageId,\n ...(actor !== undefined ? {actor} : {}),\n },\n ],\n startedAt: now,\n lastChangedAt: now,\n }\n}\n","/**\n * Authorization model — grants and mutation guards.\n *\n * Grants are most-permissive-wins value permissions. Mutation guards are\n * the compiled/persisted form of an authoring `Guard`: owner-registered,\n * scoped by `match`, gated by a GROQ `predicate`, enforced OPTIMISTICALLY\n * engine-side only.\n */\n\nimport type {DocumentValuePermission, MutationGuardAction} from './enums.ts'\n\n// Grants. Filters are GROQ strings evaluated through groq-js with the\n// document as the dataset and the actor id as `identity()`. Compose:\n// most-permissive wins.\n\nexport interface Grant {\n filter: string\n permissions: DocumentValuePermission[]\n}\n\n// Mutation guards — the compiled/persisted form of an authoring `Guard`. A\n// guard is owner-registered, scoped by `match`, gated by a GROQ `predicate`\n// (empty = unconditional deny), with an opaque `metadata` bag the predicate\n// can read. Enforcement is OPTIMISTIC engine-side only.\n//\n// `resourceType`/`resourceId` scope a guard to a single datasource: the engine\n// spans datasources and must record which one a guard belongs to (the content\n// lake is per-datasource and infers the resource from storage).\n\n/**\n * The lake document type for a mutation guard. Single source of truth — both\n * the runtime value (id construction, `compileGuard`, queries) and the\n * {@link MutationGuardDoc} `_type` literal derive from here, so the `temp.`\n * POC prefix drops in exactly one place at cutover.\n */\nexport const GUARD_DOC_TYPE = 'temp.system.guard'\n\nexport interface MutationGuardMatch {\n types?: string[]\n /** Bare document ids (resource-local; both published and `drafts.` forms). */\n idRefs?: string[]\n idPatterns?: string[]\n actions: MutationGuardAction[]\n}\n\n/**\n * The persisted body of a mutation guard — every field except the lake system\n * fields. Shared by {@link MutationGuardDoc} (the stored doc) and the engine's\n * compile inputs, so the field set lives in one place.\n */\nexport interface MutationGuardBody {\n /** Engine-layer: the single datasource this guard belongs to. */\n resourceType: string\n resourceId: string\n /** Registering identity — the engine robot. Only owner/admin may modify. */\n owner: string\n /**\n * Provenance — the workflow that registered this guard. The lake's own guard\n * model carries none of these; they exist so the engine can find its guards\n * for coherency refresh and housekeeping without parsing them out of `_id`.\n */\n sourceInstanceId: string\n sourceDefinitionId: string\n sourceStageId: string\n name?: string\n description?: string\n /** Bare document ids (resource-local; both published and `drafts.` forms). */\n match: MutationGuardMatch\n /** GROQ; empty string = unconditional deny. Bare ids/fields only — no GDRs. */\n predicate: string\n /** Caller-owned projected state the predicate reads as `guard.metadata.*`. */\n metadata: Record<string, unknown>\n}\n\nexport interface MutationGuardDoc extends MutationGuardBody {\n _id: string\n _type: typeof GUARD_DOC_TYPE\n // System fields are assigned by the lake on write — never sent on create\n // (an empty-string `_createdAt`/`_updatedAt` fails datetime validation).\n _rev?: string\n _createdAt?: string\n _updatedAt?: string\n}\n\n/**\n * Inputs to predicate evaluation: `document.before`/`after`, the `mutation`,\n * the `guard`, and `identity()`. `before` is null on create, `after` null on\n * delete.\n */\nexport interface MutationContext {\n before: ({_id: string; _type: string} & Record<string, unknown>) | null\n after: ({_id: string; _type: string} & Record<string, unknown>) | null\n action: MutationGuardAction\n /** Authenticated caller id, resolved as `identity()` in the predicate. */\n identity?: string\n}\n\n/**\n * Thrown when one or more guards deny a mutation. POC: raised by the engine /\n * bench enforcement layer; carries every denial. Fail-closed: a predicate that\n * errors or is non-true denies.\n */\nexport class MutationGuardDeniedError extends Error {\n readonly denied: Array<{guardId: string; name?: string}>\n readonly documentId: string\n readonly action: MutationGuardAction\n\n constructor(args: {\n documentId: string\n action: MutationGuardAction\n denied: Array<{guardId: string; name?: string}>\n }) {\n const ids = args.denied.map((d) => d.guardId).join(', ')\n super(`Mutation on \"${args.documentId}\" (${args.action}) denied by guard(s) [${ids}]`)\n this.name = 'MutationGuardDeniedError'\n this.denied = args.denied\n this.documentId = args.documentId\n this.action = args.action\n }\n}\n","/**\n * Pure compilation and evaluation of lake mutation guards.\n *\n * NO CLIENT. NO I/O. The shell resolves a stage `Guard`'s `match.idRefs`\n * Sources to bare ids + a resource and its `metadata` Sources to values, then\n * hands the resolved pieces here to assemble a `temp.system.guard` doc and to\n * evaluate predicates against a `before`/`after` mutation image via groq-js.\n *\n * Guard semantics:\n * - empty predicate ⇒ unconditional deny;\n * - fail-closed — a compile/eval error or non-`true` result denies;\n * - evaluation context = document before/after + mutation + guard + identity().\n *\n * Enforcement is OPTIMISTIC: the lake does not enforce `temp.system.guard`\n * yet, so a pass here is an engine *preview*, not proof. The predicate dialect\n * is groq-js delta-mode; the guard doc is referenced as the `$guard` param and\n * `identity()` resolves to the authenticated caller, the same way `permissions.ts`\n * feeds grant filters.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport {\n GUARD_DOC_TYPE,\n type MutationContext,\n type MutationGuardBody,\n type MutationGuardDoc,\n} from '../types/authorization.ts'\nimport type {MutationGuardAction} from '../types/enums.ts'\n\n/** Deterministic id so deploy/retract are query-free and idempotent. */\nexport function lakeGuardId(args: {instanceDocId: string; stageId: string; index: number}): string {\n return `${GUARD_DOC_TYPE}.${args.instanceDocId}.${args.stageId}.${args.index}`\n}\n\nexport interface CompileGuardArgs extends MutationGuardBody {\n id: string\n}\n\n/** Assemble a persisted guard doc from resolved pieces. */\nexport function compileGuard(args: CompileGuardArgs): MutationGuardDoc {\n return {\n _id: args.id,\n _type: GUARD_DOC_TYPE,\n resourceType: args.resourceType,\n resourceId: args.resourceId,\n owner: args.owner,\n sourceInstanceId: args.sourceInstanceId,\n sourceDefinitionId: args.sourceDefinitionId,\n sourceStageId: args.sourceStageId,\n ...(args.name !== undefined ? {name: args.name} : {}),\n ...(args.description !== undefined ? {description: args.description} : {}),\n match: args.match,\n predicate: args.predicate,\n metadata: args.metadata,\n } satisfies MutationGuardDoc\n}\n\n/**\n * Translate a lake-wire predicate to groq-js for optimistic POC evaluation.\n * The wire dialect binds `guard` and `mutation` as predicate identifiers;\n * groq-js has no such globals, so we expose them as `$params` and rewrite the\n * references.\n * `identity()`, `delta::*`, and `before`/`after` are native to groq-js and pass\n * through. The STORED predicate stays in wire form (bare `guard`/`mutation`) so\n * it is correct when handed to the real lake; this rewrite is eval-time only.\n */\nfunction toGroqJsPredicate(predicate: string): string {\n return predicate\n .replace(/(?<!\\$)\\bguard\\./g, '$guard.')\n .replace(/(?<!\\$)\\bmutation\\./g, '$mutation.')\n}\n\n/** Glob match supporting a single `*` wildcard per pattern. */\nfunction globMatch(pattern: string, value: string): boolean {\n if (!pattern.includes('*')) return pattern === value\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*')\n return new RegExp(`^${escaped}$`).test(value)\n}\n\n/**\n * Does this guard's `match` apply to a mutation on the given document?\n * `types` and id facets are ANDed; an unspecified facet does not constrain.\n */\nexport function guardMatches(\n guard: MutationGuardDoc,\n doc: {id: string; type?: string},\n action: MutationGuardAction,\n): boolean {\n const m = guard.match\n if (!m.actions.includes(action)) return false\n if (m.types && m.types.length > 0 && !(doc.type !== undefined && m.types.includes(doc.type))) {\n return false\n }\n const hasIdFacet = (m.idRefs && m.idRefs.length > 0) || (m.idPatterns && m.idPatterns.length > 0)\n if (hasIdFacet) {\n const byRef = m.idRefs?.includes(doc.id) ?? false\n const byPattern = m.idPatterns?.some((p) => globMatch(p, doc.id)) ?? false\n if (!byRef && !byPattern) return false\n }\n return true\n}\n\n/**\n * Evaluate a guard predicate against a mutation. Returns `true` only when the\n * predicate is strictly `true` (ALLOW). Empty predicate denies. Fail-closed:\n * any thrown error or non-`true` result denies.\n */\nexport async function evaluateMutationGuard(args: {\n guard: MutationGuardDoc\n context: MutationContext\n}): Promise<boolean> {\n const {guard, context} = args\n if (guard.predicate === '') return false // alwaysDeny\n const params = {guard, mutation: {action: context.action}}\n try {\n const tree = parse(toGroqJsPredicate(guard.predicate), {mode: 'delta', params})\n const value = await evaluate(tree, {\n before: context.before,\n after: context.after,\n params,\n ...(context.identity !== undefined ? {identity: context.identity} : {}),\n })\n return (await value.get()) === true\n } catch {\n return false\n }\n}\n\n/**\n * Run every guard whose `match` applies and collect those that DENY. Empty\n * result ⇒ allowed (optimistically).\n */\nexport async function denyingGuards(args: {\n guards: MutationGuardDoc[]\n doc: {id: string; type?: string}\n context: MutationContext\n}): Promise<MutationGuardDoc[]> {\n const {guards, doc, context} = args\n const denied: MutationGuardDoc[] = []\n for (const guard of guards) {\n if (!guardMatches(guard, doc, context.action)) continue\n if (!(await evaluateMutationGuard({guard, context}))) denied.push(guard)\n }\n return denied\n}\n","import {isGdrUri, parseGdr} from './core/refs.ts'\nimport type {ParsedGdr} from './core/refs.ts'\nimport {resolveSource} from './core/source.ts'\nimport type {Source} from './define/schema.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nexport interface Resource {\n type: string\n id: string\n}\n\nfunction resourceOf(p: ParsedGdr): Resource {\n if (p.scheme === 'dataset') return {type: 'dataset', id: `${p.projectId}.${p.dataset}`}\n return {type: p.scheme, id: p.resourceId ?? ''}\n}\n\ninterface GdrTarget {\n parsed: ParsedGdr\n type?: string\n}\n\nexport interface BindingContext {\n instance: WorkflowInstance\n stageId: string\n /** Shell-supplied clock reading (ISO) backing `source: \"now\"`. */\n now: string\n}\n\n/**\n * Resolve a single `idRefs` Source to a GDR URI + an optional author type.\n * Returns null for unresolvable / non-GDR targets (e.g. `self`).\n */\nfunction resolveIdRefTarget(src: Source, ctx: BindingContext): GdrTarget | null {\n const value = resolveSource(src, ctx)\n if (typeof value === 'string' && isGdrUri(value)) {\n return {parsed: parseGdr(value)}\n }\n if (value && typeof value === 'object') {\n const v = value as {id?: unknown; type?: unknown}\n if (typeof v.id === 'string' && isGdrUri(v.id)) {\n return typeof v.type === 'string'\n ? {parsed: parseGdr(v.id), type: v.type}\n : {parsed: parseGdr(v.id)}\n }\n }\n return null\n}\n\n/**\n * Resolve every `idRefs` Source. Returns null if any target is unresolvable\n * (the whole guard is then deferred) or if no targets are declared.\n */\nexport function resolveIdRefTargets(\n idRefs: readonly Source[] | undefined,\n ctx: BindingContext,\n): GdrTarget[] | null {\n const targets: GdrTarget[] = []\n for (const src of idRefs ?? []) {\n const target = resolveIdRefTarget(src, ctx)\n if (target === null) return null\n targets.push(target)\n }\n return targets.length === 0 ? null : targets\n}\n\n/**\n * Enforce the single-resource invariant: every target must live in the same\n * datasource. Returns that shared resource, or throws on a span.\n */\nexport function assertSingleResource(targets: readonly GdrTarget[]): Resource {\n const resource = resourceOf(targets[0]!.parsed)\n for (const g of targets) {\n const r = resourceOf(g.parsed)\n if (r.type !== resource.type || r.id !== resource.id) {\n throw new Error(\n `Guard targets span multiple resources (${resource.type}:${resource.id} vs ${r.type}:${r.id}); a guard is single-resource.`,\n )\n }\n }\n return resource\n}\n\n/** Bare ids in both published + draft forms for each target. */\nexport function bareIdRefs(targets: readonly GdrTarget[]): string[] {\n return targets.flatMap((g) => [g.parsed.documentId, `drafts.${g.parsed.documentId}`])\n}\n\n/**\n * Effective `match.types`: author-specified wins; otherwise the distinct\n * inferred types across targets, or undefined when none were inferred.\n */\nexport function resolveMatchTypes(\n targets: readonly GdrTarget[],\n authorTypes: string[] | undefined,\n): string[] | undefined {\n if (authorTypes !== undefined) return authorTypes\n const inferred = [...new Set(targets.map((g) => g.type).filter((t): t is string => !!t))]\n return inferred.length > 0 ? inferred : undefined\n}\n\n/** Project each metadata Source to its resolved value. */\nexport function resolveMetadata(\n metadata: Record<string, Source> | undefined,\n ctx: BindingContext,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [k, src] of Object.entries(metadata ?? {})) {\n out[k] = resolveSource(src, ctx)\n }\n return out\n}\n","/**\n * Shell-side lake-guard lifecycle: deploy and retract `temp.system.guard`\n * documents as a workflow enters and exits stages. NOT pure — resolves each\n * stage `Guard`'s `match.idRefs` / `metadata` Sources against the instance,\n * splits the resolved GDR into the guard's resource (resourceType/resourceId)\n * + bare ids, and writes via `clientForGdr` into that resource.\n *\n * Single-resource is enforced here: all idRefs of one guard must resolve to\n * the same datasource (the guard lives in and references only that one).\n *\n * \"Retract\" lifts the predicate to `\"true\"` (unconditionally allow) rather\n * than deleting — the `WorkflowClient` contract has no delete, and a loop-back\n * re-enters the stage and re-deploys the real predicate. POC simplification;\n * orphan accumulation + cross-dataset non-atomicity are documented seams.\n *\n * Reconcile runs post-persist, outside the instance's `ifRevisionId` guard, so\n * both primitives gate on the instance's live committed stage (see\n * {@link committedStageId}) to drop stale / superseded reconciles. The window\n * between that live-stage read and the guard write is itself non-atomic across\n * resources — the same documented-seam direction (over-lock) as above.\n *\n * Enforcement is OPTIMISTIC: deploying a guard does not make the lake enforce\n * it. The engine evaluates guards itself (core/guards.ts); the bench throws.\n */\n\nimport {compileGuard, lakeGuardId} from './core/guards.ts'\nimport type {ParsedGdr} from './core/refs.ts'\nimport type {Guard, WorkflowDefinition} from './define/schema.ts'\nimport {\n assertSingleResource,\n bareIdRefs,\n resolveIdRefTargets,\n resolveMatchTypes,\n resolveMetadata,\n} from './guard-bindings.ts'\nimport type {MutationGuardDoc} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nexport const GUARD_OWNER = 'robot:workflow-engine'\n/** Retracted predicate — unconditionally allows, lifting the guard. */\nexport const GUARD_LIFTED_PREDICATE = 'true'\n\ninterface ResolvedGuard {\n doc: MutationGuardDoc\n routeGdr: ParsedGdr\n}\n\n/**\n * Resolve a stage `Guard` into a persisted doc + the GDR to route the write.\n * Returns null when no target resolves to a GDR (e.g. `self` — instance-side\n * guards are deferred), or when targets span resources (rejected).\n */\nfunction resolveGuard(\n guard: Guard,\n index: number,\n instance: WorkflowInstance,\n stageId: string,\n now: string,\n): ResolvedGuard | null {\n const ctx = {instance, stageId, now}\n\n const targets = resolveIdRefTargets(guard.match.idRefs, ctx)\n if (targets === null) return null\n\n const resource = assertSingleResource(targets)\n const types = resolveMatchTypes(targets, guard.match.types)\n\n const doc = compileGuard({\n id: lakeGuardId({instanceDocId: instance._id, stageId, index}),\n resourceType: resource.type,\n resourceId: resource.id,\n owner: GUARD_OWNER,\n sourceInstanceId: instance._id,\n sourceDefinitionId: instance.workflowId,\n sourceStageId: stageId,\n ...(guard.name !== undefined ? {name: guard.name} : {}),\n ...(guard.description !== undefined ? {description: guard.description} : {}),\n match: {\n ...(types !== undefined ? {types} : {}),\n idRefs: bareIdRefs(targets),\n ...(guard.match.idPatterns !== undefined ? {idPatterns: guard.match.idPatterns} : {}),\n actions: guard.match.actions,\n },\n predicate: guard.predicate ?? '',\n metadata: resolveMetadata(guard.metadata, ctx),\n })\n\n return {doc, routeGdr: targets[0]!.parsed}\n}\n\nasync function upsertGuard(client: WorkflowClient, doc: MutationGuardDoc): Promise<void> {\n const existing = await client.getDocument(doc._id)\n if (!existing) {\n await client.create(doc)\n return\n }\n // Patch the whole body (provenance included) so create and update can never\n // disagree on which fields they persist. System fields are lake-assigned.\n const {_id, _type, _rev, _createdAt, _updatedAt, ...body} = doc\n await client.patch(doc._id).set(body).commit()\n}\n\nexport interface StageGuardArgs {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n definition: WorkflowDefinition\n stageId: string\n /** Shell-supplied clock reading (ISO) backing guard `source: \"now\"`. */\n now: string\n}\n\n/** Resolve a stage's guards to their routed client + guard doc, skipping any that don't resolve. */\nfunction resolvedStageGuards(\n args: StageGuardArgs,\n): Array<{client: WorkflowClient; doc: MutationGuardDoc}> {\n const stage = args.definition.stages.find((s) => s.id === args.stageId)\n const out: Array<{client: WorkflowClient; doc: MutationGuardDoc}> = []\n for (const [index, guard] of (stage?.guards ?? []).entries()) {\n const resolved = resolveGuard(guard, index, args.instance, args.stageId, args.now)\n if (resolved === null) continue\n out.push({client: args.clientForGdr(resolved.routeGdr), doc: resolved.doc})\n }\n return out\n}\n\n/**\n * Re-read the instance's committed stage from the lake. Reconcile runs as a\n * post-persist step *outside* the instance's `ifRevisionId` guard, so a stale\n * or retried reconcile can land after a newer transition already moved the\n * instance on. Both reconcile primitives gate on this live stage so they never\n * act on a stage the instance has since left. `undefined` means the instance\n * doc is gone (deleted out of band) — both primitives then no-op, leaving the\n * deployed guards untouched (the orphan seam's over-lock direction) rather than\n * blindly deploying for, or lifting the lock of, a vanished instance.\n */\nasync function committedStageId(args: StageGuardArgs): Promise<string | undefined> {\n const live = await args.client.getDocument<WorkflowInstance>(args.instance._id)\n return live?.currentStageId\n}\n\n/**\n * Deploy every guard for a stage being entered (idempotent upsert), but only\n * while the instance is still committed to that stage. A deploy that lost the\n * race to a newer transition would otherwise re-enforce a stage the instance\n * already left — a stale lock the newer transition's retract can't see. A\n * vanished instance (`undefined`) likewise no-ops: `undefined !== stageId`.\n */\nexport async function deployStageGuards(args: StageGuardArgs): Promise<void> {\n if ((await committedStageId(args)) !== args.stageId) return\n for (const {client, doc} of resolvedStageGuards(args)) {\n await upsertGuard(client, doc)\n }\n}\n\n/**\n * Retract every guard for a stage being exited (lift predicate to allow), but\n * only once the instance has genuinely moved off that stage. Skip if it is\n * still there (a concurrent loop-back re-entered the stage and must keep its\n * lock) or gone (leave the lock as the orphan seam rather than silently\n * unlocking a vanished instance — the same over-lock direction as deploy).\n */\nexport async function retractStageGuards(args: StageGuardArgs): Promise<void> {\n const live = await committedStageId(args)\n if (live === undefined || live === args.stageId) return\n for (const {client, doc} of resolvedStageGuards(args)) {\n const existing = await client.getDocument<MutationGuardDoc>(doc._id)\n if (!existing) continue\n await client.patch(doc._id).set({predicate: GUARD_LIFTED_PREDICATE}).commit()\n }\n}\n","import type {Clock} from '../clock.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {StateScope, TaskStatus} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\n\n// Public API\n\nexport interface EngineCallOptions {\n actor?: Actor\n /** Injected {@link Clock} for deterministic time; defaults to wall-clock. */\n clock?: Clock\n}\n\nexport interface TransitionResult {\n fired: boolean\n fromStageId?: StageId\n toStageId?: StageId\n transitionId?: string\n}\n\nexport interface InvokeResult {\n invoked: boolean\n taskId: TaskId\n}\n\nexport interface OpAppliedSummary {\n opType: string\n target?: {scope: StateScope; slotId: string}\n resolved?: Record<string, unknown>\n}\n\nexport interface ActionResult {\n fired: boolean\n taskId: TaskId\n action: string\n newStatus?: TaskStatus\n /** Deterministic engine primitives that ran inline during the commit. */\n ranOps?: OpAppliedSummary[]\n}\n\n/**\n * Thrown when caller-supplied params don't satisfy the action's\n * declared `params[]` — missing required fields or wrong primitive\n * type. The action does not commit; the engine has not mutated state.\n */\nexport class ActionParamsInvalidError extends Error {\n readonly action: string\n readonly taskId: TaskId\n readonly issues: {paramId: string; reason: string}[]\n constructor(args: {action: string; taskId: TaskId; issues: {paramId: string; reason: string}[]}) {\n const lines = args.issues.map((i) => ` - ${i.paramId}: ${i.reason}`).join('\\n')\n super(`Action \"${args.action}\" on task \"${args.taskId}\" rejected: invalid params\\n${lines}`)\n this.name = 'ActionParamsInvalidError'\n this.action = args.action\n this.taskId = args.taskId\n this.issues = args.issues\n }\n}\n\n/**\n * Thrown when a guard deploy fails *after* its state move committed and the\n * engine could not restore the instance to its pre-move state — either the\n * rollback write itself failed, or the move created sibling docs (spawn) that a\n * parent-only rollback cannot undo. The workflow's persisted state and its\n * deployed guards are now divergent and need manual reconciliation; the engine\n * screams rather than leaving the inconsistency silent.\n */\nexport class WorkflowStateDivergedError extends Error {\n readonly instanceId: string\n /** The guard-deploy failure that triggered the (attempted) rollback. */\n readonly guardError: unknown\n /** The rollback failure, when rollback was attempted and itself failed. */\n readonly rollbackError?: unknown\n constructor(args: {\n instanceId: string\n guardError: unknown\n rollbackError?: unknown\n reason: string\n }) {\n super(\n `Workflow \"${args.instanceId}\" state committed but its guards could not be reconciled: ${args.reason}.`,\n {cause: args.guardError},\n )\n this.name = 'WorkflowStateDivergedError'\n this.instanceId = args.instanceId\n this.guardError = args.guardError\n if (args.rollbackError !== undefined) this.rollbackError = args.rollbackError\n }\n}\n\nexport interface CompleteEffectResult {\n effectKey: string\n status: 'done' | 'failed'\n}\n\n/** Total `fireAction` commit attempts before giving up — one initial try\n * plus reloads after each lost `ifRevisionId` race. */\nexport const CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS = 3\n\n/**\n * Thrown when a `fireAction` commit loses the optimistic-locking race on\n * all {@link CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS} attempts — every reload +\n * `ifRevisionId` retry was beaten by another writer committing first.\n * Surfacing it (rather than silently overwriting) lets the caller decide\n * whether to retry later or report a write storm; nothing was committed\n * on the final attempt.\n */\nexport class ConcurrentFireActionError extends Error {\n readonly instanceId: string\n readonly taskId: TaskId\n readonly action: string\n readonly attempts: number\n constructor(args: {instanceId: string; taskId: TaskId; action: string; attempts: number}) {\n super(\n `Action \"${args.action}\" on task \"${args.taskId}\" (instance ${args.instanceId}) lost the ` +\n `optimistic-locking race ${args.attempts} attempts running — a concurrent writer kept ` +\n `committing first. Re-read and retry, or investigate a write storm on this instance.`,\n )\n this.name = 'ConcurrentFireActionError'\n this.instanceId = args.instanceId\n this.taskId = args.taskId\n this.action = args.action\n this.attempts = args.attempts\n }\n}\n\n/**\n * True when a rev-guarded write was rejected by optimistic-locking — a 409\n * from the real client or the bench's `ifRevisionId check failed`. Lets\n * callers retry on a lost race while still rethrowing real errors\n * (validation, network, missing task) rather than masking them as conflicts.\n */\nexport function isRevisionConflict(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false\n const {statusCode, message} = error as {statusCode?: unknown; message?: unknown}\n if (statusCode === 409) return true\n return typeof message === 'string' && message.includes('ifRevisionId check failed')\n}\n\n/**\n * Thrown when auto-transitions on an instance fail to stabilise within\n * {@link CascadeLimitError.limit} passes — the signature of a runaway\n * cascade. The classic trigger is two stages whose transition guards\n * stay simultaneously satisfied (e.g. an `op.state.set` lands a value\n * that trips the very guard that fired, and nothing ever clears it), so\n * the engine flip-flops and would otherwise write revisions forever.\n *\n * The cascade aborts at the limit rather than the engine hanging; the\n * instance is left at whatever stage the last completed pass reached.\n */\nexport class CascadeLimitError extends Error {\n readonly instanceId: string\n readonly limit: number\n constructor(args: {instanceId: string; limit: number}) {\n super(\n `Cascade did not stabilise after ${args.limit} auto-transitions on ${args.instanceId} — ` +\n `likely a runaway loop (transition guards that stay mutually satisfied). ` +\n `Check that each transition's filter eventually goes false.`,\n )\n this.name = 'CascadeLimitError'\n this.instanceId = args.instanceId\n this.limit = args.limit\n }\n}\n","import type {WorkflowClient} from '../types/client.ts'\nimport {WorkflowStateDivergedError} from './results.ts'\n\nexport interface DeployOrRollbackArgs {\n client: WorkflowClient\n instanceId: string\n /** The post-commit revision the rollback patch must still match. */\n committedRev: string | undefined\n /** Pre-commit field values to write back if the deploy fails. */\n restore: Record<string, unknown>\n /** Fields the move added that a rollback must remove (e.g. a fresh `completedAt`). */\n unset?: string[]\n /**\n * False when the commit also created sibling docs (a spawn transaction) that\n * a parent-only rollback cannot undo — a deploy failure then screams instead\n * of leaving orphaned children behind a half-applied move.\n */\n reversible: boolean\n /** Deploy/reconcile the stage's guards. Runs after the state has committed. */\n deploy: () => Promise<void>\n}\n\n/**\n * Deploy guards for a just-committed state move, rolling the move back if the\n * deploy fails. Ordering is deliberate: guards deploy AFTER the state commits\n * (a guard can lock the caller out of further edits, so it must follow the\n * state it enforces). On a deploy failure the engine restores the pre-commit\n * instance and re-throws the original error — the caller sees the failure with\n * state intact. When a clean rollback is impossible (spawn) or the rollback\n * write itself fails, it throws {@link WorkflowStateDivergedError} so the\n * divergence is loud, never silent.\n */\nexport async function deployOrRollback(args: DeployOrRollbackArgs): Promise<void> {\n try {\n await args.deploy()\n } catch (guardError) {\n if (!args.reversible) {\n throw new WorkflowStateDivergedError({\n instanceId: args.instanceId,\n guardError,\n reason: 'the move created child instances a parent-only rollback cannot undo',\n })\n }\n try {\n let patch = args.client.patch(args.instanceId).set(args.restore)\n if (args.unset && args.unset.length > 0) patch = patch.unset(args.unset)\n if (args.committedRev !== undefined) patch = patch.ifRevisionId(args.committedRev)\n await patch.commit()\n } catch (rollbackError) {\n throw new WorkflowStateDivergedError({\n instanceId: args.instanceId,\n guardError,\n rollbackError,\n reason: 'rollback of the committed move failed',\n })\n }\n throw guardError\n }\n}\n","/**\n * Shell-side discovery query.\n *\n * Spawn `forEach.groq` scans the lake for rows to spawn child\n * workflows over. These are NOT filters — they look at content that\n * isn't in the snapshot (typically every doc of a given type that\n * references a doc the workflow already knows about). Different\n * semantics, different primitive, different code path from\n * `evaluateFilter`.\n *\n * Keeping discovery out of the filter pipeline is what lets the core\n * stay pure. Filters eval against pre-hydrated data; discovery hits the\n * lake by design.\n */\n\nimport {paramsForLake} from './core/params.ts'\nimport {parseGdr} from './core/refs.ts'\nimport type {WorkflowClient, WorkflowPerspective} from './types/client.ts'\n\n/**\n * Run a discovery GROQ against the appropriate client.\n *\n * The query receives params with GDR IDs stripped back to bare form\n * (via `paramsForLake`) because lake refs are bare. Caller decides\n * which client to use — typically the resource client of the first\n * `doc.ref` state slot, since discovery scans look for items related\n * to docs the workflow already references.\n */\nexport async function discoverItems(args: {\n client: WorkflowClient\n groq: string\n params: Record<string, unknown>\n /**\n * Read-side perspective. When set, the engine threads the instance's\n * `perspective` field through so spawn `forEach.groq` sees a\n * release-stacked view of the lake. Unset → client default.\n */\n perspective?: WorkflowPerspective\n}): Promise<unknown> {\n const {client, groq, params, perspective} = args\n const fetchOptions = perspective !== undefined ? {perspective} : undefined\n return client.fetch(groq, paramsForLake(params), fetchOptions)\n}\n\n/**\n * Convenience: pick the right client for a discovery scan given the\n * subject's GDR URI. Bare ids (no `:`) → default client. Anything\n * parseable → routed client.\n */\nexport function clientForDiscovery(\n defaultClient: WorkflowClient,\n clientForGdr: (parsed: import('./core/refs.ts').ParsedGdr) => WorkflowClient,\n subjectGdrUri: string | undefined,\n): WorkflowClient {\n if (!subjectGdrUri || !subjectGdrUri.includes(':')) return defaultClient\n try {\n return clientForGdr(parseGdr(subjectGdrUri))\n } catch {\n return defaultClient\n }\n}\n","import type {SanityDocument} from '@sanity/types'\nimport {evaluate, parse} from 'groq-js'\n\nimport {buildParams} from '../core/params.ts'\nimport {getPath} from '../core/path.ts'\nimport {gdrFromResource, isGdrUri, selfGdr, type GlobalDocumentReference} from '../core/refs.ts'\nimport type {Source, Spawn, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {clientForDiscovery, discoverItems} from '../discover.ts'\nimport {buildInstanceBase, effectsContextEntry} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport {derivePerspectiveFromState, resolveDeclaredState} from '../state-resolution.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectsContextEntry} from '../types/effects.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {InitialStateValue, ResolvedStateSlot} from '../types/state-slots.ts'\nimport {type EngineContext, gdrToBareId} from './context.ts'\nimport type {MutableInstance} from './mutation.ts'\n\n/**\n * Maximum depth of the spawn ancestor chain. A child's depth is\n * `ancestors.length`. With this limit a spawned chain can reach\n * `root → 1 → 2 → 3 → 4 → 5 → 6` (six levels of nesting below root);\n * a spawn that would create a seventh level is rejected.\n *\n * Backstop against runtime spawn recursion that the deploy-time cycle\n * detector cannot see — definitions whose spawn fires conditionally on\n * subject state can produce dynamic recursion without a static cycle\n * in the definition graph.\n */\nconst MAX_SPAWN_DEPTH = 6\n\n/**\n * Resolve a spawn declaration's `forEach` against the parent instance,\n * create one child workflow instance per result row, prime each child's\n * initial stage, cascade auto-transitions on each, and return the refs.\n *\n * `spawn.forEach.groq` is the discovery query (lake fetch) — runs with\n * the parent's reserved params (`$self`, `$state`, `$parent`,\n * `$ancestors`, `$stage`, `$now`) stripped to bare for the lake.\n *\n * `spawn.forEach.as.initialState` is a typed projection from each row\n * to the child's `initialState` array. Two spawn-only Sources:\n * - `{ source: \"row\", path? }` reads from the iteration row.\n * - `{ source: \"parentState\", slotId, path? }` reads from the\n * parent's resolved workflow-scope state.\n *\n * The child receives no auto-stamped state — only what the projection\n * produces. The child's workflow definition declares which slots it\n * expects; this projection feeds them.\n */\nexport async function spawnChildren(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n spawn: Spawn,\n actor: Actor | undefined,\n): Promise<GlobalDocumentReference[]> {\n // Depth backstop. Parent's `ancestors.length` is its own depth; a\n // child would be at `parent.ancestors.length + 1`. Reject before any\n // lake work or item resolution — the mutation has not been persisted\n // yet, so throwing here is safe.\n if (ctx.instance.ancestors.length + 1 > MAX_SPAWN_DEPTH) {\n const chain = [...ctx.instance.ancestors.map((a) => a.id), selfGdr(ctx.instance)].join(' → ')\n throw new Error(\n `Spawn depth limit (${MAX_SPAWN_DEPTH}) exceeded on task \"${task.id}\" of ${ctx.instance._id}. ` +\n `Ancestor chain: ${chain}`,\n )\n }\n\n const now = ctx.now\n const rows = await resolveSpawnRows(ctx, spawn)\n const refs: GlobalDocumentReference[] = []\n\n for (const row of rows) {\n const projected = projectSpawnRow(ctx.instance, spawn, row, now)\n const {ref, body} = await prepareChildInstance({\n client: ctx.client,\n parent: ctx.instance,\n task,\n spawn,\n initialState: projected.initialState,\n effectsContext: projected.effectsContext,\n actor,\n now,\n })\n refs.push(ref)\n // Defer the write — `persist` drains `pendingCreates` into one\n // transaction with the parent's patch.\n mutation.pendingCreates.push(body)\n }\n\n return refs\n}\n\n/**\n * Run `spawn.forEach.groq` against the lake and return the rows. The\n * groq runs through the discovery client (resourceClients-aware) with\n * reserved params stripped to bare ids.\n */\nasync function resolveSpawnRows(ctx: EngineContext, spawn: Spawn): Promise<unknown[]> {\n const params = buildParams(ctx.instance, ctx.now)\n const groq = spawn.forEach.groq\n\n let value: unknown\n if (groq.includes('*')) {\n // Lake discovery — route through resourceClients in case the\n // spawn's GROQ targets a different Sanity resource than the\n // parent. We pick the resource by the first workflow-scope\n // `doc.ref` slot's GDR — typically the natural \"subject\" of the\n // workflow. Authors declaring a different routing target should\n // put that doc.ref slot first.\n const routingUri = firstDocRefGdrUri(ctx.instance.state)\n const client = clientForDiscovery(ctx.client, ctx.clientForGdr, routingUri)\n value = await discoverItems({\n client,\n groq,\n params,\n ...(ctx.instance.perspective !== undefined ? {perspective: ctx.instance.perspective} : {}),\n })\n } else {\n // Pure-param GROQ — evaluate in-process against an empty dataset.\n const tree = parse(groq, {params})\n const result = await evaluate(tree, {dataset: [ctx.instance], params, root: ctx.instance})\n value = await result.get()\n }\n\n if (Array.isArray(value)) return value\n if (value === null || value === undefined) return []\n return [value]\n}\n\n/** First workflow-scope `doc.ref` slot GDR URI, if any. Used to pick\n * the discovery client for spawn `forEach.groq`. */\nfunction firstDocRefGdrUri(slots: ResolvedStateSlot[] | undefined): string | undefined {\n if (!slots) return undefined\n for (const s of slots) {\n if (s._type === 'workflow.state.doc.ref' && s.value !== null) return s.value.id\n }\n return undefined\n}\n\n/**\n * Resolve a Source against the spawn-time context: row + parent state.\n * Returns the resolved value. Bare doc ids in `row` are NOT canonicalised\n * — the projection author is responsible for spelling out the GDR type\n * via a nested object or by using `Source.parentState` for ids that\n * already live in canonical form.\n */\nfunction resolveSpawnSource(\n source: Source,\n parent: WorkflowInstance,\n row: unknown,\n now: string,\n): unknown {\n switch (source.source) {\n case 'literal':\n return source.value\n case 'row':\n return source.path !== undefined ? getPath(row, source.path) : row\n case 'parentState': {\n const slot = parent.state?.find((s) => s.id === source.slotId)\n if (slot === undefined) return null\n return source.path !== undefined ? getPath(slot, source.path) : slot\n }\n case 'self':\n return selfGdr(parent)\n case 'stageId':\n return parent.currentStageId\n case 'now':\n return now\n case 'object': {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(source.fields)) {\n out[k] = resolveSpawnSource(v, parent, row, now)\n }\n return out\n }\n case 'actor':\n case 'param':\n case 'stateRead':\n case 'effectOutput':\n // These don't make sense at spawn time — no firing actor, no\n // action params, no in-progress mutation, no effect outputs.\n // Return null to fail loud rather than silently producing\n // misleading data.\n return null\n }\n}\n\n/**\n * Project a spawn's `forEach.as` against one row → the child's\n * `initialState` array + the seed map for the child's `effectsContext`.\n */\nfunction projectSpawnRow(\n parent: WorkflowInstance,\n spawn: Spawn,\n row: unknown,\n now: string,\n): {\n initialState: InitialStateValue[]\n effectsContext: Record<string, string | number | boolean | GlobalDocumentReference>\n} {\n const initialState: InitialStateValue[] = []\n for (const entry of spawn.forEach.as.initialState ?? []) {\n const raw = resolveSpawnSource(entry.value, parent, row, now)\n const value = canonicaliseSpawnValue(entry.type, raw, parent.workflowResource)\n initialState.push({\n type: entry.type as InitialStateValue['type'],\n id: entry.id,\n value: value as InitialStateValue['value'],\n } as InitialStateValue)\n }\n\n const effectsContext: Record<string, string | number | boolean | GlobalDocumentReference> = {}\n for (const [k, src] of Object.entries(spawn.forEach.as.effectsContext ?? {})) {\n const v = resolveSpawnSource(src, parent, row, now)\n if (v === undefined || v === null) continue\n if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') {\n effectsContext[k] = v\n } else if (typeof v === 'object' && 'id' in v && 'type' in v) {\n // GDR shape — schema-validated at create time; engine here just\n // trusts the projection author's typing.\n effectsContext[k] = v as GlobalDocumentReference\n }\n }\n return {initialState, effectsContext}\n}\n\n/**\n * Canonicalise a spawn-projected slot value for `doc.ref` / `doc.refs`\n * slots. Spawn projections naturally produce raw row data: bare doc\n * ids, `{ _ref, _type }` envelopes, or `{ id, type }` pairs where `id`\n * may be bare. The engine knows the spawning parent's resource, so it\n * canonicalises bare ids into GDR URIs rooted at that resource.\n *\n * Cross-resource spawns must spell the URI out in GROQ (or build a\n * `{ id: \"<full-uri>\", type: ... }` object via the `object` Source)\n * — the engine doesn't infer foreign resources.\n *\n * Non doc.ref / doc.refs slots pass through unchanged.\n */\nfunction canonicaliseSpawnValue(\n slotType: string,\n value: unknown,\n workflowResource: import('../core/refs.ts').WorkflowResource,\n): unknown {\n if (slotType === 'workflow.state.doc.ref') {\n return coerceSpawnGdr(value, workflowResource)\n }\n if (slotType === 'workflow.state.doc.refs') {\n if (!Array.isArray(value)) return value\n return value.map((v) => coerceSpawnGdr(v, workflowResource)).filter((v) => v !== null)\n }\n return value\n}\n\nfunction coerceSpawnGdr(\n raw: unknown,\n workflowResource: import('../core/refs.ts').WorkflowResource,\n): GlobalDocumentReference | null {\n // Canonicalise a bare doc id into a GDR URI rooted at this resource;\n // leave already-canonical URIs untouched.\n const toUri = (id: string) => (isGdrUri(id) ? id : gdrFromResource(workflowResource, id))\n\n if (raw === null || raw === undefined) return null\n if (typeof raw === 'object' && 'id' in raw && 'type' in raw) {\n const r = raw as {id: unknown; type: unknown}\n if (typeof r.id === 'string' && typeof r.type === 'string') {\n return {id: toUri(r.id), type: r.type}\n }\n }\n if (typeof raw === 'object' && '_ref' in raw) {\n const r = raw as {_ref: unknown}\n if (typeof r._ref === 'string') return {id: toUri(r._ref), type: 'document'}\n }\n if (typeof raw === 'string' && raw.length > 0) return {id: toUri(raw), type: 'document'}\n return null\n}\n\n/**\n * Resolve a logical (workflowId, version?) ref to a deployed\n * `workflow.definition` doc. Scopes the lookup to definitions sharing\n * at least one tag with the caller. Picks the highest `version` when\n * `version` is omitted or `\"latest\"`; otherwise the explicit version.\n *\n * Returns null when no matching definition exists.\n */\nasync function resolveLogicalDefinition(\n client: WorkflowClient,\n ref: {workflowId: string; version?: number | 'latest' | undefined},\n tags: string[],\n): Promise<(WorkflowDefinition & SanityDocument) | null> {\n const wantsExplicit = typeof ref.version === 'number'\n const params: Record<string, unknown> = {workflowId: ref.workflowId, tags}\n if (wantsExplicit) params.version = ref.version\n const groq = wantsExplicit\n ? `*[_type == \"workflow.definition\" && workflowId == $workflowId && version == $version && count(tags[@ in $tags]) > 0][0]`\n : `*[_type == \"workflow.definition\" && workflowId == $workflowId && count(tags[@ in $tags]) > 0] | order(version desc)[0]`\n const result = await client.fetch<(WorkflowDefinition & SanityDocument) | null>(groq, params)\n return result ?? null\n}\n\nasync function prepareChildInstance(args: {\n client: WorkflowClient\n parent: WorkflowInstance\n task: Task\n spawn: Spawn\n initialState: InitialStateValue[]\n effectsContext: Record<string, string | number | boolean | GlobalDocumentReference>\n actor: Actor | undefined\n now: string\n}): Promise<{ref: GlobalDocumentReference; body: WorkflowInstance}> {\n const {client, parent, task, spawn, initialState, effectsContext, actor, now} = args\n\n const definition = await resolveLogicalDefinition(client, spawn.definitionRef, parent.tags ?? [])\n if (definition === null) {\n const versionLabel =\n spawn.definitionRef.version === undefined || spawn.definitionRef.version === 'latest'\n ? 'latest'\n : `v${spawn.definitionRef.version}`\n throw new Error(\n `Spawn target workflowId=\"${spawn.definitionRef.workflowId}\" ${versionLabel} not deployed (parent ${parent._id}, task ${task.id})`,\n )\n }\n\n // Child inherits the parent's tags + workflow resource so it stays\n // visible to whichever engine spawned the parent.\n const childTags = parent.tags ?? []\n const childPrefix = childTags[0] ?? 'wf'\n const workflowResource = parent.workflowResource\n // Bare `_id` — Sanity rejects `:` in document IDs. The GDR URI form\n // (`childUri`) is what the parent's `taskEntry.spawnedInstances[]`\n // and the child's own `ancestors[]` reference.\n const childDocId = `${childPrefix}.wf-instance.${randomKey()}`\n const childUri = gdrFromResource(workflowResource, childDocId)\n const childRef: GlobalDocumentReference = {id: childUri, type: 'workflow.instance'}\n const ancestors = [\n ...parent.ancestors,\n {\n id: selfGdr(parent),\n type: 'workflow.instance',\n } as GlobalDocumentReference,\n ]\n\n // Resolve the child's workflow-scope state declarations against the\n // caller-supplied `initialState`. The child's own state[] schema\n // dictates which slot ids/types exist; the spawn projection just\n // fills the \"init\"-sourced ones. Query/write slots resolve\n // per their own source kind.\n // Child instances inherit the parent's perspective by default — if\n // the parent reads under a release stack, child filters / spawn\n // discovery should see the same stacked view of the lake.\n const inheritedPerspective = parent.perspective\n const childState = await resolveDeclaredState({\n slotDefs: definition.state,\n initialState,\n ctx: {\n client,\n now,\n selfId: childDocId,\n tags: childTags,\n workflowResource,\n ...(inheritedPerspective !== undefined ? {perspective: inheritedPerspective} : {}),\n },\n randomKey,\n })\n // A child may carry its own `release.ref` slot (projected from the\n // spawn forEach) — that takes precedence over inheritance. Otherwise\n // it inherits the parent's perspective.\n const childPerspective = derivePerspectiveFromState(childState) ?? inheritedPerspective\n\n const effectsContextEntries: EffectsContextEntry[] = Object.entries(effectsContext).map(\n ([key, value]) => {\n if (typeof value === 'object' && value !== null && 'id' in value && 'type' in value) {\n if (!isGdrUri(value.id)) {\n throw new Error(\n `spawn.forEach.as.effectsContext[\"${key}\"]: GDR id must be a \"<scheme>:...\" URI, got ${JSON.stringify(value.id)}.`,\n )\n }\n return effectsContextEntry(key, {id: value.id, type: value.type})\n }\n return effectsContextEntry(key, value)\n },\n )\n\n const base = buildInstanceBase({\n id: childDocId,\n now,\n tags: childTags,\n workflowResource,\n workflowId: definition.workflowId,\n pinnedVersion: definition.version,\n definition,\n state: childState,\n effectsContext: effectsContextEntries,\n ancestors,\n perspective: childPerspective,\n initialStageId: definition.initialStageId,\n actor,\n })\n // Body is returned to the caller; the actual `client.create` happens\n // inside the parent's persist transaction so the parent's\n // `spawnedInstances` patch and this child create commit atomically.\n // Priming + cascade run after the transaction (per-child, single-doc).\n return {ref: childRef, body: base}\n}\n\nexport async function checkSpawnCompletion(\n client: WorkflowClient,\n entry: TaskEntry,\n spawn: Spawn,\n): Promise<boolean> {\n const refs = entry.spawnedInstances ?? []\n if (refs.length === 0) {\n // Vacuous: 0/0 children done satisfies \"all\" / \"count: 0\"; \"any\" / \"count: N>0\" fails.\n const policy = spawn.completionPolicy ?? {kind: 'all'}\n return policy.kind === 'all' || (policy.kind === 'count' && policy.n === 0)\n }\n\n // Single GROQ — fetches every child's stage info in one roundtrip\n // instead of N serial `getDocument` calls. (Previously this was the\n // engine's most expensive cascade hot path for fan-out spawns.)\n // `ref.id` is the child's GDR URI; the persistent `_id` is bare.\n const ids = refs.map((r) => (r.id.includes(':') ? gdrToBareId(r.id) : r.id))\n const children = await client.fetch<\n {_id: string; currentStageId: string; definitionSnapshot: string}[]\n >(`*[_id in $ids]{_id, currentStageId, definitionSnapshot}`, {ids})\n\n let terminalCount = 0\n for (const child of children) {\n const childDef = JSON.parse(child.definitionSnapshot) as WorkflowDefinition\n const childStage = childDef.stages.find((s) => s.id === child.currentStageId)\n if (childStage?.kind === 'terminal') terminalCount++\n }\n\n const policy = spawn.completionPolicy ?? {kind: 'all'}\n switch (policy.kind) {\n case 'all':\n // refs.length here is non-zero (handled above).\n return terminalCount === refs.length\n case 'any':\n return terminalCount >= 1\n case 'count':\n return terminalCount >= policy.n\n }\n}\n","import type {Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {TaskId} from '../types/ids.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport {\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n loadContext,\n resolveTaskStateSlots,\n} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {\n findCurrentTasks,\n findTaskInCurrentStage,\n type MutableInstance,\n persist,\n requireMutationTaskEntry,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport type {EngineCallOptions, InvokeResult} from './results.ts'\nimport {checkSpawnCompletion, spawnChildren} from './spawn.ts'\n\n/**\n * Flip a task from `pending` to `active` and queue its declared effects.\n * No-op if the task is already active or done.\n */\nexport async function invokeTask(args: {\n client: WorkflowClient\n instanceId: string\n taskId: TaskId\n options?: EngineCallOptions\n}): Promise<InvokeResult> {\n const {client, instanceId, taskId, options} = args\n const ctx = await loadContext(client, instanceId, {\n ...(options?.clock ? {clock: options.clock} : {}),\n })\n return commitInvoke(ctx, taskId, options?.actor)\n}\n\nasync function commitInvoke(\n ctx: EngineContext,\n taskId: TaskId,\n actor: Actor | undefined,\n): Promise<InvokeResult> {\n const {task} = findTaskInCurrentStage(ctx, taskId)\n const entry = findCurrentTasks(ctx.instance).find((t) => t.id === taskId)\n if (entry === undefined) {\n throw new Error(`Task \"${taskId}\" has no status entry on instance ${ctx.instance._id}`)\n }\n if (entry.status !== 'pending') {\n return {invoked: false, taskId}\n }\n\n const mutation = startMutation(ctx.instance)\n const mutEntry = requireMutationTaskEntry(mutation, taskId)\n await activateTask(ctx, mutation, task, mutEntry, actor)\n await persist(ctx, mutation)\n return {invoked: true, taskId}\n}\n\n/**\n * On activation, evaluate the task's `failWhen` then `completeWhen`\n * predicates against the current snapshot. The first truthy one\n * immediately resolves the task (failure dominates), recording a\n * system-actor status change. Returns true when the task resolved so\n * the caller short-circuits the normal active path.\n */\nasync function autoResolveOnActivate(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n entry: TaskEntry,\n now: string,\n): Promise<boolean> {\n const checks: {filter: Task['failWhen']; outcome: 'failed' | 'done'; systemId: string}[] = [\n {filter: task.failWhen, outcome: 'failed', systemId: 'engine.failWhen'},\n {filter: task.completeWhen, outcome: 'done', systemId: 'engine.completeWhen'},\n ]\n for (const {filter, outcome, systemId} of checks) {\n if (filter === undefined) continue\n if (!(await ctxEvaluateFilter(ctx, filter))) continue\n entry.status = outcome\n entry.completedAt = now\n entry.completedBy = systemId\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: mutation.currentStageId,\n taskId: task.id,\n from: 'active',\n to: outcome,\n at: now,\n actor: {kind: 'system', id: systemId},\n }),\n )\n return true\n }\n return false\n}\n\nexport async function activateTask(\n ctx: EngineContext,\n mutation: MutableInstance,\n task: Task,\n entry: TaskEntry,\n actor: Actor | undefined,\n): Promise<void> {\n // One clock reading for the whole activation so startedAt, any\n // auto-resolve flip, taskActivated, and spawn stamps agree on the time.\n const now = ctx.now\n entry.status = 'active'\n entry.startedAt = now\n // Resolve task-scoped state slots declared on the task definition.\n // Skipped if the task declares none — keeps the entry shape clean.\n if (task.state !== undefined && task.state.length > 0) {\n const stage = findStage(ctx.definition, mutation.currentStageId)\n entry.state = await resolveTaskStateSlots({\n client: ctx.client,\n instance: ctx.instance,\n stage,\n task,\n now,\n })\n }\n // Auto-failure dominates auto-completion: if both predicates would\n // fire, evaluate failWhen first so the more notable signal wins.\n if (await autoResolveOnActivate(ctx, mutation, task, entry, now)) return\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.taskActivated',\n at: now,\n stageId: mutation.currentStageId,\n taskId: task.id,\n ...(actor !== undefined ? {actor} : {}),\n })\n await queueEffects(\n ctx,\n mutation,\n task.effects,\n {\n kind: 'taskInvoke',\n id: task.id,\n },\n actor,\n )\n\n // If the task has a `spawns` declaration, fan out child workflow\n // instances now. The task stays `active` — propagation will flip it\n // to `done` once the spawn's completion policy is satisfied as\n // children transition.\n if (task.spawns !== undefined) {\n const refs = await spawnChildren(ctx, mutation, task, task.spawns, actor)\n entry.spawnedInstances = refs\n for (const ref of refs) {\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.spawned',\n at: now,\n taskId: task.id,\n instanceRef: ref,\n })\n }\n\n // Vacuous-truth case: if the spawn yielded zero items and the\n // policy is satisfied without any children (`{ kind: \"all\" }` over\n // an empty set is true; `{ kind: \"count\", n: 0 }` likewise), mark\n // the task done immediately. Otherwise propagation would never fire\n // (no child transitions to ride on), and the task would be stuck.\n if (await checkSpawnCompletion(ctx.client, entry, task.spawns)) {\n const previousStatus = entry.status\n entry.status = 'done'\n entry.completedAt = now\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: mutation.currentStageId,\n taskId: task.id,\n from: previousStatus,\n to: 'done',\n at: now,\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n }\n }\n}\n\n// Internal — task status & effects\n\nexport async function buildStageTasks(ctx: EngineContext, stage: Stage): Promise<TaskEntry[]> {\n const entries: TaskEntry[] = []\n for (const task of stage.tasks ?? []) {\n const inScope = await ctxEvaluateFilter(ctx, task.filter)\n entries.push({\n _key: randomKey(),\n id: task.id,\n status: inScope ? 'pending' : 'skipped',\n ...(task.filter !== undefined\n ? {\n filterEvaluation: {\n at: ctx.now,\n truthy: inScope,\n },\n }\n : {}),\n })\n }\n return entries\n}\n\n/** Tasks that implicitly activate when their stage is entered. */\nexport function activatesOnStageEnter(task: Task): boolean {\n return (\n task.invokeOn === 'stageEnter' ||\n task.spawns !== undefined ||\n task.completeWhen !== undefined ||\n task.failWhen !== undefined\n )\n}\n","import type {Stage, Transition} from '../define/schema.ts'\nimport {deployStageGuards, retractStageGuards} from '../guards-lifecycle.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {StageId} from '../types/ids.ts'\nimport type {StageEntry} from '../types/instance-state.ts'\nimport {\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n loadContext,\n resolveStageStateSlots,\n} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {deployOrRollback} from './guard-commit.ts'\nimport {\n findOpenStageEntry,\n instanceStateFields,\n materializeInstance,\n type MutableInstance,\n persist,\n stageTransitionHistory,\n startMutation,\n} from './mutation.ts'\nimport type {EngineCallOptions, TransitionResult} from './results.ts'\nimport {activatesOnStageEnter, activateTask, buildStageTasks} from './tasks.ts'\n\n/**\n * Admin override — force the instance into `targetStageId` regardless\n * of filters or declared transitions. Use cases: Kanban-style UI where\n * each column is a stage; migration scripts; manual recovery from a\n * stuck workflow. ACL gating is enforced at the API layer.\n *\n * Behaviour mirrors a successful transition: exit current stage,\n * append a fresh StageEntry for the target, fire onExit + onEnter\n * effects, auto-activate stageEnter / spawn / completeWhen tasks,\n * cascade. The history entries carry `via: \"setStage\"` so audits can\n * distinguish filtered transitions from admin overrides.\n */\nexport async function setStage(args: {\n client: WorkflowClient\n instanceId: string\n targetStageId: StageId\n reason?: string\n options?: EngineCallOptions\n}): Promise<TransitionResult> {\n const {client, instanceId, targetStageId, reason, options} = args\n const ctx = await loadContext(client, instanceId, {\n ...(options?.clock ? {clock: options.clock} : {}),\n })\n return commitSetStage(ctx, targetStageId, reason, options?.actor)\n}\n\n/**\n * Append a fresh {@link StageEntry} for `nextStage` and run the on-entry\n * lifecycle: queue `onEnter` effects, auto-activate tasks that must run on\n * stage entry (`invokeOn: \"stageEnter\"`, or those declaring `spawns` /\n * `completeWhen` / `failWhen`), and mark the instance complete if the stage is\n * terminal. The caller owns history, prior-stage exit, persistence, and guard\n * reconciliation. `at` is the single timestamp stamped on the entry.\n */\nasync function enterStage(\n ctx: EngineContext,\n mutation: MutableInstance,\n nextStage: Stage,\n actor: Actor | undefined,\n at: string,\n): Promise<void> {\n mutation.currentStageId = nextStage.id\n const nextStageEntry: StageEntry = {\n _key: randomKey(),\n id: nextStage.id,\n enteredAt: at,\n state: await resolveStageStateSlots({\n client: ctx.client,\n instance: ctx.instance,\n stage: nextStage,\n now: at,\n }),\n tasks: await buildStageTasks(ctx, nextStage),\n }\n mutation.stages.push(nextStageEntry)\n\n await queueEffects(\n ctx,\n mutation,\n nextStage.onEnter,\n {kind: 'stageEnter', id: nextStage.id},\n actor,\n )\n\n for (const task of nextStage.tasks ?? []) {\n if (!activatesOnStageEnter(task)) continue\n const entry = nextStageEntry.tasks.find((t) => t.id === task.id)\n if (entry && entry.status === 'pending') {\n await activateTask(ctx, mutation, task, entry, actor)\n }\n }\n\n if (nextStage.kind === 'terminal') {\n mutation.completedAt = at\n }\n}\n\n/**\n * Begin a stage move: snapshot the instance into a mutation, stamp one `at`\n * timestamp for the whole move, and queue the current stage's onExit effects.\n * Shared by the setStage and transition commit paths.\n */\nasync function beginStageMove(\n ctx: EngineContext,\n currentStage: Stage,\n actor: Actor | undefined,\n): Promise<{mutation: MutableInstance; at: string}> {\n const mutation = startMutation(ctx.instance)\n const at = ctx.now\n await queueEffects(\n ctx,\n mutation,\n currentStage.onExit,\n {kind: 'stageExit', id: currentStage.id},\n actor,\n )\n return {mutation, at}\n}\n\nasync function commitSetStage(\n ctx: EngineContext,\n targetStageId: StageId,\n reason: string | undefined,\n actor: Actor | undefined,\n): Promise<TransitionResult> {\n const currentStage = findStage(ctx.definition, ctx.instance.currentStageId)\n const nextStage = findStage(ctx.definition, targetStageId)\n if (currentStage.id === nextStage.id) {\n return {fired: false}\n }\n\n const {mutation, at} = await beginStageMove(ctx, currentStage, actor)\n\n const transitionId = `setStage:${currentStage.id}->${nextStage.id}`\n mutation.history.push(\n ...stageTransitionHistory({\n fromStageId: currentStage.id,\n toStageId: nextStage.id,\n at,\n transitionId,\n via: 'setStage',\n ...(actor !== undefined ? {actor} : {}),\n ...(reason !== undefined ? {reason} : {}),\n }),\n )\n\n const priorEntry = findOpenStageEntry(mutation)\n if (priorEntry !== undefined) priorEntry.exitedAt = at\n\n await enterStage(ctx, mutation, nextStage, actor, at)\n\n await persistStageMove(ctx, mutation, currentStage.id, nextStage.id)\n\n return {\n fired: true,\n fromStageId: currentStage.id,\n toStageId: nextStage.id,\n transitionId,\n }\n}\n\n/**\n * Persist a stage move, then reconcile its lake guards — deploy the entered\n * stage's, then lift the exited stage's. The two are deliberately separate, not\n * a single `reconcile`, because of rollback ordering:\n *\n * - Deploying the entered stage's lock runs *inside* the rollback scope. If it\n * fails, the move rolls back and the **exited** stage's guards are untouched —\n * the stage we return to is still enforced. (Retract-then-deploy would have\n * left the exited stage unlocked on a deploy failure.)\n * - Lifting the exited stage's guards runs *after* the move commits, resolved\n * against the pre-move `ctx.instance` so its stage-scoped Sources still\n * resolve (post-move that stage entry is `exitedAt`-stamped). A retract\n * failure leaves a stale lock on the prior stage — the documented orphan seam,\n * the safe (over-lock) direction — rather than an unlocked stage.\n */\nasync function persistStageMove(\n ctx: EngineContext,\n mutation: MutableInstance,\n exitedStageId: StageId,\n enteredStageId: StageId,\n): Promise<void> {\n await persistThenDeploy(ctx, mutation, () =>\n deployStageGuards({\n client: ctx.client,\n clientForGdr: ctx.clientForGdr,\n instance: materializeInstance(ctx.instance, mutation),\n definition: ctx.definition,\n stageId: enteredStageId,\n now: ctx.now,\n }),\n )\n await retractStageGuards({\n client: ctx.client,\n clientForGdr: ctx.clientForGdr,\n instance: ctx.instance,\n definition: ctx.definition,\n stageId: exitedStageId,\n now: ctx.now,\n })\n}\n\n/**\n * Commit a mutation, then deploy its stage's guards — rolling the commit back\n * (or screaming when it can't) if the deploy fails, so persisted state and\n * deployed guards never silently diverge. Guards deploy AFTER the commit: a\n * guard can lock the caller out of further edits, so it must follow the state\n * it enforces. When the commit was a spawn transaction it created child docs a\n * parent-only rollback can't undo, so that case screams instead of half-undoing.\n * This is the shared commit+deploy chokepoint for the transition and action paths.\n */\nexport async function persistThenDeploy(\n ctx: EngineContext,\n mutation: MutableInstance,\n deploy: () => Promise<void>,\n): Promise<void> {\n const spawned = mutation.pendingCreates.length > 0\n const committed = await persist(ctx, mutation)\n await deployOrRollback({\n client: ctx.client,\n instanceId: ctx.instance._id,\n committedRev: committed._rev,\n restore: instanceStateFields(ctx.instance),\n unset: ctx.instance.completedAt === undefined ? ['completedAt'] : [],\n reversible: !spawned,\n deploy,\n })\n}\n\n/**\n * Re-deploy the current stage's guards against post-mutation state. A guard\n * snapshots the workflow state its `match`/`metadata` Sources resolve to at\n * deploy time; when an action's ops change that state without a stage move,\n * the engine must refresh the guard so it stays coherent (the \"use the engine,\n * stay consistent\" contract). Idempotent upsert — re-resolves each guard's\n * Sources against the new state via {@link materializeInstance}.\n *\n * Caveat: refresh only upserts. If an op changes a guard's `match.idRefs`\n * *target* (not just metadata), the re-deploy writes the guard to the new\n * resource while the old one lingers — the orphan/cross-dataset seam documented\n * in `guards-lifecycle.ts`. The metadata-change case (stable idRef) is fully\n * coherent; idRef re-homing waits on the retract/GC work.\n *\n * The caller (`commitAction`) runs this through {@link persistThenDeploy}, so a\n * failed re-deploy rolls the state change back rather than leaving it stale.\n * One coherence relaxation: {@link deployStageGuards} no-ops if a concurrent\n * transition moved the instance off `stageId` between the persist and the\n * deploy. The refresh is then correctly skipped (refreshing a left stage would\n * itself be wrong) and the state op stands — `deployOrRollback` sees success,\n * so this is not a divergence, it's the newer transition taking ownership.\n */\nexport async function refreshStageGuards(\n ctx: EngineContext,\n mutation: MutableInstance,\n stageId: StageId,\n): Promise<void> {\n await deployStageGuards({\n client: ctx.client,\n clientForGdr: ctx.clientForGdr,\n instance: materializeInstance(ctx.instance, mutation),\n definition: ctx.definition,\n stageId,\n now: ctx.now,\n })\n}\n\nexport async function commitTransition(\n ctx: EngineContext,\n action: string | undefined,\n actor: Actor | undefined,\n): Promise<TransitionResult> {\n const currentStage = findStage(ctx.definition, ctx.instance.currentStageId)\n const transition = await pickTransition(ctx, currentStage, action)\n if (transition === undefined) {\n return {fired: false}\n }\n\n const {mutation, at} = await beginStageMove(ctx, currentStage, actor)\n\n // Fire transition effects.\n await queueEffects(\n ctx,\n mutation,\n transition.effects,\n {\n kind: 'transition',\n id: transition.id ?? `${currentStage.id}->${transition.to}`,\n },\n actor,\n )\n\n // Append history.\n mutation.history.push(\n ...stageTransitionHistory({\n fromStageId: currentStage.id,\n toStageId: transition.to,\n at,\n ...(transition.id !== undefined ? {transitionId: transition.id} : {}),\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n\n // Mark the prior stage exited. There can be multiple entries with\n // the same id from loop-backs — the current one is the one without\n // exitedAt set.\n const priorEntry = findOpenStageEntry(mutation)\n if (priorEntry !== undefined) priorEntry.exitedAt = at\n\n // Move to new stage and append a fresh StageEntry with its tasks.\n const nextStage = findStage(ctx.definition, transition.to)\n await enterStage(ctx, mutation, nextStage, actor, at)\n\n await persistStageMove(ctx, mutation, currentStage.id, nextStage.id)\n\n return {\n fired: true,\n fromStageId: currentStage.id,\n toStageId: transition.to,\n ...(transition.id !== undefined ? {transitionId: transition.id} : {}),\n }\n}\n\nasync function pickTransition(\n ctx: EngineContext,\n stage: Stage,\n action: string | undefined,\n): Promise<Transition | undefined> {\n const candidates = (stage.transitions ?? []).filter((t) => {\n if (action === undefined) return t.on === undefined\n return t.on === action\n })\n for (const candidate of candidates) {\n if (await ctxEvaluateFilter(ctx, candidate.filter)) return candidate\n }\n return undefined\n}\n","// Essential commit⇄cascade mutual recursion: `mutation.persist` is the single\n// transactional commit chokepoint, and committing a parent that spawned\n// children must drive those children's lifecycle (prime → cascade → propagate)\n// inline, which itself commits through `persist`. Children are primed *within*\n// the parent's commit so the parent's spawn-completion gate observes them in the\n// same pass — deferring the drive to a higher layer would break that synchronous\n// nested-workflow semantics. Resolved at call time; module init is unaffected.\n// fallow-ignore-file circular-dependencies\nimport {type Clock, wallClock} from '../clock.ts'\nimport {resolveBindings} from '../core/bindings.ts'\nimport {evaluateFilter} from '../core/eval.ts'\nimport {buildParams} from '../core/params.ts'\nimport type {ParsedGdr} from '../core/refs.ts'\nimport type {Stage, Task, WorkflowDefinition} from '../define/schema.ts'\nimport {deployStageGuards} from '../guards-lifecycle.ts'\nimport {randomKey} from '../keys.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {StageEntry, TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {\n buildEngineContext,\n ctxEvaluateFilter,\n type EngineContext,\n findStage,\n gdrToBareId,\n loadContext,\n resolveStageStateSlots,\n} from './context.ts'\nimport {buildQueuedEffect} from './effects.ts'\nimport {deployOrRollback} from './guard-commit.ts'\nimport {\n currentTasks,\n findCurrentTasks,\n persist,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport {CascadeLimitError, type EngineCallOptions, type TransitionResult} from './results.ts'\nimport {checkSpawnCompletion} from './spawn.ts'\nimport {commitTransition} from './stages.ts'\nimport {activatesOnStageEnter, activateTask} from './tasks.ts'\n\n/**\n * Re-evaluate auto-transitions. Use after any change that might unblock\n * one (e.g. after a fireAction commits).\n */\nasync function evaluateAutoTransitions(args: {\n client: WorkflowClient\n instanceId: string\n options?: EngineCallOptions\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient\n clock?: Clock\n}): Promise<TransitionResult> {\n const {client, instanceId, options, clientForGdr, clock} = args\n const ctx = await loadContext(client, instanceId, {\n ...(clientForGdr ? {clientForGdr} : {}),\n ...(clock ? {clock} : {}),\n })\n return commitTransition(ctx, undefined, options?.actor)\n}\n\n// Initial-stage priming, cascade, propagation — used by both api.ts (for\n// fresh instances and after-call cascading) and the spawn path inside\n// activateTask. Exported so api.ts doesn't reimplement them.\n\n/**\n * Build taskStatus + queue onEnter effects + auto-activate stageEnter\n * tasks for a freshly-created instance's initial stage. Called by both\n * `workflow.startInstance` and the spawn path.\n */\nexport async function primeInitialStage(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<void> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) return\n // Idempotency: if the initial stage entry is already on the instance,\n // skip. New instances arrive here with `stages: []`.\n if (instance.stages.length > 0 || instance.pendingEffects.length > 0) return\n\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const stage = definition.stages.find((s) => s.id === instance.currentStageId)\n if (stage === undefined) return\n\n // One clock reading for the whole prime so filter `$now`, the stage\n // entry, queued effects, and the commit all agree on the time.\n const now = (clock ?? wallClock)()\n\n // Build a snapshot up-front so any `filter` on a stage-tasks entry\n // can evaluate in-memory. Same shape the cascade uses.\n const snapshot = await hydrateSnapshot({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance,\n definition,\n })\n const tasks: TaskEntry[] = []\n for (const task of stage.tasks ?? []) {\n const inScope = await evaluateFilter({\n filter: task.filter,\n definition,\n snapshot,\n params: buildParams(instance, now),\n })\n tasks.push({\n _key: randomKey(),\n id: task.id,\n status: inScope ? 'pending' : 'skipped',\n })\n }\n const initialStageEntry: StageEntry = {\n _key: randomKey(),\n id: stage.id,\n enteredAt: now,\n state: await resolveStageStateSlots({client, instance, stage, now}),\n tasks,\n }\n\n const pendingEffects: PendingEffect[] = []\n const newHistory = [...instance.history]\n for (const effect of stage.onEnter ?? []) {\n const params = await resolveBindings({\n bindings: effect.bindings,\n staticInput: effect.input,\n instance,\n now,\n ...(actor !== undefined ? {actor} : {}),\n })\n const {pending, history} = buildQueuedEffect(\n effect,\n {kind: 'stageEnter', id: stage.id},\n params,\n actor,\n now,\n )\n pendingEffects.push(pending)\n newHistory.push(history)\n }\n\n // Patch — fails fast if the instance was deleted between the\n // `create` above and this prime call. `ifRevisionId` rejects concurrent\n // priming attempts (e.g. a retried startInstance).\n const committed = await client\n .patch(instance._id)\n .set({\n stages: [initialStageEntry],\n pendingEffects,\n history: newHistory,\n lastChangedAt: now,\n })\n .ifRevisionId(instance._rev)\n .commit()\n\n // Deploy lake guards for the initial stage (no exit to retract). If the\n // deploy fails, roll the prime back to the freshly-created (unprimed) state\n // so an instance never sits primed-but-unlocked; surface the error.\n await deployOrRollback({\n client,\n instanceId: instance._id,\n committedRev: committed._rev,\n restore: {\n stages: instance.stages,\n pendingEffects: instance.pendingEffects,\n history: instance.history,\n },\n reversible: true,\n deploy: () =>\n deployStageGuards({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance,\n definition,\n stageId: stage.id,\n now,\n }),\n })\n\n await autoActivatePrimedTasks(client, instanceId, definition, stage, actor, clientForGdr, clock)\n}\n\n/**\n * After the initial stage entry is persisted, re-load and auto-activate\n * the tasks that implicitly run on stage-entry (`invokeOn: \"stageEnter\"`,\n * spawn-bearing, or carrying a `completeWhen`/`failWhen` predicate). Each\n * activation reloads + persists independently so spawns + auto-resolution\n * see committed state.\n */\nasync function autoActivatePrimedTasks(\n client: WorkflowClient,\n instanceId: string,\n definition: WorkflowDefinition,\n stage: Stage,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<void> {\n const resolvedClientForGdr = clientForGdr ?? (() => client)\n for (const task of stage.tasks ?? []) {\n if (!activatesOnStageEnter(task)) continue\n const updated = await client.getDocument<WorkflowInstance>(instanceId)\n if (!updated) continue\n const updatedCtx = await buildEngineContext({\n client,\n clientForGdr: resolvedClientForGdr,\n instance: updated,\n definition,\n ...(clock ? {clock} : {}),\n })\n const mutation = startMutation(updated)\n const mutEntry = currentTasks(mutation).find((t) => t.id === task.id)\n if (mutEntry && mutEntry.status === 'pending') {\n await activateTask(updatedCtx, mutation, task, mutEntry, actor)\n await persist(updatedCtx, mutation)\n }\n }\n}\n\n// Backpressure for the auto-transition cascade. Ops mutate state once per\n// `fireAction` (a finite authored list — no re-entrancy, so they need no\n// per-action limit of their own), but the *transitions* an op unblocks can\n// flip-flop without end. This is the single bound that catches that runaway;\n// it throws {@link CascadeLimitError} rather than writing revisions forever.\nconst CASCADE_LIMIT = 100\n\n/**\n * Walk active task entries whose authoring definition declares a\n * `completeWhen` and/or `failWhen` filter; evaluate the filters against\n * the current snapshot and flip any matching task accordingly. Returns\n * the count flipped.\n *\n * Both predicates are evaluated on the same pass. If a single task has\n * both and both are truthy, `failWhen` wins — failure dominates so the\n * more notable signal is not silently swallowed.\n *\n * The engine never runs a clock itself — this only fires if something\n * else (a `tick`, a `fireAction`, a `completeEffect`, or `startInstance`)\n * has already kicked the cascade. A scheduler crossing a deadline calls\n * `tick` (with an injected {@link Clock} under test); state-based\n * predicates rely on the caller invoking `tick` when state changes.\n */\ntype AutoResolveCandidate = {task: Task; outcome: 'done' | 'failed'}\n\n/** For each active task carrying an auto-predicate, evaluate `failWhen`\n * then `completeWhen` (failure dominates) and collect the outcome. */\nasync function gatherAutoResolveCandidates(\n ctx: EngineContext,\n tasks: Task[],\n): Promise<AutoResolveCandidate[]> {\n const currentTasksList = findCurrentTasks(ctx.instance)\n const candidates: AutoResolveCandidate[] = []\n for (const task of tasks) {\n const entry = currentTasksList.find((e) => e.id === task.id)\n if (entry?.status !== 'active') continue\n // failWhen first — failure dominates if both fire.\n if (task.failWhen !== undefined && (await ctxEvaluateFilter(ctx, task.failWhen))) {\n candidates.push({task, outcome: 'failed'})\n continue\n }\n if (task.completeWhen !== undefined && (await ctxEvaluateFilter(ctx, task.completeWhen))) {\n candidates.push({task, outcome: 'done'})\n }\n }\n return candidates\n}\n\nasync function resolveCompleteWhen(\n client: WorkflowClient,\n instanceId: string,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<number> {\n const ctx = await loadContext(client, instanceId, {\n ...(clientForGdr ? {clientForGdr} : {}),\n ...(clock ? {clock} : {}),\n })\n const stage = findStage(ctx.definition, ctx.instance.currentStageId)\n const tasksWithAutoPredicate = (stage.tasks ?? []).filter(\n (t) => t.completeWhen !== undefined || t.failWhen !== undefined,\n )\n if (tasksWithAutoPredicate.length === 0) return 0\n\n const candidates = await gatherAutoResolveCandidates(ctx, tasksWithAutoPredicate)\n if (candidates.length === 0) return 0\n\n const mutation = startMutation(ctx.instance)\n let count = 0\n for (const {task, outcome} of candidates) {\n const mutEntry = currentTasks(mutation).find((t) => t.id === task.id)\n if (mutEntry === undefined || mutEntry.status !== 'active') continue\n const previousStatus = mutEntry.status\n const actor: Actor = {\n kind: 'system',\n id: outcome === 'failed' ? 'engine.failWhen' : 'engine.completeWhen',\n }\n const now = ctx.now\n mutEntry.status = outcome\n mutEntry.completedAt = now\n mutEntry.completedBy = actor.id\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: stage.id,\n taskId: task.id,\n from: previousStatus,\n to: outcome,\n at: now,\n actor,\n }),\n )\n count++\n }\n if (count > 0) {\n await persist(ctx, mutation)\n }\n return count\n}\n\n/**\n * Cascade auto-transitions on the given instance until it lands stably.\n * Returns the count of transitions fired during the cascade. Resolves\n * any due waits before each transition pass so a wait that became due\n * can immediately unblock an `allTasksDone`-style filter.\n */\nexport async function cascadeAutoTransitions(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<number> {\n let count = 0\n while (true) {\n await resolveCompleteWhen(client, instanceId, clientForGdr, clock)\n const result = await evaluateAutoTransitions({\n client,\n instanceId,\n ...(actor !== undefined ? {options: {actor}} : {}),\n ...(clientForGdr ? {clientForGdr} : {}),\n ...(clock ? {clock} : {}),\n })\n if (!result.fired) return count\n count++\n if (count >= CASCADE_LIMIT) {\n throw new CascadeLimitError({instanceId, limit: CASCADE_LIMIT})\n }\n }\n}\n\n/**\n * Walk up an instance's ancestor chain, re-evaluating each ancestor's\n * spawn-bearing task in case its completion policy is now satisfied. If\n * a parent task flips done as a result, cascade auto-transitions on the\n * parent and recurse upward.\n *\n * This is the load-bearing primitive for nested workflows: child\n * transitions ripple up the tree, parent gates close, grand-parent\n * gates close, all the way to the root.\n */\n/** The parent whose spawn-bearing task this child has just satisfied —\n * resolved from the child's ancestor chain, or undefined when there is\n * no such parent (no ancestors, parent gone/malformed, no matching\n * spawning task, task already done, or its completion policy not yet\n * met). Isolating these guard clauses keeps {@link propagateToAncestors}\n * to the flip-and-recurse it actually performs. */\ninterface SatisfiedParentSpawn {\n parent: WorkflowInstance\n definition: WorkflowDefinition\n stage: Stage\n task: Task\n}\n\nasync function findSatisfiedParentSpawn(\n client: WorkflowClient,\n child: WorkflowInstance,\n): Promise<SatisfiedParentSpawn | undefined> {\n const parentRef = child.ancestors.at(-1)\n if (parentRef === undefined) return undefined\n // ancestors[].id is the GDR URI; the Sanity `_id` is bare.\n const parent = await client.getDocument<WorkflowInstance>(gdrToBareId(parentRef.id))\n // A misconfigured caller could put an arbitrary doc ref in ancestors[];\n // bail gracefully instead of crashing on `JSON.parse(undefined)`.\n if (!parent || parent._type !== 'workflow.instance') return undefined\n if (typeof parent.definitionSnapshot !== 'string') return undefined\n\n const definition = JSON.parse(parent.definitionSnapshot) as WorkflowDefinition\n const stage = definition.stages.find((s) => s.id === parent.currentStageId)\n if (stage === undefined) return undefined\n\n // Find the task on the parent's current stage that spawned this child.\n // `spawnedInstances[].id` is the child's GDR URI; the `_id` is bare.\n const parentCurrentTasks = findCurrentTasks(parent)\n const task = (stage.tasks ?? []).find((t) => {\n if (t.spawns === undefined) return false\n const entry = parentCurrentTasks.find((e) => e.id === t.id)\n return entry?.spawnedInstances?.some((r) => gdrToBareId(r.id) === child._id) ?? false\n })\n if (task?.spawns === undefined) return undefined\n\n const entry = parentCurrentTasks.find((e) => e.id === task.id)\n if (entry === undefined || entry.status === 'done') return undefined\n if (!(await checkSpawnCompletion(client, entry, task.spawns))) return undefined\n\n return {parent, definition, stage, task}\n}\n\nexport async function propagateToAncestors(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<void> {\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) return\n\n const found = await findSatisfiedParentSpawn(client, instance)\n if (found === undefined) return\n const {parent, definition, stage, task} = found\n\n // Flip the parent's task to done and persist.\n const ctx = await buildEngineContext({\n client,\n clientForGdr: clientForGdr ?? (() => client),\n instance: parent,\n definition,\n ...(clock ? {clock} : {}),\n })\n const mutation = startMutation(parent)\n const mutEntry = currentTasks(mutation).find((e) => e.id === task.id)\n if (mutEntry === undefined) return\n const previousStatus = mutEntry.status\n const now = ctx.now\n mutEntry.status = 'done'\n mutEntry.completedAt = now\n mutation.history.push(\n taskStatusChangedEntry({\n stageId: stage.id,\n taskId: task.id,\n from: previousStatus,\n to: 'done',\n at: now,\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n await persist(ctx, mutation)\n\n // Cascade auto-transitions on the parent. This may transition it to\n // a new stage, which itself may unblock the grandparent's task.\n await cascadeAutoTransitions(client, parent._id, actor, clientForGdr, clock)\n\n // Recurse: propagate from the parent upward.\n await propagateToAncestors(client, parent._id, actor, clientForGdr, clock)\n}\n","import type {SanityDocument} from '@sanity/types'\n\nimport type {Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {EffectHistoryEntry, EffectsContextEntry, PendingEffect} from '../types/effects.ts'\nimport type {TaskStatus} from '../types/enums.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {StageEntry, TaskEntry} from '../types/instance-state.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {cascadeAutoTransitions, primeInitialStage, propagateToAncestors} from './cascade.ts'\nimport {type EngineContext, findStage} from './context.ts'\n\n// Internal — commits\n\nexport interface MutableInstance {\n currentStageId: StageId\n state: ResolvedStateSlot[]\n stages: StageEntry[]\n pendingEffects: PendingEffect[]\n effectHistory: EffectHistoryEntry[]\n effectsContext: EffectsContextEntry[]\n history: HistoryEntry[]\n lastChangedAt: string\n completedAt?: string\n /**\n * Net-new child workflow instances queued by `spawnChildren` during\n * this mutation. Drained at `persist` time into a single same-resource\n * transaction so the parent's `spawnedInstances` patch and the child\n * `create`s commit atomically.\n */\n pendingCreates: WorkflowInstance[]\n}\n\nexport function startMutation(instance: WorkflowInstance): MutableInstance {\n return {\n currentStageId: instance.currentStageId,\n // Deep-ish copy. Per-scope state slot arrays need their own copies\n // so ops can mutate without leaking into the source.\n state: (instance.state ?? []).map((s) => ({...s})),\n stages: instance.stages.map((s) => ({\n ...s,\n state: (s.state ?? []).map((slot) => ({...slot})),\n tasks: s.tasks.map((t) => ({\n ...t,\n ...(t.state !== undefined ? {state: t.state.map((slot) => ({...slot}))} : {}),\n })),\n })),\n pendingEffects: [...instance.pendingEffects],\n effectHistory: [...instance.effectHistory],\n effectsContext: [...instance.effectsContext],\n history: [...instance.history],\n lastChangedAt: instance.lastChangedAt,\n ...(instance.completedAt !== undefined ? {completedAt: instance.completedAt} : {}),\n pendingCreates: [],\n }\n}\n\n/** Build a `taskStatusChanged` history entry, stamping a fresh `_key`.\n * `at` is the operation's clock reading (the caller's `ctx.now`). */\nexport function taskStatusChangedEntry(args: {\n stageId: StageId\n taskId: TaskId\n from: TaskStatus\n to: TaskStatus\n at: string\n actor?: Actor\n}): HistoryEntry {\n return {\n _key: randomKey(),\n _type: 'workflow.history.taskStatusChanged',\n at: args.at,\n stageId: args.stageId,\n taskId: args.taskId,\n from: args.from,\n to: args.to,\n ...(args.actor !== undefined ? {actor: args.actor} : {}),\n }\n}\n\n/**\n * Build the three-entry history sequence for a stage move:\n * `stageExited` → `transitionFired` → `stageEntered`. All three share\n * `at`, the (optional) `transitionId`, `actor`, and the `via`/`reason`\n * discriminators that distinguish filtered transitions from admin\n * overrides.\n */\nexport function stageTransitionHistory(args: {\n fromStageId: StageId\n toStageId: StageId\n at: string\n transitionId?: string\n actor?: Actor\n via?: 'transition' | 'setStage'\n reason?: string\n}): HistoryEntry[] {\n const {fromStageId, toStageId, at, transitionId, actor, via, reason} = args\n const shared = {\n at,\n ...(transitionId !== undefined ? {transitionId} : {}),\n ...(actor !== undefined ? {actor} : {}),\n ...(via !== undefined ? {via} : {}),\n ...(reason !== undefined ? {reason} : {}),\n }\n return [\n {\n _key: randomKey(),\n _type: 'workflow.history.stageExited',\n stageId: fromStageId,\n toStageId,\n ...shared,\n },\n {\n _key: randomKey(),\n _type: 'workflow.history.transitionFired',\n fromStageId,\n toStageId,\n ...shared,\n },\n {\n _key: randomKey(),\n _type: 'workflow.history.stageEntered',\n stageId: toStageId,\n fromStageId,\n ...shared,\n },\n ]\n}\n\n/**\n * The persisted state fields of an instance, sans `lastChangedAt`. Single\n * source for both `persist` (what a commit writes) and guard-failure rollback\n * (what restoring the pre-commit instance must write back), so the two can't\n * drift. `completedAt` is included only when set — callers rolling back a move\n * that newly completed an instance must `unset` it separately.\n */\nexport function instanceStateFields(\n src: Pick<\n MutableInstance,\n | 'currentStageId'\n | 'state'\n | 'stages'\n | 'pendingEffects'\n | 'effectHistory'\n | 'effectsContext'\n | 'history'\n | 'completedAt'\n >,\n): Record<string, unknown> {\n const fields: Record<string, unknown> = {\n currentStageId: src.currentStageId,\n state: src.state,\n stages: src.stages,\n pendingEffects: src.pendingEffects,\n effectHistory: src.effectHistory,\n effectsContext: src.effectsContext,\n history: src.history,\n }\n if (src.completedAt !== undefined) fields.completedAt = src.completedAt\n return fields\n}\n\n/**\n * A read-only `WorkflowInstance` view of an in-flight mutation: the persisted\n * identity/provenance fields from `base`, with the mutated `currentStageId` /\n * `state` / `stages` layered on. Guard (re)deployment resolves Sources against\n * this so it sees post-move state, not the stale loaded instance.\n */\nexport function materializeInstance(\n base: WorkflowInstance,\n mutation: MutableInstance,\n): WorkflowInstance {\n return {\n ...base,\n currentStageId: mutation.currentStageId,\n state: mutation.state,\n stages: mutation.stages,\n }\n}\n\nexport async function persist(\n ctx: EngineContext,\n mutation: MutableInstance,\n): Promise<SanityDocument> {\n // Patch (not createOrReplace): patches require the doc to exist, so\n // a deleted instance mid-cascade fails fast instead of getting\n // silently resurrected. `ifRevisionId` adds optimistic concurrency —\n // if another writer raced us, the patch errors instead of clobbering.\n const set: Record<string, unknown> = {\n ...instanceStateFields(mutation),\n lastChangedAt: ctx.now,\n }\n\n const pendingCreates = mutation.pendingCreates\n if (pendingCreates.length === 0) {\n return ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev).commit()\n }\n\n // Multi-doc same-resource write: bundle the N child creates with the\n // parent's patch in one Sanity transaction. Children inherit the\n // parent's `workflowResource` so they are always provably same-resource.\n const tx = ctx.client.transaction()\n for (const body of pendingCreates) tx.create(body)\n tx.patch(ctx.client.patch(ctx.instance._id).set(set).ifRevisionId(ctx.instance._rev))\n await tx.commit()\n mutation.pendingCreates = []\n\n // Children are now durably in the lake with the parent's\n // `spawnedInstances` recorded atomically. Prime each child's initial\n // stage, cascade to whatever stage it lands on (possibly terminal),\n // then propagate up — a child that reached terminal needs to\n // re-evaluate its parent's spawn-completion gate. Pre-refactor,\n // `spawnChildren` ran per-child create+prime+cascade synchronously\n // and `activateTask`'s in-memory `checkSpawnCompletion` flipped the\n // parent's task done in the same mutation; deferring creates into\n // the transaction means we restore that effect via explicit\n // propagation here.\n const actorForPriming: Actor | undefined = undefined\n for (const body of pendingCreates) {\n await primeInitialStage(ctx.client, body._id, actorForPriming, ctx.clientForGdr, ctx.clock)\n await cascadeAutoTransitions(ctx.client, body._id, actorForPriming, ctx.clientForGdr, ctx.clock)\n await propagateToAncestors(ctx.client, body._id, actorForPriming, ctx.clientForGdr, ctx.clock)\n }\n\n // Reload the parent so callers see the post-commit `_rev`. Persist's\n // historical return shape is the patched parent doc; preserve that.\n const reloaded = await ctx.client.getDocument<SanityDocument>(ctx.instance._id)\n if (!reloaded) {\n throw new Error(`Instance ${ctx.instance._id} disappeared after transaction commit`)\n }\n return reloaded\n}\n\n// Helpers for working with the per-stage task entries.\n//\n// \"Current\" means the StageEntry whose `exitedAt` is undefined AND whose\n// id matches `currentStageId`. On loop-backs (entering a stage that was\n// visited before), there are multiple entries with the same id — the\n// prior ones have `exitedAt` set, the current one does not.\n\n/** The open (un-exited) {@link StageEntry} matching `currentStageId`, or\n * undefined. Both {@link MutableInstance} and {@link WorkflowInstance}\n * share the `stages` + `currentStageId` shape this reads. */\nexport function findOpenStageEntry(host: {\n stages: StageEntry[]\n currentStageId: StageId\n}): StageEntry | undefined {\n return host.stages.find((s) => s.id === host.currentStageId && s.exitedAt === undefined)\n}\n\nfunction currentStageEntry(mutation: MutableInstance): StageEntry {\n const entry = findOpenStageEntry(mutation)\n if (entry === undefined) {\n throw new Error(\n `Mutation invariant broken: no current (un-exited) StageEntry for currentStageId \"${mutation.currentStageId}\"`,\n )\n }\n return entry\n}\n\nexport function currentTasks(mutation: MutableInstance): TaskEntry[] {\n return currentStageEntry(mutation).tasks\n}\n\n/** Find a task definition on the instance's current stage, throwing a\n * consistent error when it isn't declared there. */\nexport function findTaskInCurrentStage(\n ctx: EngineContext,\n taskId: TaskId,\n): {stage: Stage; task: Task} {\n const stage = findStage(ctx.definition, ctx.instance.currentStageId)\n const task = (stage.tasks ?? []).find((t) => t.id === taskId)\n if (task === undefined) {\n throw new Error(\n `Task \"${taskId}\" not found in current stage \"${stage.id}\" of ${ctx.definition.workflowId}`,\n )\n }\n return {stage, task}\n}\n\n/** The mutation copy's entry for `taskId`. Throws if it vanished — the\n * live instance and its mutation copy must agree on task identity. */\nexport function requireMutationTaskEntry(mutation: MutableInstance, taskId: TaskId): TaskEntry {\n const mutEntry = currentTasks(mutation).find((t) => t.id === taskId)\n if (mutEntry === undefined) {\n throw new Error(`Task \"${taskId}\" disappeared from mutation copy — invariant broken`)\n }\n return mutEntry\n}\n\nfunction findCurrentStageEntry(instance: WorkflowInstance): StageEntry | undefined {\n return findOpenStageEntry(instance)\n}\n\nexport function findCurrentTasks(instance: WorkflowInstance): TaskEntry[] {\n return findCurrentStageEntry(instance)?.tasks ?? []\n}\n","import {resolveBindings} from '../core/bindings.ts'\nimport type {GlobalDocumentReference} from '../core/refs.ts'\nimport type {Effect} from '../define/schema.ts'\nimport {effectsContextEntry} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectHistoryEntry, EffectOrigin, PendingEffect} from '../types/effects.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {type EngineContext, loadContext} from './context.ts'\nimport {type MutableInstance, persist, startMutation} from './mutation.ts'\nimport type {CompleteEffectResult, EngineCallOptions} from './results.ts'\n\n/**\n * Mark a queued effect as completed. Drains it from `pendingEffects`,\n * appends an `EffectHistoryEntry`, and (if `outputs` are supplied)\n * upserts those into `effectsContext` by key — making them available to\n * downstream effect bindings.\n *\n * This is the only path that mutates `effectsContext` after start.\n */\nexport async function completeEffect(args: {\n client: WorkflowClient\n instanceId: string\n effectKey: string\n status: 'done' | 'failed'\n outputs?: Record<string, string | number | boolean | GlobalDocumentReference>\n detail?: string\n error?: {message: string; stack?: string}\n durationMs?: number\n options?: EngineCallOptions\n}): Promise<CompleteEffectResult> {\n const {client, instanceId, effectKey, status, outputs, detail, error, durationMs, options} = args\n const ctx = await loadContext(client, instanceId, {\n ...(options?.clock ? {clock: options.clock} : {}),\n })\n return commitCompleteEffect(\n ctx,\n effectKey,\n status,\n outputs,\n detail,\n error,\n durationMs,\n options?.actor,\n )\n}\n\n/** Build the {@link EffectHistoryEntry} recorded when a queued effect\n * completes, carrying the pending entry's identity forward and stamping\n * the run outcome. A supplied `actor` overrides the pending entry's. */\nfunction buildEffectHistoryEntry(\n pending: PendingEffect,\n outcome: {\n status: 'done' | 'failed'\n ranAt: string\n actor: Actor | undefined\n detail: string | undefined\n error: {message: string; stack?: string} | undefined\n durationMs: number | undefined\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined\n },\n): EffectHistoryEntry {\n const {status, ranAt, actor, detail, error, durationMs, outputs} = outcome\n return {\n _key: pending._key,\n effectId: pending.effectId,\n ...(pending.title !== undefined ? {title: pending.title} : {}),\n ...(pending.description !== undefined ? {description: pending.description} : {}),\n params: pending.params,\n origin: pending.origin,\n ...(actor !== undefined ? {actor} : pending.actor !== undefined ? {actor: pending.actor} : {}),\n ranAt,\n ...(durationMs !== undefined ? {durationMs} : {}),\n status,\n ...(detail !== undefined ? {detail} : {}),\n ...(error !== undefined ? {error} : {}),\n ...(outputs !== undefined ? {outputs} : {}),\n }\n}\n\n/** Upsert completed-effect outputs into the mutation's `effectsContext`,\n * replacing any existing entry with the same id. */\nfunction upsertEffectsContext(\n mutation: MutableInstance,\n outputs: Record<string, string | number | boolean | GlobalDocumentReference>,\n): void {\n for (const [id, value] of Object.entries(outputs)) {\n const existingIndex = mutation.effectsContext.findIndex((e) => e.id === id)\n const entry = effectsContextEntry(id, value)\n if (existingIndex >= 0) mutation.effectsContext[existingIndex] = entry\n else mutation.effectsContext.push(entry)\n }\n}\n\nasync function commitCompleteEffect(\n ctx: EngineContext,\n effectKey: string,\n status: 'done' | 'failed',\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined,\n detail: string | undefined,\n error: {message: string; stack?: string} | undefined,\n durationMs: number | undefined,\n actor: Actor | undefined,\n): Promise<CompleteEffectResult> {\n const pending = ctx.instance.pendingEffects.find((e) => e._key === effectKey)\n if (pending === undefined) {\n throw new Error(`Pending effect \"${effectKey}\" not found on instance ${ctx.instance._id}`)\n }\n\n const mutation = startMutation(ctx.instance)\n mutation.pendingEffects = mutation.pendingEffects.filter((e) => e._key !== effectKey)\n\n const ranAt = ctx.now\n mutation.effectHistory.push(\n buildEffectHistoryEntry(pending, {status, ranAt, actor, detail, error, durationMs, outputs}),\n )\n\n if (status === 'done' && outputs !== undefined) {\n upsertEffectsContext(mutation, outputs)\n }\n\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.effectCompleted',\n at: ranAt,\n effectKey,\n effectId: pending.effectId,\n status,\n ...(outputs !== undefined ? {outputs} : {}),\n ...(detail !== undefined ? {detail} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n\n await persist(ctx, mutation)\n return {effectKey, status}\n}\n\n/** Materialise one queued effect: its {@link PendingEffect} envelope and\n * the matching `effectQueued` history entry, sharing a freshly-minted\n * `_key`. Caller pushes each into the right array. */\nexport function buildQueuedEffect(\n effect: Effect,\n origin: EffectOrigin,\n params: Record<string, unknown>,\n actor: Actor | undefined,\n now: string,\n): {pending: PendingEffect; history: HistoryEntry} {\n const key = randomKey()\n const pending: PendingEffect = {\n _key: key,\n _type: 'workflow.pendingEffect',\n effectId: effect.id,\n ...(effect.title !== undefined ? {title: effect.title} : {}),\n ...(effect.description !== undefined ? {description: effect.description} : {}),\n ...(effect.bindings !== undefined ? {bindings: effect.bindings} : {}),\n params,\n origin,\n ...(actor !== undefined ? {actor} : {}),\n queuedAt: now,\n }\n const history: HistoryEntry = {\n _key: randomKey(),\n _type: 'workflow.history.effectQueued',\n at: now,\n effectKey: key,\n effectId: effect.id,\n origin,\n }\n return {pending, history}\n}\n\nexport async function queueEffects(\n ctx: EngineContext,\n mutation: MutableInstance,\n effects: Effect[] | undefined,\n origin: EffectOrigin,\n actor: Actor | undefined,\n callerParams?: Record<string, unknown>,\n): Promise<void> {\n if (!effects) return\n const now = ctx.now\n // Effect bindings see the FRESHEST state — read from the in-progress\n // mutation so an op that ran earlier in the same action commit is\n // visible to a bound effect on the same action.\n const liveInstance: WorkflowInstance = {\n ...ctx.instance,\n state: mutation.state,\n stages: mutation.stages,\n effectsContext: mutation.effectsContext,\n }\n for (const effect of effects) {\n const params = await resolveBindings({\n bindings: effect.bindings,\n staticInput: effect.input,\n instance: liveInstance,\n now,\n ...(callerParams !== undefined ? {params: callerParams} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n const {pending, history} = buildQueuedEffect(effect, origin, params, actor, now)\n mutation.pendingEffects.push(pending)\n mutation.history.push(history)\n }\n}\n","import {getPath} from '../core/path.ts'\nimport {validateSlotAppendItem, validateSlotValue} from '../core/slot-validation.ts'\nimport {resolveStaticSource} from '../core/source.ts'\nimport type {Action, ActionParam, Op, OpPredicate, Source} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {StateScope} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {ResolvedStateSlot} from '../types/state-slots.ts'\nimport {findOpenStageEntry, type MutableInstance} from './mutation.ts'\nimport {ActionParamsInvalidError, type OpAppliedSummary} from './results.ts'\n\n// Action commit: param validation + op runner.\n\n/**\n * Op types that mutate workflow state (vs `workflow.op.status.set`, which only\n * flips task status). `satisfies` ties the list to the {@link Op} union, so a\n * rename or typo breaks compilation here instead of silently turning a\n * downstream state-change gate into a no-op.\n */\nconst STATE_OP_TYPES = [\n 'workflow.op.state.set',\n 'workflow.op.state.append',\n 'workflow.op.state.updateWhere',\n 'workflow.op.state.removeWhere',\n] as const satisfies readonly Op['type'][]\n\n/** Whether an applied op mutated state (and so may have invalidated a guard). */\nexport function isStateOp(summary: OpAppliedSummary): boolean {\n return (STATE_OP_TYPES as readonly string[]).includes(summary.opType)\n}\n\nexport function validateActionParams(\n action: Action,\n taskId: TaskId,\n callerParams: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const declared = action.params ?? []\n const params = callerParams ?? {}\n const issues: {paramId: string; reason: string}[] = []\n\n for (const decl of declared) {\n const value = params[decl.id]\n const present = decl.id in params && value !== undefined && value !== null\n if (decl.required === true && !present) {\n issues.push({paramId: decl.id, reason: 'required but missing'})\n continue\n }\n if (!present) continue\n const typeOk = checkParamType(value, decl)\n if (!typeOk) {\n issues.push({\n paramId: decl.id,\n reason: `expected paramType=${decl.paramType}, got ${typeof value}`,\n })\n }\n }\n if (issues.length > 0) {\n throw new ActionParamsInvalidError({action: action.id, taskId, issues})\n }\n return params\n}\n\n/** True when `value` is a non-null object carrying a string-typed `field`. */\nfunction hasStringField(value: unknown, field: string): boolean {\n return (\n typeof value === 'object' &&\n value !== null &&\n field in value &&\n typeof (value as Record<string, unknown>)[field] === 'string'\n )\n}\n\nfunction checkParamType(value: unknown, decl: ActionParam): boolean {\n switch (decl.paramType) {\n case 'string':\n case 'url':\n case 'dateTime':\n return typeof value === 'string'\n case 'number':\n return typeof value === 'number' && Number.isFinite(value)\n case 'boolean':\n return typeof value === 'boolean'\n case 'actor':\n return hasStringField(value, 'kind')\n case 'doc.ref':\n return hasStringField(value, 'id')\n case 'doc.refs':\n return (\n Array.isArray(value) &&\n value.every((v) => checkParamType(v, {...decl, paramType: 'doc.ref'}))\n )\n case 'json':\n return true\n default:\n return false\n }\n}\n\ninterface RunOpsArgs {\n ops: Op[] | undefined\n mutation: MutableInstance\n stageId: StageId\n taskId: TaskId\n actionName: string\n params: Record<string, unknown>\n actor: Actor | undefined\n /** GDR URI of the instance the ops run against, for `Source.self`. */\n self: string\n /** Shell-supplied clock reading (ISO) — `now` op-source + history `at`. */\n now: string\n}\n\nexport async function runActionOps(args: RunOpsArgs): Promise<OpAppliedSummary[]> {\n const {ops, mutation, stageId, taskId, actionName, params, actor, self, now} = args\n if (ops === undefined || ops.length === 0) return []\n const summaries: OpAppliedSummary[] = []\n for (const op of ops) {\n const summary = applyOp(op, {mutation, stageId, taskId, params, actor, self, now})\n summaries.push(summary)\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.opApplied',\n at: now,\n stageId,\n taskId,\n actionId: actionName,\n opType: summary.opType,\n ...(summary.target !== undefined ? {target: summary.target} : {}),\n ...(summary.resolved !== undefined ? {resolved: summary.resolved} : {}),\n ...(actor !== undefined ? {actor} : {}),\n })\n }\n return summaries\n}\n\ninterface OpContext {\n mutation: MutableInstance\n stageId: StageId\n taskId: TaskId\n params: Record<string, unknown>\n actor: Actor | undefined\n /** GDR URI of the instance, for `Source.self`. */\n self: string\n /** Shell-supplied clock reading (ISO) backing `source: \"now\"`. */\n now: string\n}\n\nfunction applyOp(op: Op, ctx: OpContext): OpAppliedSummary {\n switch (op.type) {\n case 'workflow.op.state.set':\n return applyStateSet(op, ctx)\n case 'workflow.op.state.append':\n return applyStateAppend(op, ctx)\n case 'workflow.op.state.updateWhere':\n return applyStateUpdateWhere(op, ctx)\n case 'workflow.op.state.removeWhere':\n return applyStateRemoveWhere(op, ctx)\n case 'workflow.op.status.set':\n return applyStatusSet(op, ctx)\n }\n}\n\nfunction applyStateSet(\n op: Extract<Op, {type: 'workflow.op.state.set'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const value = resolveOpSource(op.value, ctx)\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ true)\n if (slot !== undefined) {\n // Validate the resolved value against the slot's declared shape.\n // Wrong-shape writes throw `SlotValueShapeError` — the engine\n // aborts the action before persisting.\n validateSlotValue({slotType: slot._type, slotId: slot.id, value})\n slot.value = value as never\n }\n return {opType: op.type, target: op.target, resolved: {value}}\n}\n\nfunction applyStateAppend(\n op: Extract<Op, {type: 'workflow.op.state.append'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const item = resolveOpSource(op.item, ctx)\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ true)\n if (slot !== undefined) {\n validateSlotAppendItem({slotType: slot._type, slotId: slot.id, item})\n const current = Array.isArray(slot.value) ? slot.value : []\n slot.value = [...current, withRowKey(item)] as never\n }\n return {opType: op.type, target: op.target, resolved: {item}}\n}\n\n/** Stamp a `_key` onto a plain-object row that lacks one; scalars and\n * arrays pass through unchanged. */\nfunction withRowKey(item: unknown): unknown {\n if (typeof item === 'object' && item !== null && !Array.isArray(item) && !('_key' in item)) {\n return {_key: randomKey(), ...(item as Record<string, unknown>)}\n }\n return item\n}\n\nfunction applyStateUpdateWhere(\n op: Extract<Op, {type: 'workflow.op.state.updateWhere'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ false)\n const resolvedMerge: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(op.merge)) {\n resolvedMerge[k] = resolveOpSource(v, ctx)\n }\n if (slot !== undefined && Array.isArray(slot.value)) {\n slot.value = (slot.value as Record<string, unknown>[]).map((row) =>\n evalOpPredicate(op.where, row, ctx) ? {...row, ...resolvedMerge} : row,\n ) as never\n }\n return {opType: op.type, target: op.target, resolved: {merge: resolvedMerge}}\n}\n\nfunction applyStateRemoveWhere(\n op: Extract<Op, {type: 'workflow.op.state.removeWhere'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const slot = locateSlot(ctx, op.target, /*createIfMissing*/ false)\n if (slot !== undefined && Array.isArray(slot.value)) {\n slot.value = (slot.value as Record<string, unknown>[]).filter(\n (row) => !evalOpPredicate(op.where, row, ctx),\n ) as never\n }\n return {opType: op.type, target: op.target}\n}\n\nfunction applyStatusSet(\n op: Extract<Op, {type: 'workflow.op.status.set'}>,\n ctx: OpContext,\n): OpAppliedSummary {\n const entry = findOpenStageEntry(ctx.mutation)?.tasks.find((t) => t.id === op.taskId)\n if (entry !== undefined) entry.status = op.status\n return {opType: op.type, resolved: {taskId: op.taskId, status: op.status}}\n}\n\nfunction locateSlot(\n ctx: OpContext,\n target: {scope: StateScope; slotId: string},\n createIfMissing: boolean,\n): ResolvedStateSlot | undefined {\n let host: ResolvedStateSlot[] | undefined\n if (target.scope === 'workflow') {\n host = ctx.mutation.state\n } else if (target.scope === 'stage') {\n host = findOpenStageEntry(ctx.mutation)?.state\n } else {\n const task = findOpenStageEntry(ctx.mutation)?.tasks.find((t) => t.id === ctx.taskId)\n host = task?.state\n if (host === undefined && task !== undefined && createIfMissing) {\n task.state = []\n host = task.state\n }\n }\n if (host === undefined) {\n throw new Error(\n `Op target scope \"${target.scope}\" has no state container on this instance — declare the slot or check stage/task identity`,\n )\n }\n let slot = host.find((s) => s.id === target.slotId)\n if (slot === undefined && createIfMissing) {\n // No declared slot — synthesize a `value.string`-shaped entry as a\n // conservative default. Authors are expected to declare slots on\n // the definition; this fallback exists so ad-hoc tests don't have\n // to.\n slot = {\n _key: randomKey(),\n _type: 'workflow.state.value.string',\n id: target.slotId,\n value: null,\n } as ResolvedStateSlot\n host.push(slot)\n }\n return slot\n}\n\nfunction resolveOpSource(src: Source, ctx: OpContext): unknown {\n const staticValue = resolveStaticSource(src, ctx)\n if (staticValue.handled) return staticValue.value\n switch (src.source) {\n case 'self':\n // The instance's own GDR URI — matches `$self` in filters and\n // `Source.self` in spawn sources. A GDR string an op can stamp into\n // a value slot (or compose via `Source.object`), instead of the old\n // silent `undefined`.\n return ctx.self\n case 'stageId':\n return ctx.stageId\n case 'stateRead': {\n const value = readSlotFromMutation(ctx, src.scope, src.slotId)\n return src.path !== undefined ? getPath(value, src.path) : value\n }\n case 'effectOutput': {\n const entry = ctx.mutation.effectsContext.find((e) => e.id === src.contextId)\n if (entry === undefined) return null\n const v = src.path !== undefined ? getPath(entry.value, src.path) : entry.value\n return v === undefined ? null : v\n }\n case 'object': {\n const out: Record<string, unknown> = {}\n for (const [field, fieldSrc] of Object.entries(src.fields)) {\n out[field] = resolveOpSource(fieldSrc, ctx)\n }\n return out\n }\n case 'row':\n case 'parentState':\n // Spawn-only sources (resolved by resolveSpawnSource); not in scope here.\n return undefined\n default:\n // literal / param / actor / now resolved above by resolveStaticSource.\n return undefined\n }\n}\n\nfunction slotValue(slots: ResolvedStateSlot[] | undefined, slotId: string): unknown {\n return slots?.find((s) => s.id === slotId)?.value\n}\n\nfunction readSlotFromMutation(ctx: OpContext, scope: StateScope, slotId: string): unknown {\n if (scope === 'workflow') return slotValue(ctx.mutation.state, slotId)\n const stageEntry = findOpenStageEntry(ctx.mutation)\n if (scope === 'stage') return slotValue(stageEntry?.state, slotId)\n const task = stageEntry?.tasks.find((t) => t.id === ctx.taskId)\n return slotValue(task?.state, slotId)\n}\n\nfunction evalOpPredicate(p: OpPredicate, row: Record<string, unknown>, ctx: OpContext): boolean {\n if ('all' in p) return p.all.every((sub) => evalOpPredicate(sub, row, ctx))\n if ('any' in p) return p.any.some((sub) => evalOpPredicate(sub, row, ctx))\n const target = resolveOpSource(p.equals, ctx)\n return row[p.field] === target\n}\n","import {selfGdr} from '../core/refs.ts'\nimport type {Action, Stage, Task} from '../define/schema.ts'\nimport {randomKey} from '../keys.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {TaskStatus} from '../types/enums.ts'\nimport type {StageId, TaskId} from '../types/ids.ts'\nimport type {TaskEntry} from '../types/instance-state.ts'\nimport {ctxEvaluateFilter, type EngineContext, loadContext} from './context.ts'\nimport {queueEffects} from './effects.ts'\nimport {\n findCurrentTasks,\n findTaskInCurrentStage,\n type MutableInstance,\n requireMutationTaskEntry,\n startMutation,\n taskStatusChangedEntry,\n} from './mutation.ts'\nimport {isStateOp, runActionOps, validateActionParams} from './ops.ts'\nimport {\n type ActionResult,\n CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS,\n ConcurrentFireActionError,\n type EngineCallOptions,\n isRevisionConflict,\n} from './results.ts'\nimport {persistThenDeploy, refreshStageGuards} from './stages.ts'\n\n/**\n * Fire an action against an active task. The runtime applies the\n * declared `setStatus` flip and queues the action's effects.\n *\n * Each attempt reloads the instance (fresh `_rev`) and commits through\n * `persist`'s `ifRevisionId` guard, so two clients firing the same task\n * can't silently clobber each other. A commit that loses the race\n * reloads and retries across {@link CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS} attempts,\n * then throws {@link ConcurrentFireActionError}. Reloading also re-gates\n * the action, so a retry whose task the winning writer already completed\n * fails with the normal \"task must be active\" error rather than retrying.\n */\nexport async function fireAction(args: {\n client: WorkflowClient\n instanceId: string\n taskId: TaskId\n action: string\n /** Caller-supplied action params (validated against `Action.params[]`). */\n params?: Record<string, unknown>\n options?: EngineCallOptions\n}): Promise<ActionResult> {\n const {client, instanceId, taskId, action, params, options} = args\n for (let attempt = 1; attempt <= CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS; attempt++) {\n const ctx = await loadContext(client, instanceId, {\n ...(options?.clock ? {clock: options.clock} : {}),\n })\n try {\n return await commitAction(ctx, taskId, action, params, options?.actor)\n } catch (error) {\n if (!isRevisionConflict(error)) throw error\n // Lost the optimistic-locking race — reload and retry.\n }\n }\n throw new ConcurrentFireActionError({\n instanceId,\n taskId,\n action,\n attempts: CONCURRENT_FIRE_ACTION_MAX_ATTEMPTS,\n })\n}\n\n/**\n * Resolve and gate an action fire: locate the task + action in the\n * current stage, check the action filter, require the live task entry to\n * be `active`, and validate caller params. Throws on any failure so no\n * mutation begins. Returns the pieces the commit needs.\n */\nasync function resolveActionCommit(\n ctx: EngineContext,\n taskId: TaskId,\n actionName: string,\n callerParams: Record<string, unknown> | undefined,\n): Promise<{stage: Stage; task: Task; action: Action; params: Record<string, unknown>}> {\n const {stage, task} = findTaskInCurrentStage(ctx, taskId)\n const action = (task.actions ?? []).find((a) => a.id === actionName)\n if (action === undefined) {\n throw new Error(`Action \"${actionName}\" not declared on task \"${taskId}\"`)\n }\n\n const filterOk = await ctxEvaluateFilter(ctx, action.filter)\n if (!filterOk) {\n throw new Error(`Action \"${actionName}\" filter rejected on task \"${taskId}\"`)\n }\n\n const entry = findCurrentTasks(ctx.instance).find((t) => t.id === taskId)\n if (entry === undefined || entry.status !== 'active') {\n throw new Error(\n `Task \"${taskId}\" must be active to fire action \"${actionName}\"; status is ${entry?.status ?? 'missing'}`,\n )\n }\n\n // Validate caller params against `action.params[]` before any\n // mutation. The action does not commit if validation fails.\n const params = validateActionParams(action, taskId, callerParams)\n return {stage, task, action, params}\n}\n\n/** Apply an action's declared `setStatus` to the live task entry,\n * recording the status change. No-op (returns undefined) when the\n * action omits `setStatus` — e.g. claim/assign actions that keep the\n * task active. Returns the new status when applied. */\nfunction applyActionSetStatus(\n action: Action,\n mutation: MutableInstance,\n mutEntry: TaskEntry,\n stageId: StageId,\n taskId: TaskId,\n actor: Actor | undefined,\n now: string,\n): TaskStatus | undefined {\n if (action.setStatus === undefined) return undefined\n const initialStatus = mutEntry.status\n const newStatus = action.setStatus\n mutEntry.status = newStatus\n mutEntry.completedAt = now\n if (actor) mutEntry.completedBy = actor.id\n mutation.history.push(\n taskStatusChangedEntry({\n stageId,\n taskId,\n from: initialStatus,\n to: newStatus,\n at: now,\n ...(actor !== undefined ? {actor} : {}),\n }),\n )\n return newStatus\n}\n\nasync function commitAction(\n ctx: EngineContext,\n taskId: TaskId,\n actionName: string,\n callerParams: Record<string, unknown> | undefined,\n actor: Actor | undefined,\n): Promise<ActionResult> {\n const {stage, task, action, params} = await resolveActionCommit(\n ctx,\n taskId,\n actionName,\n callerParams,\n )\n\n const mutation = startMutation(ctx.instance)\n const mutEntry = requireMutationTaskEntry(mutation, taskId)\n // One clock reading for the whole commit so the actionFired entry, ops,\n // status flip, and queued effects all agree on the time.\n const now = ctx.now\n\n // 1. Action commit: record the actionFired entry first so ops/effects\n // have a consistent audit trail order.\n mutation.history.push({\n _key: randomKey(),\n _type: 'workflow.history.actionFired',\n at: now,\n stageId: stage.id,\n taskId,\n actionId: actionName,\n ...(actor !== undefined ? {actor} : {}),\n })\n\n // 2. Run ops inline. Sources resolve against the in-progress\n // mutation so a later op can read a value an earlier op wrote.\n // Ops can flip task status via `workflow.op.status.set`.\n const ranOps = await runActionOps({\n ops: action.ops,\n mutation,\n stageId: stage.id,\n taskId,\n actionName,\n params,\n actor,\n self: selfGdr(ctx.instance),\n now,\n })\n\n // 3. Apply the action's declared `setStatus`, if any.\n const newStatus = applyActionSetStatus(action, mutation, mutEntry, stage.id, taskId, actor, now)\n\n // 4. Queue external effects with resolved Sources (caller params +\n // actor pinned for this commit).\n await queueEffects(\n ctx,\n mutation,\n action.effects,\n {\n kind: 'action',\n id: `${task.id}:${actionName}`,\n },\n actor,\n params,\n )\n\n // Ops may have changed state a guard reads; refresh this stage's guards so\n // they stay coherent without a transition (skipped when no state op ran). A\n // failed refresh rolls the commit back rather than leaving guards stale.\n await persistThenDeploy(ctx, mutation, () =>\n ranOps.some(isStateOp) ? refreshStageGuards(ctx, mutation, stage.id) : Promise.resolve(),\n )\n\n return {\n fired: true,\n taskId,\n action: actionName,\n ...(newStatus !== undefined ? {newStatus} : {}),\n ...(ranOps.length > 0 ? {ranOps} : {}),\n }\n}\n","/**\n * Permissions — GROQ-filter-based grant evaluation.\n *\n * Sanity ACLs come back as `Grant[]`. Each grant has a GROQ `filter`\n * and a list of `permissions` it confers. Whether a permission is\n * allowed on a given document is \"does any grant whose filter matches\n * the document carry that permission?\". Most-permissive wins; multiple\n * grants compose.\n *\n * Filters are evaluated with groq-js (already a dependency for transition\n * filter evaluation) so the engine doesn't ship a second predicate engine.\n */\n\nimport {evaluate, parse} from 'groq-js'\n\nimport type {Grant} from './types/authorization.ts'\nimport type {DocumentValuePermission} from './types/enums.ts'\n\n// Parsed-filter cache, keyed by the filter string. AST is cheap to\n// reuse; the evaluation against a document is what we want to keep\n// uncached because the document changes much more often than the filter.\nconst parsedFilters = new Map<string, ReturnType<typeof parse>>()\n\n/**\n * Evaluate a grant's GROQ filter against a single document with the\n * supplied identity. Returns true iff the document survives the filter.\n *\n * The implementation parses `*[<filter>]` once per filter string,\n * evaluates against a singleton dataset, and asks the result for its\n * length — `length === 1` means the doc passed.\n */\nexport async function matchesFilter(args: {\n document: {_id?: string; _type?: string; [key: string]: unknown}\n filter: string\n userId?: string\n}): Promise<boolean> {\n const {document, filter, userId} = args\n if (!parsedFilters.has(filter)) {\n parsedFilters.set(filter, parse(`*[${filter}]`))\n }\n const ast = parsedFilters.get(filter)!\n const result = await evaluate(ast, {\n dataset: [document],\n ...(userId !== undefined ? {identity: userId} : {}),\n })\n const data = await result.get()\n return Array.isArray(data) && data.length === 1\n}\n\n/**\n * Does the supplied `grants` set grant `permission` on `document` for\n * the given user? Walks each grant; a grant counts iff its filter\n * matches AND it lists the permission. Most-permissive wins.\n */\nexport async function grantsPermissionOn(args: {\n document?: {_id?: string; _type?: string; [key: string]: unknown}\n grants: Grant[]\n permission: DocumentValuePermission\n userId?: string\n}): Promise<boolean> {\n const {document, grants, permission, userId} = args\n if (!document || grants.length === 0) return false\n\n for (const grant of grants) {\n if (!grant.permissions.includes(permission)) continue\n if (\n await matchesFilter({\n document,\n filter: grant.filter,\n ...(userId !== undefined ? {userId} : {}),\n })\n ) {\n return true\n }\n }\n return false\n}\n\n/**\n * Convenience: fetch the grants for a given resource via the supplied\n * client:\n *\n * GET <resourcePath> → Grant[]\n *\n * `resourcePath` is caller-supplied so the same helper works for\n * project ACLs (`/projects/<id>/datasets/<dataset>/acl`) and for a\n * dedicated workflow-collaboration resource. The client must support\n * the `request<T>({url})` method `@sanity/client` exposes.\n */\nexport async function fetchGrants(args: {\n client: {request: <T>(opts: {url: string; signal?: AbortSignal}) => Promise<T>}\n resourcePath: string\n signal?: AbortSignal\n}): Promise<Grant[]> {\n const {client, resourcePath, signal} = args\n return client.request<Grant[]>({url: resourcePath, ...(signal ? {signal} : {})})\n}\n","/**\n * Access state — the cohesive (actor + grants) pair the engine\n * relies on for every authorization decision: one provider, one\n * cached resolution.\n *\n * Resolution strategy:\n *\n * 1. **Override.** If the caller supplies an `access` object on the\n * verb (or the bench's `createBench({ access })`), it wins — no\n * network calls. This is the only path that fires for the test\n * bench, whose `TestClient` has no token-bearing `request` method.\n * 2. **Token.** Otherwise the engine resolves both halves from the\n * supplied `@sanity/client`:\n * - `actor` ← `client.request({ url: \"/users/me\" })`\n * - `grants` ← `client.request({ url: grantsFromPath })`\n * Run in parallel; cached per-client (and per-path for grants) via\n * WeakMap so concurrent verb calls share one fetch.\n * 3. **Refusal.** If the client can't make HTTP requests (`request`\n * undefined) and no override was supplied, the engine throws a\n * clear error pointing at the bench / explicit override.\n *\n * Grants-fetch failure degrades open (gate is skipped, real Sanity\n * write boundary still enforces). Actor-fetch failure is fatal — the\n * engine refuses to stamp history without an identity.\n */\n\nimport {fetchGrants} from './permissions.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {Grant} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\n\n/** The options bag accepted by {@link WorkflowClient.request}. */\ntype RequestOptions = Parameters<NonNullable<WorkflowClient['request']>>[0]\n\n/**\n * Sanity's `/users/me` response shape — subset of `@sanity/types`'s\n * `CurrentUser`. Declared locally so the engine doesn't take a\n * runtime dep on `@sanity/types` for a single type.\n */\ninterface SanityCurrentUser {\n id: string\n name?: string\n email?: string\n /** @deprecated singular `role` on legacy responses */\n role?: string\n roles?: {name: string; title?: string; description?: string}[]\n}\n\n/**\n * The engine's view of \"who am I, what can I do?\". `actor` is who\n * the engine stamps onto history / `completedBy` / `Source.actor`.\n * `grants` (when present) gates `permission-denied`; when absent the\n * gate is skipped and the real Sanity write boundary takes over.\n *\n * This is the RESOLVED shape — `actor` is guaranteed. For the\n * partial-override shape callers pass on verb args, see\n * `WorkflowAccessOverride`.\n */\nexport interface WorkflowAccess {\n actor: Actor\n grants?: Grant[]\n}\n\n/**\n * Partial override accepted by every public verb's `access?:`\n * argument. Any field present wins; missing halves token-resolve.\n *\n * `{ actor, grants }` — bench's all-access default; both halves\n * injected, no token round-trip.\n * `{ actor }` — \"act as another user\"; grants come from\n * `grantsFromPath` (or the gate is skipped).\n * `{ grants }` — \"preview with restricted permissions\"; actor\n * comes from `/users/me`.\n * omitted entirely — both halves token-resolved.\n */\nexport type WorkflowAccessOverride = Partial<WorkflowAccess>\n\nexport interface ResolveAccessArgs {\n /**\n * Partial override. Any field set here wins outright; any field\n * left unset falls through to token resolution.\n *\n * - `override.actor` set + `override.grants` set → returned as-is.\n * - `override.actor` set + `override.grants` unset → actor from\n * override; grants fetched from `grantsFromPath` (or undefined).\n * - `override.actor` unset + `override.grants` set → actor from\n * `/users/me`; grants from override.\n * - `override` undefined entirely → both halves fetched.\n *\n * The test bench passes a fully-populated `{ actor, grants }` so\n * the underlying TestClient (no `request` method) never hits the\n * token path. Admin/preview tooling passes one or the other.\n */\n override?: {actor?: Actor; grants?: Grant[]}\n /**\n * Where the engine should fetch grants from the supplied client\n * when `override.grants` isn't given, e.g. a Canvas resource at\n * `/canvases/<resourceId>/acl` or a dataset at\n * `/projects/<id>/datasets/<ds>/acl`.\n */\n grantsFromPath?: string\n}\n\n// Actor cache is per-client. /users/me doesn't vary by path; one\n// fetch per client lifetime suffices.\nconst actorCache = new WeakMap<object, Promise<Actor | undefined>>()\n\n// Grants cache is per-(client, path). Multiple consumers in one\n// process can share the same client across different resources.\nconst grantsCache = new WeakMap<object, Map<string, Promise<Grant[] | undefined>>>()\n\n/**\n * Resolve the engine's `WorkflowAccess` for a client. Override wins\n * outright; otherwise both halves are fetched in parallel and\n * cached. Throws if neither path yields an actor — the engine\n * refuses to operate without an identity.\n */\nexport async function resolveAccess(\n client: WorkflowClient,\n args: ResolveAccessArgs = {},\n): Promise<WorkflowAccess> {\n const overrideActor = args.override?.actor\n const overrideGrants = args.override?.grants\n\n // Fast path: bench supplies both halves; no token needed.\n if (overrideActor !== undefined && overrideGrants !== undefined) {\n return {actor: overrideActor, grants: overrideGrants}\n }\n\n // Reaching here, the fast path above ruled out \"both halves supplied\",\n // so at least one half needs the client. A client with no `request`\n // can't fetch either: throw if the missing half is the actor, otherwise\n // degrade open on grants (the production \"endpoint unreachable\" path).\n //\n // Wrap `request` once so every downstream call site (actor + grants)\n // invokes it AS a method on `client`. `@sanity/client` >= 7.22 reads a\n // private field through `this`, so a detached `const fn = client.request;\n // fn(...)` loses `this` and throws before issuing the request. The\n // wrapper stays lazy: a plain `.bind` here would dereference `request`\n // eagerly even when an override supplies the only half we need, tripping\n // clients (e.g. the in-memory bench) whose `request` is a throw-on-use\n // stub. `=== undefined` preserves the probe for clients with no `request`.\n const requestFn: NonNullable<WorkflowClient['request']> | undefined =\n client.request === undefined ? undefined : <T>(opts: RequestOptions) => client.request!<T>(opts)\n if (requestFn === undefined) {\n if (overrideActor === undefined) {\n throw new Error(\n \"workflow: no actor available. The engine resolves the actor from the client's token \" +\n \"via `client.request({ url: '/users/me' })`. Supply a real `@sanity/client` configured \" +\n 'with a token, or pass an explicit `access.actor` override (the test bench provides ' +\n 'one by default).',\n )\n }\n return {actor: overrideActor}\n }\n\n const actorPromise =\n overrideActor !== undefined ? Promise.resolve(overrideActor) : cachedActor(client, requestFn)\n\n const grantsPromise =\n overrideGrants !== undefined\n ? Promise.resolve<Grant[] | undefined>(overrideGrants)\n : args.grantsFromPath !== undefined\n ? cachedGrants(client, requestFn, args.grantsFromPath)\n : Promise.resolve<Grant[] | undefined>(undefined)\n\n const [actor, grants] = await Promise.all([actorPromise, grantsPromise])\n if (actor === undefined) {\n throw new Error(\n 'workflow: failed to resolve actor from `/users/me`. The client is configured but the ' +\n 'endpoint returned no usable identity — check the token, or pass `access.actor` explicitly.',\n )\n }\n return {actor, ...(grants !== undefined ? {grants} : {})}\n}\n\nfunction cachedActor(\n client: WorkflowClient,\n requestFn: NonNullable<WorkflowClient['request']>,\n): Promise<Actor | undefined> {\n const cached = actorCache.get(client)\n if (cached !== undefined) return cached\n\n // Evict on failure so a transient `/users/me` error (401/503/network)\n // doesn't poison the per-client cache for its lifetime — the next call\n // retries instead of permanently throwing \"failed to resolve actor\".\n const pending = fetchActor(requestFn).catch((err) => {\n if (actorCache.get(client) === pending) actorCache.delete(client)\n throw err\n })\n actorCache.set(client, pending)\n return pending\n}\n\nfunction cachedGrants(\n client: WorkflowClient,\n requestFn: NonNullable<WorkflowClient['request']>,\n resourcePath: string,\n): Promise<Grant[] | undefined> {\n let byPath = grantsCache.get(client)\n if (byPath === undefined) {\n byPath = new Map()\n grantsCache.set(client, byPath)\n }\n let cached = byPath.get(resourcePath)\n if (cached === undefined) {\n cached = fetchGrantsCached(requestFn, resourcePath)\n byPath.set(resourcePath, cached)\n }\n return cached\n}\n\nasync function fetchActor(\n requestFn: <T>(opts: {\n url?: string\n uri?: string\n signal?: AbortSignal\n tag?: string\n }) => Promise<T>,\n): Promise<Actor | undefined> {\n // `@sanity/client.request` distinguishes `uri` (project-API path,\n // resolved against the apiHost — e.g. `https://api.sanity.io/v1/users/me`)\n // from `url` (raw URL). `/users/me` is a global endpoint accessed via\n // `uri`. Studio itself uses `uri: '/users/me'` in its authStore\n // (sanity-v3 `createAuthStore.ts`). Using `url` here makes the\n // request hit the project-scoped endpoint, which returns empty for\n // the global user — causing \"no usable identity\" errors in studio.\n let user: SanityCurrentUser\n try {\n user = await requestFn<SanityCurrentUser>({\n uri: '/users/me',\n tag: 'workflow.access.resolve-actor',\n })\n } catch (err) {\n // Surface the request failure with its cause intact so the eventual\n // throw is diagnosable — and let it propagate so the per-client cache\n // is evicted and the next call retries (transient 401/503/network).\n throw new Error(\n \"workflow: /users/me request failed. The engine resolves the actor from the client's token \" +\n 'via `client.request({ uri: \"/users/me\" })`. Check the token/connectivity, or pass an ' +\n 'explicit `access.actor` override.',\n {cause: err},\n )\n }\n // A well-formed response that carries no usable identity is NOT an\n // error worth retrying — return undefined so the caller throws its\n // \"no usable identity\" message.\n if (!user || typeof user.id !== 'string' || user.id.length === 0) return undefined\n const roleNames = user.roles?.map((r) => r.name).filter((n): n is string => Boolean(n)) ?? []\n return {\n kind: 'user',\n id: user.id,\n ...(roleNames.length > 0 ? {roles: roleNames} : {}),\n }\n}\n\nasync function fetchGrantsCached(\n requestFn: NonNullable<WorkflowClient['request']>,\n resourcePath: string,\n): Promise<Grant[] | undefined> {\n try {\n return await fetchGrants({client: {request: requestFn}, resourcePath})\n } catch (err) {\n console.warn(\n `workflow: failed to fetch grants from \"${resourcePath}\"; skipping permission gate. ` +\n `Original error: ${err instanceof Error ? err.message : String(err)}`,\n )\n return undefined\n }\n}\n","/**\n * Engine-scope tags — the multi-tenant isolation primitive.\n *\n * Every engine takes a required `tags: string[]` set at construction.\n * Tags must be Sanity-ID-compatible since they're joined into IDs with\n * `.` — ASCII lowercase + digits + dashes, no leading dash, no dots.\n *\n * The first tag in the array is the *canonical* tag, used as the ID\n * prefix when the engine writes new definitions or instances. The full\n * tag set goes onto every written doc and is the basis for read\n * filtering (tag intersection between engine and doc).\n */\n\nconst TAG_RE = /^[a-z0-9][a-z0-9-]*$/\n\nexport function validateTags(tags: string[]): void {\n if (tags.length === 0) {\n throw new Error('tags: must be a non-empty array')\n }\n for (const tag of tags) {\n if (!TAG_RE.test(tag)) {\n throw new Error(\n `tags: invalid tag \"${tag}\" — must match ${TAG_RE.source} (ASCII lowercase + digits + dashes, no leading dash, no dots)`,\n )\n }\n }\n}\n\nexport function canonicalTag(tags: string[]): string {\n return tags[0]!\n}\n","/**\n * `workflow.evaluate` — the third concept.\n *\n * Reads an instance and projects \"what can this actor do right now,\n * and why not the rest?\" as a structured `WorkflowEvaluation`. Pure\n * read; never writes. Different actors see different evaluations of\n * the same instance.\n *\n * Used internally by `fireAction` to gate writes and externally by\n * UIs to render disabled-with-reason buttons.\n */\n\nimport {resolveAccess, type WorkflowAccessOverride} from './access.ts'\nimport {type Clocked, wallClock} from './clock.ts'\nimport {evaluateFilter} from './core/eval.ts'\nimport {buildParams} from './core/params.ts'\nimport type {ParsedGdr, WorkflowResource} from './core/refs.ts'\nimport type {HydratedSnapshot} from './core/snapshot.ts'\nimport type {Action, Assignee, Task, WorkflowDefinition} from './define/schema.ts'\nimport {grantsPermissionOn} from './permissions.ts'\nimport {hydrateSnapshot} from './snapshot.ts'\nimport {validateTags} from './tags.ts'\nimport type {Actor} from './types/actor.ts'\nimport type {Grant} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {TaskStatus} from './types/enums.ts'\nimport type {\n ActionEvaluation,\n DisabledReason,\n StageEvaluation,\n TaskEvaluation,\n TransitionEvaluation,\n WorkflowEvaluation,\n} from './types/evaluation.ts'\nimport type {TaskEntry} from './types/instance-state.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nconst WILDCARD_ROLE = '*'\n\nexport interface EvaluateArgs {\n client: WorkflowClient\n /** Engine-scope tags — required. */\n tags: string[]\n /** Engine workflow resource — required. */\n workflowResource: WorkflowResource\n instanceId: string\n /**\n * Optional access-state override. By default the engine resolves\n * `(actor, grants)` from the supplied client's token via\n * `/users/me` (+ `grantsFromPath`). The bench supplies its\n * `ALL_ACCESS` default here; admin tooling can use this for\n * \"view as another user\" or \"preview with restricted grants\" flows.\n */\n access?: WorkflowAccessOverride\n /**\n * URL path on the supplied client where the engine should fetch\n * grants when `access.grants` isn't supplied. Required for\n * production usage; omitting it means the engine skips the\n * `permission-denied` gate (graceful degradation — the real Sanity\n * write boundary still enforces).\n *\n * Canvas resource example: `/canvases/<resourceId>/acl`.\n * Project/dataset example: `/projects/<id>/datasets/<dataset>/acl`.\n *\n * Result is cached per `(client, path)` for the lifetime of the\n * process — grants don't change often, and tearing them down per\n * call would mean a network round-trip on every fireAction.\n */\n grantsFromPath?: string\n /**\n * Optional resource-aware client routing — see\n * `StartInstanceArgs.resourceClients`. When the workflow's subject\n * (or any ancestor) lives in a different resource than the engine's\n * client, this resolver decides which client to read it through.\n * The evaluation hydrates a GDR-keyed snapshot from those reads and\n * runs `_id`-scoped filters locally in groq-js — same model as the\n * cascade path.\n */\n resourceClients?: (parsed: ParsedGdr) => WorkflowClient | undefined\n}\n\nexport async function evaluateInstance(args: Clocked<EvaluateArgs>): Promise<WorkflowEvaluation> {\n const {client, tags, instanceId, resourceClients} = args\n // One clock reading for the whole projection so every filter's `$now`\n // agrees (and matches a frozen bench timeline). Pure read — never persisted.\n const now = (args.clock ?? wallClock)()\n validateTags(tags)\n // Resolve actor + grants together (one cached round-trip per client).\n // Caller can short-circuit by passing `access` (bench / impersonation\n // / preview). Caching lives in access.ts — same WeakMap pattern.\n const {actor, grants} = await resolveAccess(client, {\n ...(args.access !== undefined ? {override: args.access} : {}),\n ...(args.grantsFromPath !== undefined ? {grantsFromPath: args.grantsFromPath} : {}),\n })\n\n const instance = await client.getDocument<WorkflowInstance>(instanceId)\n if (!instance) {\n throw new Error(`Workflow instance \"${instanceId}\" not found`)\n }\n if (!tags.some((t) => instance.tags?.includes(t))) {\n throw new Error(`Workflow instance \"${instanceId}\" not visible to this engine (tag mismatch)`)\n }\n\n const definition = parseDefinitionSnapshot(instance)\n const stage = definition.stages.find((s) => s.id === instance.currentStageId)\n if (stage === undefined) {\n throw new Error(\n `Instance \"${instanceId}\" currentStageId \"${instance.currentStageId}\" not in definition`,\n )\n }\n\n // Build the GDR-keyed snapshot ONCE per evaluation call. Every\n // `evaluateFilter` below threads it through, so per-action/per-task\n // filter checks evaluate in-memory via groq-js with zero lake reads\n // (same model the cascade uses in engine.ts).\n const clientForGdr =\n resourceClients !== undefined\n ? (parsed: ParsedGdr) => resourceClients(parsed) ?? client\n : () => client\n const snapshot: HydratedSnapshot = await hydrateSnapshot({\n client,\n clientForGdr,\n instance,\n definition,\n })\n\n // \"Current\" stage entry: same id, no exitedAt — on loop-backs multiple\n // entries share an id, and the un-exited one is current.\n const currentStageEntry = instance.stages.find(\n (s) => s.id === instance.currentStageId && s.exitedAt === undefined,\n )\n const currentTaskEntries = currentStageEntry?.tasks ?? []\n\n const taskEvaluations: TaskEvaluation[] = []\n for (const task of stage.tasks ?? []) {\n taskEvaluations.push(\n await evaluateTask({\n task,\n statusEntry: currentTaskEntries.find((t) => t.id === task.id),\n instance,\n definition,\n actor,\n grants,\n snapshot,\n now,\n }),\n )\n }\n\n const transitionEvaluations: TransitionEvaluation[] = []\n for (const transition of stage.transitions ?? []) {\n transitionEvaluations.push({\n transition,\n filterSatisfied: await evaluateFilter({\n filter: transition.filter,\n definition,\n snapshot,\n params: buildParams(instance, now),\n }),\n })\n }\n\n const currentStage: StageEvaluation = {\n stage,\n tasks: taskEvaluations,\n transitions: transitionEvaluations,\n }\n\n const pendingOnYou = taskEvaluations.filter((t) => t.pendingOnActor)\n const canInteract = taskEvaluations.some((t) => t.actions.some((a) => a.allowed))\n\n return {\n instance,\n definition,\n actor,\n currentStage,\n pendingOnYou,\n canInteract,\n }\n}\n\ninterface EvaluateTaskArgs {\n task: Task\n statusEntry: TaskEntry | undefined\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n grants: Grant[] | undefined\n snapshot: HydratedSnapshot\n now: string\n}\n\nasync function evaluateTask(args: EvaluateTaskArgs): Promise<TaskEvaluation> {\n const {task, statusEntry, instance, definition, actor, grants, snapshot, now} = args\n const status: TaskStatus = statusEntry?.status ?? 'pending'\n\n const actions: ActionEvaluation[] = []\n for (const action of task.actions ?? []) {\n actions.push(\n await evaluateAction({\n action,\n task,\n ...(statusEntry !== undefined ? {statusEntry} : {}),\n status,\n instance,\n definition,\n actor,\n ...(grants !== undefined ? {grants} : {}),\n snapshot,\n now,\n }),\n )\n }\n\n return {\n task,\n status,\n // \"pending on actor\" treats both `pending` and `active` as waiting on\n // the assignee — pending tasks just haven't been auto-invoked yet, but\n // they're still inbox items.\n pendingOnActor:\n (status === 'active' || status === 'pending') && actorIsAssignee(actor, task.assignees ?? []),\n actions,\n }\n}\n\n// Internal — per-action verdict\n\ninterface EvaluateActionArgs {\n action: Action\n task: Task\n statusEntry?: TaskEntry\n status: TaskStatus\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n grants?: Grant[]\n snapshot: HydratedSnapshot\n now: string\n}\n\nasync function evaluateAction(args: EvaluateActionArgs): Promise<ActionEvaluation> {\n const {action, task, status, instance, definition, actor, grants, snapshot, now} = args\n\n // Gates are checked in order; the first failing one wins. Order is\n // chosen so the most informative reason surfaces first (instance-level\n // → stage-level → task-level → actor-level → permission-level →\n // filter-level).\n const syncReason =\n lifecycleReason(instance, definition, status) ?? actorReason(action, task, actor)\n if (syncReason !== undefined) return disabled(action, syncReason)\n\n const asyncReason =\n (await permissionReason(action, instance, actor, grants)) ??\n (await filterReason(action, instance, definition, snapshot, now))\n if (asyncReason !== undefined) return disabled(action, asyncReason)\n\n return {action, allowed: true}\n}\n\nfunction lifecycleReason(\n instance: WorkflowInstance,\n definition: WorkflowDefinition,\n status: TaskStatus,\n): DisabledReason | undefined {\n if (instance.completedAt !== undefined) {\n return {kind: 'instance-completed', completedAt: instance.completedAt}\n }\n if (definition.stages.find((s) => s.id === instance.currentStageId)?.kind === 'terminal') {\n return {kind: 'stage-terminal', stageId: instance.currentStageId}\n }\n if (status === 'done' || status === 'skipped' || status === 'failed') {\n return {kind: 'task-not-active', status}\n }\n return undefined\n}\n\nfunction actorReason(action: Action, task: Task, actor: Actor): DisabledReason | undefined {\n const actorRoles = actor.roles ?? []\n if (action.roles !== undefined && action.roles.length > 0) {\n const wildcard = actorRoles.includes(WILDCARD_ROLE)\n const match = wildcard || action.roles.some((r) => actorRoles.includes(r))\n if (!match) {\n return {kind: 'role-required', required: [...action.roles], actorRoles: [...actorRoles]}\n }\n }\n if (action.requireAssignment === true && !actorIsAssignee(actor, task.assignees ?? [])) {\n return {kind: 'not-assigned', assignees: [...(task.assignees ?? [])], actorId: actor.id}\n }\n return undefined\n}\n\nasync function permissionReason(\n action: Action,\n instance: WorkflowInstance,\n actor: Actor,\n grants: Grant[] | undefined,\n): Promise<DisabledReason | undefined> {\n if (grants === undefined) return undefined\n const permission = action.requiredPermission ?? 'update'\n const allowed = await grantsPermissionOn({\n document: instance,\n grants,\n permission,\n userId: actor.id,\n })\n if (allowed) return undefined\n return {kind: 'permission-denied', permission, matchingGrants: grants.length}\n}\n\nasync function filterReason(\n action: Action,\n instance: WorkflowInstance,\n definition: WorkflowDefinition,\n snapshot: HydratedSnapshot,\n now: string,\n): Promise<DisabledReason | undefined> {\n if (action.filter === undefined) return undefined\n const truthy = await evaluateFilter({\n filter: action.filter,\n definition,\n snapshot,\n params: buildParams(instance, now),\n })\n if (truthy) return undefined\n return {kind: 'filter-failed', filter: action.filter}\n}\n\nfunction disabled(action: Action, reason: DisabledReason): ActionEvaluation {\n return {action, allowed: false, disabledReason: reason}\n}\n\n// Internal — actor / assignee helpers\n\nfunction actorIsAssignee(actor: Actor, assignees: Assignee[]): boolean {\n if (assignees.length === 0) return false\n const actorRoles = actor.roles ?? []\n const wildcard = actorRoles.includes(WILDCARD_ROLE)\n for (const assignee of assignees) {\n if (assignee.kind === 'user' && assignee.id === actor.id) return true\n if (assignee.kind === 'role') {\n if (wildcard || actorRoles.includes(assignee.role)) return true\n }\n }\n return false\n}\n\nfunction parseDefinitionSnapshot(instance: WorkflowInstance): WorkflowDefinition {\n try {\n return JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n } catch (err) {\n throw new Error(\n `Failed to parse definitionSnapshot on instance \"${instance._id}\": ${\n err instanceof Error ? err.message : String(err)\n }`,\n {cause: err},\n )\n }\n}\n","/**\n * Shell-side guard housekeeping reads. The engine never reads its guards back\n * during normal operation — these exist for coherency refresh and DX/cleanup.\n *\n * Scope applies the same \"if it's in the workflow, we pull it in\" principle as\n * {@link hydrateSnapshot}, but deliberately broader: it spans the resource the\n * instance lives in AND the resource of every `doc.ref` / `doc.refs` GDR the\n * instance holds in state across ALL stages — not just the current one as\n * snapshot hydration does. Retract lifts a guard's predicate rather than\n * deleting it, so prior-stage resources still hold guard docs that housekeeping\n * must find. We query each resource for guards stamped with this instance's\n * {@link MutationGuardDoc.sourceInstanceId}.\n */\n\nimport {parseGdr, type ParsedGdr, type WorkflowResource} from './core/refs.ts'\nimport {collectSlotDocUris, resourceFromParsed} from './snapshot.ts'\nimport {GUARD_DOC_TYPE, type MutationGuardDoc} from './types/authorization.ts'\nimport type {WorkflowClient} from './types/client.ts'\nimport type {WorkflowInstance} from './types/instance.ts'\n\nconst resourceKey = (r: WorkflowResource): string => `${r.type}.${r.id}`\n\n/** Every guard in one resource, regardless of which workflow registered it. */\nexport function guardsForResource(client: WorkflowClient): Promise<MutationGuardDoc[]> {\n return client.fetch<MutationGuardDoc[]>(`*[_type == $t] | order(_id asc)`, {t: GUARD_DOC_TYPE})\n}\n\nexport interface GuardsForInstanceArgs {\n client: WorkflowClient\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n instance: WorkflowInstance\n}\n\n/**\n * All guards this instance registered, unioned across every resource it\n * touches. Dedups resources by resource key and results by `_id`.\n */\nexport async function guardsForInstance(args: GuardsForInstanceArgs): Promise<MutationGuardDoc[]> {\n const {client, clientForGdr, instance} = args\n\n const clientsByResource = new Map<string, WorkflowClient>([\n [resourceKey(instance.workflowResource), client],\n ])\n\n const stateUris = [\n ...collectSlotDocUris(instance.state),\n ...instance.stages.flatMap((stage) => collectSlotDocUris(stage.state)),\n ]\n for (const uri of stateUris) {\n const parsed = tryParseGdr(uri)\n if (parsed === undefined) continue\n const key = resourceKey(resourceFromParsed(parsed))\n if (!clientsByResource.has(key)) clientsByResource.set(key, clientForGdr(parsed))\n }\n\n const perResource = await Promise.all(\n [...clientsByResource.values()].map((c) =>\n c.fetch<MutationGuardDoc[]>(`*[_type == $t && sourceInstanceId == $id]`, {\n t: GUARD_DOC_TYPE,\n id: instance._id,\n }),\n ),\n )\n\n return dedupById(perResource.flat())\n}\n\nfunction tryParseGdr(uri: string): ParsedGdr | undefined {\n try {\n return parseGdr(uri)\n } catch {\n return undefined\n }\n}\n\nfunction dedupById(guards: MutationGuardDoc[]): MutationGuardDoc[] {\n const byId = new Map(guards.map((g) => [g._id, g]))\n return [...byId.values()].sort((a, b) => a._id.localeCompare(b._id))\n}\n","// Workflow evaluation — the third concept. Derived projection of\n// (instance + definition + actor + grants + lake state) answering\n// \"what can this actor do right now, and why not the rest?\".\n//\n// Not stored. Computed by `workflow.evaluate`. Different actors see\n// different evaluations of the same instance.\n\nimport type {\n Action,\n Assignee,\n Filter,\n Stage,\n Task,\n Transition,\n WorkflowDefinition,\n} from '../define/schema.ts'\nimport type {Actor} from './actor.ts'\nimport type {DocumentValuePermission, TaskStatus} from './enums.ts'\nimport type {ActionName, StageId, TaskId} from './ids.ts'\nimport type {WorkflowInstance} from './instance.ts'\n\nexport type DisabledReason =\n | {\n kind: 'role-required'\n required: string[]\n actorRoles: string[]\n }\n | {\n kind: 'not-assigned'\n assignees: Assignee[]\n actorId: string\n }\n | {\n kind: 'permission-denied'\n permission: DocumentValuePermission\n matchingGrants: number\n }\n | {\n kind: 'filter-failed'\n filter: Filter\n detail?: string\n }\n | {\n kind: 'task-not-active'\n status: Exclude<TaskStatus, 'active' | 'pending'>\n }\n | {kind: 'stage-terminal'; stageId: StageId}\n | {kind: 'instance-completed'; completedAt: string}\n | {\n /**\n * A deployed lake mutation guard denied (or, in optimistic engine-side\n * preview, would deny) the write. Surfacing this is an engine *preview* —\n * not proof of lake enforcement.\n */\n kind: 'mutation-guard-denied'\n guardIds: string[]\n detail?: string\n }\n\nexport interface ActionEvaluation {\n action: Action\n allowed: boolean\n /** Present iff `allowed === false`. The first failing gate wins. */\n disabledReason?: DisabledReason\n}\n\nexport interface TaskEvaluation {\n task: Task\n status: TaskStatus\n /** Whether this task is the current actor's responsibility right now. */\n pendingOnActor: boolean\n actions: ActionEvaluation[]\n}\n\nexport interface TransitionEvaluation {\n transition: Transition\n /** Result of evaluating the transition's filter at read time. */\n filterSatisfied: boolean\n}\n\nexport interface StageEvaluation {\n stage: Stage\n tasks: TaskEvaluation[]\n transitions: TransitionEvaluation[]\n}\n\nexport interface WorkflowEvaluation {\n instance: WorkflowInstance\n definition: WorkflowDefinition\n actor: Actor\n currentStage: StageEvaluation\n /** Active tasks where the actor is in `task.assignees`. */\n pendingOnYou: TaskEvaluation[]\n /** True if at least one action on any active task is allowed. */\n canInteract: boolean\n}\n\n// Typed error thrown by fireAction when the requested action's verdict\n// is `allowed: false`. Carries the structured reason so UIs can render\n// a precise message instead of parsing a string.\n\nexport class ActionDisabledError extends Error {\n readonly reason: DisabledReason\n readonly taskId: TaskId\n readonly action: ActionName\n\n constructor(args: {taskId: TaskId; action: ActionName; reason: DisabledReason}) {\n super(formatDisabledReason(args.taskId, args.action, args.reason))\n this.name = 'ActionDisabledError'\n this.reason = args.reason\n this.taskId = args.taskId\n this.action = args.action\n }\n}\n\ntype DisabledReasonDetail = {\n [K in DisabledReason['kind']]: (reason: Extract<DisabledReason, {kind: K}>) => string\n}\n\nconst disabledReasonDetail: DisabledReasonDetail = {\n 'role-required': (r) =>\n `requires one of [${r.required.join(', ')}]; actor has [${r.actorRoles.join(', ') || '(none)'}]`,\n 'not-assigned': (r) => `actor \"${r.actorId}\" is not in the task assignees`,\n 'permission-denied': (r) => `actor lacks \"${r.permission}\" permission on the workflow instance`,\n 'filter-failed': (r) => `action filter returned false${r.detail ? ` (${r.detail})` : ''}`,\n 'task-not-active': (r) => `task status is \"${r.status}\"`,\n 'stage-terminal': (r) => `stage \"${r.stageId}\" is terminal`,\n 'instance-completed': (r) => `instance completed at ${r.completedAt}`,\n 'mutation-guard-denied': (r) =>\n `blocked by mutation guard(s) [${r.guardIds.join(', ')}]${r.detail ? ` (${r.detail})` : ''}`,\n}\n\nfunction formatDisabledReason(taskId: TaskId, action: ActionName, reason: DisabledReason): string {\n const detail = (disabledReasonDetail[reason.kind] as (r: DisabledReason) => string)(reason)\n return `Action \"${taskId}:${action}\" is not allowed: ${detail}`\n}\n","import type {SanityDocument} from '@sanity/types'\n\nimport type {WorkflowResource} from '../core/refs.ts'\nimport type {WorkflowDefinition} from '../define/schema.ts'\nimport {canonicalTag} from '../tags.ts'\nimport type {WorkflowClient} from '../types/client.ts'\n\n/**\n * Mint the Sanity document `_id` for a workflow.definition. Bare form\n * — no GDR scheme prefix — because Sanity rejects `:` in document\n * IDs. Cross-resource references can construct the full GDR URI from\n * `(workflowResource, _id)` on demand.\n */\nexport function definitionDocId(\n _workflowResource: WorkflowResource,\n prefix: string,\n workflowId: string,\n version: number,\n): string {\n return `${prefix}.${workflowId}.v${version}`\n}\n\n/**\n * Topologically sort definitions so spawn-children land before their\n * parents. Refs pointing outside the batch are validated against the\n * lake — if a ref points neither to a doc in the batch nor to an\n * already-deployed definition, throw before any write.\n *\n * Cycles error.\n */\nexport async function sortByDependencies(\n client: WorkflowClient,\n definitions: WorkflowDefinition[],\n tags: string[],\n workflowResource: WorkflowResource,\n): Promise<WorkflowDefinition[]> {\n const prefix = canonicalTag(tags)\n // Track every workflowId in this batch + the versions per id. Logical\n // refs match on workflowId alone (or workflowId + version when explicit).\n const byWorkflowId = new Map<string, WorkflowDefinition[]>()\n for (const def of definitions) {\n const list = byWorkflowId.get(def.workflowId) ?? []\n list.push(def)\n byWorkflowId.set(def.workflowId, list)\n }\n const findInBatch = (ref: LogicalRef) => findRefInBatch(byWorkflowId, ref)\n\n await assertCrossBatchRefsDeployed(client, definitions, {\n tags,\n workflowResource,\n prefix,\n findInBatch,\n })\n\n return topoSortDefinitions(definitions, {workflowResource, prefix, findInBatch})\n}\n\ninterface LogicalRef {\n workflowId: string\n version?: number | 'latest'\n}\n\n/** Find the definition in the batch satisfying a logical ref: an exact\n * version match, or the highest version when the ref omits one. */\nfunction findRefInBatch(\n byWorkflowId: Map<string, WorkflowDefinition[]>,\n ref: LogicalRef,\n): WorkflowDefinition | undefined {\n const candidates = byWorkflowId.get(ref.workflowId)\n if (candidates === undefined || candidates.length === 0) return undefined\n if (typeof ref.version === 'number') return candidates.find((c) => c.version === ref.version)\n return candidates.reduce<WorkflowDefinition | undefined>(\n (best, c) => (best === undefined || c.version > best.version ? c : best),\n undefined,\n )\n}\n\n/**\n * For every spawn ref not satisfied within the batch, confirm a matching\n * `workflow.definition` is already deployed and visible to this engine's\n * tags. Throws listing every unresolved ref. No-op when all resolve.\n */\nasync function assertCrossBatchRefsDeployed(\n client: WorkflowClient,\n definitions: WorkflowDefinition[],\n ctx: {\n tags: string[]\n workflowResource: WorkflowResource\n prefix: string\n findInBatch: (ref: LogicalRef) => WorkflowDefinition | undefined\n },\n): Promise<void> {\n const missing: {from: string; ref: string}[] = []\n for (const def of definitions) {\n const fromId = definitionDocId(ctx.workflowResource, ctx.prefix, def.workflowId, def.version)\n for (const ref of refsOf(def)) {\n if (ctx.findInBatch(ref) !== undefined) continue // satisfied within batch\n const label = await resolveDeployedRefLabel(client, ref, ctx.tags)\n if (label !== undefined) missing.push({from: fromId, ref: label})\n }\n }\n if (missing.length === 0) return\n const lines = missing.map((m) => ` - ${m.from} → ${m.ref} (neither in batch nor deployed)`)\n throw new Error(\n `workflow.deployDefinitions: ${missing.length} unresolved reference${missing.length === 1 ? '' : 's'}:\\n` +\n lines.join('\\n'),\n )\n}\n\n/** Look up a logical ref in the lake. Returns undefined when a matching\n * deployed definition is visible to `tags`, or a human-readable label\n * for the unresolved ref otherwise. */\nasync function resolveDeployedRefLabel(\n client: WorkflowClient,\n ref: LogicalRef,\n tags: string[],\n): Promise<string | undefined> {\n const wantsExplicit = typeof ref.version === 'number'\n const params: Record<string, unknown> = {workflowId: ref.workflowId, tags}\n if (wantsExplicit) params.version = ref.version\n const doc = await client.fetch<(SanityDocument & {tags?: string[]}) | null>(\n definitionLookupGroq(wantsExplicit),\n params,\n )\n if (doc) return undefined\n return wantsExplicit ? `${ref.workflowId} v${ref.version}` : ref.workflowId\n}\n\n/** Children-before-parents topological sort over in-batch spawn refs.\n * Throws on a dependency cycle. */\nfunction topoSortDefinitions(\n definitions: WorkflowDefinition[],\n ctx: {\n workflowResource: WorkflowResource\n prefix: string\n findInBatch: (ref: LogicalRef) => WorkflowDefinition | undefined\n },\n): WorkflowDefinition[] {\n const visited = new Set<string>()\n const visiting = new Set<string>()\n const ordered: WorkflowDefinition[] = []\n\n const visit = (def: WorkflowDefinition): void => {\n const id = definitionDocId(ctx.workflowResource, ctx.prefix, def.workflowId, def.version)\n if (visited.has(id)) return\n if (visiting.has(id)) {\n throw new Error(`workflow.deployDefinitions: dependency cycle involving \"${id}\"`)\n }\n visiting.add(id)\n for (const ref of refsOf(def)) {\n const child = ctx.findInBatch(ref)\n if (child !== undefined) visit(child)\n }\n visiting.delete(id)\n visited.add(id)\n ordered.push(def)\n }\n\n for (const def of definitions) visit(def)\n return ordered\n}\n\n/** GROQ to resolve a deployed `workflow.definition` visible to the\n * caller's tags — explicit version, or the highest deployed version. */\nfunction definitionLookupGroq(wantsExplicit: boolean): string {\n return wantsExplicit\n ? `*[_type == \"workflow.definition\" && workflowId == $workflowId && version == $version && count(tags[@ in $tags]) > 0][0]`\n : `*[_type == \"workflow.definition\" && workflowId == $workflowId && count(tags[@ in $tags]) > 0] | order(version desc)[0]`\n}\n\n// Collect every spawn ref a definition depends on as a logical\n// `{ workflowId, version? }` reference. Hoisted out of\n// sortByDependencies so it doesn't re-capture closure on each call.\nfunction refsOf(def: WorkflowDefinition): LogicalRef[] {\n const out: LogicalRef[] = []\n for (const stage of def.stages) {\n for (const task of stage.tasks ?? []) {\n const ref = task.spawns?.definitionRef\n if (ref !== undefined) {\n out.push({\n workflowId: ref.workflowId,\n ...(ref.version !== undefined ? {version: ref.version} : {}),\n })\n }\n }\n }\n return out\n}\n\n/**\n * Compare a deployed definition document to what we'd write next. Skip\n * Sanity-managed system fields (`_rev`, `_createdAt`, `_updatedAt`) —\n * those always differ. Everything else must match exactly for the\n * deploy to be a no-op.\n */\nexport function isDefinitionUnchanged(\n existing: Record<string, unknown>,\n expected: Record<string, unknown>,\n): boolean {\n return (\n stableStringify(stripSystemFields(existing)) === stableStringify(stripSystemFields(expected))\n )\n}\n\nexport function stripSystemFields(doc: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(doc)) {\n if (k === '_rev' || k === '_createdAt' || k === '_updatedAt') continue\n out[k] = v\n }\n return out\n}\n\n/**\n * Stable JSON.stringify with sorted keys so object key order can't\n * cause a false \"changed\" diff.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value)\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`\n const entries = Object.entries(value as Record<string, unknown>).toSorted(([a], [b]) =>\n a.localeCompare(b),\n )\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(',')}}`\n}\n\nexport async function loadDefinition(\n client: WorkflowClient,\n workflowId: string,\n version: number | undefined,\n tags: string[],\n): Promise<WorkflowDefinition> {\n if (version !== undefined) {\n const doc = await client.fetch<(WorkflowDefinition & {tags?: string[]}) | null>(\n \"*[_type == 'workflow.definition' && workflowId == $id && version == $v && count(tags[@ in $engineTags]) > 0][0]\",\n {id: workflowId, v: version, engineTags: tags},\n )\n if (!doc) {\n throw new Error(`Workflow definition ${workflowId} v${version} not deployed`)\n }\n return doc\n }\n const latest = await client.fetch<WorkflowDefinition | null>(\n \"*[_type == 'workflow.definition' && workflowId == $id && count(tags[@ in $engineTags]) > 0] | order(version desc)[0]\",\n {id: workflowId, engineTags: tags},\n )\n if (!latest) {\n throw new Error(`No deployed definition for workflow ${workflowId}`)\n }\n return latest\n}\n","import {resolveAccess, type WorkflowAccessOverride} from '../access.ts'\nimport type {Clock} from '../clock.ts'\nimport {extractDocumentId, type GlobalDocumentReference, type ParsedGdr} from '../core/refs.ts'\nimport {cascadeAutoTransitions, propagateToAncestors} from '../engine/cascade.ts'\nimport {effectsContextEntry} from '../instance.ts'\nimport {validateTags} from '../tags.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {EffectsContextEntry} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport type {ResourceClientResolver} from './types.ts'\n\n// Internal helpers\n\n/**\n * Resolve a spawn `instanceRef.id` to the bare doc `_id` used by GROQ.\n * A misconfigured caller could write a malformed GDR URI into history;\n * {@link extractDocumentId} throws on those, so skip them (return no id)\n * instead of crashing the whole {@link workflow.children} call.\n */\nexport function bareIdFromSpawnRef(uri: string): string[] {\n if (!uri.includes(':')) return [uri]\n try {\n return [extractDocumentId(uri)]\n } catch {\n return []\n }\n}\n\n/**\n * Shared verb preamble: validate tags, resolve the calling actor from\n * the access override (or the client's token), and build the\n * cross-resource routing function. Every `workflow.*` verb opens this\n * way.\n */\nexport async function resolveOperationContext(args: {\n client: WorkflowClient\n tags: string[]\n resourceClients?: ResourceClientResolver\n access?: WorkflowAccessOverride\n grantsFromPath?: string\n}): Promise<{\n access: Awaited<ReturnType<typeof resolveAccess>>\n actor: Awaited<ReturnType<typeof resolveAccess>>['actor']\n clientForGdr: (parsed: ParsedGdr) => WorkflowClient\n}> {\n validateTags(args.tags)\n const access = await resolveAccess(args.client, {\n ...(args.access !== undefined ? {override: args.access} : {}),\n ...(args.grantsFromPath !== undefined ? {grantsFromPath: args.grantsFromPath} : {}),\n })\n return {\n access,\n actor: access.actor,\n clientForGdr: buildClientForGdr(args.client, args.resourceClients),\n }\n}\n\nexport async function cascade(\n client: WorkflowClient,\n instanceId: string,\n actor: Actor | undefined,\n clientForGdr?: (parsed: ParsedGdr) => WorkflowClient,\n clock?: Clock,\n): Promise<number> {\n const count = await cascadeAutoTransitions(client, instanceId, actor, clientForGdr, clock)\n await propagateToAncestors(client, instanceId, actor, clientForGdr, clock)\n return count\n}\n\n/**\n * Build the routing function from a resolver. Falls back to using the\n * default client when the resolver is absent or returns undefined.\n */\nexport function buildClientForGdr(\n defaultClient: WorkflowClient,\n resolver: ResourceClientResolver | undefined,\n): (parsed: ParsedGdr) => WorkflowClient {\n if (resolver === undefined) return () => defaultClient\n return (parsed) => resolver(parsed) ?? defaultClient\n}\n\nexport async function reload(\n client: WorkflowClient,\n instanceId: string,\n tags: string[],\n): Promise<WorkflowInstance> {\n const doc = await client.getDocument<WorkflowInstance>(instanceId)\n if (!doc) throw new Error(`Workflow instance ${instanceId} not found`)\n if (!intersectsTags(doc.tags, tags)) {\n throw new Error(`Workflow instance ${instanceId} not visible to this engine (tag mismatch)`)\n }\n return doc\n}\n\nexport function intersectsTags(\n docTags: string[] | undefined | null,\n engineTags: string[],\n): boolean {\n if (!docTags || docTags.length === 0) return false\n return engineTags.some((t) => docTags.includes(t))\n}\n\nexport function toEffectsContextEntries(\n ctx: Record<string, string | number | boolean | GlobalDocumentReference>,\n): EffectsContextEntry[] {\n return Object.entries(ctx).map(([id, value]) => effectsContextEntry(id, value))\n}\n","/**\n * The workflow API — a single coherent SDK surface, five methods.\n *\n * The model:\n *\n * - **`deployDefinition`** — once at deploy time. Persists the definition.\n * - **`startInstance`** — once per workflow run. Pins a snapshot, seeds\n * `effectsContext` (stable params for effect handlers), enters the\n * initial stage. Cascades.\n * - **`fireAction`** — the universal \"something happened\" call. Editors\n * fire actions on tasks. Runtimes fire actions on tasks in response\n * to webhooks, timer firings, etc. External signals funnel through\n * this; nothing else.\n * - **`completeEffect`** — the runtime reports a queued effect's\n * outcome. Optionally carries `outputs` that get merged into\n * `effectsContext` so a downstream effect's bindings can reference\n * them (effect chains). The only path that mutates `effectsContext`\n * after start.\n * - **`tick`** — re-evaluate auto-transitions and resolve due waits.\n * Used after any change that might unblock a filter: a content\n * mutation in the lake, a timer crossing a `completeWhen` deadline,\n * a sibling workflow completing, etc. The runtime decides which\n * instances might need a tick; the engine just re-evaluates.\n *\n * What's NOT in the API:\n *\n * - No `requestTransition`. Workflow authors should not have a way to\n * \"force\" a stage transition outside of filters firing. If you want\n * \"cancel from anywhere,\" model cancellation as a task with an action\n * that flips it to `failed`, plus an auto-transition filtered on\n * `anyTaskFailed`. Same audit trail as everything else; same\n * mechanism.\n * - No `setContext`. `effectsContext` is set at start, then mutated\n * only by completed effects' `outputs`. External signals belong on\n * tasks (via `fireAction`) or in the lake (as document mutations\n * that filters can read).\n * - No `invokeTask`. Tasks auto-activate on stage entry. Editor's first\n * `fireAction` against a pending task auto-invokes it before\n * applying the action.\n *\n * What filters can read:\n *\n * - Task state on the instance (`*[_id == $self][0].stages[id == $stage && !defined(exitedAt)][0].tasks[...]`)\n * - Document content in the lake (`*[_type == \"...\" && ...]`)\n * - Reserved params: `$self`, `$subject`, `$parent`, `$ancestors`, `$now`\n *\n * What filters must NOT read:\n *\n * - `effectsContext`. That field is for effect handler params only.\n *\n * The boundary keeps each thing doing one job: tasks are workflow state,\n * the lake is content state, effectsContext is handler fuel.\n */\n\nimport type {SanityDocument} from '@sanity/types'\nimport {evaluate as evaluateGroq, parse as parseGroq} from 'groq-js'\n\nimport {type Clocked, wallClock} from '../clock.ts'\nimport {buildParams} from '../core/params.ts'\nimport type {WorkflowResource} from '../core/refs.ts'\nimport type {StateSlot, WorkflowDefinition} from '../define/schema.ts'\nimport {fireAction as engineFireAction} from '../engine/actions.ts'\nimport {primeInitialStage} from '../engine/cascade.ts'\nimport {completeEffect as engineCompleteEffect} from '../engine/effects.ts'\nimport {setStage as engineSetStage} from '../engine/stages.ts'\nimport {invokeTask as engineInvokeTask} from '../engine/tasks.ts'\nimport {type EvaluateArgs, evaluateInstance} from '../evaluate.ts'\nimport {guardsForInstance as queryGuardsForInstance} from '../guards-query.ts'\nimport {buildInstanceBase} from '../instance.ts'\nimport {randomKey} from '../keys.ts'\nimport {\n fetchGrants as permFetchGrants,\n grantsPermissionOn as permGrantsPermissionOn,\n matchesFilter as permMatchesFilter,\n} from '../permissions.ts'\nimport {hydrateSnapshot} from '../snapshot.ts'\nimport {derivePerspectiveFromState, resolveDeclaredState} from '../state-resolution.ts'\nimport {canonicalTag, validateTags} from '../tags.ts'\nimport type {MutationGuardDoc} from '../types/authorization.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport {ActionDisabledError, type WorkflowEvaluation} from '../types/evaluation.ts'\nimport type {HistoryEntry} from '../types/history.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {\n definitionDocId,\n isDefinitionUnchanged,\n loadDefinition,\n sortByDependencies,\n} from './deploy.ts'\nimport {\n bareIdFromSpawnRef,\n buildClientForGdr,\n cascade,\n intersectsTags,\n reload,\n resolveOperationContext,\n toEffectsContextEntries,\n} from './operations.ts'\nimport type {\n CompleteEffectArgs,\n DeployDefinitionResult,\n DeployDefinitionsArgs,\n DeployDefinitionsResult,\n DispatchResult,\n FireActionArgs,\n OperationArgs,\n ResourceClientResolver,\n SetStageArgs,\n StartInstanceArgs,\n} from './types.ts'\nimport {validateDefinition} from './validate.ts'\n\n/**\n * The four-method workflow API.\n */\nexport const workflow = {\n /**\n * Persist a workflow definition to the lake. Stored as a\n * `workflow.definition` document with id\n * `workflow.definition.<workflowId>.v<version>`. Subsequent versions\n * are stored alongside earlier ones — `startInstance` picks the\n * highest version by default.\n */\n /**\n * Deploy a set of workflow definitions as one call. The SDK figures\n * out the dependency order itself (children before parents that spawn\n * them via `task.spawns.definitionRef`), idempotently writes any\n * definition whose content has changed, and reports a per-definition\n * outcome (`created` / `updated` / `unchanged`).\n *\n * Refs may point inside the batch OR at already-deployed definitions\n * in the lake — both are valid. A ref pointing at neither errors with\n * a clear message naming the missing target.\n *\n * Cycles in the dependency graph error before any write happens.\n */\n deployDefinitions: async (args: DeployDefinitionsArgs): Promise<DeployDefinitionsResult> => {\n const {client, tags, workflowResource, definitions} = args\n validateTags(tags)\n\n // 1. Validate each definition's GROQ + structural invariants\n // individually. Fail fast before we touch the lake.\n for (const def of definitions) {\n validateDefinition(def)\n }\n\n // 2. Build the dependency graph and topologically sort.\n // Children-before-parents; refs pointing outside the batch are\n // validated against the lake once.\n const ordered = await sortByDependencies(client, definitions, tags, workflowResource)\n\n // 3. Compare against the existing doc to skip unchanged definitions,\n // then write everything that DID change in a single same-resource\n // transaction. All-or-nothing — if one definition's rev check\n // fails, none of the batch lands.\n const results: DeployDefinitionResult[] = []\n const prefix = canonicalTag(tags)\n const tx = client.transaction()\n let hasWrites = false\n for (const def of ordered) {\n const id = definitionDocId(workflowResource, prefix, def.workflowId, def.version)\n const expected = {\n ...def,\n _id: id,\n _type: 'workflow.definition' as const,\n tags,\n }\n // `getDocument` returns the doc, or null/undefined when missing\n // (different clients return different falsy sentinels). Use a\n // truthy check rather than `=== null` to cover both.\n const existing = await client.getDocument<typeof expected & SanityDocument>(id)\n if (\n existing &&\n intersectsTags(existing.tags, tags) &&\n isDefinitionUnchanged(existing, expected)\n ) {\n results.push({workflowId: def.workflowId, version: def.version, status: 'unchanged'})\n continue\n }\n if (existing) {\n // Patch with rev check — fail fast if another deploy raced us.\n //\n // `set()` is a *partial* update: it overwrites the listed fields\n // but leaves any extra top-level fields untouched. That's wrong\n // for definition deploys, where a schema change can rename or\n // drop a field (e.g. `name` → `title`) and stale values would\n // otherwise linger on the deployed doc forever. Compute the\n // top-level keys that exist on `existing` but not on `expected`\n // and chain an `.unset()` so the deployed shape matches source.\n // Sanity-managed `_*` fields stay (we can't unset them anyway).\n const expectedKeys = new Set(Object.keys(expected))\n const toUnset = Object.keys(existing).filter(\n (k) => !k.startsWith('_') && !expectedKeys.has(k),\n )\n const patch = client.patch(id).set(expected).ifRevisionId(existing._rev)\n if (toUnset.length > 0) patch.unset(toUnset)\n tx.patch(patch)\n } else {\n // Net-new — `create` errors on collision instead of clobbering.\n tx.create(expected)\n }\n hasWrites = true\n results.push({\n workflowId: def.workflowId,\n version: def.version,\n status: existing ? 'updated' : 'created',\n })\n }\n if (hasWrites) await tx.commit()\n\n return {results}\n },\n\n /**\n * Spawn a new workflow instance from a deployed definition.\n *\n * Pins the snapshot at start-time, seeds `effectsContext`, enters\n * the initial stage (which builds taskStatus, queues onEnter\n * effects, auto-activates tasks). Then cascades auto-transitions\n * until stable. Returns the resulting instance.\n */\n startInstance: async (args: Clocked<StartInstanceArgs>): Promise<WorkflowInstance> => {\n const {\n client,\n tags,\n workflowResource,\n workflowId,\n version,\n initialState,\n ancestors,\n effectsContext,\n instanceId,\n perspective,\n } = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n const clock = args.clock ?? wallClock\n\n const definition = await loadDefinition(client, workflowId, version, tags)\n // Bare `_id` — Sanity rejects `:` in document IDs, so we don't\n // use a GDR URI here. Cross-resource references build the GDR\n // URI from `(workflowResource, _id)` on demand.\n const id = instanceId ?? `${canonicalTag(tags)}.wf-instance.${randomKey()}`\n\n const initialStage = definition.stages.find((s) => s.id === definition.initialStageId)\n if (initialStage === undefined) {\n throw new Error(\n `Initial stage \"${definition.initialStageId}\" missing in ${workflowId} v${definition.version}`,\n )\n }\n\n const now = clock()\n const effectsContextEntries = effectsContext ? toEffectsContextEntries(effectsContext) : []\n // Workflow-scope state slots resolve in declaration order. Later\n // slots can read earlier ones via `$state.<slotId>` in their GROQ.\n // There's no privileged slot name — `$state` exposes every\n // declared slot keyed by its author-chosen id.\n const resolvedState = await resolveDeclaredState({\n slotDefs: (definition as WorkflowDefinition & {state?: StateSlot[]}).state ?? [],\n initialState: initialState ?? [],\n ctx: {\n client,\n now,\n selfId: id,\n tags,\n workflowResource,\n ...(perspective !== undefined ? {perspective} : {}),\n },\n randomKey,\n })\n\n // Perspective resolution: an explicit `perspective` arg wins;\n // otherwise derive it from a populated `release.ref` slot. This is\n // what makes a release-targeting workflow self-describing — the\n // caller fills the slot and the engine figures out the read\n // perspective, rather than every caller having to pass it.\n const effectivePerspective = perspective ?? derivePerspectiveFromState(resolvedState)\n\n const base = buildInstanceBase({\n id,\n now,\n tags,\n workflowResource,\n workflowId: definition.workflowId,\n pinnedVersion: definition.version,\n definition,\n state: resolvedState,\n effectsContext: effectsContextEntries,\n ancestors: ancestors ?? [],\n perspective: effectivePerspective,\n initialStageId: definition.initialStageId,\n actor,\n })\n // Net-new doc: `create` errors loud if `_id` collides instead of\n // silently wiping an existing instance. Use the caller-supplied\n // `instanceId` at your own risk — collisions surface here.\n await client.create(base)\n\n await primeInitialStage(client, id, actor, clientForGdr, clock)\n await cascade(client, id, actor, clientForGdr, clock)\n\n return reload(client, id, tags)\n },\n\n /**\n * Fire an action against a task. If the task is pending, it is\n * auto-invoked first (pending → active) so callers don't have to know\n * the lifecycle. Cascades auto-transitions and propagates to ancestors\n * after the action commits.\n *\n * This is the universal \"something happened\" call. Editors fire it.\n * Runtimes fire it in response to webhooks, effect completions, and\n * timer firings. External signals never bypass this.\n */\n fireAction: async (args: Clocked<FireActionArgs>): Promise<DispatchResult> => {\n const {\n client,\n tags,\n workflowResource,\n instanceId,\n taskId,\n action,\n params,\n idempotent,\n resourceClients,\n } = args\n const {access, actor, clientForGdr} = await resolveOperationContext(args)\n const clock = args.clock ?? wallClock\n\n const before = await reload(client, instanceId, tags)\n const currentStageEntry = before.stages.find(\n (s) => s.id === before.currentStageId && s.exitedAt === undefined,\n )\n const taskEntry = currentStageEntry?.tasks.find((t) => t.id === taskId)\n if (taskEntry === undefined && idempotent === true) {\n return {instance: before, cascaded: 0, fired: false}\n }\n\n // Soft-gate via evaluation. We project the instance from the\n // actor's perspective and check the requested action's verdict\n // before invoking the engine. If denied, throw the structured\n // ActionDisabledError so callers can render `reason` directly.\n //\n // Reuse the already-resolved `access` (no second token/grant\n // round-trip) by passing it through as the override.\n const evaluation = await evaluateInstance({\n client,\n tags,\n workflowResource,\n instanceId,\n access,\n clock,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n })\n const taskEval = evaluation.currentStage.tasks.find((t) => t.task.id === taskId)\n const actionEval = taskEval?.actions.find((a) => a.action.id === action)\n if (actionEval !== undefined && !actionEval.allowed && actionEval.disabledReason) {\n throw new ActionDisabledError({\n taskId,\n action,\n reason: actionEval.disabledReason,\n })\n }\n\n if (taskEntry?.status === 'pending') {\n await engineInvokeTask({\n client,\n instanceId,\n taskId,\n options: {actor, clock},\n })\n }\n\n const actionResult = await engineFireAction({\n client,\n instanceId,\n taskId,\n action,\n ...(params !== undefined ? {params} : {}),\n options: {actor, clock},\n })\n\n const cascaded = await cascade(client, instanceId, actor, clientForGdr, clock)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: true,\n ...(actionResult.ranOps !== undefined ? {ranOps: actionResult.ranOps} : {}),\n }\n },\n\n /**\n * Report a queued effect's outcome. Drains it from `pendingEffects`,\n * appends an `effectHistory` entry, and (if `outputs` are supplied\n * and the effect succeeded) upserts those values into\n * `effectsContext` by key — so downstream effect bindings can\n * reference them. Cascades after.\n */\n completeEffect: async (args: Clocked<CompleteEffectArgs>): Promise<DispatchResult> => {\n const {client, tags, instanceId, effectKey, status, outputs, detail, error, durationMs} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n const clock = args.clock ?? wallClock\n await engineCompleteEffect({\n client,\n instanceId,\n effectKey,\n status,\n ...(outputs !== undefined ? {outputs} : {}),\n ...(detail !== undefined ? {detail} : {}),\n ...(error !== undefined ? {error} : {}),\n ...(durationMs !== undefined ? {durationMs} : {}),\n options: {...(actor !== undefined ? {actor} : {}), clock},\n })\n const cascaded = await cascade(client, instanceId, actor, clientForGdr, clock)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: true,\n }\n },\n\n /**\n * Re-evaluate auto-transitions and resolve due waits until stable.\n *\n * Used by the runtime after any event that might affect the workflow\n * but isn't itself a task action: a subject doc was patched, a sibling\n * workflow completed, the clock crossed a `completeWhen` deadline, etc.\n * The runtime doesn't need to know what changed — it just nudges\n * affected instances and the engine re-evaluates.\n */\n tick: async (args: Clocked<OperationArgs>): Promise<DispatchResult> => {\n const {client, tags, instanceId} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n const clock = args.clock ?? wallClock\n await reload(client, instanceId, tags)\n const cascaded = await cascade(client, instanceId, actor, clientForGdr, clock)\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: cascaded > 0,\n }\n },\n\n /**\n * Admin override — force the instance into `targetStageId` regardless\n * of filters or declared transitions. ACL gating should be enforced\n * upstream; this verb performs the mechanical move.\n */\n setStage: async (args: Clocked<SetStageArgs>): Promise<DispatchResult> => {\n const {client, tags, instanceId, targetStageId, reason} = args\n const {actor, clientForGdr} = await resolveOperationContext(args)\n const clock = args.clock ?? wallClock\n await reload(client, instanceId, tags)\n const result = await engineSetStage({\n client,\n instanceId,\n targetStageId,\n ...(reason !== undefined ? {reason} : {}),\n options: {...(actor !== undefined ? {actor} : {}), clock},\n })\n const cascaded = result.fired\n ? await cascade(client, instanceId, actor, clientForGdr, clock)\n : 0\n return {\n instance: await reload(client, instanceId, tags),\n cascaded,\n fired: result.fired,\n }\n },\n\n /**\n * Fetch a workflow instance by id, scoped to the engine's tags.\n * Throws when the instance doesn't exist or isn't visible to this\n * engine.\n */\n getInstance: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n }): Promise<WorkflowInstance> => {\n const {client, tags, instanceId} = args\n validateTags(tags)\n return reload(client, instanceId, tags)\n },\n\n guardsForInstance: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n resourceClients?: ResourceClientResolver\n }): Promise<MutationGuardDoc[]> => {\n const {client, tags, instanceId, resourceClients} = args\n validateTags(tags)\n const instance = await reload(client, instanceId, tags)\n return queryGuardsForInstance({\n client,\n clientForGdr: buildClientForGdr(client, resourceClients),\n instance,\n })\n },\n\n /**\n * Run a caller-supplied GROQ query with the engine's tags bound as\n * `$engineTags`. This does NOT rewrite the query — arbitrary GROQ\n * can't be safely tag-scoped after the fact — so the CALLER MUST\n * filter on `$engineTags` (e.g.\n * `count(tags[@ in $engineTags]) > 0`). To guard against accidental\n * cross-tenant reads, a query that never references `$engineTags` is\n * rejected before it reaches the lake. Caller is responsible for type\n * narrowing the result.\n */\n query: async <T = unknown>(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n groq: string\n params?: Record<string, unknown>\n }): Promise<T> => {\n const {client, tags, groq, params} = args\n validateTags(tags)\n if (!groq.includes('$engineTags')) {\n throw new Error(\n `workflow.query: query must filter on $engineTags to stay tag-scoped (e.g. \"count(tags[@ in $engineTags]) > 0\"); got: ${groq}`,\n )\n }\n return client.fetch<T>(groq, {...params, engineTags: tags})\n },\n\n /**\n * Snapshot-aware GROQ — runs against the same in-memory view that\n * filters see for a given instance.\n *\n * Hydrates the instance's snapshot (instance + subject + ancestors\n * + every doc declared by a `doc.ref` / `doc.refs` slot in scope),\n * then evaluates the supplied GROQ in groq-js against that dataset.\n * Reserved params are auto-bound: `$self`, `$subject`, `$parent`,\n * `$ancestors`, `$stage`, `$now` — all in GDR URI form to match the\n * snapshot's keying.\n *\n * Use when an external consumer (a UI, a debug pane, a test) wants\n * to ask \"what does the engine see for this workflow right now?\"\n * without re-implementing hydration. Pure read — never writes.\n */\n queryInScope: async <T = unknown>(\n args: Clocked<{\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n groq: string\n params?: Record<string, unknown>\n }>,\n ): Promise<T> => {\n const {client, tags, instanceId, groq, params, resourceClients} = args\n const clock = args.clock ?? wallClock\n validateTags(tags)\n const instance = await reload(client, instanceId, tags)\n const definition = JSON.parse(instance.definitionSnapshot) as WorkflowDefinition\n const clientForGdr = buildClientForGdr(client, resourceClients)\n const snapshot = await hydrateSnapshot({client, clientForGdr, instance, definition})\n const reserved = buildParams(instance, clock())\n const tree = parseGroq(groq, {params: {...reserved, ...params}})\n const evaluated = await evaluateGroq(tree, {\n dataset: snapshot.docs,\n params: {...reserved, ...params},\n })\n return (await evaluated.get()) as T\n },\n\n /**\n * List every pending effect on the instance. Returns the same entries\n * the runtime would see — claimed and unclaimed alike.\n */\n listPendingEffects: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n }): Promise<PendingEffect[]> => {\n const inst = await reload(args.client, args.instanceId, args.tags)\n return inst.pendingEffects\n },\n\n /**\n * Filter pending effects on the instance by criteria. `claimed`\n * filters on claim presence; `names` restricts to specific effect\n * names. Both filters compose (AND).\n */\n findPendingEffects: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n claimed?: boolean\n names?: string[]\n }): Promise<PendingEffect[]> => {\n const inst = await reload(args.client, args.instanceId, args.tags)\n return inst.pendingEffects.filter((e) => {\n if (args.claimed === true && e.claim === undefined) return false\n if (args.claimed === false && e.claim !== undefined) return false\n if (args.names !== undefined && !args.names.includes(e.effectId)) return false\n return true\n })\n },\n\n /**\n * Project the instance from a given actor's perspective. Returns a\n * `WorkflowEvaluation` with per-action verdicts (`allowed` + a\n * structured `disabledReason`). Pure read; never writes.\n *\n * Used by UIs to render disabled-with-reason buttons and by\n * `fireAction` to gate writes via the same logic.\n */\n evaluate: async (args: Clocked<EvaluateArgs>): Promise<WorkflowEvaluation> => {\n return evaluateInstance(args)\n },\n\n /**\n * Materialised spawned children of a parent instance.\n *\n * Walks `history` for `workflow.history.spawned` events — the durable\n * record. (The per-task `spawnedInstances` field on the active stage\n * only exists while that stage is current; history survives.) Strips\n * the GDR URI on each `instanceRef` to a bare `_id`, fetches the\n * instances, drops any that aren't visible to this engine's tags, and\n * returns them sorted by `startedAt` ascending.\n *\n * Pass `taskId` to restrict to a single spawning task on the parent.\n */\n children: async (args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n instanceId: string\n taskId?: string\n }): Promise<WorkflowInstance[]> => {\n const {client, tags, instanceId, taskId} = args\n validateTags(tags)\n const parent = await reload(client, instanceId, tags)\n const isSpawned = (\n h: HistoryEntry,\n ): h is Extract<HistoryEntry, {_type: 'workflow.history.spawned'}> =>\n h._type === 'workflow.history.spawned'\n const ids = parent.history\n .filter(isSpawned)\n .filter((h) => taskId === undefined || h.taskId === taskId)\n .flatMap((h) => bareIdFromSpawnRef(h.instanceRef.id))\n if (ids.length === 0) return []\n // Single GROQ — server-side filters by id set + engine tags, sorts\n // by startedAt. Beats N `getDocument` roundtrips for fan-outs.\n //\n // Visibility: this assumes spawn writes were committed with default\n // `visibility: \"sync\"` (which is what @sanity/client does and what\n // the engine relies on everywhere else). If a write path ever opts\n // into `async`, this query will silently miss freshly-spawned\n // children — but every other GROQ in the engine has the same\n // assumption, so we're not making things worse here.\n return client.fetch<WorkflowInstance[]>(\n `*[_id in $ids && count(tags[@ in $engineTags]) > 0] | order(startedAt asc)`,\n {ids, engineTags: tags},\n )\n },\n\n /**\n * Permission helpers — Sanity ACL grants evaluated against documents\n * via GROQ. Used by `workflow.evaluate` to soft-gate actions when the\n * caller supplies grants.\n */\n permissions: {\n matchesFilter: permMatchesFilter,\n grantsPermissionOn: permGrantsPermissionOn,\n fetchGrants: permFetchGrants,\n },\n}\n","import type {WorkflowAccessOverride} from '../access.ts'\nimport type {GlobalDocumentReference, WorkflowResource} from '../core/refs.ts'\nimport type {Effect, WorkflowDefinition} from '../define/schema.ts'\nimport {isRevisionConflict} from '../engine/results.ts'\nimport {validateTags} from '../tags.ts'\nimport type {Actor} from '../types/actor.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {reload} from './operations.ts'\nimport type {\n DrainEffectsResult,\n EffectHandler,\n EngineLogger,\n LoggerFactory,\n MissingHandlerDeployInfo,\n MissingHandlerInfo,\n MissingHandlerPolicy,\n ResourceClientResolver,\n VerifyDeployedDefinitionsResult,\n} from './types.ts'\nimport {workflow} from './workflow.ts'\n\nexport async function verifyDeployedDefinitionsInternal(args: {\n client: WorkflowClient\n tags: string[]\n effectHandlers: Record<string, EffectHandler>\n missingHandler: MissingHandlerPolicy\n logger: LoggerFactory\n}): Promise<VerifyDeployedDefinitionsResult> {\n const {client, tags, effectHandlers, missingHandler, logger} = args\n validateTags(tags)\n const log = logger('verifyDeployedDefinitions')\n const definitions = await client.fetch<(WorkflowDefinition & {_id: string})[]>(\n '*[_type == \"workflow.definition\" && count(tags[@ in $engineTags]) > 0] | order(workflowId asc, version asc)',\n {engineTags: tags},\n )\n\n const seen: {workflowId: string; version: number; _id: string}[] = []\n const missingByName = new Map<string, {definitionId: string; locations: Set<string>}>()\n for (const def of definitions) {\n seen.push({workflowId: def.workflowId, version: def.version, _id: def._id})\n walkEffectNames(def, (name, location) => {\n if (effectHandlers[name] !== undefined) return\n const key = `${name}@@${def._id}`\n let bucket = missingByName.get(key)\n if (bucket === undefined) {\n bucket = {definitionId: def._id, locations: new Set()}\n missingByName.set(key, bucket)\n }\n bucket.locations.add(location)\n })\n }\n\n const missing: VerifyDeployedDefinitionsResult['missing'] = []\n for (const [key, bucket] of missingByName.entries()) {\n const name = key.split('@@')[0]!\n missing.push({\n name,\n definitionId: bucket.definitionId,\n locations: [...bucket.locations].toSorted(),\n })\n }\n\n for (const m of missing) {\n const info: MissingHandlerDeployInfo = {\n phase: 'deploy',\n name: m.name,\n locations: m.locations,\n definitionId: m.definitionId,\n }\n const verdict = await applyMissingHandler(missingHandler, info, log)\n if (verdict === 'fail') {\n throw new Error(\n `verifyDeployedDefinitions: missing handler for \"${m.name}\" referenced by ${m.definitionId} at ${m.locations.join(', ')}`,\n )\n }\n }\n\n return {definitions: seen, missing}\n}\n\n/** Walk every external effect reference in a definition, invoking the\n * visitor with each name + a structural location string. */\nfunction walkEffectNames(\n def: WorkflowDefinition & {_id?: string},\n visit: (id: string, location: string) => void,\n): void {\n const visitEffects = (effects: Effect[] | undefined, location: string) => {\n for (const e of effects ?? []) visit(e.id, location)\n }\n for (const stage of def.stages ?? []) {\n visitEffects(stage.onEnter, `stage[${stage.id}].onEnter`)\n visitEffects(stage.onExit, `stage[${stage.id}].onExit`)\n for (const t of stage.tasks ?? []) {\n visitEffects(t.effects, `stage[${stage.id}].task[${t.id}].effects`)\n for (const a of t.actions ?? []) {\n visitEffects(a.effects, `stage[${stage.id}].task[${t.id}].action[${a.id}].effects`)\n }\n }\n for (const tr of stage.transitions ?? []) {\n visitEffects(tr.effects, `stage[${stage.id}].transition[${tr.to}].effects`)\n }\n }\n}\n\n// drainEffects — three-write claim protocol per pending entry.\n//\n// 1. CLAIM: load instance (rev R0). Stamp `claim` on an unclaimed entry.\n// Persist via patch().set().ifRevisionId(R0). On rev mismatch\n// (someone else committed), restart and pick a different entry.\n// 2. DISPATCH: invoke the registered handler in a try/catch.\n// 3. COMPLETE: call `completeEffect` which moves the entry from\n// `pendingEffects[]` to `effectHistory[]` and cascades.\n//\n// Returns drained / failed / skipped buckets. Skipped means missing\n// handler (subject to the engine's missingHandler policy).\n\nexport async function drainEffectsInternal(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n effectHandlers: Record<string, EffectHandler>\n missingHandler: MissingHandlerPolicy\n logger: LoggerFactory\n /** Identity override for the drainer. Defaults to a system actor. */\n access?: WorkflowAccessOverride\n}): Promise<DrainEffectsResult> {\n const {\n client,\n tags,\n workflowResource,\n resourceClients,\n instanceId,\n effectHandlers,\n missingHandler,\n logger,\n } = args\n const drainerActor: Actor = args.access?.actor ?? {kind: 'system', id: 'engine.drainEffects'}\n // The completion call goes through workflow.completeEffect which\n // also accepts WorkflowAccessOverride; we hand it the drainer's\n // identity (override.actor or the system fallback) and pass any\n // explicit grants through verbatim.\n const completionAccess: WorkflowAccessOverride = {\n actor: drainerActor,\n ...(args.access?.grants !== undefined ? {grants: args.access.grants} : {}),\n }\n validateTags(tags)\n const log = logger('drainEffects')\n const drained: PendingEffect[] = []\n const failed: PendingEffect[] = []\n const skipped: PendingEffect[] = []\n // Keys of entries we've decided to skip (missing handler, policy\n // allows). We never claim them, so a plain `continue` would re-pick\n // the same entry forever — exclude them from the candidate search so\n // later entries that DO have handlers still drain.\n const skippedKeys = new Set<string>()\n\n while (true) {\n const before = await reload(client, instanceId, tags)\n const candidate = before.pendingEffects.find(\n (e) => e.claim === undefined && !skippedKeys.has(e._key),\n )\n if (candidate === undefined) break\n\n const handler = effectHandlers[candidate.effectId]\n if (handler === undefined) {\n await assertSkippableOrThrow(missingHandler, candidate, instanceId, log)\n skipped.push(candidate)\n skippedKeys.add(candidate._key)\n continue\n }\n\n const claimed = await claimPendingEffect(client, before, candidate._key, drainerActor)\n if (!claimed) continue // 409 — re-read and retry a fresh candidate.\n\n const {outputs, dispatchError} = await dispatchEffect(handler, candidate, {\n client,\n instanceId,\n logger,\n })\n\n await reportEffectOutcome({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n instanceId,\n effectKey: candidate._key,\n access: completionAccess,\n outputs,\n dispatchError,\n })\n\n if (dispatchError === undefined) drained.push(candidate)\n else failed.push(candidate)\n }\n\n return {drained, failed, skipped}\n}\n\n/** Report a dispatched effect's outcome through `workflow.completeEffect`,\n * translating the dispatch result into the `done`/`failed` status +\n * optional outputs/error the API expects. */\nasync function reportEffectOutcome(args: {\n client: WorkflowClient\n tags: string[]\n workflowResource: WorkflowResource\n resourceClients?: ResourceClientResolver\n instanceId: string\n effectKey: string\n access: WorkflowAccessOverride\n outputs: Record<string, string | number | boolean | GlobalDocumentReference> | undefined\n dispatchError: {message: string; stack?: string} | undefined\n}): Promise<void> {\n const {outputs, dispatchError, resourceClients, ...rest} = args\n await workflow.completeEffect({\n ...rest,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n status: dispatchError === undefined ? 'done' : 'failed',\n ...(outputs !== undefined ? {outputs} : {}),\n ...(dispatchError !== undefined ? {error: dispatchError} : {}),\n })\n}\n\n/** Apply the missing-handler policy to an unhandled candidate. Throws\n * when the policy resolves to `fail`; returns when the entry may be\n * skipped. */\nasync function assertSkippableOrThrow(\n missingHandler: MissingHandlerPolicy,\n candidate: PendingEffect,\n instanceId: string,\n log: EngineLogger,\n): Promise<void> {\n const policyResult = await applyMissingHandler(\n missingHandler,\n {phase: 'drain', name: candidate.effectId, effectKey: candidate._key, instanceId},\n log,\n )\n if (policyResult === 'fail') {\n throw new Error(\n `drainEffects: no handler registered for \"${candidate.effectId}\" (effectKey=${candidate._key}, instanceId=${instanceId})`,\n )\n }\n}\n\n/**\n * Claim a single pending entry by stamping `claim` conditional on the\n * instance's current `_rev`. Returns false on a 409 rev mismatch (a\n * concurrent writer raced us) so the caller re-reads and retries.\n */\nasync function claimPendingEffect(\n client: WorkflowClient,\n instance: WorkflowInstance,\n effectKey: string,\n drainerActor: Actor,\n): Promise<boolean> {\n const claim = {\n _type: 'workflow.pendingEffect.claim' as const,\n claimedAt: new Date().toISOString(),\n claimedBy: drainerActor,\n }\n try {\n await client\n .patch(instance._id)\n .ifRevisionId(instance._rev)\n .set({[`pendingEffects[_key==\"${effectKey}\"].claim`]: claim})\n .commit()\n return true\n } catch (error) {\n // Only a lost rev race means \"another drainer claimed it\" — re-read and\n // try a fresh candidate. A real error (network, malformed patch) must\n // surface rather than masquerade as a benign claim miss.\n if (!isRevisionConflict(error)) throw error\n return false\n }\n}\n\n/** Invoke a handler, capturing its `outputs` or shaping a thrown error\n * into the `{message, stack?}` envelope `completeEffect` expects. */\nasync function dispatchEffect(\n handler: EffectHandler,\n candidate: PendingEffect,\n ctx: {client: WorkflowClient; instanceId: string; logger: LoggerFactory},\n): Promise<{\n outputs?: Record<string, string | number | boolean | GlobalDocumentReference>\n dispatchError?: {message: string; stack?: string}\n}> {\n try {\n const result = await handler(candidate.params, {\n client: ctx.client,\n instanceId: ctx.instanceId,\n effectKey: candidate._key,\n log: (message, extra) => ctx.logger(`effect.${candidate.effectId}`).info(message, extra),\n })\n return result?.outputs !== undefined ? {outputs: result.outputs} : {}\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n const stack = err instanceof Error && err.stack !== undefined ? err.stack : undefined\n return {dispatchError: stack !== undefined ? {message, stack} : {message}}\n }\n}\n\nasync function applyMissingHandler(\n policy: MissingHandlerPolicy,\n info: MissingHandlerInfo,\n log: EngineLogger,\n): Promise<'fail' | 'skip'> {\n if (policy === 'fail') return 'fail'\n if (policy === 'skip') {\n log.warn(`Missing effect handler \"${info.name}\" — skipping`, {info})\n return 'skip'\n }\n try {\n await policy(info)\n return 'skip'\n } catch {\n return 'fail'\n }\n}\n","import type {WorkflowAccessOverride} from '../access.ts'\nimport type {Clock} from '../clock.ts'\nimport type {WorkflowResource} from '../core/refs.ts'\nimport {type EvaluateArgs, evaluateInstance} from '../evaluate.ts'\nimport {validateTags} from '../tags.ts'\nimport type {MutationGuardDoc} from '../types/authorization.ts'\nimport type {WorkflowClient} from '../types/client.ts'\nimport type {PendingEffect} from '../types/effects.ts'\nimport type {WorkflowInstance} from '../types/instance.ts'\nimport {drainEffectsInternal, verifyDeployedDefinitionsInternal} from './drain.ts'\nimport type {\n CompleteEffectArgs,\n DeployDefinitionsArgs,\n DeployDefinitionsResult,\n DispatchResult,\n DrainEffectsResult,\n EffectHandler,\n EngineLogger,\n FireActionArgs,\n LoggerFactory,\n MissingHandlerPolicy,\n OperationArgs,\n ResourceClientResolver,\n SetStageArgs,\n StartInstanceArgs,\n VerifyDeployedDefinitionsResult,\n} from './types.ts'\nimport {workflow} from './workflow.ts'\n\n// createEngine factory.\n//\n// Pre-binds `client`, `tags`, `workflowResource` (and optional\n// `effectHandlers`, `missingHandler`, `loggerFactory`) so callers don't\n// repeat them on every call. Exposes the same verb surface as the\n// `workflow.*` namespace; the namespace stays for callers that want the\n// raw, unbound functions.\n\nexport interface CreateEngineArgs {\n client: WorkflowClient\n workflowResource: WorkflowResource\n tags: string[]\n /**\n * Optional routing for cross-resource reads. When the engine needs\n * a doc whose GDR points at a resource other than its own, it calls\n * the resolver; if the resolver returns a client, that one is used.\n * Otherwise the engine's default `client` is used (best for\n * single-resource setups — most demos).\n */\n resourceClients?: ResourceClientResolver\n effectHandlers?: Record<string, EffectHandler>\n missingHandler?: MissingHandlerPolicy\n loggerFactory?: LoggerFactory\n /**\n * Deterministic-time seam, pinned once for this engine and threaded\n * into every verb it drives — `$now`, the `now` op-source, and the\n * timestamps the engine stamps all read from it. Omit (the default) to\n * use real wall-clock time; production never sets this. The test bench\n * (`@sanity/workflow-engine-test`) wraps this same seam as `setNow` /\n * `advance`. Deliberately engine-construction config, NOT a per-verb\n * option.\n */\n clock?: Clock\n}\n\ntype Bound<\n Args extends {client: WorkflowClient; tags: string[]; workflowResource: WorkflowResource},\n> = Omit<Args, 'client' | 'tags' | 'workflowResource'>\n\nexport interface Engine {\n /** Engine-scoped bindings — exposed for the few advanced consumers\n * (e.g. test bench, drain workers) that need them; the verbs already\n * thread them through internally. */\n readonly client: WorkflowClient\n readonly tags: readonly string[]\n readonly workflowResource: WorkflowResource\n readonly effectHandlers: Readonly<Record<string, EffectHandler>>\n readonly missingHandler: MissingHandlerPolicy\n readonly logger: LoggerFactory\n\n deployDefinitions: (args: Bound<DeployDefinitionsArgs>) => Promise<DeployDefinitionsResult>\n startInstance: (args: Bound<StartInstanceArgs>) => Promise<WorkflowInstance>\n fireAction: (args: Bound<FireActionArgs>) => Promise<DispatchResult>\n completeEffect: (args: Bound<CompleteEffectArgs>) => Promise<DispatchResult>\n tick: (args: Bound<OperationArgs>) => Promise<DispatchResult>\n evaluateInstance: (args: Bound<EvaluateArgs>) => ReturnType<typeof evaluateInstance>\n\n /** Admin override — bypass filters/transitions and force the stage. */\n setStage: (args: Bound<SetStageArgs>) => Promise<DispatchResult>\n /** Fetch a workflow instance by id. */\n getInstance: (args: {instanceId: string}) => Promise<WorkflowInstance>\n /** Every lake mutation guard this instance registered, unioned across the\n * instance's own resource and the resource of each `doc.ref`/`doc.refs`\n * GDR it holds in state. For coherency refresh and housekeeping. */\n guardsForInstance: (args: {instanceId: string}) => Promise<MutationGuardDoc[]>\n /** Spawned children of a parent instance, optionally filtered by the\n * spawning task. Sorted by `startedAt` asc. */\n children: (args: {instanceId: string; taskId?: string}) => Promise<WorkflowInstance[]>\n /** GROQ query against the engine's workflow resource. `$engineTags`\n * is bound for tag-aware filtering. */\n query: <T = unknown>(args: {groq: string; params?: Record<string, unknown>}) => Promise<T>\n /** Snapshot-aware GROQ — runs against the same in-memory view the\n * engine's filters see for the supplied instance. Reserved params\n * (`$self`, `$subject`, `$ancestors`, `$now`, `$stage`) are bound\n * in GDR URI form to match the snapshot's keying. */\n queryInScope: <T = unknown>(args: {\n instanceId: string\n groq: string\n params?: Record<string, unknown>\n }) => Promise<T>\n /** List every pending effect on an instance. */\n listPendingEffects: (args: {instanceId: string}) => Promise<PendingEffect[]>\n /** Filter pending effects by claimed status and/or effect names. */\n findPendingEffects: (args: {\n instanceId: string\n claimed?: boolean\n names?: string[]\n }) => Promise<PendingEffect[]>\n /** Dispatch unclaimed effects through registered handlers. The\n * drainer's identity defaults to a `{ kind: \"system\", id: \"engine.drainEffects\" }`\n * actor; pass `access` to override (e.g. impersonate a real user\n * whose grants you want the dispatch to respect). */\n drainEffects: (args: {\n instanceId: string\n access?: WorkflowAccessOverride\n }) => Promise<DrainEffectsResult>\n /**\n * Inspect every workflow.definition in the engine's tags and apply\n * the configured missingHandler policy at `phase: \"deploy\"` for any\n * effect name without a registered handler. Catches \"definition\n * shipped, handler removed\" misconfigurations at startup instead of\n * three days later when the effect fires.\n *\n * Returns the list of (definitionId, name, locations) tuples it saw.\n * Throws if missingHandler resolved as \"fail\" for any of them.\n */\n verifyDeployedDefinitions: () => Promise<VerifyDeployedDefinitionsResult>\n}\n\n/**\n * Default LoggerFactory — writes through the global `console`. Exposed\n * so callers outside `createEngine` (drive scripts, the\n * drain-effects helper) can use the same logger shape the engine uses\n * internally. Returns a fresh `EngineLogger` per call; the `name`\n * shows up as a `[name]` prefix on every line.\n */\nexport const defaultLoggerFactory: LoggerFactory = (name) => ({\n // info/warn/error all go to stderr — these are diagnostic, not\n // program output. Keeps stdout reserved for the caller's own data\n // so progress markers (process.stdout.write) and logger lines\n // don't interleave on the same line.\n info: (message, extra) => console.error(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n warn: (message, extra) => console.warn(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n error: (message, extra) =>\n console.error(`[${name}] ${message}`, extra !== undefined ? extra : ''),\n})\n\n/**\n * No-op logger. Default for library callers that don't want any\n * output unless explicitly opted in.\n */\nexport const silentLogger: EngineLogger = {\n info: () => {},\n warn: () => {},\n error: () => {},\n}\n\n/**\n * Construct an engine bound to a workflow resource + tags. The returned\n * object exposes the same verbs as the `workflow.*` namespace, minus\n * the boilerplate config arguments (client / tags / workflowResource)\n * which are pinned at construction.\n *\n * Effect handlers + missingHandler are stored for future drain wiring\n * (Step 10). They have no effect on `fireAction` / `tick` /\n * `completeEffect` today — those still expect the runtime to dispatch\n * effects and report back via `completeEffect`.\n */\nexport function createEngine(args: CreateEngineArgs): Engine {\n const {client, workflowResource, tags, resourceClients, clock} = args\n validateTags(tags)\n const effectHandlers = args.effectHandlers ?? {}\n const missingHandler = args.missingHandler ?? 'fail'\n const logger = args.loggerFactory ?? defaultLoggerFactory\n\n const bind = <\n A extends {client: WorkflowClient; tags: string[]; workflowResource: WorkflowResource},\n >(\n rest: Omit<A, 'client' | 'tags' | 'workflowResource'>,\n ): A =>\n ({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n ...(clock !== undefined ? {clock} : {}),\n ...rest,\n }) as A\n\n return {\n client,\n tags,\n workflowResource,\n effectHandlers,\n missingHandler,\n logger,\n deployDefinitions: (rest) => workflow.deployDefinitions(bind<DeployDefinitionsArgs>(rest)),\n startInstance: (rest) => workflow.startInstance(bind<StartInstanceArgs>(rest)),\n fireAction: (rest) => workflow.fireAction(bind<FireActionArgs>(rest)),\n completeEffect: (rest) => workflow.completeEffect(bind<CompleteEffectArgs>(rest)),\n tick: (rest) => workflow.tick(bind<OperationArgs>(rest)),\n evaluateInstance: (rest) => evaluateInstance(bind<EvaluateArgs>(rest)),\n\n setStage: (rest) => workflow.setStage(bind<SetStageArgs>(rest)),\n getInstance: ({instanceId}) =>\n workflow.getInstance({client, tags, workflowResource, instanceId}),\n guardsForInstance: ({instanceId}) =>\n workflow.guardsForInstance({\n client,\n tags,\n workflowResource,\n instanceId,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n }),\n children: ({instanceId, taskId}) =>\n workflow.children({\n client,\n tags,\n workflowResource,\n instanceId,\n ...(taskId !== undefined ? {taskId} : {}),\n }),\n query: ({groq, params}) =>\n workflow.query({\n client,\n tags,\n workflowResource,\n groq,\n ...(params !== undefined ? {params} : {}),\n }),\n queryInScope: ({instanceId, groq, params}) =>\n workflow.queryInScope({\n client,\n tags,\n workflowResource,\n instanceId,\n groq,\n ...(params !== undefined ? {params} : {}),\n ...(clock !== undefined ? {clock} : {}),\n }),\n listPendingEffects: ({instanceId}) =>\n workflow.listPendingEffects({client, tags, workflowResource, instanceId}),\n findPendingEffects: ({instanceId, claimed, names}) =>\n workflow.findPendingEffects({\n client,\n tags,\n workflowResource,\n instanceId,\n ...(claimed !== undefined ? {claimed} : {}),\n ...(names !== undefined ? {names} : {}),\n }),\n drainEffects: ({instanceId, access}) =>\n drainEffectsInternal({\n client,\n tags,\n workflowResource,\n ...(resourceClients !== undefined ? {resourceClients} : {}),\n instanceId,\n effectHandlers,\n missingHandler,\n logger,\n ...(access !== undefined ? {access} : {}),\n }),\n verifyDeployedDefinitions: () =>\n verifyDeployedDefinitionsInternal({\n client,\n tags,\n effectHandlers,\n missingHandler,\n logger,\n }),\n }\n}\n","/**\n * Display metadata for every `workflow.*` `_type` literal the engine\n * persists (history entries, state-slot kinds, ops, effects-context\n * entry kinds, authoring-shape discriminators). Each entry exposes\n *\n * - `title` — short label for chips, badges, headings\n * - `description` — longer prose for tooltips / inspector panes\n *\n * UIs that render a workflow.instance audit log should NEVER show\n * `workflow.history.transitionFired` raw — they look it up here and\n * render `\"Transition fired\"` instead.\n *\n * Stable, additive surface: adding a new `_type` to the engine must\n * also add an entry here.\n */\n\nexport interface DisplayMetadata {\n readonly title: string\n readonly description: string\n}\n\n/**\n * History-entry `_type` discriminators. Order roughly matches the\n * order a typical run produces them in a single fire-action commit.\n */\nexport const HISTORY_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.history.stageEntered': {\n title: 'Stage entered',\n description: 'The instance crossed into a new stage.',\n },\n 'workflow.history.stageExited': {\n title: 'Stage exited',\n description: 'The instance left a stage on the way to the next one.',\n },\n 'workflow.history.taskActivated': {\n title: 'Task activated',\n description: 'A task flipped from `pending` to `active` and its onEnter effects queued.',\n },\n 'workflow.history.taskStatusChanged': {\n title: 'Task status changed',\n description: \"An action or op flipped a task's status (active → done / skipped / failed).\",\n },\n 'workflow.history.actionFired': {\n title: 'Action fired',\n description:\n 'An action was invoked against a task — ops ran, status may have flipped, effects queued.',\n },\n 'workflow.history.transitionFired': {\n title: 'Transition fired',\n description: 'A transition committed and the instance moved to a new stage.',\n },\n 'workflow.history.effectQueued': {\n title: 'Effect queued',\n description: 'A pending effect was added to the queue, waiting for a drainer to dispatch it.',\n },\n 'workflow.history.effectCompleted': {\n title: 'Effect completed',\n description:\n 'A drainer ran an effect handler to completion (done or failed) and merged its outputs into effectsContext.',\n },\n 'workflow.history.spawned': {\n title: 'Spawned child',\n description: 'A `task.spawns` declaration spawned a child workflow instance.',\n },\n 'workflow.history.opApplied': {\n title: 'Op applied',\n description:\n 'An inline state-mutation op (state.set / state.append / status.set / etc.) ran during an action commit.',\n },\n}\n\n/**\n * State-slot `_type` discriminators. The slot's variant defines what\n * shape `value` takes (single GDR vs array, scalar vs notes log).\n */\nexport const STATE_SLOT_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.state.doc.ref': {\n title: 'Document reference',\n description: 'Single GDR pointer at a document in this or another resource.',\n },\n 'workflow.state.doc.refs': {\n title: 'Document references',\n description: 'Ordered list of GDR pointers — multi-doc selection.',\n },\n 'workflow.state.query': {\n title: 'Query result',\n description:\n 'Snapshot of a GROQ projection captured at slot-resolve time; resolvedAt is stamped on the value.',\n },\n 'workflow.state.value.string': {\n title: 'String value',\n description: 'Free-form string slot.',\n },\n 'workflow.state.value.url': {\n title: 'URL value',\n description: 'Validated URL slot.',\n },\n 'workflow.state.value.number': {\n title: 'Number value',\n description: 'Numeric slot.',\n },\n 'workflow.state.value.boolean': {\n title: 'Boolean value',\n description: 'True/false slot.',\n },\n 'workflow.state.value.dateTime': {\n title: 'Date / time value',\n description: 'ISO-timestamp slot.',\n },\n 'workflow.state.checklist': {\n title: 'Checklist',\n description: 'Append-only list of checkable items; ops add/update/remove entries.',\n },\n 'workflow.state.notes': {\n title: 'Notes log',\n description: 'Append-only structured-note log (signoffs, comments, audit rows).',\n },\n 'workflow.state.assignees': {\n title: 'Assignees',\n description: 'Ordered list of typed (user|role) assignees.',\n },\n}\n\n/**\n * Op `_type` discriminators.\n */\nexport const OP_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.op.state.set': {\n title: 'Set slot',\n description: \"Overwrite a state slot's value with a resolved Source.\",\n },\n 'workflow.op.state.append': {\n title: 'Append to slot',\n description:\n 'Push a resolved item onto an array-typed slot (notes, checklist, assignees, refs).',\n },\n 'workflow.op.state.updateWhere': {\n title: 'Update matching rows',\n description: 'Merge fields into rows of an array-typed slot that match the predicate.',\n },\n 'workflow.op.state.removeWhere': {\n title: 'Remove matching rows',\n description: 'Drop rows of an array-typed slot that match the predicate.',\n },\n 'workflow.op.status.set': {\n title: 'Set task status',\n description: \"Flip a task's status explicitly (action.setStatus is the more common path).\",\n },\n}\n\n/**\n * EffectsContext entry kinds.\n */\nexport const EFFECTS_CONTEXT_DISPLAY: Record<string, DisplayMetadata> = {\n 'effectsContext.string': {\n title: 'String',\n description: 'Stable string parameter for effect handlers.',\n },\n 'effectsContext.number': {\n title: 'Number',\n description: 'Stable numeric parameter for effect handlers.',\n },\n 'effectsContext.boolean': {\n title: 'Boolean',\n description: 'Stable boolean parameter for effect handlers.',\n },\n 'effectsContext.ref': {\n title: 'GDR reference',\n description: 'Stable GDR pointer parameter for effect handlers.',\n },\n 'effectsContext.json': {\n title: 'JSON',\n description: 'Stable JSON payload for effect handlers.',\n },\n}\n\n/**\n * Authoring-shape discriminators (used when declaring a workflow).\n */\nexport const AUTHORING_DISPLAY: Record<string, DisplayMetadata> = {\n 'workflow.stage': {\n title: 'Stage',\n description: 'A bucket of tasks the workflow is currently in.',\n },\n 'workflow.task': {\n title: 'Task',\n description: 'A unit of work inside a stage; carries actions and may spawn children.',\n },\n 'workflow.action': {\n title: 'Action',\n description: 'An invocable transition on a task — runs ops, queues effects, may flip status.',\n },\n 'workflow.action.param': {\n title: 'Action param',\n description: 'Caller-supplied parameter on an action; validated before any commit.',\n },\n 'workflow.transition': {\n title: 'Transition',\n description: 'An edge between stages, gated by a filter.',\n },\n 'workflow.predicate': {\n title: 'Predicate',\n description: 'Named GROQ filter, reusable across transitions / tasks / actions.',\n },\n 'workflow.effect': {\n title: 'Effect',\n description:\n 'Externally-dispatched side effect; queued on commit, drained by a runtime, completed asynchronously.',\n },\n 'workflow.spawn': {\n title: 'Spawn',\n description: 'Declares a task that fans out one or more child workflow instances.',\n },\n 'workflow.pendingEffect': {\n title: 'Pending effect',\n description: 'An effect that has been queued but not yet dispatched.',\n },\n 'workflow.pendingEffect.claim': {\n title: 'Claim',\n description: \"A drainer's lock on a pending effect while it dispatches.\",\n },\n 'workflow.definition': {\n title: 'Workflow definition',\n description: 'An immutable workflow blueprint pinned by `workflowId` + `version`.',\n },\n 'workflow.instance': {\n title: 'Workflow instance',\n description: 'A running (or finished) workflow against a subject.',\n },\n}\n\n/**\n * Single combined map for callers that don't care which family the\n * key belongs to (e.g. an audit row showing any `_type`).\n */\nexport const DISPLAY: Record<string, DisplayMetadata> = {\n ...HISTORY_DISPLAY,\n ...STATE_SLOT_DISPLAY,\n ...OP_DISPLAY,\n ...EFFECTS_CONTEXT_DISPLAY,\n ...AUTHORING_DISPLAY,\n}\n\n/**\n * Lookup helper. Returns a friendly title for any known `_type`, or\n * the original key when unknown so UIs degrade gracefully.\n */\nexport function displayTitle(typeKey: string | undefined): string {\n if (!typeKey) return ''\n return DISPLAY[typeKey]?.title ?? typeKey\n}\n\n/**\n * Same idea but returns the description, or undefined when unknown.\n */\nexport function displayDescription(typeKey: string | undefined): string | undefined {\n if (!typeKey) return undefined\n return DISPLAY[typeKey]?.description\n}\n"],"names":["v","parseGroq","tree","parse","evaluate","gdrUri","doc","randomKey","slotValue","policy","engineInvokeTask","engineFireAction","engineCompleteEffect","engineSetStage","queryGuardsForInstance","evaluateGroq"],"mappings":"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"}