@sanity/workflow-engine 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/define.d.ts CHANGED
@@ -1987,6 +1987,17 @@ declare const AuthoringStageSchema: v.StrictObjectSchema<
1987
1987
  v.StringSchema<undefined>,
1988
1988
  undefined
1989
1989
  >;
1990
+ /**
1991
+ * When true, the caller MUST supply this entry at start (via
1992
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
1993
+ * missing required entry throws rather than silently defaulting to
1994
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
1995
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
1996
+ */
1997
+ readonly required: v.OptionalSchema<
1998
+ v.BooleanSchema<undefined>,
1999
+ undefined
2000
+ >;
1990
2001
  readonly source: v.GenericSchema<SourceInternal>;
1991
2002
  },
1992
2003
  undefined
@@ -2536,6 +2547,17 @@ declare const AuthoringStageSchema: v.StrictObjectSchema<
2536
2547
  v.StringSchema<undefined>,
2537
2548
  undefined
2538
2549
  >;
2550
+ /**
2551
+ * When true, the caller MUST supply this entry at start (via
2552
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
2553
+ * missing required entry throws rather than silently defaulting to
2554
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
2555
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
2556
+ */
2557
+ readonly required: v.OptionalSchema<
2558
+ v.BooleanSchema<undefined>,
2559
+ undefined
2560
+ >;
2539
2561
  readonly source: v.GenericSchema<SourceInternal>;
2540
2562
  },
2541
2563
  undefined
@@ -2605,6 +2627,17 @@ declare const AuthoringStateEntrySchema: v.UnionSchema<
2605
2627
  v.StringSchema<undefined>,
2606
2628
  undefined
2607
2629
  >;
2630
+ /**
2631
+ * When true, the caller MUST supply this entry at start (via
2632
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
2633
+ * missing required entry throws rather than silently defaulting to
2634
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
2635
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
2636
+ */
2637
+ readonly required: v.OptionalSchema<
2638
+ v.BooleanSchema<undefined>,
2639
+ undefined
2640
+ >;
2608
2641
  readonly source: v.GenericSchema<SourceInternal>;
2609
2642
  },
2610
2643
  undefined
@@ -3749,6 +3782,17 @@ declare const AuthoringTaskSchema: v.StrictObjectSchema<
3749
3782
  v.StringSchema<undefined>,
3750
3783
  undefined
3751
3784
  >;
3785
+ /**
3786
+ * When true, the caller MUST supply this entry at start (via
3787
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
3788
+ * missing required entry throws rather than silently defaulting to
3789
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
3790
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
3791
+ */
3792
+ readonly required: v.OptionalSchema<
3793
+ v.BooleanSchema<undefined>,
3794
+ undefined
3795
+ >;
3752
3796
  readonly source: v.GenericSchema<SourceInternal>;
3753
3797
  },
3754
3798
  undefined
@@ -4111,6 +4155,22 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
4111
4155
  ]
4112
4156
  >;
4113
4157
  description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
4158
+ /**
4159
+ * Whether a human may start this workflow standalone. `'child'` marks a
4160
+ * spawn-only definition — instantiated by a parent via `task.subworkflows`,
4161
+ * never started cold from a picker. Omitted ⇒ `'workflow'` (startable).
4162
+ * Advisory: consumers filter their start pickers on it (see
4163
+ * {@link isStartableDefinition}); the engine does NOT refuse a
4164
+ * `startInstance` on a `'child'` def — load-bearing `required` state is the
4165
+ * runtime backstop.
4166
+ */
4167
+ role: v.OptionalSchema<
4168
+ v.PicklistSchema<
4169
+ readonly ["workflow", "child"],
4170
+ `Invalid option: expected one of ${string}`
4171
+ >,
4172
+ undefined
4173
+ >;
4114
4174
  /** Reference field: named for the target, holds the stage's `name`. */
4115
4175
  initialStage: v.SchemaWithPipe<
4116
4176
  readonly [
@@ -4157,6 +4217,17 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
4157
4217
  v.StringSchema<undefined>,
4158
4218
  undefined
4159
4219
  >;
4220
+ /**
4221
+ * When true, the caller MUST supply this entry at start (via
4222
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
4223
+ * missing required entry throws rather than silently defaulting to
4224
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
4225
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
4226
+ */
4227
+ readonly required: v.OptionalSchema<
4228
+ v.BooleanSchema<undefined>,
4229
+ undefined
4230
+ >;
4160
4231
  readonly source: v.GenericSchema<SourceInternal>;
4161
4232
  },
4162
4233
  undefined
@@ -5485,6 +5556,17 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
5485
5556
  v.StringSchema<undefined>,
5486
5557
  undefined
5487
5558
  >;
5559
+ /**
5560
+ * When true, the caller MUST supply this entry at start (via
5561
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
5562
+ * missing required entry throws rather than silently defaulting to
5563
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
5564
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
5565
+ */
5566
+ readonly required: v.OptionalSchema<
5567
+ v.BooleanSchema<undefined>,
5568
+ undefined
5569
+ >;
5488
5570
  readonly source: v.GenericSchema<SourceInternal>;
5489
5571
  },
5490
5572
  undefined
@@ -6097,6 +6179,17 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
6097
6179
  v.StringSchema<undefined>,
6098
6180
  undefined
6099
6181
  >;
6182
+ /**
6183
+ * When true, the caller MUST supply this entry at start (via
6184
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
6185
+ * missing required entry throws rather than silently defaulting to
6186
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
6187
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
6188
+ */
6189
+ readonly required: v.OptionalSchema<
6190
+ v.BooleanSchema<undefined>,
6191
+ undefined
6192
+ >;
6100
6193
  readonly source: v.GenericSchema<SourceInternal>;
6101
6194
  },
6102
6195
  undefined
@@ -6468,6 +6561,7 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
6468
6561
  name: string;
6469
6562
  title?: string | undefined;
6470
6563
  description?: string | undefined;
6564
+ required?: boolean | undefined;
6471
6565
  source: SourceInternal;
6472
6566
  }
6473
6567
  | {
@@ -6609,6 +6703,7 @@ declare const AuthoringWorkflowSchema: v.StrictObjectSchema<
6609
6703
  name: string;
6610
6704
  title?: string | undefined;
6611
6705
  description?: string | undefined;
6706
+ required?: boolean | undefined;
6612
6707
  source: SourceInternal;
6613
6708
  }
6614
6709
  | {
@@ -6973,6 +7068,22 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
6973
7068
  ]
6974
7069
  >;
6975
7070
  description: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
7071
+ /**
7072
+ * Whether a human may start this workflow standalone. `'child'` marks a
7073
+ * spawn-only definition — instantiated by a parent via `task.subworkflows`,
7074
+ * never started cold from a picker. Omitted ⇒ `'workflow'` (startable).
7075
+ * Advisory: consumers filter their start pickers on it (see
7076
+ * {@link isStartableDefinition}); the engine does NOT refuse a
7077
+ * `startInstance` on a `'child'` def — load-bearing `required` state is the
7078
+ * runtime backstop.
7079
+ */
7080
+ role: v.OptionalSchema<
7081
+ v.PicklistSchema<
7082
+ readonly ["workflow", "child"],
7083
+ `Invalid option: expected one of ${string}`
7084
+ >,
7085
+ undefined
7086
+ >;
6976
7087
  /** Reference field: named for the target, holds the stage's `name`. */
6977
7088
  initialStage: v.SchemaWithPipe<
6978
7089
  readonly [
@@ -7017,6 +7128,17 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
7017
7128
  v.StringSchema<undefined>,
7018
7129
  undefined
7019
7130
  >;
7131
+ /**
7132
+ * When true, the caller MUST supply this entry at start (via
7133
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
7134
+ * missing required entry throws rather than silently defaulting to
7135
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
7136
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
7137
+ */
7138
+ readonly required: v.OptionalSchema<
7139
+ v.BooleanSchema<undefined>,
7140
+ undefined
7141
+ >;
7020
7142
  readonly source: v.GenericSchema<SourceInternal>;
7021
7143
  },
7022
7144
  undefined
@@ -7901,6 +8023,17 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
7901
8023
  v.StringSchema<undefined>,
7902
8024
  undefined
7903
8025
  >;
8026
+ /**
8027
+ * When true, the caller MUST supply this entry at start (via
8028
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
8029
+ * missing required entry throws rather than silently defaulting to
8030
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
8031
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
8032
+ */
8033
+ readonly required: v.OptionalSchema<
8034
+ v.BooleanSchema<undefined>,
8035
+ undefined
8036
+ >;
7904
8037
  readonly source: v.GenericSchema<SourceInternal>;
7905
8038
  },
7906
8039
  undefined
@@ -8377,6 +8510,17 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
8377
8510
  v.StringSchema<undefined>,
8378
8511
  undefined
8379
8512
  >;
8513
+ /**
8514
+ * When true, the caller MUST supply this entry at start (via
8515
+ * `initialState`) or spawn (via the parent's `subworkflows.with`). A
8516
+ * missing required entry throws rather than silently defaulting to
8517
+ * `null`/`[]` — the same fail-fast an action's `required` param gets.
8518
+ * Valid only on a workflow-scope `init`-sourced entry (deploy invariant).
8519
+ */
8520
+ readonly required: v.OptionalSchema<
8521
+ v.BooleanSchema<undefined>,
8522
+ undefined
8523
+ >;
8380
8524
  readonly source: v.GenericSchema<SourceInternal>;
8381
8525
  },
8382
8526
  undefined
@@ -8615,6 +8759,7 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
8615
8759
  name: string;
8616
8760
  title?: string | undefined;
8617
8761
  description?: string | undefined;
8762
+ required?: boolean | undefined;
8618
8763
  source: SourceInternal;
8619
8764
  }[]
8620
8765
  | undefined;
@@ -8734,6 +8879,7 @@ declare const WorkflowDefinitionSchema: v.StrictObjectSchema<
8734
8879
  name: string;
8735
8880
  title?: string | undefined;
8736
8881
  description?: string | undefined;
8882
+ required?: boolean | undefined;
8737
8883
  source: SourceInternal;
8738
8884
  }[]
8739
8885
  | undefined;
package/dist/define.js CHANGED
@@ -41,6 +41,7 @@ function desugarWorkflow(authoring) {
41
41
  version: authoring.version,
42
42
  title: authoring.title,
43
43
  description: authoring.description,
44
+ role: authoring.role,
44
45
  initialStage: authoring.initialStage,
45
46
  predicates: authoring.predicates
46
47
  }),
@@ -346,22 +347,37 @@ function checkGuardNames(def, issues) {
346
347
  );
347
348
  }
348
349
  function stateScopes(def) {
349
- const scopes = [{ entries: def.state, path: ["state"], label: "workflow state" }];
350
+ const scopes = [
351
+ { entries: def.state, scope: "workflow", path: ["state"], label: "workflow state" }
352
+ ];
350
353
  for (const [i, stage] of def.stages.entries()) {
351
354
  scopes.push({
352
355
  entries: stage.state,
356
+ scope: "stage",
353
357
  path: ["stages", i, "state"],
354
358
  label: `stage "${stage.name}" state`
355
359
  });
356
360
  for (const [j, task] of (stage.tasks ?? []).entries())
357
361
  scopes.push({
358
362
  entries: task.state,
363
+ scope: "task",
359
364
  path: ["stages", i, "tasks", j, "state"],
360
365
  label: `task "${task.name}" state`
361
366
  });
362
367
  }
363
368
  return scopes;
364
369
  }
370
+ function checkRequiredState(def, issues) {
371
+ for (const { entries, scope, path, label } of stateScopes(def))
372
+ for (const [n, entry] of (entries ?? []).entries())
373
+ entry.required === !0 && (scope !== "workflow" ? issues.push({
374
+ path: [...path, n, "required"],
375
+ message: `${label} entry "${entry.name}" is \`required\`, but \`required\` applies only to workflow-scope \`init\` entries \u2014 only those are caller-supplied at start/spawn`
376
+ }) : entry.source.type !== "init" && issues.push({
377
+ path: [...path, n, "required"],
378
+ message: `state entry "${entry.name}" is \`required\` but its source is "${entry.source.type}" \u2014 \`required\` applies only to \`init\`-sourced entries (the caller fills them at start/spawn)`
379
+ }));
380
+ }
365
381
  function checkStateEntryNames(def, issues) {
366
382
  for (const { entries, path, label } of stateScopes(def))
367
383
  checkDuplicates(
@@ -474,7 +490,7 @@ function checkAssigneesEntries(def, issues) {
474
490
  }
475
491
  function checkWorkflowInvariants(def) {
476
492
  const issues = [], stageNames = checkStages(def, issues);
477
- return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues), checkStateEntryNames(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), issues;
493
+ return checkInitialStage(def, stageNames, issues), checkTransitionTargets(def, stageNames, issues), checkEffectNames(def, issues), checkGuardNames(def, issues), checkStateEntryNames(def, issues), checkRequiredState(def, issues), checkPredicates(def, issues), checkCanOutsideActionFilters(def, issues), checkAssigneesEntries(def, issues), issues;
478
494
  }
479
495
  function defineWorkflow(definition) {
480
496
  const label = labelFor("defineWorkflow", definition), parsed = parseOrThrow(AuthoringWorkflowSchema, definition, label), { definition: stored, issues: desugarIssues } = desugarWorkflow(parsed), issues = [...desugarIssues, ...checkWorkflowInvariants(stored)];
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sources":["../src/define/groq.ts","../src/define/desugar.ts","../src/define/invariants.ts","../src/define/index.ts"],"sourcesContent":["/**\n * Hygienic GROQ interpolation for define-time condition building.\n *\n * Parameterized predicate reuse lives in the host language — a TypeScript\n * function producing a condition string — and this tag is its safe splice:\n * interpolated *values* serialize as GROQ literals (JSON literal syntax is\n * valid GROQ), never as raw query text, so quoting and precedence cannot\n * break. The produced string is stored as a plain condition and validated at\n * deploy like any other.\n *\n * ```ts\n * const regulated = (kinds: string[]) => groq`$state.subject.category in ${kinds}`\n * defineTask({ name: \"legal\", filter: regulated([\"finance\", \"health\"]), … })\n * ```\n */\nexport function groq(strings: TemplateStringsArray, ...values: unknown[]): string {\n return strings.reduce((out, part, i) => {\n if (i === 0) return part\n return `${out}${serializeGroqValue(values[i - 1])}${part}`\n }, '')\n}\n\nfunction serializeGroqValue(value: unknown): string {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) {\n throw new Error(\n `groq tag cannot serialize ${typeof value} — interpolate JSON-representable values only`,\n )\n }\n return serialized\n}\n","/**\n * Define-time expansion: authoring input (primitives + sugar) → the stored\n * definition (primitives only). Storage never sees a sugar type.\n *\n * Every expansion is strictly **in-bounds** — confined to the node that\n * declares it. A pattern that spans nodes (the `claim` state/action pair) is\n * tied by an ordinary deploy-checked *reference*, never by creation: sugar\n * never adds a state entry, an action, or anything else outside its node, so\n * the authored arrays remain the complete inventory of the definition.\n *\n * Reference scopes resolve **lexically** here — most-local outward\n * (task → stage → workflow), like variable lookup — so every stored op\n * TARGET carries an explicit `scope` the runtime never re-resolves.\n * `Source.stateRead` VALUES are different: their `scope` stays optional in\n * the stored form, and an omitted scope resolves lexically at read time.\n */\n\nimport {groq} from './groq.ts'\nimport type {\n Action,\n AuthoringAction,\n AuthoringOp,\n AuthoringStateEntry,\n AuthoringStateRef,\n AuthoringTask,\n AuthoringTransition,\n AuthoringWorkflow,\n IssuePath,\n Op,\n Source,\n StateEntry,\n StoredStateRef,\n Task,\n Transition,\n TransitionOp,\n ValidationIssue,\n WorkflowDefinition,\n} from './schema.ts'\n\n/** One lexical layer: the state entries declared at a scope, by name. */\ntype ScopeLayer = ReadonlyMap<string, StateEntry>\n\n/**\n * The lexical environment a reference resolves in: innermost first. A task's\n * ops see task → stage → workflow; a transition's ops see stage → workflow\n * (the stage's tasks are tearing down when a transition fires).\n */\ninterface LexicalEnv {\n layers: readonly {scope: 'workflow' | 'stage' | 'task'; entries: ScopeLayer}[]\n}\n\ninterface DesugarResult {\n definition: WorkflowDefinition\n issues: ValidationIssue[]\n}\n\ninterface Ctx {\n issues: ValidationIssue[]\n /**\n * Entries declared via the `claim` sugar type, keyed by the desugared\n * entry object (the same object the lexical layers hand back), so pairing\n * is exact per declaration — never by bare name across scopes.\n */\n claimStates: Map<StateEntry, {name: string; path: IssuePath}>\n /** Claim-state entries that at least one `claim` action resolved to — pair validation. */\n claimedStates: Set<StateEntry>\n}\n\nexport function desugarWorkflow(authoring: AuthoringWorkflow): DesugarResult {\n const ctx: Ctx = {issues: [], claimStates: new Map(), claimedStates: new Set()}\n\n const workflowState = desugarStateEntries(authoring.state, ['state'], ctx)\n const workflowLayer = layerOf(workflowState)\n\n const stages = authoring.stages.map((stage, i) => {\n const path: IssuePath = ['stages', i]\n const stageState = desugarStateEntries(stage.state, [...path, 'state'], ctx)\n const stageEnv: LexicalEnv = {\n layers: [\n {scope: 'stage', entries: layerOf(stageState)},\n {scope: 'workflow', entries: workflowLayer},\n ],\n }\n const tasks = (stage.tasks ?? []).map((task, j) =>\n desugarTask(task, [...path, 'tasks', j], stageEnv, ctx),\n )\n const transitions = (stage.transitions ?? []).map((transition, k) =>\n desugarTransition(transition, [...path, 'transitions', k], stageEnv, ctx),\n )\n return {\n ...stripUndefined({\n name: stage.name,\n title: stage.title,\n description: stage.description,\n guards: stage.guards,\n }),\n ...(stageState ? {state: stageState} : {}),\n ...(tasks.length > 0 ? {tasks} : {}),\n ...(transitions.length > 0 ? {transitions} : {}),\n }\n })\n\n checkUnclaimedClaimStates(ctx)\n\n const definition = {\n ...stripUndefined({\n name: authoring.name,\n version: authoring.version,\n title: authoring.title,\n description: authoring.description,\n initialStage: authoring.initialStage,\n predicates: authoring.predicates,\n }),\n ...(workflowState ? {state: workflowState} : {}),\n stages,\n } as WorkflowDefinition\n\n return {definition, issues: ctx.issues}\n}\n\n// State entries — the `claim` sugar expands to value.actor with an implied\n// `write` source, strictly within the entry.\n\nfunction desugarStateEntries(\n entries: readonly AuthoringStateEntry[] | undefined,\n path: IssuePath,\n ctx: Ctx,\n): StateEntry[] | undefined {\n if (!entries || entries.length === 0) return entries === undefined ? undefined : []\n return entries.map((entry, i) => {\n if (entry.type !== 'claim') return entry\n const desugared = {\n ...stripUndefined({name: entry.name, title: entry.title, description: entry.description}),\n type: 'value.actor',\n source: {type: 'write'},\n } as StateEntry\n ctx.claimStates.set(desugared, {name: entry.name, path: [...path, i]})\n return desugared\n })\n}\n\nfunction layerOf(entries: readonly StateEntry[] | undefined): ScopeLayer {\n return new Map((entries ?? []).map((entry) => [entry.name, entry]))\n}\n\n// Tasks — activation defaults to `manual` (a task never activates silently;\n// \"auto\" is the explicit opt-in), ops resolve in the task's lexical env, and\n// each action expands within itself.\n\nfunction desugarTask(task: AuthoringTask, path: IssuePath, stageEnv: LexicalEnv, ctx: Ctx): Task {\n const taskState = desugarStateEntries(task.state, [...path, 'state'], ctx)\n const env: LexicalEnv = {\n layers: [{scope: 'task', entries: layerOf(taskState)}, ...stageEnv.layers],\n }\n const ops = desugarOps(task.ops, [...path, 'ops'], env, task.name, ctx)\n const actions = (task.actions ?? []).map((action, a) =>\n desugarAction(action, [...path, 'actions', a], env, task.name, ctx),\n )\n return {\n ...stripUndefined({\n name: task.name,\n title: task.title,\n description: task.description,\n filter: task.filter,\n requirements: task.requirements,\n completeWhen: task.completeWhen,\n failWhen: task.failWhen,\n effects: task.effects,\n subworkflows: task.subworkflows,\n }),\n activation: task.activation ?? 'manual',\n ...(taskState ? {state: taskState} : {}),\n ...(ops ? {ops} : {}),\n ...(actions.length > 0 ? {actions} : {}),\n } as Task\n}\n\n// Actions — the `claim` sugar type and the `roles` / `status` field sugars.\n\nfunction desugarAction(\n action: AuthoringAction,\n path: IssuePath,\n env: LexicalEnv,\n taskName: string,\n ctx: Ctx,\n): Action {\n // Only the claim sugar variant carries a `type` — raw actions have none.\n if ('type' in action) {\n return desugarClaimAction(action, path, env, ctx)\n }\n\n const filter = composeFilter([rolesCondition(action.roles), action.filter])\n const ops = desugarOps(action.ops, [...path, 'ops'], env, taskName, ctx) ?? []\n if (action.status !== undefined) {\n // Appended AFTER the authored ops — the expansion has a defined position.\n ops.push({type: 'status.set', task: taskName, status: action.status})\n }\n return {\n ...stripUndefined({\n name: action.name,\n title: action.title,\n description: action.description,\n params: action.params,\n effects: action.effects,\n }),\n ...(filter ? {filter} : {}),\n ...(ops.length > 0 ? {ops} : {}),\n } as Action\n}\n\nfunction desugarClaimAction(\n action: Extract<AuthoringAction, {type: 'claim'}>,\n path: IssuePath,\n env: LexicalEnv,\n ctx: Ctx,\n): Action {\n const ref = typeof action.state === 'string' ? {state: action.state} : action.state\n const resolved = resolveRef(ref, env, [...path, 'state'], ctx)\n if (resolved) {\n const entry = entryAt(env, resolved)\n if (entry && entry.type !== 'value.actor') {\n ctx.issues.push({\n path: [...path, 'state'],\n message:\n `claim action \"${action.name}\" references \"${resolved.state}\" of kind ` +\n `\"${entry.type}\" — a claim pair needs an actor-valued entry ` +\n `(a \"claim\" or \"value.actor\" state declaration)`,\n })\n }\n checkShadowedClaimTarget(action.name, ref.state, resolved, env, [...path, 'state'], ctx)\n if (entry) ctx.claimedStates.add(entry)\n }\n\n const noSteal = `!defined($state.${ref.state})`\n const filter = composeFilter([noSteal, rolesCondition(action.roles), action.filter])\n const ops: Op[] = resolved ? [{type: 'state.set', target: resolved, value: {type: 'actor'}}] : []\n return {\n ...stripUndefined({\n name: action.name,\n title: action.title,\n description: action.description,\n params: action.params,\n effects: action.effects,\n }),\n filter,\n ...(ops.length > 0 ? {ops} : {}),\n } as Action\n}\n\n/**\n * The claim action's two halves must address ONE entry: the no-steal filter\n * reads `$state.<name>` (nearest declaring scope wins in the rendered\n * overlay), while the `state.set` op writes the resolved ref. An explicit\n * `scope:` that lands on an entry lexically shadowed at the action's\n * position would split them — the filter checks the shadowing entry, the\n * op claims the shadowed one — so that is a define-time error.\n */\nfunction checkShadowedClaimTarget(\n actionName: string,\n state: string,\n resolved: StoredStateRef,\n env: LexicalEnv,\n path: IssuePath,\n ctx: Ctx,\n): void {\n const nearest = env.layers.find((l) => l.entries.has(state))\n if (nearest === undefined || nearest.scope === resolved.scope) return\n ctx.issues.push({\n path,\n message:\n `claim action \"${actionName}\" targets \"${state}\" at scope \"${resolved.scope}\", but a ` +\n `nearer ${nearest.scope}-scope entry of the same name shadows it in $state — the ` +\n `no-steal filter would read the shadowing entry while the claim writes the ` +\n `\"${resolved.scope}\" one. Rename one of the entries or claim the nearer one`,\n })\n}\n\n/** Pair validation, the other direction: a `claim` state nothing claims into. */\nfunction checkUnclaimedClaimStates(ctx: Ctx): void {\n for (const [entry, {name, path}] of ctx.claimStates) {\n if (ctx.claimedStates.has(entry)) continue\n ctx.issues.push({\n path,\n message:\n `claim state \"${name}\" is never referenced by a claim action — ` +\n `you announced the pattern and wrote half of it. Declare a ` +\n `defineAction({ type: \"claim\", state: \"${name}\" }) or use a raw value.actor entry`,\n })\n }\n}\n\n// Transitions — an omitted filter desugars to the safe, dominant gate.\n// The lexical env for transition ops skips the task layer: the stage's tasks\n// are tearing down when a transition fires.\n\nfunction desugarTransition(\n transition: AuthoringTransition,\n path: IssuePath,\n stageEnv: LexicalEnv,\n ctx: Ctx,\n): Transition {\n const ops = desugarOps(transition.ops, [...path, 'ops'], stageEnv, undefined, ctx)\n return {\n ...stripUndefined({\n name: transition.name,\n title: transition.title,\n description: transition.description,\n to: transition.to,\n effects: transition.effects,\n }),\n filter: transition.filter ?? '$allTasksDone',\n ...(ops ? {ops: ops as TransitionOp[]} : {}),\n } as Transition\n}\n\n// Ops — the `audit` sugar (a stamped append, in-bounds: it only touches its\n// own value) plus lexical target resolution and the firing-task default on\n// `status.set`.\n\nfunction desugarOps(\n ops: readonly AuthoringOp[] | undefined,\n path: IssuePath,\n env: LexicalEnv,\n firingTask: string | undefined,\n ctx: Ctx,\n): Op[] | undefined {\n if (!ops) return undefined\n return ops.map((op, i) => desugarOp(op, [...path, i], env, firingTask, ctx))\n}\n\nfunction desugarOp(\n op: AuthoringOp,\n path: IssuePath,\n env: LexicalEnv,\n firingTask: string | undefined,\n ctx: Ctx,\n): Op {\n if (op.type === 'status.set') {\n const task = op.task ?? firingTask\n if (task === undefined) {\n ctx.issues.push({\n path: [...path, 'task'],\n message: 'status.set outside an action must name its target task',\n })\n }\n return {type: 'status.set', task: task ?? '', status: op.status}\n }\n if (op.type === 'audit') return desugarAuditOp(op, path, env, ctx)\n const target = resolveRef(op.target, env, [...path, 'target'], ctx) ?? fallbackRef(op.target)\n return {...op, target} as Op\n}\n\nconst AUDIT_STAMPS = {actor: {type: 'actor'}, at: {type: 'now'}} as const\n\nfunction desugarAuditOp(\n op: Extract<AuthoringOp, {type: 'audit'}>,\n path: IssuePath,\n env: LexicalEnv,\n ctx: Ctx,\n): Op {\n const target = resolveRef(op.target, env, [...path, 'target'], ctx) ?? fallbackRef(op.target)\n if (op.value.type !== 'object') {\n ctx.issues.push({\n path: [...path, 'value'],\n message: `audit value must be an object source carrying the domain fields (got \"${op.value.type}\")`,\n })\n return {type: 'state.append', target, value: op.value}\n }\n const actorField = op.stampFields?.actor ?? 'actor'\n const atField = op.stampFields?.at ?? 'at'\n const fields: Record<string, Source> = {...op.value.fields}\n for (const [stamp, source] of [\n [actorField, AUDIT_STAMPS.actor],\n [atField, AUDIT_STAMPS.at],\n ] as const) {\n if (stamp in fields) {\n ctx.issues.push({\n path: [...path, 'value', 'fields', stamp],\n message:\n `audit stamp field \"${stamp}\" collides with an authored domain field — ` +\n `rename yours or remap the stamp via stampFields`,\n })\n continue\n }\n fields[stamp] = source\n }\n return {type: 'state.append', target, value: {type: 'object', fields}}\n}\n\n// Lexical reference resolution — most-local outward, like variable lookup.\n// An explicit `scope` overrides; an unresolvable reference fails loud.\n\nfunction resolveRef(\n ref: AuthoringStateRef,\n env: LexicalEnv,\n path: IssuePath,\n ctx: Ctx,\n): StoredStateRef | undefined {\n const layers =\n ref.scope === undefined ? env.layers : env.layers.filter((l) => l.scope === ref.scope)\n for (const layer of layers) {\n if (layer.entries.has(ref.state)) return {scope: layer.scope, state: ref.state}\n }\n const reachable = env.layers.flatMap((l) => [...l.entries.keys()].map((n) => `${l.scope}:${n}`))\n ctx.issues.push({\n path,\n message:\n `state reference \"${ref.state}\"${ref.scope ? ` (scope \"${ref.scope}\")` : ''} does not ` +\n `resolve to a declared entry. Reachable: ${reachable.join(', ') || '(none)'}`,\n })\n return undefined\n}\n\nfunction entryAt(env: LexicalEnv, ref: StoredStateRef): StateEntry | undefined {\n return env.layers.find((l) => l.scope === ref.scope)?.entries.get(ref.state)\n}\n\n/** Keeps the stored shape parseable after a resolution issue was reported. */\nfunction fallbackRef(ref: AuthoringStateRef): StoredStateRef {\n return {scope: ref.scope ?? 'workflow', state: ref.state}\n}\n\n// Small shared helpers\n\nfunction rolesCondition(roles: readonly string[] | undefined): string | undefined {\n if (!roles || roles.length === 0) return undefined\n return groq`count($actor.roles[@ in ${roles}]) > 0`\n}\n\nfunction composeFilter(parts: (string | undefined)[]): string | undefined {\n const present = parts.filter((p): p is string => p !== undefined)\n if (present.length === 0) return undefined\n if (present.length === 1) return present[0]\n return present.map((p) => `(${p})`).join(' && ')\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {}\n for (const [k, value] of Object.entries(obj)) {\n if (value !== undefined) out[k] = value\n }\n return out as T\n}\n","import type {Effect, IssuePath, Op, Task, ValidationIssue, WorkflowDefinition} from './schema.ts'\nimport {GROQ_IDENTIFIER} from './schema.ts'\n\n/**\n * The rendered-scope variable names the engine binds for conditions. An\n * author predicate redefining one would silently shadow engine behaviour,\n * so it is rejected at deploy — engine-owned and author names share one\n * namespace, fail loud.\n */\nconst RESERVED_CONDITION_VARS = [\n 'state',\n 'actor',\n 'assigned',\n 'can',\n 'row',\n 'now',\n 'effects',\n 'tasks',\n 'subworkflows',\n 'self',\n 'stage',\n 'parent',\n 'ancestors',\n 'allTasksDone',\n 'anyTaskFailed',\n] as const\n\n/**\n * Caller-bound vars a predicate body may not read: predicates pre-evaluate\n * once per instance against the built-in scope (no caller), while the\n * commit-path re-evaluates conditions WITH the caller bound — the same\n * predicate would give divergent verdicts on the two paths.\n */\nconst PREDICATE_CALLER_VARS = ['actor', 'assigned', 'can'] as const\n\nfunction knownList(ids: Iterable<string>): string {\n return [...ids].map((s) => `\"${s}\"`).join(', ')\n}\n\nfunction checkDuplicates(\n names: Iterable<{name: string; path: IssuePath}>,\n what: string,\n issues: ValidationIssue[],\n): Set<string> {\n const seen = new Set<string>()\n for (const {name, path} of names) {\n if (seen.has(name)) {\n issues.push({path, message: `duplicate ${what} \"${name}\" (already declared earlier)`})\n }\n seen.add(name)\n }\n return seen\n}\n\nfunction checkStages(def: WorkflowDefinition, issues: ValidationIssue[]): Set<string> {\n const stageNames = checkDuplicates(\n def.stages.map((stage, i) => ({name: stage.name, path: ['stages', i, 'name']})),\n 'stage name',\n issues,\n )\n for (const [i, stage] of def.stages.entries()) {\n const taskNames = checkDuplicates(\n (stage.tasks ?? []).map((task, j) => ({\n name: task.name,\n path: ['stages', i, 'tasks', j, 'name'],\n })),\n `task name in stage \"${stage.name}\"`,\n issues,\n )\n checkDuplicates(\n (stage.transitions ?? []).map((t, k) => ({\n name: t.name,\n path: ['stages', i, 'transitions', k, 'name'],\n })),\n `transition name in stage \"${stage.name}\"`,\n issues,\n )\n checkTasks(def, i, taskNames, issues)\n }\n return stageNames\n}\n\nfunction checkTasks(\n def: WorkflowDefinition,\n i: number,\n taskNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n const stage = def.stages[i]!\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n const path: IssuePath = ['stages', i, 'tasks', j]\n checkDuplicates(\n (task.actions ?? []).map((action, a) => ({\n name: action.name,\n path: [...path, 'actions', a, 'name'],\n })),\n `action name in task \"${task.name}\"`,\n issues,\n )\n checkStatusSetTargets(task, taskNames, path, issues)\n }\n}\n\n/**\n * A `status.set` may re-activate a SIBLING task — the name must exist in\n * the stage. Both op sites can carry one: action ops and the task's own\n * activation ops. (Transition ops cannot — the schema's transition-op\n * subset excludes `status.set` at parse time.)\n */\nfunction checkStatusSetTargets(\n task: Task,\n taskNames: Set<string>,\n path: IssuePath,\n issues: ValidationIssue[],\n): void {\n checkStatusSetOps(task.ops, taskNames, [...path, 'ops'], issues)\n for (const [a, action] of (task.actions ?? []).entries()) {\n checkStatusSetOps(action.ops, taskNames, [...path, 'actions', a, 'ops'], issues)\n }\n}\n\nfunction checkStatusSetOps(\n ops: readonly Op[] | undefined,\n taskNames: Set<string>,\n path: IssuePath,\n issues: ValidationIssue[],\n): void {\n for (const [o, op] of (ops ?? []).entries()) {\n if (op.type !== 'status.set' || taskNames.has(op.task)) continue\n issues.push({\n path: [...path, o, 'task'],\n message:\n `status.set targets task \"${op.task}\" which is not declared in this stage. ` +\n `Known tasks: ${knownList(taskNames)}`,\n })\n }\n}\n\nfunction checkInitialStage(\n def: WorkflowDefinition,\n stageNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n if (stageNames.has(def.initialStage)) return\n issues.push({\n path: ['initialStage'],\n message:\n `initialStage \"${def.initialStage}\" is not a declared stage. ` +\n `Known stages: ${knownList(stageNames)}`,\n })\n}\n\nfunction checkTransitionTargets(\n def: WorkflowDefinition,\n stageNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n for (const [i, stage] of def.stages.entries()) {\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n if (stageNames.has(t.to)) continue\n issues.push({\n path: ['stages', i, 'transitions', k, 'to'],\n message:\n `transition target \"${t.to}\" is not a declared stage. ` +\n `Known stages: ${knownList(stageNames)}`,\n })\n }\n }\n}\n\n/**\n * Effect names are the registry keys handlers bind to AND the `$effects.<name>`\n * read keys — unique across the whole definition so a read is unambiguous.\n * Reusing one handler function under two names happens in app code.\n */\nfunction checkEffectNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const sites: {name: string; path: IssuePath}[] = []\n for (const [i, stage] of def.stages.entries()) {\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n collectEffects(task.effects, ['stages', i, 'tasks', j, 'effects'], sites)\n for (const [a, action] of (task.actions ?? []).entries()) {\n collectEffects(action.effects, ['stages', i, 'tasks', j, 'actions', a, 'effects'], sites)\n }\n }\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n collectEffects(t.effects, ['stages', i, 'transitions', k, 'effects'], sites)\n }\n }\n checkDuplicates(sites, 'effect name (registry key — unique per definition)', issues)\n}\n\nfunction collectEffects(\n effects: readonly {name: string}[] | undefined,\n path: IssuePath,\n sites: {name: string; path: IssuePath}[],\n): void {\n for (const [e, effect] of (effects ?? []).entries()) {\n sites.push({name: effect.name, path: [...path, e, 'name']})\n }\n}\n\n/**\n * The guard lake `_id` derives from (instanceId, guard.name) — see\n * {@link lakeGuardId}'s callers. A duplicate guard name ANYWHERE in the\n * definition aliases two guards onto one lake document: when a stage move\n * deploys the entered stage's guard and then the exited stage's retract\n * patches the SAME `_id` to an unconditional allow, a hard lock is silently\n * lifted. Unique per definition, not per stage.\n */\nfunction checkGuardNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const sites = def.stages.flatMap((stage, i) =>\n (stage.guards ?? []).map((guard, g): {name: string; path: IssuePath} => ({\n name: guard.name,\n path: ['stages', i, 'guards', g, 'name'],\n })),\n )\n checkDuplicates(\n sites,\n 'guard name (the guard lake _id derives from it — unique per definition)',\n issues,\n )\n}\n\ninterface StateScopeSite {\n entries: readonly {type: string; name: string}[] | undefined\n path: IssuePath\n label: string\n}\n\nfunction stateScopes(def: WorkflowDefinition): StateScopeSite[] {\n const scopes: StateScopeSite[] = [{entries: def.state, path: ['state'], label: 'workflow state'}]\n for (const [i, stage] of def.stages.entries()) {\n scopes.push({\n entries: stage.state,\n path: ['stages', i, 'state'],\n label: `stage \"${stage.name}\" state`,\n })\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n scopes.push({\n entries: task.state,\n path: ['stages', i, 'tasks', j, 'state'],\n label: `task \"${task.name}\" state`,\n })\n }\n }\n return scopes\n}\n\n/**\n * State entry names are the per-scope lookup keys (`$state.<name>`, op\n * targets, runtime `find()` reads) — a duplicate within one scope makes\n * different readers silently land on different entries.\n */\nfunction checkStateEntryNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const {entries, path, label} of stateScopes(def)) {\n checkDuplicates(\n (entries ?? []).map((entry, n) => ({name: entry.name, path: [...path, n, 'name']})),\n `state entry name in ${label}`,\n issues,\n )\n }\n}\n\nfunction checkPredicates(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const reserved = new Set<string>(RESERVED_CONDITION_VARS)\n const names = Object.keys(def.predicates ?? {})\n for (const name of names) {\n if (!reserved.has(name)) continue\n issues.push({\n path: ['predicates', name],\n message: `predicate \"${name}\" shadows the built-in $${name} — pick another name`,\n })\n }\n for (const [name, groq] of Object.entries(def.predicates ?? {})) {\n checkPredicateBody(name, groq, names, issues)\n }\n}\n\nfunction checkPredicateBody(\n name: string,\n groq: string,\n names: string[],\n issues: ValidationIssue[],\n): void {\n for (const caller of PREDICATE_CALLER_VARS) {\n if (!referencesVar(groq, caller)) continue\n issues.push({\n path: ['predicates', name],\n message:\n `predicate \"${name}\" reads $${caller} — predicates are instance-level (pre-evaluated ` +\n `once, without a caller); compose caller gates at the condition site instead`,\n })\n }\n // Predicates pre-evaluate against the built-in scope only, so a body\n // referencing a sibling would need a dependency order — fail loud instead.\n for (const other of names) {\n if (other === name || !referencesVar(groq, other)) continue\n issues.push({\n path: ['predicates', name],\n message:\n `predicate \"${name}\" references predicate $${other} — predicates may read ` +\n `built-in vars only (no cross-references; compose at the condition site instead)`,\n })\n }\n}\n\n/**\n * Whether a condition body reads `$<name>`. Only identifier-safe names can\n * appear as a GROQ var at all (and only they splice into a RegExp without\n * escaping), so anything else is a no-reference by construction.\n */\nfunction referencesVar(groq: string, name: string): boolean {\n if (!GROQ_IDENTIFIER.test(name)) return false\n return new RegExp(`\\\\$${name}\\\\b`).test(groq)\n}\n\ninterface ConditionSite {\n groq: string\n path: IssuePath\n label: string\n}\n\n/**\n * `$can` (the caller's advisory grants) is bound only while an action\n * fires — every other condition site evaluates without it and would hit\n * an unbound-param error mid-cascade at runtime. Reject it everywhere but\n * action filters.\n */\nfunction checkCanOutsideActionFilters(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const site of nonActionFilterConditionSites(def)) {\n if (!referencesVar(site.groq, 'can')) continue\n issues.push({\n path: site.path,\n message:\n `${site.label} reads $can — $can (the caller's grants) is bound only when an ` +\n `action fires, so it may appear in action filters only`,\n })\n }\n}\n\nfunction nonActionFilterConditionSites(def: WorkflowDefinition): ConditionSite[] {\n const sites: ConditionSite[] = []\n for (const [i, stage] of def.stages.entries()) {\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n sites.push({\n groq: t.filter,\n path: ['stages', i, 'transitions', k, 'filter'],\n label: `transition \"${t.name}\" filter`,\n })\n collectBindingSites(\n t.effects,\n ['stages', i, 'transitions', k, 'effects'],\n `transition \"${t.name}\"`,\n sites,\n )\n }\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n collectTaskConditionSites(task, ['stages', i, 'tasks', j], sites)\n }\n }\n return sites\n}\n\nfunction collectTaskConditionSites(task: Task, path: IssuePath, sites: ConditionSite[]): void {\n for (const field of ['filter', 'completeWhen', 'failWhen'] as const) {\n const groq = task[field]\n if (groq !== undefined) {\n sites.push({groq, path: [...path, field], label: `task \"${task.name}\".${field}`})\n }\n }\n collectBindingSites(task.effects, [...path, 'effects'], `task \"${task.name}\"`, sites)\n for (const [a, action] of (task.actions ?? []).entries()) {\n collectBindingSites(\n action.effects,\n [...path, 'actions', a, 'effects'],\n `action \"${action.name}\"`,\n sites,\n )\n }\n collectSubworkflowSites(task, path, sites)\n}\n\nfunction collectSubworkflowSites(task: Task, path: IssuePath, sites: ConditionSite[]): void {\n const sub = task.subworkflows\n if (sub === undefined) return\n const subPath = [...path, 'subworkflows']\n sites.push({\n groq: sub.forEach,\n path: [...subPath, 'forEach'],\n label: `task \"${task.name}\".subworkflows.forEach`,\n })\n for (const [group, record] of [\n ['with', sub.with],\n ['context', sub.context],\n ] as const) {\n for (const [key, groq] of Object.entries(record ?? {})) {\n sites.push({\n groq,\n path: [...subPath, group, key],\n label: `task \"${task.name}\".subworkflows.${group} \"${key}\"`,\n })\n }\n }\n}\n\nfunction collectBindingSites(\n effects: readonly Effect[] | undefined,\n path: IssuePath,\n label: string,\n sites: ConditionSite[],\n): void {\n for (const [e, effect] of (effects ?? []).entries()) {\n for (const [key, groq] of Object.entries(effect.bindings ?? {})) {\n sites.push({\n groq,\n path: [...path, e, 'bindings', key],\n label: `${label} effect \"${effect.name}\" binding \"${key}\"`,\n })\n }\n }\n}\n\n/** The inbox and `$assigned` read the assignees-kind entry — at most one per scope. */\nfunction checkAssigneesEntries(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const {entries, path} of stateScopes(def)) {\n const assignees = (entries ?? []).filter((e) => e.type === 'assignees')\n if (assignees.length <= 1) continue\n issues.push({\n path,\n message: 'at most one assignees-kind state entry per scope — the inbox reads it by kind',\n })\n }\n}\n\n/**\n * Run every cross-field invariant of a (desugared, stored-shape) workflow\n * definition, returning issues whose paths land on the offending field. Kept\n * separate from the structural schema so each invariant is independently\n * named and testable, and runs only after the structural parse succeeds.\n */\nexport function checkWorkflowInvariants(def: WorkflowDefinition): ValidationIssue[] {\n const issues: ValidationIssue[] = []\n const stageNames = checkStages(def, issues)\n checkInitialStage(def, stageNames, issues)\n checkTransitionTargets(def, stageNames, issues)\n checkEffectNames(def, issues)\n checkGuardNames(def, issues)\n checkStateEntryNames(def, issues)\n checkPredicates(def, issues)\n checkCanOutsideActionFilters(def, issues)\n checkAssigneesEntries(def, issues)\n return issues\n}\n","/**\n * Authoring helpers — schema-first.\n *\n * The schemas in `./schema.ts` are the canonical source of truth for what a\n * workflow author may write. Each `define*` helper validates one authoring\n * node (raw primitive or sugar type) so a type error lands on the offending\n * element with autocomplete — the Sanity idiom (`defineConfig` / `defineType`\n * / `defineField`), which is also why identity is `name` everywhere.\n *\n * `defineWorkflow` is the composer and the compile boundary: it parses the\n * authoring tree, **desugars** it (sugar types and field sugars expand\n * in-bounds, lexical scopes resolve, defaults fill — see `./desugar.ts`),\n * then checks cross-field invariants on the resulting STORED definition.\n * What it returns is exactly what deploys: primitives only.\n */\n\nimport * as v from 'valibot'\n\nimport {desugarWorkflow} from './desugar.ts'\nimport {checkWorkflowInvariants} from './invariants.ts'\nimport {\n AuthoringActionSchema,\n AuthoringOpSchema,\n AuthoringStageSchema,\n AuthoringStateEntrySchema,\n AuthoringTaskSchema,\n AuthoringTransitionSchema,\n AuthoringWorkflowSchema,\n EffectSchema,\n GuardSchema,\n formatValidationError,\n issuesFromValibot,\n type AuthoringAction,\n type AuthoringOp,\n type AuthoringStage,\n type AuthoringStateEntry,\n type AuthoringTask,\n type AuthoringTransition,\n type AuthoringWorkflow,\n type Effect,\n type Guard,\n type ValidationIssue,\n type WorkflowDefinition,\n} from './schema.ts'\n\nexport {groq} from './groq.ts'\n\n/**\n * Validate, desugar, and return a workflow definition in its stored shape.\n * Throws with a formatted, path-prefixed error message if validation fails.\n *\n * Example error:\n *\n * ```\n * defineWorkflow(\"article-review\") failed validation (2 issues):\n * - stages[1].transitions[0].to: transition target \"ready\" is not a declared stage. Known stages: \"drafting\", \"review\", \"approved\"\n * - predicates.allTasksDone: predicate \"allTasksDone\" shadows the built-in $allTasksDone — pick another name\n * ```\n */\nexport function defineWorkflow(definition: AuthoringWorkflow): WorkflowDefinition {\n const label = labelFor('defineWorkflow', definition)\n // Structural parse first; desugar and cross-field invariants only run on a\n // structurally-valid authoring tree (their logic assumes the shape holds).\n const parsed = parseOrThrow(AuthoringWorkflowSchema, definition, label)\n const {definition: stored, issues: desugarIssues} = desugarWorkflow(parsed)\n const issues: ValidationIssue[] = [...desugarIssues, ...checkWorkflowInvariants(stored)]\n if (issues.length > 0) throw new Error(formatValidationError(label, issues))\n return stored\n}\n\n// Companion `define*` helpers — one per authoring node. Each validates the\n// AUTHORING shape (primitives + sugar); expansion happens when the node is\n// composed into `defineWorkflow`.\n\nexport function defineStage(stage: AuthoringStage): AuthoringStage {\n return parseOrThrow(AuthoringStageSchema, stage, labelFor('defineStage', stage))\n}\n\nexport function defineTask(task: AuthoringTask): AuthoringTask {\n return parseOrThrow(AuthoringTaskSchema, task, labelFor('defineTask', task))\n}\n\nexport function defineAction(action: AuthoringAction): AuthoringAction {\n return parseOrThrow(AuthoringActionSchema, action, labelFor('defineAction', action))\n}\n\nexport function defineTransition(transition: AuthoringTransition): AuthoringTransition {\n return parseOrThrow(AuthoringTransitionSchema, transition, transitionLabel(transition))\n}\n\nexport function defineState(entry: AuthoringStateEntry): AuthoringStateEntry {\n return parseOrThrow(AuthoringStateEntrySchema, entry, labelFor('defineState', entry))\n}\n\nexport function defineOp(op: AuthoringOp): AuthoringOp {\n return parseOrThrow(AuthoringOpSchema, op, 'defineOp')\n}\n\nexport function defineGuard(guard: Guard): Guard {\n return parseOrThrow(GuardSchema, guard, labelFor('defineGuard', guard))\n}\n\n/**\n * Validate and return an effect declaration — the registry model: `name` is\n * the effect's only identity; the host app registers a handler against it.\n */\nexport function defineEffect(effect: Effect): Effect {\n return parseOrThrow(EffectSchema, effect, labelFor('defineEffect', effect))\n}\n\nfunction transitionLabel(transition: AuthoringTransition): string {\n const {name, to} = transition as {name?: unknown; to?: unknown}\n if (typeof name === 'string') return `defineTransition(\"${name}\")`\n if (typeof to === 'string') return `defineTransition(→ \"${to}\")`\n return 'defineTransition'\n}\n\n// Effect handler descriptor (runtime side)\n\n/**\n * Effect handler descriptor, registered by the runtime against an effect\n * `name` (1:1 — the stored definition never references code). The description\n * and param shape live in the registry, which the SDK snapshots into\n * `pendingEffects[]` at queue time.\n */\nexport interface EffectDescriptor {\n name: string\n description?: string\n params?: EffectDescriptorParam[]\n}\n\nexport interface EffectDescriptorParam {\n name: string\n type: 'string' | 'number' | 'boolean' | 'object' | 'string[]'\n required?: boolean\n description?: string\n}\n\nexport function defineEffectDescriptor(descriptor: EffectDescriptor): EffectDescriptor {\n if (!descriptor.name) throw new Error('EffectDescriptor missing name')\n return descriptor\n}\n\n// Internal — shared parse + label\n\nfunction parseOrThrow<T>(schema: v.GenericSchema<unknown, T>, input: T, label: string): T {\n const result = v.safeParse(schema, input)\n if (!result.success) {\n throw new Error(formatValidationError(label, issuesFromValibot(result.issues)))\n }\n return result.output\n}\n\nfunction labelFor(fn: string, value: unknown): string {\n if (value && typeof value === 'object' && 'name' in value) {\n const raw = (value as Record<string, unknown>).name\n if (typeof raw === 'string') return `${fn}(\"${raw}\")`\n }\n return fn\n}\n"],"names":["groq"],"mappings":"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"}
1
+ {"version":3,"file":"define.js","sources":["../src/define/groq.ts","../src/define/desugar.ts","../src/define/invariants.ts","../src/define/index.ts"],"sourcesContent":["/**\n * Hygienic GROQ interpolation for define-time condition building.\n *\n * Parameterized predicate reuse lives in the host language — a TypeScript\n * function producing a condition string — and this tag is its safe splice:\n * interpolated *values* serialize as GROQ literals (JSON literal syntax is\n * valid GROQ), never as raw query text, so quoting and precedence cannot\n * break. The produced string is stored as a plain condition and validated at\n * deploy like any other.\n *\n * ```ts\n * const regulated = (kinds: string[]) => groq`$state.subject.category in ${kinds}`\n * defineTask({ name: \"legal\", filter: regulated([\"finance\", \"health\"]), … })\n * ```\n */\nexport function groq(strings: TemplateStringsArray, ...values: unknown[]): string {\n return strings.reduce((out, part, i) => {\n if (i === 0) return part\n return `${out}${serializeGroqValue(values[i - 1])}${part}`\n }, '')\n}\n\nfunction serializeGroqValue(value: unknown): string {\n const serialized = JSON.stringify(value)\n if (serialized === undefined) {\n throw new Error(\n `groq tag cannot serialize ${typeof value} — interpolate JSON-representable values only`,\n )\n }\n return serialized\n}\n","/**\n * Define-time expansion: authoring input (primitives + sugar) → the stored\n * definition (primitives only). Storage never sees a sugar type.\n *\n * Every expansion is strictly **in-bounds** — confined to the node that\n * declares it. A pattern that spans nodes (the `claim` state/action pair) is\n * tied by an ordinary deploy-checked *reference*, never by creation: sugar\n * never adds a state entry, an action, or anything else outside its node, so\n * the authored arrays remain the complete inventory of the definition.\n *\n * Reference scopes resolve **lexically** here — most-local outward\n * (task → stage → workflow), like variable lookup — so every stored op\n * TARGET carries an explicit `scope` the runtime never re-resolves.\n * `Source.stateRead` VALUES are different: their `scope` stays optional in\n * the stored form, and an omitted scope resolves lexically at read time.\n */\n\nimport {groq} from './groq.ts'\nimport type {\n Action,\n AuthoringAction,\n AuthoringOp,\n AuthoringStateEntry,\n AuthoringStateRef,\n AuthoringTask,\n AuthoringTransition,\n AuthoringWorkflow,\n IssuePath,\n Op,\n Source,\n StateEntry,\n StoredStateRef,\n Task,\n Transition,\n TransitionOp,\n ValidationIssue,\n WorkflowDefinition,\n} from './schema.ts'\n\n/** One lexical layer: the state entries declared at a scope, by name. */\ntype ScopeLayer = ReadonlyMap<string, StateEntry>\n\n/**\n * The lexical environment a reference resolves in: innermost first. A task's\n * ops see task → stage → workflow; a transition's ops see stage → workflow\n * (the stage's tasks are tearing down when a transition fires).\n */\ninterface LexicalEnv {\n layers: readonly {scope: 'workflow' | 'stage' | 'task'; entries: ScopeLayer}[]\n}\n\ninterface DesugarResult {\n definition: WorkflowDefinition\n issues: ValidationIssue[]\n}\n\ninterface Ctx {\n issues: ValidationIssue[]\n /**\n * Entries declared via the `claim` sugar type, keyed by the desugared\n * entry object (the same object the lexical layers hand back), so pairing\n * is exact per declaration — never by bare name across scopes.\n */\n claimStates: Map<StateEntry, {name: string; path: IssuePath}>\n /** Claim-state entries that at least one `claim` action resolved to — pair validation. */\n claimedStates: Set<StateEntry>\n}\n\nexport function desugarWorkflow(authoring: AuthoringWorkflow): DesugarResult {\n const ctx: Ctx = {issues: [], claimStates: new Map(), claimedStates: new Set()}\n\n const workflowState = desugarStateEntries(authoring.state, ['state'], ctx)\n const workflowLayer = layerOf(workflowState)\n\n const stages = authoring.stages.map((stage, i) => {\n const path: IssuePath = ['stages', i]\n const stageState = desugarStateEntries(stage.state, [...path, 'state'], ctx)\n const stageEnv: LexicalEnv = {\n layers: [\n {scope: 'stage', entries: layerOf(stageState)},\n {scope: 'workflow', entries: workflowLayer},\n ],\n }\n const tasks = (stage.tasks ?? []).map((task, j) =>\n desugarTask(task, [...path, 'tasks', j], stageEnv, ctx),\n )\n const transitions = (stage.transitions ?? []).map((transition, k) =>\n desugarTransition(transition, [...path, 'transitions', k], stageEnv, ctx),\n )\n return {\n ...stripUndefined({\n name: stage.name,\n title: stage.title,\n description: stage.description,\n guards: stage.guards,\n }),\n ...(stageState ? {state: stageState} : {}),\n ...(tasks.length > 0 ? {tasks} : {}),\n ...(transitions.length > 0 ? {transitions} : {}),\n }\n })\n\n checkUnclaimedClaimStates(ctx)\n\n const definition = {\n ...stripUndefined({\n name: authoring.name,\n version: authoring.version,\n title: authoring.title,\n description: authoring.description,\n role: authoring.role,\n initialStage: authoring.initialStage,\n predicates: authoring.predicates,\n }),\n ...(workflowState ? {state: workflowState} : {}),\n stages,\n } as WorkflowDefinition\n\n return {definition, issues: ctx.issues}\n}\n\n// State entries — the `claim` sugar expands to value.actor with an implied\n// `write` source, strictly within the entry.\n\nfunction desugarStateEntries(\n entries: readonly AuthoringStateEntry[] | undefined,\n path: IssuePath,\n ctx: Ctx,\n): StateEntry[] | undefined {\n if (!entries || entries.length === 0) return entries === undefined ? undefined : []\n return entries.map((entry, i) => {\n if (entry.type !== 'claim') return entry\n const desugared = {\n ...stripUndefined({name: entry.name, title: entry.title, description: entry.description}),\n type: 'value.actor',\n source: {type: 'write'},\n } as StateEntry\n ctx.claimStates.set(desugared, {name: entry.name, path: [...path, i]})\n return desugared\n })\n}\n\nfunction layerOf(entries: readonly StateEntry[] | undefined): ScopeLayer {\n return new Map((entries ?? []).map((entry) => [entry.name, entry]))\n}\n\n// Tasks — activation defaults to `manual` (a task never activates silently;\n// \"auto\" is the explicit opt-in), ops resolve in the task's lexical env, and\n// each action expands within itself.\n\nfunction desugarTask(task: AuthoringTask, path: IssuePath, stageEnv: LexicalEnv, ctx: Ctx): Task {\n const taskState = desugarStateEntries(task.state, [...path, 'state'], ctx)\n const env: LexicalEnv = {\n layers: [{scope: 'task', entries: layerOf(taskState)}, ...stageEnv.layers],\n }\n const ops = desugarOps(task.ops, [...path, 'ops'], env, task.name, ctx)\n const actions = (task.actions ?? []).map((action, a) =>\n desugarAction(action, [...path, 'actions', a], env, task.name, ctx),\n )\n return {\n ...stripUndefined({\n name: task.name,\n title: task.title,\n description: task.description,\n filter: task.filter,\n requirements: task.requirements,\n completeWhen: task.completeWhen,\n failWhen: task.failWhen,\n effects: task.effects,\n subworkflows: task.subworkflows,\n }),\n activation: task.activation ?? 'manual',\n ...(taskState ? {state: taskState} : {}),\n ...(ops ? {ops} : {}),\n ...(actions.length > 0 ? {actions} : {}),\n } as Task\n}\n\n// Actions — the `claim` sugar type and the `roles` / `status` field sugars.\n\nfunction desugarAction(\n action: AuthoringAction,\n path: IssuePath,\n env: LexicalEnv,\n taskName: string,\n ctx: Ctx,\n): Action {\n // Only the claim sugar variant carries a `type` — raw actions have none.\n if ('type' in action) {\n return desugarClaimAction(action, path, env, ctx)\n }\n\n const filter = composeFilter([rolesCondition(action.roles), action.filter])\n const ops = desugarOps(action.ops, [...path, 'ops'], env, taskName, ctx) ?? []\n if (action.status !== undefined) {\n // Appended AFTER the authored ops — the expansion has a defined position.\n ops.push({type: 'status.set', task: taskName, status: action.status})\n }\n return {\n ...stripUndefined({\n name: action.name,\n title: action.title,\n description: action.description,\n params: action.params,\n effects: action.effects,\n }),\n ...(filter ? {filter} : {}),\n ...(ops.length > 0 ? {ops} : {}),\n } as Action\n}\n\nfunction desugarClaimAction(\n action: Extract<AuthoringAction, {type: 'claim'}>,\n path: IssuePath,\n env: LexicalEnv,\n ctx: Ctx,\n): Action {\n const ref = typeof action.state === 'string' ? {state: action.state} : action.state\n const resolved = resolveRef(ref, env, [...path, 'state'], ctx)\n if (resolved) {\n const entry = entryAt(env, resolved)\n if (entry && entry.type !== 'value.actor') {\n ctx.issues.push({\n path: [...path, 'state'],\n message:\n `claim action \"${action.name}\" references \"${resolved.state}\" of kind ` +\n `\"${entry.type}\" — a claim pair needs an actor-valued entry ` +\n `(a \"claim\" or \"value.actor\" state declaration)`,\n })\n }\n checkShadowedClaimTarget(action.name, ref.state, resolved, env, [...path, 'state'], ctx)\n if (entry) ctx.claimedStates.add(entry)\n }\n\n const noSteal = `!defined($state.${ref.state})`\n const filter = composeFilter([noSteal, rolesCondition(action.roles), action.filter])\n const ops: Op[] = resolved ? [{type: 'state.set', target: resolved, value: {type: 'actor'}}] : []\n return {\n ...stripUndefined({\n name: action.name,\n title: action.title,\n description: action.description,\n params: action.params,\n effects: action.effects,\n }),\n filter,\n ...(ops.length > 0 ? {ops} : {}),\n } as Action\n}\n\n/**\n * The claim action's two halves must address ONE entry: the no-steal filter\n * reads `$state.<name>` (nearest declaring scope wins in the rendered\n * overlay), while the `state.set` op writes the resolved ref. An explicit\n * `scope:` that lands on an entry lexically shadowed at the action's\n * position would split them — the filter checks the shadowing entry, the\n * op claims the shadowed one — so that is a define-time error.\n */\nfunction checkShadowedClaimTarget(\n actionName: string,\n state: string,\n resolved: StoredStateRef,\n env: LexicalEnv,\n path: IssuePath,\n ctx: Ctx,\n): void {\n const nearest = env.layers.find((l) => l.entries.has(state))\n if (nearest === undefined || nearest.scope === resolved.scope) return\n ctx.issues.push({\n path,\n message:\n `claim action \"${actionName}\" targets \"${state}\" at scope \"${resolved.scope}\", but a ` +\n `nearer ${nearest.scope}-scope entry of the same name shadows it in $state — the ` +\n `no-steal filter would read the shadowing entry while the claim writes the ` +\n `\"${resolved.scope}\" one. Rename one of the entries or claim the nearer one`,\n })\n}\n\n/** Pair validation, the other direction: a `claim` state nothing claims into. */\nfunction checkUnclaimedClaimStates(ctx: Ctx): void {\n for (const [entry, {name, path}] of ctx.claimStates) {\n if (ctx.claimedStates.has(entry)) continue\n ctx.issues.push({\n path,\n message:\n `claim state \"${name}\" is never referenced by a claim action — ` +\n `you announced the pattern and wrote half of it. Declare a ` +\n `defineAction({ type: \"claim\", state: \"${name}\" }) or use a raw value.actor entry`,\n })\n }\n}\n\n// Transitions — an omitted filter desugars to the safe, dominant gate.\n// The lexical env for transition ops skips the task layer: the stage's tasks\n// are tearing down when a transition fires.\n\nfunction desugarTransition(\n transition: AuthoringTransition,\n path: IssuePath,\n stageEnv: LexicalEnv,\n ctx: Ctx,\n): Transition {\n const ops = desugarOps(transition.ops, [...path, 'ops'], stageEnv, undefined, ctx)\n return {\n ...stripUndefined({\n name: transition.name,\n title: transition.title,\n description: transition.description,\n to: transition.to,\n effects: transition.effects,\n }),\n filter: transition.filter ?? '$allTasksDone',\n ...(ops ? {ops: ops as TransitionOp[]} : {}),\n } as Transition\n}\n\n// Ops — the `audit` sugar (a stamped append, in-bounds: it only touches its\n// own value) plus lexical target resolution and the firing-task default on\n// `status.set`.\n\nfunction desugarOps(\n ops: readonly AuthoringOp[] | undefined,\n path: IssuePath,\n env: LexicalEnv,\n firingTask: string | undefined,\n ctx: Ctx,\n): Op[] | undefined {\n if (!ops) return undefined\n return ops.map((op, i) => desugarOp(op, [...path, i], env, firingTask, ctx))\n}\n\nfunction desugarOp(\n op: AuthoringOp,\n path: IssuePath,\n env: LexicalEnv,\n firingTask: string | undefined,\n ctx: Ctx,\n): Op {\n if (op.type === 'status.set') {\n const task = op.task ?? firingTask\n if (task === undefined) {\n ctx.issues.push({\n path: [...path, 'task'],\n message: 'status.set outside an action must name its target task',\n })\n }\n return {type: 'status.set', task: task ?? '', status: op.status}\n }\n if (op.type === 'audit') return desugarAuditOp(op, path, env, ctx)\n const target = resolveRef(op.target, env, [...path, 'target'], ctx) ?? fallbackRef(op.target)\n return {...op, target} as Op\n}\n\nconst AUDIT_STAMPS = {actor: {type: 'actor'}, at: {type: 'now'}} as const\n\nfunction desugarAuditOp(\n op: Extract<AuthoringOp, {type: 'audit'}>,\n path: IssuePath,\n env: LexicalEnv,\n ctx: Ctx,\n): Op {\n const target = resolveRef(op.target, env, [...path, 'target'], ctx) ?? fallbackRef(op.target)\n if (op.value.type !== 'object') {\n ctx.issues.push({\n path: [...path, 'value'],\n message: `audit value must be an object source carrying the domain fields (got \"${op.value.type}\")`,\n })\n return {type: 'state.append', target, value: op.value}\n }\n const actorField = op.stampFields?.actor ?? 'actor'\n const atField = op.stampFields?.at ?? 'at'\n const fields: Record<string, Source> = {...op.value.fields}\n for (const [stamp, source] of [\n [actorField, AUDIT_STAMPS.actor],\n [atField, AUDIT_STAMPS.at],\n ] as const) {\n if (stamp in fields) {\n ctx.issues.push({\n path: [...path, 'value', 'fields', stamp],\n message:\n `audit stamp field \"${stamp}\" collides with an authored domain field — ` +\n `rename yours or remap the stamp via stampFields`,\n })\n continue\n }\n fields[stamp] = source\n }\n return {type: 'state.append', target, value: {type: 'object', fields}}\n}\n\n// Lexical reference resolution — most-local outward, like variable lookup.\n// An explicit `scope` overrides; an unresolvable reference fails loud.\n\nfunction resolveRef(\n ref: AuthoringStateRef,\n env: LexicalEnv,\n path: IssuePath,\n ctx: Ctx,\n): StoredStateRef | undefined {\n const layers =\n ref.scope === undefined ? env.layers : env.layers.filter((l) => l.scope === ref.scope)\n for (const layer of layers) {\n if (layer.entries.has(ref.state)) return {scope: layer.scope, state: ref.state}\n }\n const reachable = env.layers.flatMap((l) => [...l.entries.keys()].map((n) => `${l.scope}:${n}`))\n ctx.issues.push({\n path,\n message:\n `state reference \"${ref.state}\"${ref.scope ? ` (scope \"${ref.scope}\")` : ''} does not ` +\n `resolve to a declared entry. Reachable: ${reachable.join(', ') || '(none)'}`,\n })\n return undefined\n}\n\nfunction entryAt(env: LexicalEnv, ref: StoredStateRef): StateEntry | undefined {\n return env.layers.find((l) => l.scope === ref.scope)?.entries.get(ref.state)\n}\n\n/** Keeps the stored shape parseable after a resolution issue was reported. */\nfunction fallbackRef(ref: AuthoringStateRef): StoredStateRef {\n return {scope: ref.scope ?? 'workflow', state: ref.state}\n}\n\n// Small shared helpers\n\nfunction rolesCondition(roles: readonly string[] | undefined): string | undefined {\n if (!roles || roles.length === 0) return undefined\n return groq`count($actor.roles[@ in ${roles}]) > 0`\n}\n\nfunction composeFilter(parts: (string | undefined)[]): string | undefined {\n const present = parts.filter((p): p is string => p !== undefined)\n if (present.length === 0) return undefined\n if (present.length === 1) return present[0]\n return present.map((p) => `(${p})`).join(' && ')\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {}\n for (const [k, value] of Object.entries(obj)) {\n if (value !== undefined) out[k] = value\n }\n return out as T\n}\n","import type {\n Effect,\n IssuePath,\n Op,\n StateEntry,\n Task,\n ValidationIssue,\n WorkflowDefinition,\n} from './schema.ts'\nimport {GROQ_IDENTIFIER} from './schema.ts'\n\n/**\n * The rendered-scope variable names the engine binds for conditions. An\n * author predicate redefining one would silently shadow engine behaviour,\n * so it is rejected at deploy — engine-owned and author names share one\n * namespace, fail loud.\n */\nconst RESERVED_CONDITION_VARS = [\n 'state',\n 'actor',\n 'assigned',\n 'can',\n 'row',\n 'now',\n 'effects',\n 'tasks',\n 'subworkflows',\n 'self',\n 'stage',\n 'parent',\n 'ancestors',\n 'allTasksDone',\n 'anyTaskFailed',\n] as const\n\n/**\n * Caller-bound vars a predicate body may not read: predicates pre-evaluate\n * once per instance against the built-in scope (no caller), while the\n * commit-path re-evaluates conditions WITH the caller bound — the same\n * predicate would give divergent verdicts on the two paths.\n */\nconst PREDICATE_CALLER_VARS = ['actor', 'assigned', 'can'] as const\n\nfunction knownList(ids: Iterable<string>): string {\n return [...ids].map((s) => `\"${s}\"`).join(', ')\n}\n\nfunction checkDuplicates(\n names: Iterable<{name: string; path: IssuePath}>,\n what: string,\n issues: ValidationIssue[],\n): Set<string> {\n const seen = new Set<string>()\n for (const {name, path} of names) {\n if (seen.has(name)) {\n issues.push({path, message: `duplicate ${what} \"${name}\" (already declared earlier)`})\n }\n seen.add(name)\n }\n return seen\n}\n\nfunction checkStages(def: WorkflowDefinition, issues: ValidationIssue[]): Set<string> {\n const stageNames = checkDuplicates(\n def.stages.map((stage, i) => ({name: stage.name, path: ['stages', i, 'name']})),\n 'stage name',\n issues,\n )\n for (const [i, stage] of def.stages.entries()) {\n const taskNames = checkDuplicates(\n (stage.tasks ?? []).map((task, j) => ({\n name: task.name,\n path: ['stages', i, 'tasks', j, 'name'],\n })),\n `task name in stage \"${stage.name}\"`,\n issues,\n )\n checkDuplicates(\n (stage.transitions ?? []).map((t, k) => ({\n name: t.name,\n path: ['stages', i, 'transitions', k, 'name'],\n })),\n `transition name in stage \"${stage.name}\"`,\n issues,\n )\n checkTasks(def, i, taskNames, issues)\n }\n return stageNames\n}\n\nfunction checkTasks(\n def: WorkflowDefinition,\n i: number,\n taskNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n const stage = def.stages[i]!\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n const path: IssuePath = ['stages', i, 'tasks', j]\n checkDuplicates(\n (task.actions ?? []).map((action, a) => ({\n name: action.name,\n path: [...path, 'actions', a, 'name'],\n })),\n `action name in task \"${task.name}\"`,\n issues,\n )\n checkStatusSetTargets(task, taskNames, path, issues)\n }\n}\n\n/**\n * A `status.set` may re-activate a SIBLING task — the name must exist in\n * the stage. Both op sites can carry one: action ops and the task's own\n * activation ops. (Transition ops cannot — the schema's transition-op\n * subset excludes `status.set` at parse time.)\n */\nfunction checkStatusSetTargets(\n task: Task,\n taskNames: Set<string>,\n path: IssuePath,\n issues: ValidationIssue[],\n): void {\n checkStatusSetOps(task.ops, taskNames, [...path, 'ops'], issues)\n for (const [a, action] of (task.actions ?? []).entries()) {\n checkStatusSetOps(action.ops, taskNames, [...path, 'actions', a, 'ops'], issues)\n }\n}\n\nfunction checkStatusSetOps(\n ops: readonly Op[] | undefined,\n taskNames: Set<string>,\n path: IssuePath,\n issues: ValidationIssue[],\n): void {\n for (const [o, op] of (ops ?? []).entries()) {\n if (op.type !== 'status.set' || taskNames.has(op.task)) continue\n issues.push({\n path: [...path, o, 'task'],\n message:\n `status.set targets task \"${op.task}\" which is not declared in this stage. ` +\n `Known tasks: ${knownList(taskNames)}`,\n })\n }\n}\n\nfunction checkInitialStage(\n def: WorkflowDefinition,\n stageNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n if (stageNames.has(def.initialStage)) return\n issues.push({\n path: ['initialStage'],\n message:\n `initialStage \"${def.initialStage}\" is not a declared stage. ` +\n `Known stages: ${knownList(stageNames)}`,\n })\n}\n\nfunction checkTransitionTargets(\n def: WorkflowDefinition,\n stageNames: Set<string>,\n issues: ValidationIssue[],\n): void {\n for (const [i, stage] of def.stages.entries()) {\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n if (stageNames.has(t.to)) continue\n issues.push({\n path: ['stages', i, 'transitions', k, 'to'],\n message:\n `transition target \"${t.to}\" is not a declared stage. ` +\n `Known stages: ${knownList(stageNames)}`,\n })\n }\n }\n}\n\n/**\n * Effect names are the registry keys handlers bind to AND the `$effects.<name>`\n * read keys — unique across the whole definition so a read is unambiguous.\n * Reusing one handler function under two names happens in app code.\n */\nfunction checkEffectNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const sites: {name: string; path: IssuePath}[] = []\n for (const [i, stage] of def.stages.entries()) {\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n collectEffects(task.effects, ['stages', i, 'tasks', j, 'effects'], sites)\n for (const [a, action] of (task.actions ?? []).entries()) {\n collectEffects(action.effects, ['stages', i, 'tasks', j, 'actions', a, 'effects'], sites)\n }\n }\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n collectEffects(t.effects, ['stages', i, 'transitions', k, 'effects'], sites)\n }\n }\n checkDuplicates(sites, 'effect name (registry key — unique per definition)', issues)\n}\n\nfunction collectEffects(\n effects: readonly {name: string}[] | undefined,\n path: IssuePath,\n sites: {name: string; path: IssuePath}[],\n): void {\n for (const [e, effect] of (effects ?? []).entries()) {\n sites.push({name: effect.name, path: [...path, e, 'name']})\n }\n}\n\n/**\n * The guard lake `_id` derives from (instanceId, guard.name) — see\n * {@link lakeGuardId}'s callers. A duplicate guard name ANYWHERE in the\n * definition aliases two guards onto one lake document: when a stage move\n * deploys the entered stage's guard and then the exited stage's retract\n * patches the SAME `_id` to an unconditional allow, a hard lock is silently\n * lifted. Unique per definition, not per stage.\n */\nfunction checkGuardNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const sites = def.stages.flatMap((stage, i) =>\n (stage.guards ?? []).map((guard, g): {name: string; path: IssuePath} => ({\n name: guard.name,\n path: ['stages', i, 'guards', g, 'name'],\n })),\n )\n checkDuplicates(\n sites,\n 'guard name (the guard lake _id derives from it — unique per definition)',\n issues,\n )\n}\n\ninterface StateScopeSite {\n entries: readonly StateEntry[] | undefined\n scope: 'workflow' | 'stage' | 'task'\n path: IssuePath\n label: string\n}\n\nfunction stateScopes(def: WorkflowDefinition): StateScopeSite[] {\n const scopes: StateScopeSite[] = [\n {entries: def.state, scope: 'workflow', path: ['state'], label: 'workflow state'},\n ]\n for (const [i, stage] of def.stages.entries()) {\n scopes.push({\n entries: stage.state,\n scope: 'stage',\n path: ['stages', i, 'state'],\n label: `stage \"${stage.name}\" state`,\n })\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n scopes.push({\n entries: task.state,\n scope: 'task',\n path: ['stages', i, 'tasks', j, 'state'],\n label: `task \"${task.name}\" state`,\n })\n }\n }\n return scopes\n}\n\n/**\n * `required` is the start/spawn fail-fast for a load-bearing `init` slot: the\n * caller MUST fill it or {@link RequiredStateNotProvidedError} fires. It only\n * makes sense on a WORKFLOW-scope `init` entry — that is the one scope a caller\n * seeds (via `initialState` at start, or the parent's `subworkflows.with` at\n * spawn). Stage/task state is engine-resolved at entry/activation with no\n * caller seed, and a non-`init` source fills itself — so `required` anywhere\n * else can never be satisfied. Reject it at deploy rather than ship a slot that\n * always throws.\n */\nfunction checkRequiredState(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const {entries, scope, path, label} of stateScopes(def)) {\n for (const [n, entry] of (entries ?? []).entries()) {\n if (entry.required !== true) continue\n if (scope !== 'workflow') {\n issues.push({\n path: [...path, n, 'required'],\n message:\n `${label} entry \"${entry.name}\" is \\`required\\`, but \\`required\\` applies only to ` +\n `workflow-scope \\`init\\` entries — only those are caller-supplied at start/spawn`,\n })\n } else if (entry.source.type !== 'init') {\n issues.push({\n path: [...path, n, 'required'],\n message:\n `state entry \"${entry.name}\" is \\`required\\` but its source is \"${entry.source.type}\" — ` +\n `\\`required\\` applies only to \\`init\\`-sourced entries (the caller fills them at start/spawn)`,\n })\n }\n }\n }\n}\n\n/**\n * State entry names are the per-scope lookup keys (`$state.<name>`, op\n * targets, runtime `find()` reads) — a duplicate within one scope makes\n * different readers silently land on different entries.\n */\nfunction checkStateEntryNames(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const {entries, path, label} of stateScopes(def)) {\n checkDuplicates(\n (entries ?? []).map((entry, n) => ({name: entry.name, path: [...path, n, 'name']})),\n `state entry name in ${label}`,\n issues,\n )\n }\n}\n\nfunction checkPredicates(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n const reserved = new Set<string>(RESERVED_CONDITION_VARS)\n const names = Object.keys(def.predicates ?? {})\n for (const name of names) {\n if (!reserved.has(name)) continue\n issues.push({\n path: ['predicates', name],\n message: `predicate \"${name}\" shadows the built-in $${name} — pick another name`,\n })\n }\n for (const [name, groq] of Object.entries(def.predicates ?? {})) {\n checkPredicateBody(name, groq, names, issues)\n }\n}\n\nfunction checkPredicateBody(\n name: string,\n groq: string,\n names: string[],\n issues: ValidationIssue[],\n): void {\n for (const caller of PREDICATE_CALLER_VARS) {\n if (!referencesVar(groq, caller)) continue\n issues.push({\n path: ['predicates', name],\n message:\n `predicate \"${name}\" reads $${caller} — predicates are instance-level (pre-evaluated ` +\n `once, without a caller); compose caller gates at the condition site instead`,\n })\n }\n // Predicates pre-evaluate against the built-in scope only, so a body\n // referencing a sibling would need a dependency order — fail loud instead.\n for (const other of names) {\n if (other === name || !referencesVar(groq, other)) continue\n issues.push({\n path: ['predicates', name],\n message:\n `predicate \"${name}\" references predicate $${other} — predicates may read ` +\n `built-in vars only (no cross-references; compose at the condition site instead)`,\n })\n }\n}\n\n/**\n * Whether a condition body reads `$<name>`. Only identifier-safe names can\n * appear as a GROQ var at all (and only they splice into a RegExp without\n * escaping), so anything else is a no-reference by construction.\n */\nfunction referencesVar(groq: string, name: string): boolean {\n if (!GROQ_IDENTIFIER.test(name)) return false\n return new RegExp(`\\\\$${name}\\\\b`).test(groq)\n}\n\ninterface ConditionSite {\n groq: string\n path: IssuePath\n label: string\n}\n\n/**\n * `$can` (the caller's advisory grants) is bound only while an action\n * fires — every other condition site evaluates without it and would hit\n * an unbound-param error mid-cascade at runtime. Reject it everywhere but\n * action filters.\n */\nfunction checkCanOutsideActionFilters(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const site of nonActionFilterConditionSites(def)) {\n if (!referencesVar(site.groq, 'can')) continue\n issues.push({\n path: site.path,\n message:\n `${site.label} reads $can — $can (the caller's grants) is bound only when an ` +\n `action fires, so it may appear in action filters only`,\n })\n }\n}\n\nfunction nonActionFilterConditionSites(def: WorkflowDefinition): ConditionSite[] {\n const sites: ConditionSite[] = []\n for (const [i, stage] of def.stages.entries()) {\n for (const [k, t] of (stage.transitions ?? []).entries()) {\n sites.push({\n groq: t.filter,\n path: ['stages', i, 'transitions', k, 'filter'],\n label: `transition \"${t.name}\" filter`,\n })\n collectBindingSites(\n t.effects,\n ['stages', i, 'transitions', k, 'effects'],\n `transition \"${t.name}\"`,\n sites,\n )\n }\n for (const [j, task] of (stage.tasks ?? []).entries()) {\n collectTaskConditionSites(task, ['stages', i, 'tasks', j], sites)\n }\n }\n return sites\n}\n\nfunction collectTaskConditionSites(task: Task, path: IssuePath, sites: ConditionSite[]): void {\n for (const field of ['filter', 'completeWhen', 'failWhen'] as const) {\n const groq = task[field]\n if (groq !== undefined) {\n sites.push({groq, path: [...path, field], label: `task \"${task.name}\".${field}`})\n }\n }\n collectBindingSites(task.effects, [...path, 'effects'], `task \"${task.name}\"`, sites)\n for (const [a, action] of (task.actions ?? []).entries()) {\n collectBindingSites(\n action.effects,\n [...path, 'actions', a, 'effects'],\n `action \"${action.name}\"`,\n sites,\n )\n }\n collectSubworkflowSites(task, path, sites)\n}\n\nfunction collectSubworkflowSites(task: Task, path: IssuePath, sites: ConditionSite[]): void {\n const sub = task.subworkflows\n if (sub === undefined) return\n const subPath = [...path, 'subworkflows']\n sites.push({\n groq: sub.forEach,\n path: [...subPath, 'forEach'],\n label: `task \"${task.name}\".subworkflows.forEach`,\n })\n for (const [group, record] of [\n ['with', sub.with],\n ['context', sub.context],\n ] as const) {\n for (const [key, groq] of Object.entries(record ?? {})) {\n sites.push({\n groq,\n path: [...subPath, group, key],\n label: `task \"${task.name}\".subworkflows.${group} \"${key}\"`,\n })\n }\n }\n}\n\nfunction collectBindingSites(\n effects: readonly Effect[] | undefined,\n path: IssuePath,\n label: string,\n sites: ConditionSite[],\n): void {\n for (const [e, effect] of (effects ?? []).entries()) {\n for (const [key, groq] of Object.entries(effect.bindings ?? {})) {\n sites.push({\n groq,\n path: [...path, e, 'bindings', key],\n label: `${label} effect \"${effect.name}\" binding \"${key}\"`,\n })\n }\n }\n}\n\n/** The inbox and `$assigned` read the assignees-kind entry — at most one per scope. */\nfunction checkAssigneesEntries(def: WorkflowDefinition, issues: ValidationIssue[]): void {\n for (const {entries, path} of stateScopes(def)) {\n const assignees = (entries ?? []).filter((e) => e.type === 'assignees')\n if (assignees.length <= 1) continue\n issues.push({\n path,\n message: 'at most one assignees-kind state entry per scope — the inbox reads it by kind',\n })\n }\n}\n\n/**\n * Run every cross-field invariant of a (desugared, stored-shape) workflow\n * definition, returning issues whose paths land on the offending field. Kept\n * separate from the structural schema so each invariant is independently\n * named and testable, and runs only after the structural parse succeeds.\n */\nexport function checkWorkflowInvariants(def: WorkflowDefinition): ValidationIssue[] {\n const issues: ValidationIssue[] = []\n const stageNames = checkStages(def, issues)\n checkInitialStage(def, stageNames, issues)\n checkTransitionTargets(def, stageNames, issues)\n checkEffectNames(def, issues)\n checkGuardNames(def, issues)\n checkStateEntryNames(def, issues)\n checkRequiredState(def, issues)\n checkPredicates(def, issues)\n checkCanOutsideActionFilters(def, issues)\n checkAssigneesEntries(def, issues)\n return issues\n}\n","/**\n * Authoring helpers — schema-first.\n *\n * The schemas in `./schema.ts` are the canonical source of truth for what a\n * workflow author may write. Each `define*` helper validates one authoring\n * node (raw primitive or sugar type) so a type error lands on the offending\n * element with autocomplete — the Sanity idiom (`defineConfig` / `defineType`\n * / `defineField`), which is also why identity is `name` everywhere.\n *\n * `defineWorkflow` is the composer and the compile boundary: it parses the\n * authoring tree, **desugars** it (sugar types and field sugars expand\n * in-bounds, lexical scopes resolve, defaults fill — see `./desugar.ts`),\n * then checks cross-field invariants on the resulting STORED definition.\n * What it returns is exactly what deploys: primitives only.\n */\n\nimport * as v from 'valibot'\n\nimport {desugarWorkflow} from './desugar.ts'\nimport {checkWorkflowInvariants} from './invariants.ts'\nimport {\n AuthoringActionSchema,\n AuthoringOpSchema,\n AuthoringStageSchema,\n AuthoringStateEntrySchema,\n AuthoringTaskSchema,\n AuthoringTransitionSchema,\n AuthoringWorkflowSchema,\n EffectSchema,\n GuardSchema,\n formatValidationError,\n issuesFromValibot,\n type AuthoringAction,\n type AuthoringOp,\n type AuthoringStage,\n type AuthoringStateEntry,\n type AuthoringTask,\n type AuthoringTransition,\n type AuthoringWorkflow,\n type Effect,\n type Guard,\n type ValidationIssue,\n type WorkflowDefinition,\n} from './schema.ts'\n\nexport {groq} from './groq.ts'\n\n/**\n * Validate, desugar, and return a workflow definition in its stored shape.\n * Throws with a formatted, path-prefixed error message if validation fails.\n *\n * Example error:\n *\n * ```\n * defineWorkflow(\"article-review\") failed validation (2 issues):\n * - stages[1].transitions[0].to: transition target \"ready\" is not a declared stage. Known stages: \"drafting\", \"review\", \"approved\"\n * - predicates.allTasksDone: predicate \"allTasksDone\" shadows the built-in $allTasksDone — pick another name\n * ```\n */\nexport function defineWorkflow(definition: AuthoringWorkflow): WorkflowDefinition {\n const label = labelFor('defineWorkflow', definition)\n // Structural parse first; desugar and cross-field invariants only run on a\n // structurally-valid authoring tree (their logic assumes the shape holds).\n const parsed = parseOrThrow(AuthoringWorkflowSchema, definition, label)\n const {definition: stored, issues: desugarIssues} = desugarWorkflow(parsed)\n const issues: ValidationIssue[] = [...desugarIssues, ...checkWorkflowInvariants(stored)]\n if (issues.length > 0) throw new Error(formatValidationError(label, issues))\n return stored\n}\n\n// Companion `define*` helpers — one per authoring node. Each validates the\n// AUTHORING shape (primitives + sugar); expansion happens when the node is\n// composed into `defineWorkflow`.\n\nexport function defineStage(stage: AuthoringStage): AuthoringStage {\n return parseOrThrow(AuthoringStageSchema, stage, labelFor('defineStage', stage))\n}\n\nexport function defineTask(task: AuthoringTask): AuthoringTask {\n return parseOrThrow(AuthoringTaskSchema, task, labelFor('defineTask', task))\n}\n\nexport function defineAction(action: AuthoringAction): AuthoringAction {\n return parseOrThrow(AuthoringActionSchema, action, labelFor('defineAction', action))\n}\n\nexport function defineTransition(transition: AuthoringTransition): AuthoringTransition {\n return parseOrThrow(AuthoringTransitionSchema, transition, transitionLabel(transition))\n}\n\nexport function defineState(entry: AuthoringStateEntry): AuthoringStateEntry {\n return parseOrThrow(AuthoringStateEntrySchema, entry, labelFor('defineState', entry))\n}\n\nexport function defineOp(op: AuthoringOp): AuthoringOp {\n return parseOrThrow(AuthoringOpSchema, op, 'defineOp')\n}\n\nexport function defineGuard(guard: Guard): Guard {\n return parseOrThrow(GuardSchema, guard, labelFor('defineGuard', guard))\n}\n\n/**\n * Validate and return an effect declaration — the registry model: `name` is\n * the effect's only identity; the host app registers a handler against it.\n */\nexport function defineEffect(effect: Effect): Effect {\n return parseOrThrow(EffectSchema, effect, labelFor('defineEffect', effect))\n}\n\nfunction transitionLabel(transition: AuthoringTransition): string {\n const {name, to} = transition as {name?: unknown; to?: unknown}\n if (typeof name === 'string') return `defineTransition(\"${name}\")`\n if (typeof to === 'string') return `defineTransition(→ \"${to}\")`\n return 'defineTransition'\n}\n\n// Effect handler descriptor (runtime side)\n\n/**\n * Effect handler descriptor, registered by the runtime against an effect\n * `name` (1:1 — the stored definition never references code). The description\n * and param shape live in the registry, which the SDK snapshots into\n * `pendingEffects[]` at queue time.\n */\nexport interface EffectDescriptor {\n name: string\n description?: string\n params?: EffectDescriptorParam[]\n}\n\nexport interface EffectDescriptorParam {\n name: string\n type: 'string' | 'number' | 'boolean' | 'object' | 'string[]'\n required?: boolean\n description?: string\n}\n\nexport function defineEffectDescriptor(descriptor: EffectDescriptor): EffectDescriptor {\n if (!descriptor.name) throw new Error('EffectDescriptor missing name')\n return descriptor\n}\n\n// Internal — shared parse + label\n\nfunction parseOrThrow<T>(schema: v.GenericSchema<unknown, T>, input: T, label: string): T {\n const result = v.safeParse(schema, input)\n if (!result.success) {\n throw new Error(formatValidationError(label, issuesFromValibot(result.issues)))\n }\n return result.output\n}\n\nfunction labelFor(fn: string, value: unknown): string {\n if (value && typeof value === 'object' && 'name' in value) {\n const raw = (value as Record<string, unknown>).name\n if (typeof raw === 'string') return `${fn}(\"${raw}\")`\n }\n return fn\n}\n"],"names":["groq"],"mappings":";;AAeO,SAAS,KAAK,YAAkC,QAA2B;AAChF,SAAO,QAAQ,OAAO,CAAC,KAAK,MAAM,MAC5B,MAAM,IAAU,OACb,GAAG,GAAG,GAAG,mBAAmB,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IACvD,EAAE;AACP;AAEA,SAAS,mBAAmB,OAAwB;AAClD,QAAM,aAAa,KAAK,UAAU,KAAK;AACvC,MAAI,eAAe;AACjB,UAAM,IAAI;AAAA,MACR,6BAA6B,OAAO,KAAK;AAAA,IAAA;AAG7C,SAAO;AACT;ACsCO,SAAS,gBAAgB,WAA6C;AAC3E,QAAM,MAAW,EAAC,QAAQ,CAAA,GAAI,aAAa,oBAAI,OAAO,eAAe,oBAAI,IAAA,EAAI,GAEvE,gBAAgB,oBAAoB,UAAU,OAAO,CAAC,OAAO,GAAG,GAAG,GACnE,gBAAgB,QAAQ,aAAa,GAErC,SAAS,UAAU,OAAO,IAAI,CAAC,OAAO,MAAM;AAChD,UAAM,OAAkB,CAAC,UAAU,CAAC,GAC9B,aAAa,oBAAoB,MAAM,OAAO,CAAC,GAAG,MAAM,OAAO,GAAG,GAAG,GACrE,WAAuB;AAAA,MAC3B,QAAQ;AAAA,QACN,EAAC,OAAO,SAAS,SAAS,QAAQ,UAAU,EAAA;AAAA,QAC5C,EAAC,OAAO,YAAY,SAAS,cAAA;AAAA,MAAa;AAAA,IAC5C,GAEI,SAAS,MAAM,SAAS,CAAA,GAAI;AAAA,MAAI,CAAC,MAAM,MAC3C,YAAY,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,UAAU,GAAG;AAAA,IAAA,GAElD,eAAe,MAAM,eAAe,CAAA,GAAI;AAAA,MAAI,CAAC,YAAY,MAC7D,kBAAkB,YAAY,CAAC,GAAG,MAAM,eAAe,CAAC,GAAG,UAAU,GAAG;AAAA,IAAA;AAE1E,WAAO;AAAA,MACL,GAAG,eAAe;AAAA,QAChB,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,aAAa,MAAM;AAAA,QACnB,QAAQ,MAAM;AAAA,MAAA,CACf;AAAA,MACD,GAAI,aAAa,EAAC,OAAO,WAAA,IAAc,CAAA;AAAA,MACvC,GAAI,MAAM,SAAS,IAAI,EAAC,MAAA,IAAS,CAAA;AAAA,MACjC,GAAI,YAAY,SAAS,IAAI,EAAC,YAAA,IAAe,CAAA;AAAA,IAAC;AAAA,EAElD,CAAC;AAED,SAAA,0BAA0B,GAAG,GAgBtB,EAAC,YAdW;AAAA,IACjB,GAAG,eAAe;AAAA,MAChB,MAAM,UAAU;AAAA,MAChB,SAAS,UAAU;AAAA,MACnB,OAAO,UAAU;AAAA,MACjB,aAAa,UAAU;AAAA,MACvB,MAAM,UAAU;AAAA,MAChB,cAAc,UAAU;AAAA,MACxB,YAAY,UAAU;AAAA,IAAA,CACvB;AAAA,IACD,GAAI,gBAAgB,EAAC,OAAO,cAAA,IAAiB,CAAA;AAAA,IAC7C;AAAA,EAAA,GAGkB,QAAQ,IAAI,OAAA;AAClC;AAKA,SAAS,oBACP,SACA,MACA,KAC0B;AAC1B,SAAI,CAAC,WAAW,QAAQ,WAAW,IAAU,YAAY,SAAY,SAAY,CAAA,IAC1E,QAAQ,IAAI,CAAC,OAAO,MAAM;AAC/B,QAAI,MAAM,SAAS,QAAS,QAAO;AACnC,UAAM,YAAY;AAAA,MAChB,GAAG,eAAe,EAAC,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,aAAa,MAAM,YAAA,CAAY;AAAA,MACxF,MAAM;AAAA,MACN,QAAQ,EAAC,MAAM,QAAA;AAAA,IAAO;AAExB,WAAA,IAAI,YAAY,IAAI,WAAW,EAAC,MAAM,MAAM,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,EAAA,CAAE,GAC9D;AAAA,EACT,CAAC;AACH;AAEA,SAAS,QAAQ,SAAwD;AACvE,SAAO,IAAI,KAAK,WAAW,CAAA,GAAI,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC;AACpE;AAMA,SAAS,YAAY,MAAqB,MAAiB,UAAsB,KAAgB;AAC/F,QAAM,YAAY,oBAAoB,KAAK,OAAO,CAAC,GAAG,MAAM,OAAO,GAAG,GAAG,GACnE,MAAkB;AAAA,IACtB,QAAQ,CAAC,EAAC,OAAO,QAAQ,SAAS,QAAQ,SAAS,EAAA,GAAI,GAAG,SAAS,MAAM;AAAA,EAAA,GAErE,MAAM,WAAW,KAAK,KAAK,CAAC,GAAG,MAAM,KAAK,GAAG,KAAK,KAAK,MAAM,GAAG,GAChE,WAAW,KAAK,WAAW,CAAA,GAAI;AAAA,IAAI,CAAC,QAAQ,MAChD,cAAc,QAAQ,CAAC,GAAG,MAAM,WAAW,CAAC,GAAG,KAAK,KAAK,MAAM,GAAG;AAAA,EAAA;AAEpE,SAAO;AAAA,IACL,GAAG,eAAe;AAAA,MAChB,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,cAAc,KAAK;AAAA,IAAA,CACpB;AAAA,IACD,YAAY,KAAK,cAAc;AAAA,IAC/B,GAAI,YAAY,EAAC,OAAO,UAAA,IAAa,CAAA;AAAA,IACrC,GAAI,MAAM,EAAC,IAAA,IAAO,CAAA;AAAA,IAClB,GAAI,QAAQ,SAAS,IAAI,EAAC,QAAA,IAAW,CAAA;AAAA,EAAC;AAE1C;AAIA,SAAS,cACP,QACA,MACA,KACA,UACA,KACQ;AAER,MAAI,UAAU;AACZ,WAAO,mBAAmB,QAAQ,MAAM,KAAK,GAAG;AAGlD,QAAM,SAAS,cAAc,CAAC,eAAe,OAAO,KAAK,GAAG,OAAO,MAAM,CAAC,GACpE,MAAM,WAAW,OAAO,KAAK,CAAC,GAAG,MAAM,KAAK,GAAG,KAAK,UAAU,GAAG,KAAK,CAAA;AAC5E,SAAI,OAAO,WAAW,UAEpB,IAAI,KAAK,EAAC,MAAM,cAAc,MAAM,UAAU,QAAQ,OAAO,OAAA,CAAO,GAE/D;AAAA,IACL,GAAG,eAAe;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,OAAO,OAAO;AAAA,MACd,aAAa,OAAO;AAAA,MACpB,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,IAAA,CACjB;AAAA,IACD,GAAI,SAAS,EAAC,OAAA,IAAU,CAAA;AAAA,IACxB,GAAI,IAAI,SAAS,IAAI,EAAC,IAAA,IAAO,CAAA;AAAA,EAAC;AAElC;AAEA,SAAS,mBACP,QACA,MACA,KACA,KACQ;AACR,QAAM,MAAM,OAAO,OAAO,SAAU,WAAW,EAAC,OAAO,OAAO,UAAS,OAAO,OACxE,WAAW,WAAW,KAAK,KAAK,CAAC,GAAG,MAAM,OAAO,GAAG,GAAG;AAC7D,MAAI,UAAU;AACZ,UAAM,QAAQ,QAAQ,KAAK,QAAQ;AAC/B,aAAS,MAAM,SAAS,iBAC1B,IAAI,OAAO,KAAK;AAAA,MACd,MAAM,CAAC,GAAG,MAAM,OAAO;AAAA,MACvB,SACE,iBAAiB,OAAO,IAAI,iBAAiB,SAAS,KAAK,cACvD,MAAM,IAAI;AAAA,IAAA,CAEjB,GAEH,yBAAyB,OAAO,MAAM,IAAI,OAAO,UAAU,KAAK,CAAC,GAAG,MAAM,OAAO,GAAG,GAAG,GACnF,SAAO,IAAI,cAAc,IAAI,KAAK;AAAA,EACxC;AAEA,QAAM,UAAU,mBAAmB,IAAI,KAAK,KACtC,SAAS,cAAc,CAAC,SAAS,eAAe,OAAO,KAAK,GAAG,OAAO,MAAM,CAAC,GAC7E,MAAY,WAAW,CAAC,EAAC,MAAM,aAAa,QAAQ,UAAU,OAAO,EAAC,MAAM,QAAA,EAAO,CAAE,IAAI,CAAA;AAC/F,SAAO;AAAA,IACL,GAAG,eAAe;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,OAAO,OAAO;AAAA,MACd,aAAa,OAAO;AAAA,MACpB,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,IAAA,CACjB;AAAA,IACD;AAAA,IACA,GAAI,IAAI,SAAS,IAAI,EAAC,IAAA,IAAO,CAAA;AAAA,EAAC;AAElC;AAUA,SAAS,yBACP,YACA,OACA,UACA,KACA,MACA,KACM;AACN,QAAM,UAAU,IAAI,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC;AACvD,cAAY,UAAa,QAAQ,UAAU,SAAS,SACxD,IAAI,OAAO,KAAK;AAAA,IACd;AAAA,IACA,SACE,iBAAiB,UAAU,cAAc,KAAK,eAAe,SAAS,KAAK,mBACjE,QAAQ,KAAK,4IAEnB,SAAS,KAAK;AAAA,EAAA,CACrB;AACH;AAGA,SAAS,0BAA0B,KAAgB;AACjD,aAAW,CAAC,OAAO,EAAC,MAAM,KAAA,CAAK,KAAK,IAAI;AAClC,QAAI,cAAc,IAAI,KAAK,KAC/B,IAAI,OAAO,KAAK;AAAA,MACd;AAAA,MACA,SACE,gBAAgB,IAAI,kJAEqB,IAAI;AAAA,IAAA,CAChD;AAEL;AAMA,SAAS,kBACP,YACA,MACA,UACA,KACY;AACZ,QAAM,MAAM,WAAW,WAAW,KAAK,CAAC,GAAG,MAAM,KAAK,GAAG,UAAU,QAAW,GAAG;AACjF,SAAO;AAAA,IACL,GAAG,eAAe;AAAA,MAChB,MAAM,WAAW;AAAA,MACjB,OAAO,WAAW;AAAA,MAClB,aAAa,WAAW;AAAA,MACxB,IAAI,WAAW;AAAA,MACf,SAAS,WAAW;AAAA,IAAA,CACrB;AAAA,IACD,QAAQ,WAAW,UAAU;AAAA,IAC7B,GAAI,MAAM,EAAC,QAA8B,CAAA;AAAA,EAAC;AAE9C;AAMA,SAAS,WACP,KACA,MACA,KACA,YACA,KACkB;AAClB,MAAK;AACL,WAAO,IAAI,IAAI,CAAC,IAAI,MAAM,UAAU,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,YAAY,GAAG,CAAC;AAC7E;AAEA,SAAS,UACP,IACA,MACA,KACA,YACA,KACI;AACJ,MAAI,GAAG,SAAS,cAAc;AAC5B,UAAM,OAAO,GAAG,QAAQ;AACxB,WAAI,SAAS,UACX,IAAI,OAAO,KAAK;AAAA,MACd,MAAM,CAAC,GAAG,MAAM,MAAM;AAAA,MACtB,SAAS;AAAA,IAAA,CACV,GAEI,EAAC,MAAM,cAAc,MAAM,QAAQ,IAAI,QAAQ,GAAG,OAAA;AAAA,EAC3D;AACA,MAAI,GAAG,SAAS,QAAS,QAAO,eAAe,IAAI,MAAM,KAAK,GAAG;AACjE,QAAM,SAAS,WAAW,GAAG,QAAQ,KAAK,CAAC,GAAG,MAAM,QAAQ,GAAG,GAAG,KAAK,YAAY,GAAG,MAAM;AAC5F,SAAO,EAAC,GAAG,IAAI,OAAA;AACjB;AAEA,MAAM,eAAe,EAAC,OAAO,EAAC,MAAM,QAAA,GAAU,IAAI,EAAC,MAAM,QAAK;AAE9D,SAAS,eACP,IACA,MACA,KACA,KACI;AACJ,QAAM,SAAS,WAAW,GAAG,QAAQ,KAAK,CAAC,GAAG,MAAM,QAAQ,GAAG,GAAG,KAAK,YAAY,GAAG,MAAM;AAC5F,MAAI,GAAG,MAAM,SAAS;AACpB,WAAA,IAAI,OAAO,KAAK;AAAA,MACd,MAAM,CAAC,GAAG,MAAM,OAAO;AAAA,MACvB,SAAS,yEAAyE,GAAG,MAAM,IAAI;AAAA,IAAA,CAChG,GACM,EAAC,MAAM,gBAAgB,QAAQ,OAAO,GAAG,MAAA;AAElD,QAAM,aAAa,GAAG,aAAa,SAAS,SACtC,UAAU,GAAG,aAAa,MAAM,MAChC,SAAiC,EAAC,GAAG,GAAG,MAAM,OAAA;AACpD,aAAW,CAAC,OAAO,MAAM,KAAK;AAAA,IAC5B,CAAC,YAAY,aAAa,KAAK;AAAA,IAC/B,CAAC,SAAS,aAAa,EAAE;AAAA,EAAA,GACf;AACV,QAAI,SAAS,QAAQ;AACnB,UAAI,OAAO,KAAK;AAAA,QACd,MAAM,CAAC,GAAG,MAAM,SAAS,UAAU,KAAK;AAAA,QACxC,SACE,sBAAsB,KAAK;AAAA,MAAA,CAE9B;AACD;AAAA,IACF;AACA,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO,EAAC,MAAM,gBAAgB,QAAQ,OAAO,EAAC,MAAM,UAAU,SAAM;AACtE;AAKA,SAAS,WACP,KACA,KACA,MACA,KAC4B;AAC5B,QAAM,SACJ,IAAI,UAAU,SAAY,IAAI,SAAS,IAAI,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK;AACvF,aAAW,SAAS;AAClB,QAAI,MAAM,QAAQ,IAAI,IAAI,KAAK,EAAG,QAAO,EAAC,OAAO,MAAM,OAAO,OAAO,IAAI,MAAA;AAE3E,QAAM,YAAY,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,KAAA,CAAM,EAAE,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAC/F,MAAI,OAAO,KAAK;AAAA,IACd;AAAA,IACA,SACE,oBAAoB,IAAI,KAAK,IAAI,IAAI,QAAQ,YAAY,IAAI,KAAK,OAAO,EAAE,qDAChC,UAAU,KAAK,IAAI,KAAK,QAAQ;AAAA,EAAA,CAC9E;AAEH;AAEA,SAAS,QAAQ,KAAiB,KAA6C;AAC7E,SAAO,IAAI,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,IAAI,KAAK,GAAG,QAAQ,IAAI,IAAI,KAAK;AAC7E;AAGA,SAAS,YAAY,KAAwC;AAC3D,SAAO,EAAC,OAAO,IAAI,SAAS,YAAY,OAAO,IAAI,MAAA;AACrD;AAIA,SAAS,eAAe,OAA0D;AAChF,MAAI,EAAA,CAAC,SAAS,MAAM,WAAW;AAC/B,WAAO,+BAA+B,KAAK;AAC7C;AAEA,SAAS,cAAc,OAAmD;AACxE,QAAM,UAAU,MAAM,OAAO,CAAC,MAAmB,MAAM,MAAS;AAChE,MAAI,QAAQ,WAAW;AACvB,WAAI,QAAQ,WAAW,IAAU,QAAQ,CAAC,IACnC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,MAAM;AACjD;AAEA,SAAS,eAAkD,KAAW;AACpE,QAAM,MAA+B,CAAA;AACrC,aAAW,CAAC,GAAG,KAAK,KAAK,OAAO,QAAQ,GAAG;AACrC,cAAU,WAAW,IAAI,CAAC,IAAI;AAEpC,SAAO;AACT;AC1aA,MAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQM,wBAAwB,CAAC,SAAS,YAAY,KAAK;AAEzD,SAAS,UAAU,KAA+B;AAChD,SAAO,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI;AAChD;AAEA,SAAS,gBACP,OACA,MACA,QACa;AACb,QAAM,2BAAW,IAAA;AACjB,aAAW,EAAC,MAAM,KAAA,KAAS;AACrB,SAAK,IAAI,IAAI,KACf,OAAO,KAAK,EAAC,MAAM,SAAS,aAAa,IAAI,KAAK,IAAI,+BAAA,CAA+B,GAEvF,KAAK,IAAI,IAAI;AAEf,SAAO;AACT;AAEA,SAAS,YAAY,KAAyB,QAAwC;AACpF,QAAM,aAAa;AAAA,IACjB,IAAI,OAAO,IAAI,CAAC,OAAO,OAAO,EAAC,MAAM,MAAM,MAAM,MAAM,CAAC,UAAU,GAAG,MAAM,IAAG;AAAA,IAC9E;AAAA,IACA;AAAA,EAAA;AAEF,aAAW,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,WAAW;AAC7C,UAAM,YAAY;AAAA,OACf,MAAM,SAAS,CAAA,GAAI,IAAI,CAAC,MAAM,OAAO;AAAA,QACpC,MAAM,KAAK;AAAA,QACX,MAAM,CAAC,UAAU,GAAG,SAAS,GAAG,MAAM;AAAA,MAAA,EACtC;AAAA,MACF,uBAAuB,MAAM,IAAI;AAAA,MACjC;AAAA,IAAA;AAEF;AAAA,OACG,MAAM,eAAe,CAAA,GAAI,IAAI,CAAC,GAAG,OAAO;AAAA,QACvC,MAAM,EAAE;AAAA,QACR,MAAM,CAAC,UAAU,GAAG,eAAe,GAAG,MAAM;AAAA,MAAA,EAC5C;AAAA,MACF,6BAA6B,MAAM,IAAI;AAAA,MACvC;AAAA,IAAA,GAEF,WAAW,KAAK,GAAG,WAAW,MAAM;AAAA,EACtC;AACA,SAAO;AACT;AAEA,SAAS,WACP,KACA,GACA,WACA,QACM;AACN,QAAM,QAAQ,IAAI,OAAO,CAAC;AAC1B,aAAW,CAAC,GAAG,IAAI,MAAM,MAAM,SAAS,IAAI,WAAW;AACrD,UAAM,OAAkB,CAAC,UAAU,GAAG,SAAS,CAAC;AAChD;AAAA,OACG,KAAK,WAAW,CAAA,GAAI,IAAI,CAAC,QAAQ,OAAO;AAAA,QACvC,MAAM,OAAO;AAAA,QACb,MAAM,CAAC,GAAG,MAAM,WAAW,GAAG,MAAM;AAAA,MAAA,EACpC;AAAA,MACF,wBAAwB,KAAK,IAAI;AAAA,MACjC;AAAA,IAAA,GAEF,sBAAsB,MAAM,WAAW,MAAM,MAAM;AAAA,EACrD;AACF;AAQA,SAAS,sBACP,MACA,WACA,MACA,QACM;AACN,oBAAkB,KAAK,KAAK,WAAW,CAAC,GAAG,MAAM,KAAK,GAAG,MAAM;AAC/D,aAAW,CAAC,GAAG,MAAM,MAAM,KAAK,WAAW,CAAA,GAAI,QAAA;AAC7C,sBAAkB,OAAO,KAAK,WAAW,CAAC,GAAG,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM;AAEnF;AAEA,SAAS,kBACP,KACA,WACA,MACA,QACM;AACN,aAAW,CAAC,GAAG,EAAE,MAAM,OAAO,CAAA,GAAI,QAAA;AAC5B,OAAG,SAAS,gBAAgB,UAAU,IAAI,GAAG,IAAI,KACrD,OAAO,KAAK;AAAA,MACV,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM;AAAA,MACzB,SACE,4BAA4B,GAAG,IAAI,uDACnB,UAAU,SAAS,CAAC;AAAA,IAAA,CACvC;AAEL;AAEA,SAAS,kBACP,KACA,YACA,QACM;AACF,aAAW,IAAI,IAAI,YAAY,KACnC,OAAO,KAAK;AAAA,IACV,MAAM,CAAC,cAAc;AAAA,IACrB,SACE,iBAAiB,IAAI,YAAY,4CAChB,UAAU,UAAU,CAAC;AAAA,EAAA,CACzC;AACH;AAEA,SAAS,uBACP,KACA,YACA,QACM;AACN,aAAW,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,QAAA;AAClC,eAAW,CAAC,GAAG,CAAC,MAAM,MAAM,eAAe,CAAA,GAAI,QAAA;AACzC,iBAAW,IAAI,EAAE,EAAE,KACvB,OAAO,KAAK;AAAA,QACV,MAAM,CAAC,UAAU,GAAG,eAAe,GAAG,IAAI;AAAA,QAC1C,SACE,sBAAsB,EAAE,EAAE,4CACT,UAAU,UAAU,CAAC;AAAA,MAAA,CACzC;AAGP;AAOA,SAAS,iBAAiB,KAAyB,QAAiC;AAClF,QAAM,QAA2C,CAAA;AACjD,aAAW,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,WAAW;AAC7C,eAAW,CAAC,GAAG,IAAI,MAAM,MAAM,SAAS,IAAI,WAAW;AACrD,qBAAe,KAAK,SAAS,CAAC,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK;AACxE,iBAAW,CAAC,GAAG,MAAM,MAAM,KAAK,WAAW,CAAA,GAAI,QAAA;AAC7C,uBAAe,OAAO,SAAS,CAAC,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,KAAK;AAAA,IAE5F;AACA,eAAW,CAAC,GAAG,CAAC,MAAM,MAAM,eAAe,CAAA,GAAI,QAAA;AAC7C,qBAAe,EAAE,SAAS,CAAC,UAAU,GAAG,eAAe,GAAG,SAAS,GAAG,KAAK;AAAA,EAE/E;AACA,kBAAgB,OAAO,2DAAsD,MAAM;AACrF;AAEA,SAAS,eACP,SACA,MACA,OACM;AACN,aAAW,CAAC,GAAG,MAAM,MAAM,WAAW,CAAA,GAAI,QAAA;AACxC,UAAM,KAAK,EAAC,MAAM,OAAO,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,EAAA,CAAE;AAE9D;AAUA,SAAS,gBAAgB,KAAyB,QAAiC;AACjF,QAAM,QAAQ,IAAI,OAAO;AAAA,IAAQ,CAAC,OAAO,OACtC,MAAM,UAAU,CAAA,GAAI,IAAI,CAAC,OAAO,OAAwC;AAAA,MACvE,MAAM,MAAM;AAAA,MACZ,MAAM,CAAC,UAAU,GAAG,UAAU,GAAG,MAAM;AAAA,IAAA,EACvC;AAAA,EAAA;AAEJ;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AASA,SAAS,YAAY,KAA2C;AAC9D,QAAM,SAA2B;AAAA,IAC/B,EAAC,SAAS,IAAI,OAAO,OAAO,YAAY,MAAM,CAAC,OAAO,GAAG,OAAO,iBAAA;AAAA,EAAgB;AAElF,aAAW,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,WAAW;AAC7C,WAAO,KAAK;AAAA,MACV,SAAS,MAAM;AAAA,MACf,OAAO;AAAA,MACP,MAAM,CAAC,UAAU,GAAG,OAAO;AAAA,MAC3B,OAAO,UAAU,MAAM,IAAI;AAAA,IAAA,CAC5B;AACD,eAAW,CAAC,GAAG,IAAI,MAAM,MAAM,SAAS,CAAA,GAAI,QAAA;AAC1C,aAAO,KAAK;AAAA,QACV,SAAS,KAAK;AAAA,QACd,OAAO;AAAA,QACP,MAAM,CAAC,UAAU,GAAG,SAAS,GAAG,OAAO;AAAA,QACvC,OAAO,SAAS,KAAK,IAAI;AAAA,MAAA,CAC1B;AAAA,EAEL;AACA,SAAO;AACT;AAYA,SAAS,mBAAmB,KAAyB,QAAiC;AACpF,aAAW,EAAC,SAAS,OAAO,MAAM,MAAA,KAAU,YAAY,GAAG;AACzD,eAAW,CAAC,GAAG,KAAK,MAAM,WAAW,CAAA,GAAI,QAAA;AACnC,YAAM,aAAa,OACnB,UAAU,aACZ,OAAO,KAAK;AAAA,QACV,MAAM,CAAC,GAAG,MAAM,GAAG,UAAU;AAAA,QAC7B,SACE,GAAG,KAAK,WAAW,MAAM,IAAI;AAAA,MAAA,CAEhC,IACQ,MAAM,OAAO,SAAS,UAC/B,OAAO,KAAK;AAAA,QACV,MAAM,CAAC,GAAG,MAAM,GAAG,UAAU;AAAA,QAC7B,SACE,gBAAgB,MAAM,IAAI,wCAAwC,MAAM,OAAO,IAAI;AAAA,MAAA,CAEtF;AAIT;AAOA,SAAS,qBAAqB,KAAyB,QAAiC;AACtF,aAAW,EAAC,SAAS,MAAM,MAAA,KAAU,YAAY,GAAG;AAClD;AAAA,OACG,WAAW,CAAA,GAAI,IAAI,CAAC,OAAO,OAAO,EAAC,MAAM,MAAM,MAAM,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,IAAG;AAAA,MAClF,uBAAuB,KAAK;AAAA,MAC5B;AAAA,IAAA;AAGN;AAEA,SAAS,gBAAgB,KAAyB,QAAiC;AACjF,QAAM,WAAW,IAAI,IAAY,uBAAuB,GAClD,QAAQ,OAAO,KAAK,IAAI,cAAc,EAAE;AAC9C,aAAW,QAAQ;AACZ,aAAS,IAAI,IAAI,KACtB,OAAO,KAAK;AAAA,MACV,MAAM,CAAC,cAAc,IAAI;AAAA,MACzB,SAAS,cAAc,IAAI,2BAA2B,IAAI;AAAA,IAAA,CAC3D;AAEH,aAAW,CAAC,MAAMA,KAAI,KAAK,OAAO,QAAQ,IAAI,cAAc,EAAE;AAC5D,uBAAmB,MAAMA,OAAM,OAAO,MAAM;AAEhD;AAEA,SAAS,mBACP,MACAA,OACA,OACA,QACM;AACN,aAAW,UAAU;AACd,kBAAcA,OAAM,MAAM,KAC/B,OAAO,KAAK;AAAA,MACV,MAAM,CAAC,cAAc,IAAI;AAAA,MACzB,SACE,cAAc,IAAI,YAAY,MAAM;AAAA,IAAA,CAEvC;AAIH,aAAW,SAAS;AACd,cAAU,QAAQ,CAAC,cAAcA,OAAM,KAAK,KAChD,OAAO,KAAK;AAAA,MACV,MAAM,CAAC,cAAc,IAAI;AAAA,MACzB,SACE,cAAc,IAAI,2BAA2B,KAAK;AAAA,IAAA,CAErD;AAEL;AAOA,SAAS,cAAcA,OAAc,MAAuB;AAC1D,SAAK,gBAAgB,KAAK,IAAI,IACvB,IAAI,OAAO,MAAM,IAAI,KAAK,EAAE,KAAKA,KAAI,IADJ;AAE1C;AAcA,SAAS,6BAA6B,KAAyB,QAAiC;AAC9F,aAAW,QAAQ,8BAA8B,GAAG;AAC7C,kBAAc,KAAK,MAAM,KAAK,KACnC,OAAO,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,SACE,GAAG,KAAK,KAAK;AAAA,IAAA,CAEhB;AAEL;AAEA,SAAS,8BAA8B,KAA0C;AAC/E,QAAM,QAAyB,CAAA;AAC/B,aAAW,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,WAAW;AAC7C,eAAW,CAAC,GAAG,CAAC,MAAM,MAAM,eAAe,CAAA,GAAI,QAAA;AAC7C,YAAM,KAAK;AAAA,QACT,MAAM,EAAE;AAAA,QACR,MAAM,CAAC,UAAU,GAAG,eAAe,GAAG,QAAQ;AAAA,QAC9C,OAAO,eAAe,EAAE,IAAI;AAAA,MAAA,CAC7B,GACD;AAAA,QACE,EAAE;AAAA,QACF,CAAC,UAAU,GAAG,eAAe,GAAG,SAAS;AAAA,QACzC,eAAe,EAAE,IAAI;AAAA,QACrB;AAAA,MAAA;AAGJ,eAAW,CAAC,GAAG,IAAI,MAAM,MAAM,SAAS,CAAA,GAAI,QAAA;AAC1C,gCAA0B,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,KAAK;AAAA,EAEpE;AACA,SAAO;AACT;AAEA,SAAS,0BAA0B,MAAY,MAAiB,OAA8B;AAC5F,aAAW,SAAS,CAAC,UAAU,gBAAgB,UAAU,GAAY;AACnE,UAAMA,QAAO,KAAK,KAAK;AACnB,IAAAA,UAAS,UACX,MAAM,KAAK,EAAC,MAAAA,OAAM,MAAM,CAAC,GAAG,MAAM,KAAK,GAAG,OAAO,SAAS,KAAK,IAAI,KAAK,KAAK,IAAG;AAAA,EAEpF;AACA,sBAAoB,KAAK,SAAS,CAAC,GAAG,MAAM,SAAS,GAAG,SAAS,KAAK,IAAI,KAAK,KAAK;AACpF,aAAW,CAAC,GAAG,MAAM,MAAM,KAAK,WAAW,CAAA,GAAI,QAAA;AAC7C;AAAA,MACE,OAAO;AAAA,MACP,CAAC,GAAG,MAAM,WAAW,GAAG,SAAS;AAAA,MACjC,WAAW,OAAO,IAAI;AAAA,MACtB;AAAA,IAAA;AAGJ,0BAAwB,MAAM,MAAM,KAAK;AAC3C;AAEA,SAAS,wBAAwB,MAAY,MAAiB,OAA8B;AAC1F,QAAM,MAAM,KAAK;AACjB,MAAI,QAAQ,OAAW;AACvB,QAAM,UAAU,CAAC,GAAG,MAAM,cAAc;AACxC,QAAM,KAAK;AAAA,IACT,MAAM,IAAI;AAAA,IACV,MAAM,CAAC,GAAG,SAAS,SAAS;AAAA,IAC5B,OAAO,SAAS,KAAK,IAAI;AAAA,EAAA,CAC1B;AACD,aAAW,CAAC,OAAO,MAAM,KAAK;AAAA,IAC5B,CAAC,QAAQ,IAAI,IAAI;AAAA,IACjB,CAAC,WAAW,IAAI,OAAO;AAAA,EAAA;AAEvB,eAAW,CAAC,KAAKA,KAAI,KAAK,OAAO,QAAQ,UAAU,EAAE;AACnD,YAAM,KAAK;AAAA,QACT,MAAAA;AAAA,QACA,MAAM,CAAC,GAAG,SAAS,OAAO,GAAG;AAAA,QAC7B,OAAO,SAAS,KAAK,IAAI,kBAAkB,KAAK,KAAK,GAAG;AAAA,MAAA,CACzD;AAGP;AAEA,SAAS,oBACP,SACA,MACA,OACA,OACM;AACN,aAAW,CAAC,GAAG,MAAM,MAAM,WAAW,CAAA,GAAI,QAAA;AACxC,eAAW,CAAC,KAAKA,KAAI,KAAK,OAAO,QAAQ,OAAO,YAAY,EAAE;AAC5D,YAAM,KAAK;AAAA,QACT,MAAAA;AAAA,QACA,MAAM,CAAC,GAAG,MAAM,GAAG,YAAY,GAAG;AAAA,QAClC,OAAO,GAAG,KAAK,YAAY,OAAO,IAAI,cAAc,GAAG;AAAA,MAAA,CACxD;AAGP;AAGA,SAAS,sBAAsB,KAAyB,QAAiC;AACvF,aAAW,EAAC,SAAS,KAAA,KAAS,YAAY,GAAG;AAE3C,KADmB,WAAW,CAAA,GAAI,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EACxD,UAAU,KACxB,OAAO,KAAK;AAAA,MACV;AAAA,MACA,SAAS;AAAA,IAAA,CACV;AAEL;AAQO,SAAS,wBAAwB,KAA4C;AAClF,QAAM,SAA4B,CAAA,GAC5B,aAAa,YAAY,KAAK,MAAM;AAC1C,SAAA,kBAAkB,KAAK,YAAY,MAAM,GACzC,uBAAuB,KAAK,YAAY,MAAM,GAC9C,iBAAiB,KAAK,MAAM,GAC5B,gBAAgB,KAAK,MAAM,GAC3B,qBAAqB,KAAK,MAAM,GAChC,mBAAmB,KAAK,MAAM,GAC9B,gBAAgB,KAAK,MAAM,GAC3B,6BAA6B,KAAK,MAAM,GACxC,sBAAsB,KAAK,MAAM,GAC1B;AACT;ACxbO,SAAS,eAAe,YAAmD;AAChF,QAAM,QAAQ,SAAS,kBAAkB,UAAU,GAG7C,SAAS,aAAa,yBAAyB,YAAY,KAAK,GAChE,EAAC,YAAY,QAAQ,QAAQ,kBAAiB,gBAAgB,MAAM,GACpE,SAA4B,CAAC,GAAG,eAAe,GAAG,wBAAwB,MAAM,CAAC;AACvF,MAAI,OAAO,SAAS,EAAG,OAAM,IAAI,MAAM,sBAAsB,OAAO,MAAM,CAAC;AAC3E,SAAO;AACT;AAMO,SAAS,YAAY,OAAuC;AACjE,SAAO,aAAa,sBAAsB,OAAO,SAAS,eAAe,KAAK,CAAC;AACjF;AAEO,SAAS,WAAW,MAAoC;AAC7D,SAAO,aAAa,qBAAqB,MAAM,SAAS,cAAc,IAAI,CAAC;AAC7E;AAEO,SAAS,aAAa,QAA0C;AACrE,SAAO,aAAa,uBAAuB,QAAQ,SAAS,gBAAgB,MAAM,CAAC;AACrF;AAEO,SAAS,iBAAiB,YAAsD;AACrF,SAAO,aAAa,2BAA2B,YAAY,gBAAgB,UAAU,CAAC;AACxF;AAEO,SAAS,YAAY,OAAiD;AAC3E,SAAO,aAAa,2BAA2B,OAAO,SAAS,eAAe,KAAK,CAAC;AACtF;AAEO,SAAS,SAAS,IAA8B;AACrD,SAAO,aAAa,mBAAmB,IAAI,UAAU;AACvD;AAEO,SAAS,YAAY,OAAqB;AAC/C,SAAO,aAAa,aAAa,OAAO,SAAS,eAAe,KAAK,CAAC;AACxE;AAMO,SAAS,aAAa,QAAwB;AACnD,SAAO,aAAa,cAAc,QAAQ,SAAS,gBAAgB,MAAM,CAAC;AAC5E;AAEA,SAAS,gBAAgB,YAAyC;AAChE,QAAM,EAAC,MAAM,GAAA,IAAM;AACnB,SAAI,OAAO,QAAS,WAAiB,qBAAqB,IAAI,OAC1D,OAAO,MAAO,WAAiB,4BAAuB,EAAE,OACrD;AACT;AAuBO,SAAS,uBAAuB,YAAgD;AACrF,MAAI,CAAC,WAAW,KAAM,OAAM,IAAI,MAAM,+BAA+B;AACrE,SAAO;AACT;AAIA,SAAS,aAAgB,QAAqC,OAAU,OAAkB;AACxF,QAAM,SAAS,EAAE,UAAU,QAAQ,KAAK;AACxC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,sBAAsB,OAAO,kBAAkB,OAAO,MAAM,CAAC,CAAC;AAEhF,SAAO,OAAO;AAChB;AAEA,SAAS,SAAS,IAAY,OAAwB;AACpD,MAAI,SAAS,OAAO,SAAU,YAAY,UAAU,OAAO;AACzD,UAAM,MAAO,MAAkC;AAC/C,QAAI,OAAO,OAAQ,iBAAiB,GAAG,EAAE,KAAK,GAAG;AAAA,EACnD;AACA,SAAO;AACT;"}