@directive-run/core 1.20.2 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +33 -0
  2. package/dist/adapter-utils.cjs +1 -1
  3. package/dist/adapter-utils.d.cts +2 -2
  4. package/dist/adapter-utils.d.ts +2 -2
  5. package/dist/adapter-utils.js +1 -1
  6. package/dist/chunk-6NCC6RBC.js +3 -0
  7. package/dist/chunk-6NCC6RBC.js.map +1 -0
  8. package/dist/chunk-6PF2FRBG.js +7 -0
  9. package/dist/chunk-6PF2FRBG.js.map +1 -0
  10. package/dist/{chunk-RWFKUNF7.cjs → chunk-GACC2DMS.cjs} +2 -2
  11. package/dist/{chunk-RWFKUNF7.cjs.map → chunk-GACC2DMS.cjs.map} +1 -1
  12. package/dist/{chunk-4MNQDXH7.cjs → chunk-GBCWXTXW.cjs} +3 -3
  13. package/dist/chunk-GBCWXTXW.cjs.map +1 -0
  14. package/dist/chunk-GKMJ7NMP.cjs +7 -0
  15. package/dist/chunk-GKMJ7NMP.cjs.map +1 -0
  16. package/dist/{chunk-WKCMOU2F.js → chunk-KGTBTGOY.js} +2 -2
  17. package/dist/{chunk-WKCMOU2F.js.map → chunk-KGTBTGOY.js.map} +1 -1
  18. package/dist/{chunk-4QCKAJCX.cjs → chunk-MARZI3EY.cjs} +2 -2
  19. package/dist/{chunk-4QCKAJCX.cjs.map → chunk-MARZI3EY.cjs.map} +1 -1
  20. package/dist/chunk-OAPD3HIG.cjs +16 -0
  21. package/dist/chunk-OAPD3HIG.cjs.map +1 -0
  22. package/dist/chunk-QTY2FXZY.cjs +3 -0
  23. package/dist/chunk-QTY2FXZY.cjs.map +1 -0
  24. package/dist/{chunk-O4GQEV4G.js → chunk-RBF653NR.js} +2 -2
  25. package/dist/{chunk-O4GQEV4G.js.map → chunk-RBF653NR.js.map} +1 -1
  26. package/dist/{chunk-PXRV64PA.js → chunk-SFUVPP4L.js} +3 -3
  27. package/dist/chunk-SFUVPP4L.js.map +1 -0
  28. package/dist/chunk-YJEDX2JX.js +16 -0
  29. package/dist/chunk-YJEDX2JX.js.map +1 -0
  30. package/dist/{index-D_K7eEOF.d.ts → index-BgKC_ZT_.d.ts} +1 -1
  31. package/dist/{index-DApsqJ0h.d.cts → index-DRPkZ8HE.d.cts} +1 -1
  32. package/dist/index.cjs +2 -2
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +47 -43
  35. package/dist/index.d.ts +47 -43
  36. package/dist/index.js +2 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/internals.cjs +1 -1
  39. package/dist/internals.d.cts +60 -28
  40. package/dist/internals.d.ts +60 -28
  41. package/dist/internals.js +1 -1
  42. package/dist/plugins/index.cjs +2 -2
  43. package/dist/plugins/index.cjs.map +1 -1
  44. package/dist/plugins/index.d.cts +159 -3
  45. package/dist/plugins/index.d.ts +159 -3
  46. package/dist/plugins/index.js +2 -2
  47. package/dist/plugins/index.js.map +1 -1
  48. package/dist/{plugins-C6MxOvot.d.cts → plugins-5Supk7it.d.cts} +174 -43
  49. package/dist/{plugins-C6MxOvot.d.ts → plugins-5Supk7it.d.ts} +174 -43
  50. package/dist/{predicate-C92yT5IR.d.ts → predicate-C9oMO_ny.d.ts} +1 -1
  51. package/dist/{predicate-CV3YJDup.d.cts → predicate-DYb-3Mvl.d.cts} +1 -1
  52. package/dist/system-5FKUBLLV.cjs +2 -0
  53. package/dist/{system-BXCEQBBS.cjs.map → system-5FKUBLLV.cjs.map} +1 -1
  54. package/dist/system-6YWCXQOQ.js +2 -0
  55. package/dist/{system-AWEKWMNI.js.map → system-6YWCXQOQ.js.map} +1 -1
  56. package/dist/testing.cjs +1 -1
  57. package/dist/testing.d.cts +1 -1
  58. package/dist/testing.d.ts +1 -1
  59. package/dist/testing.js +1 -1
  60. package/dist/{utils-BZBBwS5A.d.cts → utils-DY8KTiD6.d.cts} +20 -7
  61. package/dist/{utils-BZBBwS5A.d.ts → utils-DY8KTiD6.d.ts} +20 -7
  62. package/dist/worker.cjs +1 -1
  63. package/dist/worker.d.cts +1 -1
  64. package/dist/worker.d.ts +1 -1
  65. package/dist/worker.js +1 -1
  66. package/package.json +1 -1
  67. package/dist/chunk-3ETCZLAY.js +0 -7
  68. package/dist/chunk-3ETCZLAY.js.map +0 -1
  69. package/dist/chunk-4MNQDXH7.cjs.map +0 -1
  70. package/dist/chunk-CLJMEU2A.js +0 -3
  71. package/dist/chunk-CLJMEU2A.js.map +0 -1
  72. package/dist/chunk-JGPPJV5P.cjs +0 -7
  73. package/dist/chunk-JGPPJV5P.cjs.map +0 -1
  74. package/dist/chunk-MDMMMZUZ.cjs +0 -3
  75. package/dist/chunk-MDMMMZUZ.cjs.map +0 -1
  76. package/dist/chunk-PNB73G3E.cjs +0 -16
  77. package/dist/chunk-PNB73G3E.cjs.map +0 -1
  78. package/dist/chunk-PXRV64PA.js.map +0 -1
  79. package/dist/chunk-QQEXRNAI.js +0 -16
  80. package/dist/chunk-QQEXRNAI.js.map +0 -1
  81. package/dist/system-AWEKWMNI.js +0 -2
  82. package/dist/system-BXCEQBBS.cjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/types/predicate.ts","../src/core/schema-introspection.ts","../src/core/predicate.ts"],"names":["PREDICATE_OPERATORS","PREDICATE_COMBINATORS","PRIMITIVE_KINDS","parseTypeName","typeName","branded","getKind","schema","dev_true_default","s","kindNode","getSchemaFieldKinds","out","root","facts","key","builder","node","innerKey","innerNode","COMMON_OPS","ORDERABLE_OPS","STRING_OPS","getOperatorsForKind","sets","m","first","intersection","op","listAllPredicateOperators","MAX_PREDICATE_DEPTH","isPlainObject","v","isPlainObjectStrict","proto","isOperatorObject","count","hasDollarKey","k","devWarn","isPredicate","c","walkPredicate","spec","visitor","path","seen","depth","clause","i","clausePath","obj","kind","children","child","childPath","value","opObj","isEmptyOrConfigPredicate","isPredicateBody","isTemplate","validatePredicate","checkValueJsonSafe","at","el","checkOperand","_factPath","operand","operandPath","factPath","dangerousRegex","source","validatePredicateAgainstSchema","kindMap","opts","errors","operatorCount","maxOperatorCount","maxArrayOperandLength","_operandPath","e","regexSource","allowedOps","_value","deepEqualSeen","pairId","id","deepEqual","a","b","guard","bArr","w","bEntries","used","ka","va","found","kb","vb","ak","bk","toComparable","relational","actual","applyOperator","prevValue","lo","hi","message","evalField","prev","keys","evaluatePredicate","fact","p","evaluatePredicateExplained","pathPrefix","childSpecs","passCount","pass","memoizedCache","memoizePredicate","predicate","cached","fn","extractDeps","prefix","deps","IDENTIFIER","stringifyValueQuiet","stringifyValue","evaluateTemplate","scope","tpl","end","present","extractTemplateKeys","evaluateKeySelector","selector","field","stableStringify","applyPatch","payload","set","safePayload","refKey"],"mappings":"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","file":"chunk-RWFKUNF7.cjs","sourcesContent":["/**\n * Data-configuration predicates and templates.\n *\n * A {@link FactPredicate} is a declarative, serializable boolean spec over a\n * module's fact namespace — the data form of a constraint `when`, an effect\n * `on`, or a boolean derivation. A {@link FactTemplate} is the value-producing\n * counterpart: a fact-interpolating string.\n *\n * Convention: `$` marks an operator/expression node inside a predicate or\n * template body (`$eq`, `$gte`, `$all`, `$template`, `$set`, `$ref`).\n * Definition arms (`compute`, `handler`, `patch`) stay sigil-free.\n *\n * Operators are `$`-prefixed so they can never collide with a fact key —\n * schema keys starting with `$` are rejected at registration.\n */\n\n// ============================================================================\n// Operators\n// ============================================================================\n\n/** Comparison operator names — the `$`-prefixed keys inside an operator object. */\nexport type PredicateOp =\n | \"$eq\"\n | \"$ne\"\n | \"$in\"\n | \"$nin\"\n | \"$exists\"\n | \"$gt\"\n | \"$gte\"\n | \"$lt\"\n | \"$lte\"\n | \"$between\"\n | \"$matches\"\n | \"$startsWith\"\n | \"$endsWith\"\n | \"$contains\"\n | \"$changed\";\n\n/** Combinator node keys. */\nexport type PredicateCombinatorKey = \"$all\" | \"$any\" | \"$not\";\n\n/**\n * Every reserved `$`-key recognized inside a predicate body.\n *\n * @internal\n */\nexport const PREDICATE_OPERATORS: ReadonlySet<string> = new Set<string>([\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n \"$changed\",\n]);\n\n/**\n * Combinator keys, as a runtime set.\n *\n * @internal\n */\nexport const PREDICATE_COMBINATORS: ReadonlySet<string> = new Set<string>([\n \"$all\",\n \"$any\",\n \"$not\",\n]);\n\n// ============================================================================\n// Operator object\n// ============================================================================\n\n/**\n * `true` when `V` supports relational operators (`$gt` … `$between`).\n * `[V]` tuple-wrapping suppresses distribution over union-typed facts.\n */\ntype IsOrderable<V> = [V] extends [number | bigint | Date]\n ? true\n : [V] extends [string]\n ? true\n : false;\n\n/**\n * The operator object permitted for a fact of type `V`. Built as a\n * **per-operator union** (one operator per member) rather than an\n * intersection — a typo'd operator (`$eqq`) then matches no member and is a\n * compile error, and a relational operator on a non-orderable fact resolves\n * to `never`.\n *\n * One operator per object — for two operators on the same fact, write the\n * array form or `$all`. This is by design (the type is the source of truth).\n *\n * `$matches` requires `RegExp`. The runtime throws on string operands.\n *\n * @example\n * ```ts\n * const op1: OperatorObject<number> = { $gte: 30 };\n * const op2: OperatorObject<string> = { $matches: /^J/i };\n * const op3: OperatorObject<string> = { $in: [\"red\", \"yellow\"] };\n * const op4: OperatorObject<string> = { $startsWith: \"Ada\" };\n * const op5: OperatorObject<string> = { $endsWith: \".com\" };\n * ```\n */\nexport type OperatorObject<V> =\n | { $eq: V }\n | { $ne: V }\n | { $in: readonly V[] }\n | { $nin: readonly V[] }\n | { $exists: boolean }\n | { $changed: true }\n | (IsOrderable<V> extends true\n ?\n | { $gt: V }\n | { $gte: V }\n | { $lt: V }\n | { $lte: V }\n | { $between: readonly [V, V] }\n : never)\n | ([V] extends [string]\n ?\n | { $matches: RegExp }\n | { $contains: string }\n | { $startsWith: string }\n | { $endsWith: string }\n : never)\n | ([V] extends [readonly (infer E)[]] ? { $contains: E } : never);\n\n/**\n * The spec for a single fact key: a bare value (equality), an operator\n * object, or — for an object-typed fact — a nested predicate (partial match).\n */\ntype PredicateField<V> =\n | V\n | OperatorObject<V>\n | ([V] extends [readonly unknown[]]\n ? never\n : [V] extends [object]\n ? PredicateObject<V>\n : never);\n\n// ============================================================================\n// FactPredicate\n// ============================================================================\n\n/**\n * Object form — every key is a fact name, every value a\n * {@link PredicateField}. Multiple keys are AND-ed. A nested object value\n * recurses (partial match), which is how cross-module namespaced predicates\n * (`{ self: { phase: \"red\" }, auth: { token: { $exists: true } } }`) work.\n */\nexport type PredicateObject<F> = {\n [K in keyof F]?: PredicateField<F[K]>;\n};\n\n/** Array form — explicit clauses, AND-ed. The codegen/devtools-friendly form. */\nexport type PredicateClause<F> = {\n [K in keyof F]: {\n readonly fact: K;\n readonly op: PredicateOp;\n readonly value: unknown;\n };\n}[keyof F];\n\n/** Combinator node — exactly one of `$all` / `$any` / `$not`. */\nexport type PredicateCombinator<F> =\n | { $all: readonly FactPredicate<F>[]; $any?: never; $not?: never }\n | { $any: readonly FactPredicate<F>[]; $all?: never; $not?: never }\n | { $not: FactPredicate<F>; $all?: never; $any?: never };\n\n/**\n * A declarative boolean spec over a fact namespace `F`. The data form of a\n * constraint `when`, an effect `on`, or a boolean derivation. Accepts an\n * object form, an array-of-clauses form, or a combinator node.\n *\n * Keys are **fact names only** — derivations are not addressable from inside\n * a predicate. To gate on a derivation, either reference the underlying fact\n * the derivation reads, or fall back to the function form of `when` / `on`.\n *\n * @example\n * ```ts\n * // Object form (the common case)\n * const p1: FactPredicate<{ phase: string; elapsed: number }> = {\n * phase: \"red\",\n * elapsed: { $gte: 30 },\n * };\n *\n * // Combinator form\n * const p2: FactPredicate<{ phase: string }> = {\n * $any: [{ phase: \"red\" }, { phase: \"yellow\" }],\n * };\n * ```\n */\nexport type FactPredicate<F> =\n | PredicateObject<F>\n | readonly PredicateClause<F>[]\n | PredicateCombinator<F>;\n\n// ============================================================================\n// FactTemplate\n// ============================================================================\n\n/**\n * A fact-interpolating string expression. `${key}` placeholders are replaced\n * with the named fact's value; `$${` emits a literal `${`. The value-producing\n * counterpart to {@link FactPredicate} — usable as a string derivation, a\n * constraint `require` field value, or an event `patch` value.\n *\n * @example { $template: \"Phase ${phase} for ${elapsed}s\" }\n */\nexport interface FactTemplate {\n readonly $template: string;\n}\n\n// ============================================================================\n// Selectors (resolver key, event patch)\n// ============================================================================\n\n/**\n * *Note: despite the \"Selector\" name, this does not select from facts — it\n * projects fields of the requirement payload for stable-stringification.*\n *\n * A resolver dedup key written as data: an ordered list of requirement-payload\n * field names. `key: [\"type\", \"to\"]` dedupes requirements by those fields.\n *\n * @example\n * ```ts\n * resolvers: {\n * fetch: {\n * requirement: \"FETCH\",\n * key: [\"url\", \"method\"] satisfies KeySelector<{ url: string; method: string }>,\n * resolve: doFetch,\n * },\n * }\n * ```\n */\nexport type KeySelector<R> = readonly (keyof R & string)[];\n\n/**\n * *Note: Directive's `$ref` is **not** a JSON Pointer or JSON Schema `$ref`.\n * It is a payload field copy — equivalent to `event.payload[key]`. Renaming\n * to `$from` is tracked as a possible v1.6+ additive alias.*\n *\n * A typed single-field copy from an event payload. Lives in the patch-spec\n * namespace — used inside a {@link PatchSpec} `$set` value.\n *\n * @example\n * ```ts\n * patch: { $set: { userId: { $ref: \"id\" } satisfies PayloadRef<{ id: string }> } }\n * ```\n */\nexport interface PayloadRef<P> {\n readonly $ref: keyof P & string;\n}\n\n/**\n * A patch value: a literal, a typed payload copy, or (for string facts) a\n * template. Lives in the patch-spec namespace — used inside a {@link PatchSpec}\n * `$set` block.\n *\n * @example\n * ```ts\n * const v1: PatchValue<boolean, { active: boolean }> = true;\n * const v2: PatchValue<string, { name: string }> = { $ref: \"name\" };\n * const v3: PatchValue<string, { name: string }> = { $template: \"user ${name}\" };\n * ```\n */\nexport type PatchValue<V, P> =\n | V\n | PayloadRef<P>\n | ([V] extends [string] ? FactTemplate : never);\n\n/**\n * An event handler written as data: assigns facts from literals, payload\n * fields (`$ref`), or interpolated strings (`$template`).\n *\n * @example\n * ```ts\n * const spec: PatchSpec<{ status: string; label: string }, { name: string }> = {\n * $set: {\n * status: \"active\",\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * ```\n */\nexport interface PatchSpec<F, P> {\n readonly $set: { [K in keyof F]?: PatchValue<F[K], P> };\n}\n\n// ============================================================================\n// Explain\n// ============================================================================\n\n/**\n * The per-clause result of an explained predicate evaluation. One entry per\n * leaf operator (`$eq`, `$gte`, …); combinator nodes (`$all`, `$any`, `$not`)\n * may also appear as headers when the runtime emits them — hence the union\n * over {@link PredicateCombinatorKey}.\n *\n * @example\n * ```ts\n * const result: ClauseResult = {\n * path: \"elapsed\",\n * op: \"$gte\",\n * expected: 30,\n * actual: 20,\n * pass: false,\n * };\n * ```\n */\nexport interface ClauseResult {\n /** Dotted path to the fact (`elapsed`, `auth.token`). */\n readonly path: string;\n /** The operator applied (`$gte`, `$eq`, …) — `$eq` for a bare value. */\n readonly op: PredicateOp | PredicateCombinatorKey;\n /**\n * The value the predicate expected. For combinator clauses (`$all`,\n * `$any`, `$not`) this is the child count.\n */\n readonly expected: unknown;\n /**\n * The actual fact value at evaluation time. For combinator clauses this\n * is the number of child clauses that passed.\n */\n readonly actual: unknown;\n /** Whether this clause passed. */\n readonly pass: boolean;\n /**\n * Children of a combinator clause (`$all`, `$any`, `$not`). Preserves the\n * tree shape of the original predicate so renderers (devtools,\n * `system.explain()`) can indent nested clauses.\n */\n readonly children?: ClauseResult[];\n}\n","/**\n * Schema Introspection\n *\n * A runtime discriminant for every `t.*()` builder result, so downstream\n * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`)\n * can ask \"what kind is this fact?\" without grepping the source.\n *\n * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`.\n * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.)\n * preserve / decorate it. When `_kind` is absent (legacy or third-party\n * builder), the parser falls back to reading the freeform `_typeName`\n * string. When even that fails: `{ kind: \"unknown\" }` — graceful close.\n *\n * This module has zero hot-path cost; it is only invoked when an\n * introspecting caller asks for it.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { PREDICATE_OPERATORS, type PredicateOp } from \"./types/predicate.js\";\n\n/**\n * Minimal structural shape for a schema-builder result that\n * introspection cares about. Avoids the contravariance trap on\n * `ExtendedSchemaType<T>` when `T = unknown` (which makes\n * `ChainableString` un-assignable to `ExtendedSchemaType<unknown>`\n * via the `_refinements` field). Any builder result is structurally\n * compatible with this shape.\n */\nexport interface IntrospectableSchema {\n readonly _kind?: SchemaKindNode;\n readonly _typeName?: string;\n}\n\n// ============================================================================\n// SchemaKindNode tree\n// ============================================================================\n\n/**\n * The closed set of kinds a Directive schema field can be.\n *\n * Drives operator availability via {@link getOperatorsForKind}: e.g.\n * `\"number\"` gets the orderable operators (`$gte`, `$lte`); `\"boolean\"`\n * does not.\n */\nexport type SchemaKind =\n | \"number\"\n | \"string\"\n | \"boolean\"\n | \"bigint\"\n | \"date\"\n | \"array\"\n | \"object\"\n | \"record\"\n | \"tuple\"\n | \"enum\"\n | \"literal\"\n | \"union\"\n | \"branded\"\n | \"unknown\";\n\n/**\n * A tree-shaped discriminator for a schema field. Composite kinds\n * (array, object, tuple, etc.) carry their element / shape information\n * so an LLM-prompt builder can show \"cartTotal is a number\" AND\n * \"items is an array of { sku: string, qty: number }\".\n *\n * `nullable` / `hasDefault` flags appear on the inner node (NOT a\n * wrapping kind) so operator-lookup on `t.number().nullable()` returns\n * the number's operators unchanged — `$gte` works on the non-null arm.\n */\nexport type SchemaKindNode = (\n | { kind: \"number\" | \"string\" | \"boolean\" | \"bigint\" | \"date\" | \"unknown\" }\n | {\n kind: \"literal\";\n value: string | number | boolean | null;\n primitive: \"string\" | \"number\" | \"boolean\" | \"null\";\n }\n | {\n kind: \"enum\";\n values: readonly (string | number)[];\n primitive: \"string\" | \"number\";\n }\n | { kind: \"array\"; element: SchemaKindNode }\n | { kind: \"tuple\"; elements: readonly SchemaKindNode[] }\n | { kind: \"object\"; shape: Record<string, SchemaKindNode> }\n | { kind: \"record\"; value: SchemaKindNode }\n | { kind: \"union\"; members: readonly SchemaKindNode[] }\n | { kind: \"branded\"; inner: SchemaKindNode }\n) & {\n /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */\n nullable?: boolean;\n /** True if the schema has a `.default()`. */\n hasDefault?: boolean;\n};\n\n// ============================================================================\n// Parse `_typeName` → SchemaKindNode (fallback for legacy / third-party)\n// ============================================================================\n\nconst PRIMITIVE_KINDS = new Set<SchemaKind>([\n \"number\",\n \"string\",\n \"boolean\",\n \"bigint\",\n \"date\",\n \"unknown\",\n]);\n\n/**\n * Best-effort parse of a freeform `_typeName` string into a structured\n * kind node. Used only when `_kind` is absent. Always falls back to\n * `{ kind: \"unknown\" }`; never throws.\n */\nfunction parseTypeName(typeName: string | undefined): SchemaKindNode {\n if (!typeName) return { kind: \"unknown\" };\n\n // \"Branded<inner>\" — recurse.\n const branded = /^Branded<(.+)>$/.exec(typeName);\n if (branded) {\n return { kind: \"branded\", inner: parseTypeName(branded[1]) };\n }\n\n // \"X | null\" / \"X | undefined\" — nullable wrapper.\n if (typeName.endsWith(\" | null\") || typeName.endsWith(\" | undefined\")) {\n const inner = parseTypeName(typeName.replace(/ \\| (null|undefined)$/, \"\"));\n\n return { ...inner, nullable: true };\n }\n\n // Bare primitive.\n if (PRIMITIVE_KINDS.has(typeName as SchemaKind)) {\n return { kind: typeName as SchemaKind } as SchemaKindNode;\n }\n\n // String-flavored named types (email, uuid, url, etc.) all map to \"string\"\n // for operator purposes.\n if (/^(email|uuid|url|cuid|datetime|iso\\b)/i.test(typeName)) {\n return { kind: \"string\" };\n }\n\n // Generic union \"X | Y | Z\" → union of parsed members (used by t.union()).\n if (typeName.includes(\" | \")) {\n const members = typeName.split(\" | \").map(parseTypeName);\n\n return { kind: \"union\", members };\n }\n\n // Bare names we recognize as composite without elements.\n if (typeName === \"array\")\n return { kind: \"array\", element: { kind: \"unknown\" } };\n if (typeName === \"object\") return { kind: \"object\", shape: {} };\n if (typeName === \"record\")\n return { kind: \"record\", value: { kind: \"unknown\" } };\n if (typeName === \"tuple\") return { kind: \"tuple\", elements: [] };\n if (typeName === \"union\") return { kind: \"union\", members: [] };\n\n return { kind: \"unknown\" };\n}\n\n// ============================================================================\n// Get the kind node for a single schema field\n// ============================================================================\n\n/**\n * Return the {@link SchemaKindNode} for a schema field. Prefers the\n * explicit `_kind` discriminant set by the builder; falls back to\n * parsing the freeform `_typeName` string for legacy / third-party\n * builders that don't set `_kind`.\n *\n * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder\n * that throws on property access returns `{ kind: \"unknown\" }` instead of\n * propagating the throw to introspecting callers.\n *\n * In dev mode, a function input (`typeof schema === \"function\"`) emits a\n * warning — common foot-gun where the caller forgot to invoke a builder\n * factory (e.g. wrote `t.number` instead of `t.number()`).\n *\n * @example\n * ```ts\n * getKind(t.number()) // → { kind: \"number\" }\n * getKind(t.string().nullable()) // → { kind: \"string\", nullable: true }\n * getKind(t.array(t.number())) // → { kind: \"array\", element: { kind: \"number\" } }\n * ```\n */\nexport function getKind(schema: unknown): SchemaKindNode {\n if (schema === null || schema === undefined) return { kind: \"unknown\" };\n if (typeof schema === \"function\") {\n if (isDevelopment) {\n console.warn(\n \"[Directive] getKind: received a function — did you forget () on a t.* builder? Example: write `t.number()`, not `t.number`.\",\n );\n }\n\n return { kind: \"unknown\" };\n }\n if (typeof schema !== \"object\") return { kind: \"unknown\" };\n const s = schema as IntrospectableSchema;\n\n // Hostile-getter guard: a third-party builder that throws on `_kind` /\n // `_typeName` reads must not crash an introspecting caller.\n let kindNode: SchemaKindNode | undefined;\n try {\n kindNode = s._kind;\n } catch {\n return { kind: \"unknown\" };\n }\n if (kindNode) return kindNode;\n\n let typeName: string | undefined;\n try {\n typeName = s._typeName;\n } catch {\n return { kind: \"unknown\" };\n }\n\n return parseTypeName(typeName);\n}\n\n// ============================================================================\n// Walk a module schema → Map<dotted-path, SchemaKindNode>\n// ============================================================================\n\n/**\n * Walk the `facts` block of a module schema and emit a flat map from\n * dotted path → kind node. Nested `t.object()` shapes flatten using\n * `.` as the separator, matching the convention used by\n * `OperatorObject<V>`'s nested-path support.\n *\n * Passing a top-level schema directly (without the `facts:` wrapper)\n * also works — anything iterable as `Record<string, ExtendedSchemaType>`\n * is acceptable.\n *\n * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is\n * silently skipped (treated as `{ kind: \"unknown\" }` for that field)\n * rather than aborting the whole walk.\n *\n * In dev mode, a top-level schema that yields an empty map (no\n * introspectable keys) emits a warning — common foot-gun where the\n * caller passed `myModule` instead of `myModule.schema`.\n */\nexport function getSchemaFieldKinds(\n schema: unknown,\n): Map<string, SchemaKindNode> {\n const out = new Map<string, SchemaKindNode>();\n if (!schema || typeof schema !== \"object\") return out;\n const root = schema as Record<string, unknown>;\n const factsCandidate =\n \"facts\" in root && root.facts && typeof root.facts === \"object\"\n ? root.facts\n : root;\n const facts = factsCandidate as Record<string, unknown>;\n\n for (const [key, builder] of Object.entries(facts)) {\n if (!builder || typeof builder !== \"object\") continue;\n let node: SchemaKindNode;\n try {\n node = getKind(builder);\n } catch {\n // A pathological builder whose getter throws past getKind's own\n // guards — skip the field but keep walking the rest.\n continue;\n }\n out.set(key, node);\n\n // Flatten nested object shapes one level — matches OperatorObject<V>'s\n // dotted-path support.\n if (node.kind === \"object\") {\n for (const [innerKey, innerNode] of Object.entries(node.shape)) {\n out.set(`${key}.${innerKey}`, innerNode);\n }\n }\n }\n\n if (out.size === 0 && isDevelopment) {\n console.warn(\n \"[Directive] getSchemaFieldKinds: schema appears empty (no introspectable keys). Did you pass the module instead of its schema? Pass `myModule.schema`, not `myModule`.\",\n );\n }\n\n return out;\n}\n\n// ============================================================================\n// Operator allowlist per kind\n// ============================================================================\n\nconst COMMON_OPS: readonly PredicateOp[] = [\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n];\n\nconst ORDERABLE_OPS: readonly PredicateOp[] = [\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n];\n\nconst STRING_OPS: readonly PredicateOp[] = [\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n];\n\n/**\n * Return the set of `PredicateOp` strings that are valid against a\n * given {@link SchemaKindNode}.\n *\n * Mirrors the type-level matrix encoded in `OperatorObject<V>` in\n * `types/predicate.ts` — drift between the two is enforced by the\n * compile-time conformance test\n * (`schema-introspection-conformance.test-d.ts`).\n *\n * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists`\n * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`,\n * `$lt`, `$lte`, `$between`\n * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains`\n * - **Array:** + `$contains` (over the element type)\n * - **Union:** *intersection* across members (the operand must be valid\n * for every branch).\n * - **Branded:** delegates to the inner kind.\n * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in`\n * operand restricted at the LLM-prompt layer (not enforced here).\n *\n * `nullable` does not change operator availability — `$gte` on a\n * nullable number is fine on the non-null arm; `$exists` handles null.\n */\nexport function getOperatorsForKind(\n node: SchemaKindNode,\n): readonly PredicateOp[] {\n switch (node.kind) {\n case \"number\":\n case \"bigint\":\n case \"date\":\n return [...COMMON_OPS, ...ORDERABLE_OPS];\n case \"string\":\n return [...COMMON_OPS, ...ORDERABLE_OPS, ...STRING_OPS];\n case \"boolean\":\n case \"unknown\":\n return COMMON_OPS;\n case \"array\":\n return [...COMMON_OPS, \"$contains\"];\n case \"object\":\n case \"record\":\n case \"tuple\":\n return COMMON_OPS;\n case \"literal\":\n case \"enum\":\n // Operators allowed by the underlying primitive.\n return getOperatorsForKind(\n node.primitive === \"number\"\n ? { kind: \"number\" }\n : node.primitive === \"boolean\"\n ? { kind: \"boolean\" }\n : node.primitive === \"null\"\n ? { kind: \"unknown\" }\n : { kind: \"string\" },\n );\n case \"branded\":\n return getOperatorsForKind(node.inner);\n case \"union\": {\n // Intersection of operators valid on every member.\n if (node.members.length === 0) return COMMON_OPS;\n const sets = node.members.map((m) => new Set(getOperatorsForKind(m)));\n const first = sets[0]!;\n const intersection: PredicateOp[] = [];\n for (const op of first) {\n if (sets.every((s) => s.has(op))) intersection.push(op);\n }\n\n return intersection;\n }\n default: {\n // Exhaustiveness check — TS will flag if a new kind is added without\n // a switch arm.\n const _exhaustive: never = node;\n void _exhaustive;\n\n return COMMON_OPS;\n }\n }\n}\n\n/**\n * Return all known predicate operators — convenience for prompt builders\n * that need to show the LLM the full set.\n */\nexport function listAllPredicateOperators(): readonly PredicateOp[] {\n return Array.from(PREDICATE_OPERATORS) as readonly PredicateOp[];\n}\n","/**\n * Runtime for data-configuration predicates and templates.\n *\n * Pure module — imports only its own types. Reads facts through whatever\n * object it is handed (the reactive `Facts` proxy in production, a plain\n * snapshot in tests), so it never depends on the engine, store, or tracking.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { stableStringify } from \"../utils/utils.js\";\nimport {\n type ClauseResult,\n type FactTemplate,\n PREDICATE_OPERATORS,\n type PatchSpec,\n type PredicateOp,\n} from \"./types/predicate.js\";\n\n// ============================================================================\n// Recursion bound\n// ============================================================================\n\n/**\n * Maximum predicate-AST recursion depth. Legitimate cross-module predicates\n * nest fewer than ~15 levels; 64 is generous but bounded — past it the runtime\n * dev-warns and bails rather than risking a stack overflow on a cyclic or\n * pathologically deep spec. Shared by every structural predicate walker\n * ({@link walkPredicate}, {@link evaluatePredicate}) so the cap lives in one\n * place.\n */\nexport const MAX_PREDICATE_DEPTH = 64;\n\n// ============================================================================\n// Discriminators\n// ============================================================================\n\n/** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */\ntype Scope = Record<string, unknown>;\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n\n return !(v instanceof Date) && !(v instanceof RegExp);\n}\n\n/**\n * True when `v` is a plain `{}` literal (its prototype is `Object.prototype`\n * or `null`). Excludes class instances, Date, RegExp, Map, Set, Promise, etc.\n */\nfunction isPlainObjectStrict(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n const proto = Object.getPrototypeOf(v);\n\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * True when every own key of `v` is a recognized `$`-operator (and there is ≥1).\n * If any key starts with `$` but is not a known operator, dev-warn (typo) and\n * still treat the value as an operator object so the typo is not masked as a\n * literal — `applyOperator` will return false for the unknown op.\n */\nfunction isOperatorObject(v: unknown): v is Record<string, unknown> {\n if (!isPlainObject(v)) {\n return false;\n }\n\n let count = 0;\n let hasDollarKey = false;\n for (const k of Object.keys(v)) {\n if (k.startsWith(\"$\")) {\n hasDollarKey = true;\n if (!PREDICATE_OPERATORS.has(k)) {\n devWarn(\n `predicate: unknown operator \"${k}\" — looks like a typo. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n } else if (hasDollarKey || count === 0) {\n // Mixed $/non-$ keys aren't an operator object; let the caller treat\n // it as a literal/recursive predicate. The non-$ key check happens\n // below by short-circuiting when a non-$ key appears.\n return false;\n }\n count++;\n }\n\n if (!hasDollarKey) {\n return false;\n }\n\n // All keys are `$`-prefixed: this is an operator object, even if some keys\n // are typos. An unknown op makes applyOperator() return false.\n return count > 0;\n}\n\n/**\n * True when `v` is a data-form spec (predicate object/array) rather than a\n * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.)\n * — only plain `{}` literals and arrays of plain clause shapes qualify.\n *\n * @example\n * ```ts\n * isPredicate({ phase: \"red\" }); // true\n * isPredicate((f) => f.phase === \"red\"); // false\n * isPredicate([{ fact: \"phase\", op: \"$eq\", value: \"red\" }]); // true\n * ```\n */\nexport function isPredicate(v: unknown): boolean {\n if (v === null) {\n return false;\n }\n if (Array.isArray(v)) {\n return v.every(\n (c) =>\n isPlainObjectStrict(c) &&\n \"fact\" in (c as object) &&\n \"op\" in (c as object),\n );\n }\n\n return isPlainObjectStrict(v);\n}\n\n// ============================================================================\n// Structural traversal\n// ============================================================================\n\n/**\n * Visitor passed to {@link walkPredicate}. Every callback is optional; a\n * walker implements only the arms it cares about.\n */\nexport interface PredicateVisitor {\n /**\n * A leaf operator clause: a fact + a `$`-operator + its operand. Fires once\n * per operator in a multi-operator object.\n *\n * @param factPath - Dotted path to the fact (`elapsed`, `auth.token`).\n * @param op - The operator key (`$gte`, `$matches`, …).\n * @param operand - The operator's operand value.\n * @param operandPath - Dotted path to the operand for diagnostics\n * (`elapsed.$gte`, `value` / `[0].value` for the array-clause form).\n */\n operator?(\n factPath: string,\n op: string,\n operand: unknown,\n operandPath: string,\n ): void;\n /**\n * A bare-value (equality) clause — a fact mapped to a non-object literal,\n * an array, or a non-plain class instance (Date, RegExp, Set, …).\n *\n * @param factPath - Dotted path to the fact.\n * @param value - The equality operand.\n */\n literal?(factPath: string, value: unknown): void;\n /**\n * A combinator node (`$all` / `$any` / `$not`), called before descending.\n * Return `false` to skip its children.\n */\n combinator?(kind: \"$all\" | \"$any\" | \"$not\"): boolean | void;\n /**\n * A nested-object (cross-module pivot) key, called before descending.\n * Return `false` to skip its children.\n */\n nested?(key: string): boolean | void;\n /**\n * A `$`-prefixed key appearing where a fact key was expected — either an\n * unknown/typo operator, or an operator mixed with fact keys at predicate\n * top level.\n *\n * @param key - The stray `$`-key.\n * @param factPath - Dotted path to the stray key.\n */\n strayOperatorKey?(key: string, factPath: string): void;\n /**\n * Called when traversal bails out early — a cycle was re-encountered or\n * the depth cap was hit. The subtree below the bail point is NOT visited.\n */\n bail?(reason: \"cycle\" | \"depth\"): void;\n}\n\n/**\n * Single depth-guarded, cycle-guarded structural traversal of a predicate\n * AST. The pure structural walkers — dependency extraction, `$changed`\n * detection, empty/config detection, serialization validation — share this\n * so a new operator or combinator is threaded through one place.\n *\n * Handles the object form, the array-clause form, combinator nodes, nested\n * cross-module objects, operator objects, and bare-value literals. It does\n * **not** evaluate — see {@link evaluatePredicate} for that.\n *\n * @internal\n */\nexport function walkPredicate(\n spec: unknown,\n visitor: PredicateVisitor,\n path = \"\",\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): void {\n if (depth > MAX_PREDICATE_DEPTH) {\n if (isDevelopment) {\n console.warn(\n `[Directive] predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n }\n visitor.bail?.(\"depth\");\n\n return;\n }\n\n // Array-clause form — each `{ fact, op, value }` clause is a leaf operator.\n if (Array.isArray(spec)) {\n spec.forEach((clause, i) => {\n if (!isPlainObject(clause)) {\n return;\n }\n const c = clause as Record<string, unknown>;\n if (typeof c.fact === \"string\" && typeof c.op === \"string\") {\n const clausePath = path ? `${path}[${i}]` : `[${i}]`;\n visitor.operator?.(\n path ? `${path}.${c.fact}` : c.fact,\n c.op,\n c.value,\n `${clausePath}.value`,\n );\n }\n });\n\n return;\n }\n\n if (!isPlainObject(spec)) {\n return;\n }\n if (seen.has(spec)) {\n if (isDevelopment) {\n console.warn(\"[Directive] walkPredicate: cyclic predicate spec\");\n }\n visitor.bail?.(\"cycle\");\n\n return;\n }\n seen.add(spec);\n\n const obj = spec as Record<string, unknown>;\n\n // Combinator node — descend into children unless the visitor opts out.\n for (const kind of [\"$all\", \"$any\", \"$not\"] as const) {\n if (kind in obj) {\n const descend = visitor.combinator?.(kind);\n if (descend === false) {\n return;\n }\n const children =\n kind === \"$not\" ? [obj.$not] : ((obj[kind] as unknown[]) ?? []);\n for (const child of children) {\n walkPredicate(child, visitor, path, seen, depth + 1);\n }\n\n return;\n }\n }\n\n // Object form — one entry per key.\n for (const key of Object.keys(obj)) {\n const childPath = path ? `${path}.${key}` : key;\n\n if (key.startsWith(\"$\")) {\n // A `$`-key at fact position — typo operator or top-level operator\n // mixed with fact keys. Surface it; do not descend.\n visitor.strayOperatorKey?.(key, childPath);\n continue;\n }\n\n const value = obj[key];\n\n if (isOperatorObject(value)) {\n const opObj = value as Record<string, unknown>;\n for (const op of Object.keys(opObj)) {\n visitor.operator?.(childPath, op, opObj[op], `${childPath}.${op}`);\n }\n continue;\n }\n\n // Only a strict plain object (`{}` / `Object.create(null)`) recurses as\n // a nested cross-module predicate. A Set, Map, or class instance is a\n // bare-value leaf — surfacing it as `literal` lets a walker inspect its\n // runtime class (e.g. validatePredicate's JSON-serializability check).\n if (isPlainObjectStrict(value)) {\n const descend = visitor.nested?.(key);\n if (descend === false) {\n continue;\n }\n walkPredicate(value, visitor, childPath, seen, depth + 1);\n continue;\n }\n\n // Bare value — equality leaf (also array / Set / Map / class instances).\n visitor.literal?.(childPath, value);\n }\n}\n\n/**\n * True when `v` structurally passes {@link isPredicate} but contains no\n * operators, no combinators, and no fact-clause entries that resolve to a\n * primitive/operator leaf — i.e. an empty `{}` or a deeply-nested object\n * tree that never bottoms out in a leaf value. Used by the dynamic\n * `register()` / `assign()` paths to dev-warn when a config object is\n * passed where a predicate (or function) was expected.\n *\n * Returns `false` for arrays — array-form predicates with `fact`+`op`\n * clauses are handled by the structural `isPredicate` check upstream.\n *\n * @example\n * ```ts\n * isEmptyOrConfigPredicate({}); // true (empty — config-object misuse)\n * isEmptyOrConfigPredicate({ phase: \"red\" }); // false (real fact clause)\n * isEmptyOrConfigPredicate({ $eq: 5 }); // false (operator)\n * isEmptyOrConfigPredicate({ count: { $gt: 5 } }); // false (operator clause)\n * ```\n *\n * @internal\n */\nexport function isEmptyOrConfigPredicate(v: unknown): boolean {\n // Arrays and non-plain-object specs are never \"empty config objects\".\n if (!isPlainObjectStrict(v)) {\n return false;\n }\n\n // A spec is a config tree only when walkPredicate fires NONE of the\n // predicate-semantic callbacks — no operator, no combinator, no literal\n // leaf, no stray `$`-key. Nested plain objects are descended; an empty\n // `{}` or a tree of empty `{}` fires nothing and stays \"config\". A cycle\n // or depth-cap bail is treated as \"not a config object\" (can't determine\n // — fail safe so the dev-warn is not spuriously emitted).\n let isPredicateBody = false;\n walkPredicate(v, {\n operator() {\n isPredicateBody = true;\n },\n literal() {\n isPredicateBody = true;\n },\n combinator() {\n isPredicateBody = true;\n },\n strayOperatorKey() {\n isPredicateBody = true;\n },\n bail() {\n isPredicateBody = true;\n },\n });\n\n return !isPredicateBody;\n}\n\n/**\n * True when `v` is a {@link FactTemplate} (`{ $template: string }`).\n *\n * @example\n * ```ts\n * isTemplate({ $template: \"Hi ${name}\" }); // true\n * isTemplate({ $set: { name: \"x\" } }); // false\n * ```\n */\nexport function isTemplate(v: unknown): v is FactTemplate {\n return (\n isPlainObject(v) &&\n Object.hasOwn(v, \"$template\") &&\n typeof (v as { $template: unknown }).$template === \"string\"\n );\n}\n\n// ============================================================================\n// Load-time validation\n// ============================================================================\n\n/**\n * Throw when a predicate spec contains an operand that cannot survive a\n * JSON round-trip — i.e. that would silently mis-evaluate if the spec was\n * loaded from `JSON.parse`.\n *\n * Three failure classes are detected:\n *\n * - **Lost `RegExp` operand.** A `$matches` operand that is not a\n * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as\n * `{}`, so a `$matches` clause with an empty-object operand is the\n * signature of a regex that did not survive serialization. Reify it\n * with `new RegExp(pattern, flags)` before installing the predicate.\n * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a\n * `bigint` operand cannot have been produced by a JSON pipeline and\n * cannot be persisted by one either.\n * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all\n * members; a predicate carrying one is not JSON-safe.\n *\n * This is an opt-in helper — the engine does not call it automatically.\n * Users who load predicates from JSON should call it after `JSON.parse`\n * to fail loud rather than silently mis-evaluate. See the\n * \"Serialization\" section of RFC-0004.\n *\n * @example\n * ```ts\n * validatePredicate({ phase: { $matches: {} } });\n * // throws — empty object where a RegExp is required\n *\n * validatePredicate({ phase: \"red\", elapsed: { $gte: 30 } });\n * // ok — JSON-clean operands\n * ```\n */\nexport function validatePredicate(spec: unknown, path = \"\"): void {\n /**\n * Recursively walk an operand's object/array structure, throwing on any\n * value that cannot survive a JSON round-trip — `bigint`, `Set`, `Map`, or\n * a nested `RegExp`. Depth- and cycle-guarded. A top-level operand is\n * inspected by the operator-specific {@link checkOperand} (which permits a\n * `RegExp` as the direct `$matches` operand); this helper handles values\n * nested *inside* a plain-object or array operand, where a `RegExp` is just\n * as JSON-unsafe as a `Set`.\n */\n function checkValueJsonSafe(\n value: unknown,\n at: string,\n seen: WeakSet<object>,\n depth: number,\n ): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (value instanceof RegExp) {\n throw new Error(\n `[Directive] validatePredicate: RegExp operand at \"${at}\" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`,\n );\n }\n if (value === null || typeof value !== \"object\") {\n return;\n }\n if (depth > MAX_PREDICATE_DEPTH) {\n return;\n }\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, seen, depth + 1);\n });\n\n return;\n }\n\n for (const k of Object.keys(value as Record<string, unknown>)) {\n checkValueJsonSafe(\n (value as Record<string, unknown>)[k],\n at ? `${at}.${k}` : k,\n seen,\n depth + 1,\n );\n }\n }\n\n /** Throw on a JSON-unrehydratable operand value. */\n function checkOperand(value: unknown, op: string, at: string): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (op === \"$matches\" && !(value instanceof RegExp)) {\n throw new Error(\n `[Directive] validatePredicate: $matches operand at \"${at}\" must be a RegExp; got ${value === null ? \"null\" : typeof value}. A regex lost to JSON.parse becomes {} — reify with new RegExp(pattern, flags) before installing.`,\n );\n }\n // A plain-object / array operand (e.g. `$eq: { ... }`, `$in: [ ... ]`)\n // can carry a `bigint`, `Set`, `Map`, or nested `RegExp` arbitrarily deep\n // — `checkOperand` only sees the operand's top type, so recurse into its\n // structure. The direct `$matches` RegExp is handled above and never\n // reaches this branch (a RegExp is not a plain object / array).\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, new WeakSet(), 1);\n });\n } else if (isPlainObjectStrict(value)) {\n for (const k of Object.keys(value)) {\n checkValueJsonSafe(value[k], `${at}.${k}`, new WeakSet(), 1);\n }\n }\n }\n\n // Top-level Set / Map node — a regex / set / map handed in directly as the\n // whole spec. walkPredicate would treat it as an empty object, so check\n // the entry node here.\n if (spec instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (spec instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n\n // Single structural traversal — every operator clause and equality leaf is\n // checked for a JSON-unrehydratable operand. The walker threads the dotted\n // operand path so error messages point at the offending clause.\n walkPredicate(spec, {\n operator(_factPath, op, operand, operandPath) {\n checkOperand(operand, op, path ? `${path}.${operandPath}` : operandPath);\n },\n literal(factPath, value) {\n checkOperand(value, \"\", path ? `${path}.${factPath}` : factPath);\n },\n });\n}\n\n// ============================================================================\n// Schema-aware validation (semantic — operator on kind, operator-count cap)\n// ============================================================================\n\nimport {\n type SchemaKindNode,\n getOperatorsForKind,\n} from \"./schema-introspection.js\";\n\nexport interface SchemaValidationError {\n /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */\n readonly path: string;\n /** The operator that failed (or the literal-equality marker `$eq`). */\n readonly op: string;\n /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */\n readonly kind?: SchemaKindNode;\n /** The operators that ARE allowed for this fact's kind. */\n readonly allowedOps?: readonly string[];\n /** Human-readable failure reason (suitable for feeding back to an LLM). */\n readonly reason: string;\n}\n\nexport interface SchemaValidationOptions {\n /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */\n readonly maxOperatorCount?: number;\n /**\n * Reject `$in` / `$nin` operands that contain more than this many elements\n * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000\n * — beyond that, a downstream query compiler may degrade quadratically.\n */\n readonly maxArrayOperandLength?: number;\n}\n\n/**\n * Heuristic: flag a regex source string that has obvious nested quantifiers\n * (e.g. `(.+)+`, `(.*)*`, `(\\w+)+`, `(a|a)+`) — the classic ReDoS shapes.\n * Not a full ReDoS prover; intentionally conservative so a string-rehydrated\n * `$matches` operand can be rejected before it ever reaches `RegExp.test`.\n *\n * Callers MUST NOT treat a `false` result as \"safe\" — a determined adversary\n * can craft patterns this heuristic misses. The right answer for untrusted\n * regex is \"don't accept untrusted regex\"; this helper exists to catch the\n * obvious foot-guns.\n *\n * @example\n * ```ts\n * dangerousRegex(\"(a+)+\"); // → true\n * dangerousRegex(\"(.*)*\"); // → true\n * dangerousRegex(\"(\\\\w+)+\"); // → true\n * dangerousRegex(\"^[a-z]+$\"); // → false\n * ```\n */\nexport function dangerousRegex(source: string): boolean {\n if (typeof source !== \"string\" || source.length === 0) {\n return false;\n }\n // Nested quantifiers — a group ending in `*` or `+` (or `{n,}`) immediately\n // followed by another `*` / `+` / `{n,}` quantifier. Allow `?` between\n // (lazy) since `(...)?+` is still pathological. Also catch `{n,m}` upper\n // bounds when they wrap a quantified group.\n //\n // Patterns flagged:\n // (.+)+ (.*)* (.+)* (.*)+\n // (\\w+)+ (\\d*)+ ([abc]+)+\n // (a|a)+ (a|b|c)* ((x))+ (?:x+)+\n //\n // The check looks for a closing `)` preceded by a quantifier-bearing token\n // (`+`, `*`, `}` from `{n,m}`, or `+?` / `*?` lazy) and followed by another\n // quantifier (`+`, `*`, or `{n,`).\n const nestedQuantifier = /\\)(?:[+*]\\??|\\{\\d+,?\\d*\\})\\s*[+*?]\\s*[+*]/;\n if (nestedQuantifier.test(source)) {\n return true;\n }\n // Group whose inner content already has a `+` / `*` / `{n,}` quantifier on\n // a character class or token, and the group is then itself quantified.\n // E.g. `(a+)+`, `(\\w+)+`, `(.*)*`, `([abc]+)*`.\n const groupedQuantified =\n /\\(([^()]*?[+*]|[^()]*?\\{\\d+,?\\d*\\})[^()]*\\)\\s*[+*]/;\n if (groupedQuantified.test(source)) {\n return true;\n }\n // Alternation of identical branches: `(a|a)+`, `(foo|foo)*`.\n const sameBranchAlt = /\\(\\??:?([^()|]+)\\|\\1\\)\\s*[+*]/;\n if (sameBranchAlt.test(source)) {\n return true;\n }\n\n return false;\n}\n\nexport type SchemaValidationResult =\n | { ok: true; operatorCount: number }\n | {\n ok: false;\n errors: readonly SchemaValidationError[];\n operatorCount: number;\n };\n\n/**\n * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate\n * against a schema's runtime kind map. Catches errors that\n * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a\n * boolean fact), unknown fact paths, and (optionally) operator-count\n * exhaustion DoS attempts.\n *\n * Pair with {@link validatePredicate} (structural / JSON safety) for full\n * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a\n * module schema.\n *\n * Designed for the LLM-emit retry loop: returns a list of errors with\n * structured `{path, op, kind, allowedOps, reason}` rather than throwing,\n * so the caller can feed the errors back to the model.\n *\n * @example\n * ```ts\n * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } });\n * const result = validatePredicateAgainstSchema(\n * { cartTotal: { $gte: 50 }, active: { $gte: true } },\n * kindMap,\n * );\n * // → { ok: false, errors: [{ path: \"active\", op: \"$gte\", reason: \"...\" }], operatorCount: 2 }\n * ```\n */\nexport function validatePredicateAgainstSchema(\n spec: unknown,\n kindMap: Map<string, SchemaKindNode>,\n opts: SchemaValidationOptions = {},\n): SchemaValidationResult {\n const errors: SchemaValidationError[] = [];\n let operatorCount = 0;\n const maxOperatorCount = opts.maxOperatorCount;\n const maxArrayOperandLength = opts.maxArrayOperandLength;\n\n walkPredicate(spec, {\n operator(factPath, op, operand, _operandPath) {\n operatorCount++;\n if (maxOperatorCount !== undefined && operatorCount > maxOperatorCount) {\n // Don't pile up identical errors past the cap; one is enough.\n if (!errors.some((e) => e.reason.includes(\"maxOperatorCount\"))) {\n errors.push({\n path: factPath,\n op,\n reason: `Predicate exceeds maxOperatorCount=${maxOperatorCount} — too many clauses (DoS guard).`,\n });\n }\n\n return;\n }\n\n // M1: $in / $nin operand length cap — too-large array operands choke\n // downstream query planners and OR-tree compilers.\n if (\n maxArrayOperandLength !== undefined &&\n (op === \"$in\" || op === \"$nin\") &&\n Array.isArray(operand) &&\n operand.length > maxArrayOperandLength\n ) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator ${op} operand exceeds maxArrayOperandLength=${maxArrayOperandLength} (got ${operand.length}) — too large for a query planner.`,\n });\n\n return;\n }\n\n // M2: $matches operand ReDoS heuristic — flag obvious nested\n // quantifiers in either a RegExp or a string-form pattern. String-form\n // patterns are rejected at evaluation time (see applyOperator), but\n // a static check here catches them before they ever load.\n //\n // WARNING: don't rehydrate LLM-emitted string-form regex without your\n // own complexity audit; `dangerousRegex()` is a foot-gun catcher, not\n // a ReDoS prover.\n if (op === \"$matches\") {\n let regexSource: string | undefined;\n if (operand instanceof RegExp) {\n regexSource = operand.source;\n } else if (typeof operand === \"string\") {\n regexSource = operand;\n }\n if (regexSource !== undefined && dangerousRegex(regexSource)) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator $matches operand at \"${factPath}\" contains nested quantifiers (ReDoS risk: ${JSON.stringify(regexSource)}). Reject untrusted regex or rewrite without nested + / *.`,\n });\n\n return;\n }\n }\n\n const kind = kindMap.get(factPath);\n if (!kind) {\n errors.push({\n path: factPath,\n op,\n reason: `Unknown fact \"${factPath}\" — not in schema. Known facts: ${\n kindMap.size === 0\n ? \"(empty schema)\"\n : Array.from(kindMap.keys()).join(\", \")\n }`,\n });\n\n return;\n }\n\n const allowedOps = getOperatorsForKind(kind);\n if (!allowedOps.includes(op as never)) {\n errors.push({\n path: factPath,\n op,\n kind,\n allowedOps,\n reason: `Operator \"${op}\" is not allowed on fact \"${factPath}\" of kind \"${kind.kind}\". Allowed operators for this kind: ${allowedOps.join(\", \")}.`,\n });\n }\n },\n literal(factPath, _value) {\n operatorCount++;\n // Bare-value (equality) — always permitted as long as fact exists.\n if (!kindMap.has(factPath)) {\n errors.push({\n path: factPath,\n op: \"$eq\",\n reason: `Unknown fact \"${factPath}\" — not in schema.`,\n });\n }\n },\n strayOperatorKey(key, factPath) {\n errors.push({\n path: factPath,\n op: key,\n reason: `Stray operator key \"${key}\" at \"${factPath}\" — operators must live inside a fact's operator object, not at the predicate top level.`,\n });\n },\n });\n\n if (errors.length === 0) return { ok: true, operatorCount };\n\n return { ok: false, errors, operatorCount };\n}\n\n// ============================================================================\n// Equality\n// ============================================================================\n\n/**\n * Pairwise cycle-guard state shared across a single `deepEqual` traversal.\n *\n * Asymmetric cycles (only one side cyclic) must not short-circuit; we only\n * treat a pair as equal when the same `(a, b)` pair is re-encountered.\n */\ninterface DeepEqualSeen {\n ids: WeakMap<object, number>;\n next: { v: number };\n pairs: Set<string>;\n}\n\nfunction deepEqualSeen(): DeepEqualSeen {\n return { ids: new WeakMap(), next: { v: 1 }, pairs: new Set() };\n}\n\nfunction pairId(seen: DeepEqualSeen, obj: object): number {\n let id = seen.ids.get(obj);\n if (id === undefined) {\n id = seen.next.v++;\n seen.ids.set(obj, id);\n }\n\n return id;\n}\n\n/** Structural equality with NaN/Date handling and a pairwise cycle guard. */\nfunction deepEqual(a: unknown, b: unknown, seen?: DeepEqualSeen): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (\n typeof a !== \"object\" ||\n typeof b !== \"object\" ||\n a === null ||\n b === null\n ) {\n return false;\n }\n\n const guard = seen ?? deepEqualSeen();\n const key = `${pairId(guard, a)}:${pairId(guard, b)}`;\n if (guard.pairs.has(key)) {\n return true; // same (a, b) pair re-encountered — treat as equal\n }\n guard.pairs.add(key);\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n\n return a.every((v, i) => deepEqual(v, b[i], guard));\n }\n\n // Set equality — same size, every element of `a` has a structurally-equal\n // counterpart in `b`. Must precede the `Object.keys` fallback below because\n // `Object.keys(new Set(...))` is always `[]`, which would otherwise let\n // any two Sets (or any two Maps) compare equal regardless of contents.\n if (a instanceof Set || b instanceof Set) {\n if (!(a instanceof Set) || !(b instanceof Set) || a.size !== b.size) {\n return false;\n }\n const bArr = [...b];\n\n return [...a].every((v) => bArr.some((w) => deepEqual(v, w, guard)));\n }\n\n // Map equality — same size, every key in `a` matches a key in `b` with a\n // structurally-equal value. Greedy match with a used-flag to handle\n // structural (non-reference) key equality correctly.\n if (a instanceof Map || b instanceof Map) {\n if (!(a instanceof Map) || !(b instanceof Map) || a.size !== b.size) {\n return false;\n }\n const bEntries = [...b.entries()];\n const used = new Array<boolean>(bEntries.length).fill(false);\n for (const [ka, va] of a) {\n let found = false;\n for (let i = 0; i < bEntries.length; i++) {\n if (used[i]) {\n continue;\n }\n const [kb, vb] = bEntries[i]!;\n if (deepEqual(ka, kb, guard) && deepEqual(va, vb, guard)) {\n used[i] = true;\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n\n return true;\n }\n\n const ak = Object.keys(a as object);\n const bk = Object.keys(b as object);\n if (ak.length !== bk.length) {\n return false;\n }\n\n return ak.every(\n (k) =>\n Object.hasOwn(b as object, k) &&\n deepEqual(\n (a as Record<string, unknown>)[k],\n (b as Record<string, unknown>)[k],\n guard,\n ),\n );\n}\n\n// ============================================================================\n// Operators\n// ============================================================================\n\nfunction toComparable(v: unknown): number | bigint | string | undefined {\n if (v instanceof Date) {\n return v.getTime();\n }\n if (typeof v === \"number\" || typeof v === \"bigint\" || typeof v === \"string\") {\n return v;\n }\n\n return undefined;\n}\n\nfunction relational(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n): boolean {\n const a = toComparable(actual);\n const b = toComparable(operand);\n if (a === undefined || b === undefined || typeof a !== typeof b) {\n return false;\n }\n\n switch (op) {\n case \"$gt\":\n return a > b;\n case \"$gte\":\n return a >= b;\n case \"$lt\":\n return a < b;\n case \"$lte\":\n return a <= b;\n default:\n return false;\n }\n}\n\n/** Apply one operator. `prevValue` is supplied only for `$changed`. */\nfunction applyOperator(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n prevValue: unknown,\n): boolean {\n switch (op) {\n case \"$eq\":\n return deepEqual(actual, operand);\n case \"$ne\":\n return !deepEqual(actual, operand);\n case \"$in\":\n return (\n Array.isArray(operand) && operand.some((v) => deepEqual(actual, v))\n );\n case \"$nin\":\n return (\n Array.isArray(operand) && !operand.some((v) => deepEqual(actual, v))\n );\n case \"$exists\":\n return operand === (actual !== undefined);\n case \"$changed\":\n return !deepEqual(actual, prevValue);\n case \"$gt\":\n case \"$gte\":\n case \"$lt\":\n case \"$lte\":\n return relational(op, actual, operand);\n case \"$between\": {\n if (!Array.isArray(operand) || operand.length !== 2) {\n return false;\n }\n const lo = toComparable(operand[0]);\n const hi = toComparable(operand[1]);\n if (\n lo !== undefined &&\n hi !== undefined &&\n typeof lo === typeof hi &&\n lo > hi\n ) {\n devWarn(\"$between: reversed pair — [min, max] required\");\n\n return false;\n }\n\n return (\n relational(\"$gte\", actual, operand[0]) &&\n relational(\"$lte\", actual, operand[1])\n );\n }\n case \"$matches\": {\n if (!(operand instanceof RegExp)) {\n // String operands are not accepted — a string cannot carry flags\n // (case-insensitivity, dotall, multiline) and would also enable a\n // ReDoS surface for data-loaded predicates. Throw immediately so\n // the bug surfaces at the point of use.\n throw new Error(\n \"[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).\",\n );\n }\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return operand.test(actual);\n }\n case \"$startsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.startsWith(String(operand));\n case \"$endsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.endsWith(String(operand));\n case \"$contains\":\n if (typeof actual === \"string\") {\n return actual.includes(String(operand));\n }\n if (Array.isArray(actual)) {\n return actual.some((v) => deepEqual(v, operand));\n }\n // Set membership — uses `.has()` which is reference-equality for\n // objects (matches native Set semantics) and value-equality for\n // primitives. Map `$contains` is deferred to v2; users who need it\n // today can fall back to a function-form predicate.\n if (actual instanceof Set) {\n return actual.has(operand);\n }\n\n return false;\n default:\n return false;\n }\n}\n\n// ============================================================================\n// Evaluation\n// ============================================================================\n\nfunction devWarn(message: string): void {\n if (isDevelopment) {\n console.warn(`[Directive] ${message}`);\n }\n}\n\nfunction evalField(\n value: unknown,\n actual: unknown,\n prev: unknown,\n depth: number,\n): boolean {\n if (isOperatorObject(value)) {\n const keys = Object.keys(value);\n // Type rejects multi-operator objects; the runtime ANDs them on a\n // best-effort basis but dev-warns so the author knows to switch to the\n // array form or `$all`.\n if (keys.length > 1) {\n devWarn(\n `predicate: operator object has ${keys.length} operators (${keys.join(\", \")}) — write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`,\n );\n }\n for (const op of keys) {\n if (!applyOperator(op as PredicateOp, actual, value[op], prev)) {\n return false;\n }\n }\n\n return true;\n }\n\n // A plain (non-operator) object recurses — nested / namespaced predicate.\n if (isPlainObject(value)) {\n return evaluatePredicate(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev) ? prev : undefined,\n depth + 1,\n );\n }\n\n // Bare value → equality.\n return deepEqual(actual, value);\n}\n\n/**\n * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous\n * snapshot) is consulted only by the `$changed` operator.\n *\n * @example\n * ```ts\n * evaluatePredicate({ phase: \"red\", elapsed: { $gte: 30 } }, { phase: \"red\", elapsed: 45 });\n * // → true\n * evaluatePredicate({ $any: [{ phase: \"red\" }, { phase: \"yellow\" }] }, { phase: \"green\" });\n * // → false\n * ```\n */\nexport function evaluatePredicate(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n depth = 0,\n): boolean {\n // `freezeSpec` permits cycles (it uses a WeakSet seen-guard), so a\n // registered spec can be self-referential. Cap recursion to defend the\n // reconcile loop against a stack overflow at evaluation time.\n if (depth > MAX_PREDICATE_DEPTH) {\n devWarn(\n `predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n\n return false;\n }\n // Array form — clauses AND-ed.\n if (Array.isArray(spec)) {\n return spec.every((clause) => {\n if (!isPlainObject(clause)) {\n return false;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n\n return applyOperator(op, facts?.[fact], value, prev?.[fact]);\n });\n }\n\n if (!isPlainObject(spec)) {\n return Boolean(spec);\n }\n\n // Combinator node.\n if (\"$all\" in spec) {\n return (spec.$all as unknown[]).every((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$any\" in spec) {\n return (spec.$any as unknown[]).some((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$not\" in spec) {\n return !evaluatePredicate(spec.$not, facts, prev, depth + 1);\n }\n\n // Object form — every key AND-ed.\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `predicate: operator \"${key}\" mixed with fact keys — wrap operators in a per-fact object`,\n );\n\n return false;\n }\n if (!evalField(spec[key], facts?.[key], prev?.[key], depth)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Evaluate a predicate and return a per-clause breakdown — the data feed for\n * devtools, `system.explain()`, and `directive explain`.\n *\n * @example\n * ```ts\n * evaluatePredicateExplained(\n * { phase: \"red\", elapsed: { $gte: 30 } },\n * { phase: \"red\", elapsed: 20 },\n * );\n * // → [\n * // { path: \"phase\", op: \"$eq\", expected: \"red\", actual: \"red\", pass: true },\n * // { path: \"elapsed\", op: \"$gte\", expected: 30, actual: 20, pass: false },\n * // ]\n * ```\n */\nexport function evaluatePredicateExplained(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n pathPrefix = \"\",\n): ClauseResult[] {\n const out: ClauseResult[] = [];\n\n if (Array.isArray(spec)) {\n for (const clause of spec) {\n if (!isPlainObject(clause)) {\n continue;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n const actual = facts?.[fact];\n out.push({\n path: pathPrefix + fact,\n op,\n expected: value,\n actual,\n pass: applyOperator(op, actual, value, prev?.[fact]),\n });\n }\n\n return out;\n }\n\n if (!isPlainObject(spec)) {\n return out;\n }\n\n for (const key of [\"$all\", \"$any\", \"$not\"] as const) {\n if (key in spec) {\n const childSpecs =\n key === \"$not\" ? [spec.$not] : (spec[key] as unknown[]);\n const children: ClauseResult[] = [];\n for (const child of childSpecs) {\n children.push(\n ...evaluatePredicateExplained(child, facts, prev, pathPrefix),\n );\n }\n const passCount = children.filter((c) => c.pass).length;\n let pass: boolean;\n if (key === \"$all\") {\n pass = children.length === 0 || passCount === children.length;\n } else if (key === \"$any\") {\n pass = children.length > 0 && passCount > 0;\n } else {\n // $not — single child wrapped above\n pass = !children.every((c) => c.pass);\n }\n out.push({\n path: pathPrefix || key,\n op: key,\n expected: childSpecs.length,\n actual: passCount,\n pass,\n children,\n });\n\n return out;\n }\n }\n\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n continue;\n }\n const value = spec[key];\n const actual = facts?.[key];\n const path = pathPrefix + key;\n\n if (isOperatorObject(value)) {\n for (const op of Object.keys(value)) {\n out.push({\n path,\n op: op as PredicateOp,\n expected: value[op],\n actual,\n pass: applyOperator(\n op as PredicateOp,\n actual,\n value[op],\n prev?.[key],\n ),\n });\n }\n } else if (isPlainObject(value)) {\n out.push(\n ...evaluatePredicateExplained(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev?.[key]) ? (prev?.[key] as Scope) : undefined,\n `${path}.`,\n ),\n );\n } else {\n out.push({\n path,\n op: \"$eq\",\n expected: value,\n actual,\n pass: deepEqual(actual, value),\n });\n }\n }\n\n return out;\n}\n\nconst memoizedCache = new WeakMap<\n object,\n (facts: Scope, prev?: Scope) => boolean\n>();\n\n/**\n * Memoize a predicate as a reusable evaluation closure.\n *\n * The returned function accepts any `facts` scope (the reactive proxy in\n * production, a plain object in tests) plus an optional `prev` snapshot for\n * `$changed`. The closure is cached **by predicate identity** in a\n * `WeakMap`, so passing the same `predicate` reference repeatedly is\n * allocation-free; cleanup is automatic once the predicate is no longer\n * reachable.\n *\n * Note: no actual compilation happens — the returned closure re-walks the\n * spec on every call via `evaluatePredicate`. The name reflects what the\n * function does (closure memoization keyed by predicate identity), not a\n * bytecode/AST compile step.\n *\n * Intended for advanced users who want a stable function reference per\n * predicate (custom devtools, batched analyses). Regular module code does\n * not need to call this — the engine wraps data-form `when` / `on` specs\n * automatically at registration.\n *\n * @example\n * ```ts\n * const predicate = { phase: \"red\", elapsed: { $gte: 30 } };\n * const check = memoizePredicate(predicate);\n * check({ phase: \"red\", elapsed: 45 }); // → true\n * check({ phase: \"red\", elapsed: 5 }); // → false\n * ```\n */\nexport function memoizePredicate(\n predicate: object,\n): (facts: Scope, prev?: Scope) => boolean {\n if (predicate === null || typeof predicate !== \"object\") {\n throw new Error(\n `[Directive] memoizePredicate: predicate must be a plain object or array; got ${typeof predicate}`,\n );\n }\n const cached = memoizedCache.get(predicate);\n if (cached) {\n return cached;\n }\n\n const fn = (facts: Scope, prev?: Scope): boolean =>\n evaluatePredicate(predicate, facts, prev);\n memoizedCache.set(predicate, fn);\n\n return fn;\n}\n\n// ============================================================================\n// Dependency extraction\n// ============================================================================\n\n/**\n * Collect the fact keys a predicate references. Used for static analysis,\n * devtools, and effect `on` dependency wiring. Nested predicates contribute\n * dotted keys (`auth.token`).\n *\n * @example\n * ```ts\n * extractDeps({ phase: \"red\", elapsed: { $gte: 30 } });\n * // → Set { \"phase\", \"elapsed\" }\n * extractDeps({ self: { phase: \"red\" }, auth: { token: { $exists: true } } });\n * // → Set { \"self.phase\", \"auth.token\" }\n * ```\n */\nexport function extractDeps(spec: unknown, prefix = \"\"): Set<string> {\n const deps = new Set<string>();\n\n // Single structural traversal — every operator clause and equality leaf\n // contributes its dotted fact path. Combinators and nested objects are\n // descended automatically; stray `$`-keys never synthesize phantom deps.\n walkPredicate(spec, {\n operator(factPath) {\n deps.add(prefix + factPath);\n },\n literal(factPath) {\n deps.add(prefix + factPath);\n },\n strayOperatorKey(key) {\n // A `$`-key at fact position never synthesizes a phantom dep. A typo'd\n // operator (e.g. `$eqq`) additionally dev-warns; a known operator\n // mixed with fact keys is skipped silently (evaluatePredicate warns).\n if (!PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `extractDeps: unknown operator \"${key}\" — skipping. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n },\n });\n\n return deps;\n}\n\n// ============================================================================\n// Templates\n// ============================================================================\n\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** Stringify a value without dev-warns for null/undefined — used when the\n * caller has already emitted a higher-level diagnostic (e.g. \"unknown key\"). */\nfunction stringifyValueQuiet(v: unknown): string {\n if (typeof v === \"symbol\") {\n return \"\";\n }\n if (v === undefined || v === null) {\n return \"\";\n }\n\n return String(v);\n}\n\nfunction stringifyValue(v: unknown, key?: string): string {\n if (typeof v === \"symbol\") {\n devWarn(\"template: cannot interpolate a symbol value — using empty string\");\n\n return \"\";\n }\n if (v === undefined) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}undefined — using empty string`,\n );\n\n return \"\";\n }\n if (v === null) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}null — using empty string`,\n );\n\n return \"\";\n }\n\n return String(v);\n}\n\n/**\n * Interpolate a {@link FactTemplate} against a scope. Single-pass character\n * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal\n * `${`; unknown keys dev-warn and yield an empty string.\n *\n * @example\n * ```ts\n * evaluateTemplate({ $template: \"Hi ${name}!\" }, { name: \"Ada\" });\n * // → \"Hi Ada!\"\n * evaluateTemplate({ $template: \"$${price}\" }, {});\n * // → \"${price}\"\n * ```\n */\nexport function evaluateTemplate(spec: FactTemplate, scope: Scope): string {\n const tpl = spec.$template;\n let out = \"\";\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n out += \"${\";\n i += 3;\n continue;\n }\n\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n devWarn(`template: unterminated \"\\${\" in ${JSON.stringify(tpl)}`);\n out += tpl.slice(i);\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (!IDENTIFIER.test(key)) {\n devWarn(\n `template: invalid placeholder \"\\${${key}}\" — not an identifier`,\n );\n } else {\n // `stringifyValue` dev-warns separately for null vs undefined; here\n // we only warn when the key itself is missing from the scope (vs\n // present-but-null), so users see distinct diagnostics. Use\n // Object.hasOwn rather than `in` so prototype-chain keys (e.g.\n // `toString`, `constructor`) are never interpolated.\n const present = scope != null && Object.hasOwn(scope, key);\n const value = present ? scope[key] : undefined;\n if (!present) {\n devWarn(`template: unknown key \"${key}\"`);\n out += stringifyValueQuiet(value);\n } else {\n out += stringifyValue(value, key);\n }\n }\n i = end + 1;\n continue;\n }\n\n out += tpl[i];\n i++;\n }\n\n return out;\n}\n\n/**\n * Collect the placeholder keys referenced by a template. The static-analysis\n * counterpart to {@link extractDeps} — useful for devtools, codegen, and\n * \"which facts does this template read\" inspections. Only valid identifier\n * placeholders are collected; malformed ones are ignored.\n *\n * @example\n * ```ts\n * extractTemplateKeys({ $template: \"${firstName} ${lastName}\" });\n * // → Set { \"firstName\", \"lastName\" }\n * extractTemplateKeys({ $template: \"$${literal}\" });\n * // → Set {} (escaped — not a placeholder)\n * ```\n */\nexport function extractTemplateKeys(spec: FactTemplate): Set<string> {\n const keys = new Set<string>();\n const tpl = spec.$template;\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n i += 3;\n continue;\n }\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (IDENTIFIER.test(key)) {\n keys.add(key);\n }\n i = end + 1;\n continue;\n }\n i++;\n }\n\n return keys;\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\n/**\n * Build a stable dedup key by selecting fields from a requirement payload.\n * Order-as-declared; values are stable-stringified (keys sorted recursively)\n * so two payloads with the same fields in different orders dedupe to the\n * same key.\n *\n * @example\n * ```ts\n * evaluateKeySelector([\"url\", \"method\"], { url: \"/a\", method: \"GET\" });\n * // → '\"/a\"|\"GET\"'\n * evaluateKeySelector([\"id\"], { id: 42 });\n * // → '42'\n * ```\n */\nexport function evaluateKeySelector(\n selector: readonly string[],\n source: Record<string, unknown>,\n): string {\n return selector.map((field) => stableStringify(source?.[field])).join(\"|\");\n}\n\n// ============================================================================\n// Patch\n// ============================================================================\n\n/**\n * Apply a {@link PatchSpec} — assign facts from literals, payload copies\n * (`$ref`), or interpolated strings (`$template`). Mutates through the passed\n * `facts` proxy so change-tracking and downstream invalidation fire.\n *\n * @example\n * ```ts\n * const spec = {\n * $set: {\n * active: true,\n * userId: { $ref: \"id\" },\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * applyPatch(spec, facts, { id: \"u_1\", name: \"Ada\" });\n * // facts.active = true; facts.userId = \"u_1\"; facts.label = \"user Ada\"\n * ```\n */\nexport function applyPatch(\n spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>,\n facts: Record<string, unknown>,\n payload: Record<string, unknown>,\n): void {\n const set = spec.$set;\n const safePayload = payload ?? {};\n for (const key of Object.keys(set)) {\n const value = (set as Record<string, unknown>)[key];\n\n if (isTemplate(value)) {\n facts[key] = evaluateTemplate(value, safePayload);\n } else if (\n isPlainObject(value) &&\n Object.hasOwn(value, \"$ref\") &&\n typeof value.$ref === \"string\"\n ) {\n const refKey = value.$ref;\n // Use Object.hasOwn rather than `in` — tightens defense against\n // prototype-chain lookups so a payload `__proto__` shape can't smuggle\n // an inherited property into the fact assignment. The proxy already\n // blocks writes to dangerous keys, but this keeps the read symmetric.\n if (!Object.hasOwn(safePayload, refKey)) {\n devWarn(\n `applyPatch: $ref \"${refKey}\" is missing from event payload — assigning undefined to fact \"${key}\"`,\n );\n }\n facts[key] = safePayload[refKey];\n } else {\n facts[key] = value;\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/core/types/predicate.ts","../src/core/schema-introspection.ts","../src/core/predicate.ts"],"names":["PREDICATE_OPERATORS","PREDICATE_COMBINATORS","PRIMITIVE_KINDS","parseTypeName","typeName","branded","getKind","schema","dev_true_default","s","kindNode","getSchemaFieldKinds","out","root","facts","key","builder","node","innerKey","innerNode","COMMON_OPS","ORDERABLE_OPS","STRING_OPS","getOperatorsForKind","sets","m","first","intersection","op","listAllPredicateOperators","MAX_PREDICATE_DEPTH","isPlainObject","v","isPlainObjectStrict","proto","isOperatorObject","count","hasDollarKey","k","devWarn","isPredicate","c","walkPredicate","spec","visitor","path","seen","depth","clause","i","clausePath","obj","kind","children","child","childPath","value","opObj","isEmptyOrConfigPredicate","isPredicateBody","isTemplate","validatePredicate","checkValueJsonSafe","at","el","checkOperand","_factPath","operand","operandPath","factPath","dangerousRegex","source","validatePredicateAgainstSchema","kindMap","opts","errors","operatorCount","maxOperatorCount","maxArrayOperandLength","_operandPath","e","regexSource","allowedOps","_value","deepEqualSeen","pairId","id","deepEqual","a","b","guard","bArr","w","bEntries","used","ka","va","found","kb","vb","ak","bk","toComparable","relational","actual","applyOperator","prevValue","lo","hi","message","evalField","prev","keys","evaluatePredicate","fact","p","evaluatePredicateExplained","pathPrefix","childSpecs","passCount","pass","memoizedCache","memoizePredicate","predicate","cached","fn","extractDeps","prefix","deps","IDENTIFIER","stringifyValueQuiet","stringifyValue","evaluateTemplate","scope","tpl","end","present","extractTemplateKeys","evaluateKeySelector","selector","field","stableStringify","applyPatch","payload","set","safePayload","refKey"],"mappings":"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","file":"chunk-GACC2DMS.cjs","sourcesContent":["/**\n * Data-configuration predicates and templates.\n *\n * A {@link FactPredicate} is a declarative, serializable boolean spec over a\n * module's fact namespace — the data form of a constraint `when`, an effect\n * `on`, or a boolean derivation. A {@link FactTemplate} is the value-producing\n * counterpart: a fact-interpolating string.\n *\n * Convention: `$` marks an operator/expression node inside a predicate or\n * template body (`$eq`, `$gte`, `$all`, `$template`, `$set`, `$ref`).\n * Definition arms (`compute`, `handler`, `patch`) stay sigil-free.\n *\n * Operators are `$`-prefixed so they can never collide with a fact key —\n * schema keys starting with `$` are rejected at registration.\n */\n\n// ============================================================================\n// Operators\n// ============================================================================\n\n/** Comparison operator names — the `$`-prefixed keys inside an operator object. */\nexport type PredicateOp =\n | \"$eq\"\n | \"$ne\"\n | \"$in\"\n | \"$nin\"\n | \"$exists\"\n | \"$gt\"\n | \"$gte\"\n | \"$lt\"\n | \"$lte\"\n | \"$between\"\n | \"$matches\"\n | \"$startsWith\"\n | \"$endsWith\"\n | \"$contains\"\n | \"$changed\";\n\n/** Combinator node keys. */\nexport type PredicateCombinatorKey = \"$all\" | \"$any\" | \"$not\";\n\n/**\n * Every reserved `$`-key recognized inside a predicate body.\n *\n * @internal\n */\nexport const PREDICATE_OPERATORS: ReadonlySet<string> = new Set<string>([\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n \"$changed\",\n]);\n\n/**\n * Combinator keys, as a runtime set.\n *\n * @internal\n */\nexport const PREDICATE_COMBINATORS: ReadonlySet<string> = new Set<string>([\n \"$all\",\n \"$any\",\n \"$not\",\n]);\n\n// ============================================================================\n// Operator object\n// ============================================================================\n\n/**\n * `true` when `V` supports relational operators (`$gt` … `$between`).\n * `[V]` tuple-wrapping suppresses distribution over union-typed facts.\n */\ntype IsOrderable<V> = [V] extends [number | bigint | Date]\n ? true\n : [V] extends [string]\n ? true\n : false;\n\n/**\n * The operator object permitted for a fact of type `V`. Built as a\n * **per-operator union** (one operator per member) rather than an\n * intersection — a typo'd operator (`$eqq`) then matches no member and is a\n * compile error, and a relational operator on a non-orderable fact resolves\n * to `never`.\n *\n * One operator per object — for two operators on the same fact, write the\n * array form or `$all`. This is by design (the type is the source of truth).\n *\n * `$matches` requires `RegExp`. The runtime throws on string operands.\n *\n * @example\n * ```ts\n * const op1: OperatorObject<number> = { $gte: 30 };\n * const op2: OperatorObject<string> = { $matches: /^J/i };\n * const op3: OperatorObject<string> = { $in: [\"red\", \"yellow\"] };\n * const op4: OperatorObject<string> = { $startsWith: \"Ada\" };\n * const op5: OperatorObject<string> = { $endsWith: \".com\" };\n * ```\n */\nexport type OperatorObject<V> =\n | { $eq: V }\n | { $ne: V }\n | { $in: readonly V[] }\n | { $nin: readonly V[] }\n | { $exists: boolean }\n | { $changed: true }\n | (IsOrderable<V> extends true\n ?\n | { $gt: V }\n | { $gte: V }\n | { $lt: V }\n | { $lte: V }\n | { $between: readonly [V, V] }\n : never)\n | ([V] extends [string]\n ?\n | { $matches: RegExp }\n | { $contains: string }\n | { $startsWith: string }\n | { $endsWith: string }\n : never)\n | ([V] extends [readonly (infer E)[]] ? { $contains: E } : never);\n\n/**\n * The spec for a single fact key: a bare value (equality), an operator\n * object, or — for an object-typed fact — a nested predicate (partial match).\n */\ntype PredicateField<V> =\n | V\n | OperatorObject<V>\n | ([V] extends [readonly unknown[]]\n ? never\n : [V] extends [object]\n ? PredicateObject<V>\n : never);\n\n// ============================================================================\n// FactPredicate\n// ============================================================================\n\n/**\n * Object form — every key is a fact name, every value a\n * {@link PredicateField}. Multiple keys are AND-ed. A nested object value\n * recurses (partial match), which is how cross-module namespaced predicates\n * (`{ self: { phase: \"red\" }, auth: { token: { $exists: true } } }`) work.\n */\nexport type PredicateObject<F> = {\n [K in keyof F]?: PredicateField<F[K]>;\n};\n\n/** Array form — explicit clauses, AND-ed. The codegen/devtools-friendly form. */\nexport type PredicateClause<F> = {\n [K in keyof F]: {\n readonly fact: K;\n readonly op: PredicateOp;\n readonly value: unknown;\n };\n}[keyof F];\n\n/** Combinator node — exactly one of `$all` / `$any` / `$not`. */\nexport type PredicateCombinator<F> =\n | { $all: readonly FactPredicate<F>[]; $any?: never; $not?: never }\n | { $any: readonly FactPredicate<F>[]; $all?: never; $not?: never }\n | { $not: FactPredicate<F>; $all?: never; $any?: never };\n\n/**\n * A declarative boolean spec over a fact namespace `F`. The data form of a\n * constraint `when`, an effect `on`, or a boolean derivation. Accepts an\n * object form, an array-of-clauses form, or a combinator node.\n *\n * Keys are **fact names only** — derivations are not addressable from inside\n * a predicate. To gate on a derivation, either reference the underlying fact\n * the derivation reads, or fall back to the function form of `when` / `on`.\n *\n * @example\n * ```ts\n * // Object form (the common case)\n * const p1: FactPredicate<{ phase: string; elapsed: number }> = {\n * phase: \"red\",\n * elapsed: { $gte: 30 },\n * };\n *\n * // Combinator form\n * const p2: FactPredicate<{ phase: string }> = {\n * $any: [{ phase: \"red\" }, { phase: \"yellow\" }],\n * };\n * ```\n */\nexport type FactPredicate<F> =\n | PredicateObject<F>\n | readonly PredicateClause<F>[]\n | PredicateCombinator<F>;\n\n// ============================================================================\n// FactTemplate\n// ============================================================================\n\n/**\n * A fact-interpolating string expression. `${key}` placeholders are replaced\n * with the named fact's value; `$${` emits a literal `${`. The value-producing\n * counterpart to {@link FactPredicate} — usable as a string derivation, a\n * constraint `require` field value, or an event `patch` value.\n *\n * @example { $template: \"Phase ${phase} for ${elapsed}s\" }\n */\nexport interface FactTemplate {\n readonly $template: string;\n}\n\n// ============================================================================\n// Selectors (resolver key, event patch)\n// ============================================================================\n\n/**\n * *Note: despite the \"Selector\" name, this does not select from facts — it\n * projects fields of the requirement payload for stable-stringification.*\n *\n * A resolver dedup key written as data: an ordered list of requirement-payload\n * field names. `key: [\"type\", \"to\"]` dedupes requirements by those fields.\n *\n * @example\n * ```ts\n * resolvers: {\n * fetch: {\n * requirement: \"FETCH\",\n * key: [\"url\", \"method\"] satisfies KeySelector<{ url: string; method: string }>,\n * resolve: doFetch,\n * },\n * }\n * ```\n */\nexport type KeySelector<R> = readonly (keyof R & string)[];\n\n/**\n * *Note: Directive's `$ref` is **not** a JSON Pointer or JSON Schema `$ref`.\n * It is a payload field copy — equivalent to `event.payload[key]`. Renaming\n * to `$from` is tracked as a possible v1.6+ additive alias.*\n *\n * A typed single-field copy from an event payload. Lives in the patch-spec\n * namespace — used inside a {@link PatchSpec} `$set` value.\n *\n * @example\n * ```ts\n * patch: { $set: { userId: { $ref: \"id\" } satisfies PayloadRef<{ id: string }> } }\n * ```\n */\nexport interface PayloadRef<P> {\n readonly $ref: keyof P & string;\n}\n\n/**\n * A patch value: a literal, a typed payload copy, or (for string facts) a\n * template. Lives in the patch-spec namespace — used inside a {@link PatchSpec}\n * `$set` block.\n *\n * @example\n * ```ts\n * const v1: PatchValue<boolean, { active: boolean }> = true;\n * const v2: PatchValue<string, { name: string }> = { $ref: \"name\" };\n * const v3: PatchValue<string, { name: string }> = { $template: \"user ${name}\" };\n * ```\n */\nexport type PatchValue<V, P> =\n | V\n | PayloadRef<P>\n | ([V] extends [string] ? FactTemplate : never);\n\n/**\n * An event handler written as data: assigns facts from literals, payload\n * fields (`$ref`), or interpolated strings (`$template`).\n *\n * @example\n * ```ts\n * const spec: PatchSpec<{ status: string; label: string }, { name: string }> = {\n * $set: {\n * status: \"active\",\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * ```\n */\nexport interface PatchSpec<F, P> {\n readonly $set: { [K in keyof F]?: PatchValue<F[K], P> };\n}\n\n// ============================================================================\n// Explain\n// ============================================================================\n\n/**\n * The per-clause result of an explained predicate evaluation. One entry per\n * leaf operator (`$eq`, `$gte`, …); combinator nodes (`$all`, `$any`, `$not`)\n * may also appear as headers when the runtime emits them — hence the union\n * over {@link PredicateCombinatorKey}.\n *\n * @example\n * ```ts\n * const result: ClauseResult = {\n * path: \"elapsed\",\n * op: \"$gte\",\n * expected: 30,\n * actual: 20,\n * pass: false,\n * };\n * ```\n */\nexport interface ClauseResult {\n /** Dotted path to the fact (`elapsed`, `auth.token`). */\n readonly path: string;\n /** The operator applied (`$gte`, `$eq`, …) — `$eq` for a bare value. */\n readonly op: PredicateOp | PredicateCombinatorKey;\n /**\n * The value the predicate expected. For combinator clauses (`$all`,\n * `$any`, `$not`) this is the child count.\n */\n readonly expected: unknown;\n /**\n * The actual fact value at evaluation time. For combinator clauses this\n * is the number of child clauses that passed.\n */\n readonly actual: unknown;\n /** Whether this clause passed. */\n readonly pass: boolean;\n /**\n * Children of a combinator clause (`$all`, `$any`, `$not`). Preserves the\n * tree shape of the original predicate so renderers (devtools,\n * `system.explain()`) can indent nested clauses.\n */\n readonly children?: ClauseResult[];\n}\n","/**\n * Schema Introspection\n *\n * A runtime discriminant for every `t.*()` builder result, so downstream\n * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`)\n * can ask \"what kind is this fact?\" without grepping the source.\n *\n * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`.\n * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.)\n * preserve / decorate it. When `_kind` is absent (legacy or third-party\n * builder), the parser falls back to reading the freeform `_typeName`\n * string. When even that fails: `{ kind: \"unknown\" }` — graceful close.\n *\n * This module has zero hot-path cost; it is only invoked when an\n * introspecting caller asks for it.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { PREDICATE_OPERATORS, type PredicateOp } from \"./types/predicate.js\";\n\n/**\n * Minimal structural shape for a schema-builder result that\n * introspection cares about. Avoids the contravariance trap on\n * `ExtendedSchemaType<T>` when `T = unknown` (which makes\n * `ChainableString` un-assignable to `ExtendedSchemaType<unknown>`\n * via the `_refinements` field). Any builder result is structurally\n * compatible with this shape.\n */\nexport interface IntrospectableSchema {\n readonly _kind?: SchemaKindNode;\n readonly _typeName?: string;\n}\n\n// ============================================================================\n// SchemaKindNode tree\n// ============================================================================\n\n/**\n * The closed set of kinds a Directive schema field can be.\n *\n * Drives operator availability via {@link getOperatorsForKind}: e.g.\n * `\"number\"` gets the orderable operators (`$gte`, `$lte`); `\"boolean\"`\n * does not.\n */\nexport type SchemaKind =\n | \"number\"\n | \"string\"\n | \"boolean\"\n | \"bigint\"\n | \"date\"\n | \"array\"\n | \"object\"\n | \"record\"\n | \"tuple\"\n | \"enum\"\n | \"literal\"\n | \"union\"\n | \"branded\"\n | \"unknown\";\n\n/**\n * A tree-shaped discriminator for a schema field. Composite kinds\n * (array, object, tuple, etc.) carry their element / shape information\n * so an LLM-prompt builder can show \"cartTotal is a number\" AND\n * \"items is an array of { sku: string, qty: number }\".\n *\n * `nullable` / `hasDefault` flags appear on the inner node (NOT a\n * wrapping kind) so operator-lookup on `t.number().nullable()` returns\n * the number's operators unchanged — `$gte` works on the non-null arm.\n */\nexport type SchemaKindNode = (\n | { kind: \"number\" | \"string\" | \"boolean\" | \"bigint\" | \"date\" | \"unknown\" }\n | {\n kind: \"literal\";\n value: string | number | boolean | null;\n primitive: \"string\" | \"number\" | \"boolean\" | \"null\";\n }\n | {\n kind: \"enum\";\n values: readonly (string | number)[];\n primitive: \"string\" | \"number\";\n }\n | { kind: \"array\"; element: SchemaKindNode }\n | { kind: \"tuple\"; elements: readonly SchemaKindNode[] }\n | { kind: \"object\"; shape: Record<string, SchemaKindNode> }\n | { kind: \"record\"; value: SchemaKindNode }\n | { kind: \"union\"; members: readonly SchemaKindNode[] }\n | { kind: \"branded\"; inner: SchemaKindNode }\n) & {\n /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */\n nullable?: boolean;\n /** True if the schema has a `.default()`. */\n hasDefault?: boolean;\n};\n\n// ============================================================================\n// Parse `_typeName` → SchemaKindNode (fallback for legacy / third-party)\n// ============================================================================\n\nconst PRIMITIVE_KINDS = new Set<SchemaKind>([\n \"number\",\n \"string\",\n \"boolean\",\n \"bigint\",\n \"date\",\n \"unknown\",\n]);\n\n/**\n * Best-effort parse of a freeform `_typeName` string into a structured\n * kind node. Used only when `_kind` is absent. Always falls back to\n * `{ kind: \"unknown\" }`; never throws.\n */\nfunction parseTypeName(typeName: string | undefined): SchemaKindNode {\n if (!typeName) return { kind: \"unknown\" };\n\n // \"Branded<inner>\" — recurse.\n const branded = /^Branded<(.+)>$/.exec(typeName);\n if (branded) {\n return { kind: \"branded\", inner: parseTypeName(branded[1]) };\n }\n\n // \"X | null\" / \"X | undefined\" — nullable wrapper.\n if (typeName.endsWith(\" | null\") || typeName.endsWith(\" | undefined\")) {\n const inner = parseTypeName(typeName.replace(/ \\| (null|undefined)$/, \"\"));\n\n return { ...inner, nullable: true };\n }\n\n // Bare primitive.\n if (PRIMITIVE_KINDS.has(typeName as SchemaKind)) {\n return { kind: typeName as SchemaKind } as SchemaKindNode;\n }\n\n // String-flavored named types (email, uuid, url, etc.) all map to \"string\"\n // for operator purposes.\n if (/^(email|uuid|url|cuid|datetime|iso\\b)/i.test(typeName)) {\n return { kind: \"string\" };\n }\n\n // Generic union \"X | Y | Z\" → union of parsed members (used by t.union()).\n if (typeName.includes(\" | \")) {\n const members = typeName.split(\" | \").map(parseTypeName);\n\n return { kind: \"union\", members };\n }\n\n // Bare names we recognize as composite without elements.\n if (typeName === \"array\")\n return { kind: \"array\", element: { kind: \"unknown\" } };\n if (typeName === \"object\") return { kind: \"object\", shape: {} };\n if (typeName === \"record\")\n return { kind: \"record\", value: { kind: \"unknown\" } };\n if (typeName === \"tuple\") return { kind: \"tuple\", elements: [] };\n if (typeName === \"union\") return { kind: \"union\", members: [] };\n\n return { kind: \"unknown\" };\n}\n\n// ============================================================================\n// Get the kind node for a single schema field\n// ============================================================================\n\n/**\n * Return the {@link SchemaKindNode} for a schema field. Prefers the\n * explicit `_kind` discriminant set by the builder; falls back to\n * parsing the freeform `_typeName` string for legacy / third-party\n * builders that don't set `_kind`.\n *\n * Hostile-getter safe: `_kind` / `_typeName` reads are wrapped — a builder\n * that throws on property access returns `{ kind: \"unknown\" }` instead of\n * propagating the throw to introspecting callers.\n *\n * In dev mode, a function input (`typeof schema === \"function\"`) emits a\n * warning — common foot-gun where the caller forgot to invoke a builder\n * factory (e.g. wrote `t.number` instead of `t.number()`).\n *\n * @example\n * ```ts\n * getKind(t.number()) // → { kind: \"number\" }\n * getKind(t.string().nullable()) // → { kind: \"string\", nullable: true }\n * getKind(t.array(t.number())) // → { kind: \"array\", element: { kind: \"number\" } }\n * ```\n */\nexport function getKind(schema: unknown): SchemaKindNode {\n if (schema === null || schema === undefined) return { kind: \"unknown\" };\n if (typeof schema === \"function\") {\n if (isDevelopment) {\n console.warn(\n \"[Directive] getKind: received a function — did you forget () on a t.* builder? Example: write `t.number()`, not `t.number`.\",\n );\n }\n\n return { kind: \"unknown\" };\n }\n if (typeof schema !== \"object\") return { kind: \"unknown\" };\n const s = schema as IntrospectableSchema;\n\n // Hostile-getter guard: a third-party builder that throws on `_kind` /\n // `_typeName` reads must not crash an introspecting caller.\n let kindNode: SchemaKindNode | undefined;\n try {\n kindNode = s._kind;\n } catch {\n return { kind: \"unknown\" };\n }\n if (kindNode) return kindNode;\n\n let typeName: string | undefined;\n try {\n typeName = s._typeName;\n } catch {\n return { kind: \"unknown\" };\n }\n\n return parseTypeName(typeName);\n}\n\n// ============================================================================\n// Walk a module schema → Map<dotted-path, SchemaKindNode>\n// ============================================================================\n\n/**\n * Walk the `facts` block of a module schema and emit a flat map from\n * dotted path → kind node. Nested `t.object()` shapes flatten using\n * `.` as the separator, matching the convention used by\n * `OperatorObject<V>`'s nested-path support.\n *\n * Passing a top-level schema directly (without the `facts:` wrapper)\n * also works — anything iterable as `Record<string, ExtendedSchemaType>`\n * is acceptable.\n *\n * Hostile-getter safe: a builder whose `_kind` / `_typeName` throws is\n * silently skipped (treated as `{ kind: \"unknown\" }` for that field)\n * rather than aborting the whole walk.\n *\n * In dev mode, a top-level schema that yields an empty map (no\n * introspectable keys) emits a warning — common foot-gun where the\n * caller passed `myModule` instead of `myModule.schema`.\n */\nexport function getSchemaFieldKinds(\n schema: unknown,\n): Map<string, SchemaKindNode> {\n const out = new Map<string, SchemaKindNode>();\n if (!schema || typeof schema !== \"object\") return out;\n const root = schema as Record<string, unknown>;\n const factsCandidate =\n \"facts\" in root && root.facts && typeof root.facts === \"object\"\n ? root.facts\n : root;\n const facts = factsCandidate as Record<string, unknown>;\n\n for (const [key, builder] of Object.entries(facts)) {\n if (!builder || typeof builder !== \"object\") continue;\n let node: SchemaKindNode;\n try {\n node = getKind(builder);\n } catch {\n // A pathological builder whose getter throws past getKind's own\n // guards — skip the field but keep walking the rest.\n continue;\n }\n out.set(key, node);\n\n // Flatten nested object shapes one level — matches OperatorObject<V>'s\n // dotted-path support.\n if (node.kind === \"object\") {\n for (const [innerKey, innerNode] of Object.entries(node.shape)) {\n out.set(`${key}.${innerKey}`, innerNode);\n }\n }\n }\n\n if (out.size === 0 && isDevelopment) {\n console.warn(\n \"[Directive] getSchemaFieldKinds: schema appears empty (no introspectable keys). Did you pass the module instead of its schema? Pass `myModule.schema`, not `myModule`.\",\n );\n }\n\n return out;\n}\n\n// ============================================================================\n// Operator allowlist per kind\n// ============================================================================\n\nconst COMMON_OPS: readonly PredicateOp[] = [\n \"$eq\",\n \"$ne\",\n \"$in\",\n \"$nin\",\n \"$exists\",\n];\n\nconst ORDERABLE_OPS: readonly PredicateOp[] = [\n \"$gt\",\n \"$gte\",\n \"$lt\",\n \"$lte\",\n \"$between\",\n];\n\nconst STRING_OPS: readonly PredicateOp[] = [\n \"$matches\",\n \"$startsWith\",\n \"$endsWith\",\n \"$contains\",\n];\n\n/**\n * Return the set of `PredicateOp` strings that are valid against a\n * given {@link SchemaKindNode}.\n *\n * Mirrors the type-level matrix encoded in `OperatorObject<V>` in\n * `types/predicate.ts` — drift between the two is enforced by the\n * compile-time conformance test\n * (`schema-introspection-conformance.test-d.ts`).\n *\n * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists`\n * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`,\n * `$lt`, `$lte`, `$between`\n * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains`\n * - **Array:** + `$contains` (over the element type)\n * - **Union:** *intersection* across members (the operand must be valid\n * for every branch).\n * - **Branded:** delegates to the inner kind.\n * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in`\n * operand restricted at the LLM-prompt layer (not enforced here).\n *\n * `nullable` does not change operator availability — `$gte` on a\n * nullable number is fine on the non-null arm; `$exists` handles null.\n */\nexport function getOperatorsForKind(\n node: SchemaKindNode,\n): readonly PredicateOp[] {\n switch (node.kind) {\n case \"number\":\n case \"bigint\":\n case \"date\":\n return [...COMMON_OPS, ...ORDERABLE_OPS];\n case \"string\":\n return [...COMMON_OPS, ...ORDERABLE_OPS, ...STRING_OPS];\n case \"boolean\":\n case \"unknown\":\n return COMMON_OPS;\n case \"array\":\n return [...COMMON_OPS, \"$contains\"];\n case \"object\":\n case \"record\":\n case \"tuple\":\n return COMMON_OPS;\n case \"literal\":\n case \"enum\":\n // Operators allowed by the underlying primitive.\n return getOperatorsForKind(\n node.primitive === \"number\"\n ? { kind: \"number\" }\n : node.primitive === \"boolean\"\n ? { kind: \"boolean\" }\n : node.primitive === \"null\"\n ? { kind: \"unknown\" }\n : { kind: \"string\" },\n );\n case \"branded\":\n return getOperatorsForKind(node.inner);\n case \"union\": {\n // Intersection of operators valid on every member.\n if (node.members.length === 0) return COMMON_OPS;\n const sets = node.members.map((m) => new Set(getOperatorsForKind(m)));\n const first = sets[0]!;\n const intersection: PredicateOp[] = [];\n for (const op of first) {\n if (sets.every((s) => s.has(op))) intersection.push(op);\n }\n\n return intersection;\n }\n default: {\n // Exhaustiveness check — TS will flag if a new kind is added without\n // a switch arm.\n const _exhaustive: never = node;\n void _exhaustive;\n\n return COMMON_OPS;\n }\n }\n}\n\n/**\n * Return all known predicate operators — convenience for prompt builders\n * that need to show the LLM the full set.\n */\nexport function listAllPredicateOperators(): readonly PredicateOp[] {\n return Array.from(PREDICATE_OPERATORS) as readonly PredicateOp[];\n}\n","/**\n * Runtime for data-configuration predicates and templates.\n *\n * Pure module — imports only its own types. Reads facts through whatever\n * object it is handed (the reactive `Facts` proxy in production, a plain\n * snapshot in tests), so it never depends on the engine, store, or tracking.\n */\n\nimport isDevelopment from \"#is-development\";\nimport { stableStringify } from \"../utils/utils.js\";\nimport {\n type ClauseResult,\n type FactTemplate,\n PREDICATE_OPERATORS,\n type PatchSpec,\n type PredicateOp,\n} from \"./types/predicate.js\";\n\n// ============================================================================\n// Recursion bound\n// ============================================================================\n\n/**\n * Maximum predicate-AST recursion depth. Legitimate cross-module predicates\n * nest fewer than ~15 levels; 64 is generous but bounded — past it the runtime\n * dev-warns and bails rather than risking a stack overflow on a cyclic or\n * pathologically deep spec. Shared by every structural predicate walker\n * ({@link walkPredicate}, {@link evaluatePredicate}) so the cap lives in one\n * place.\n */\nexport const MAX_PREDICATE_DEPTH = 64;\n\n// ============================================================================\n// Discriminators\n// ============================================================================\n\n/** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */\ntype Scope = Record<string, unknown>;\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n\n return !(v instanceof Date) && !(v instanceof RegExp);\n}\n\n/**\n * True when `v` is a plain `{}` literal (its prototype is `Object.prototype`\n * or `null`). Excludes class instances, Date, RegExp, Map, Set, Promise, etc.\n */\nfunction isPlainObjectStrict(v: unknown): v is Record<string, unknown> {\n if (typeof v !== \"object\" || v === null || Array.isArray(v)) {\n return false;\n }\n const proto = Object.getPrototypeOf(v);\n\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * True when every own key of `v` is a recognized `$`-operator (and there is ≥1).\n * If any key starts with `$` but is not a known operator, dev-warn (typo) and\n * still treat the value as an operator object so the typo is not masked as a\n * literal — `applyOperator` will return false for the unknown op.\n */\nfunction isOperatorObject(v: unknown): v is Record<string, unknown> {\n if (!isPlainObject(v)) {\n return false;\n }\n\n let count = 0;\n let hasDollarKey = false;\n for (const k of Object.keys(v)) {\n if (k.startsWith(\"$\")) {\n hasDollarKey = true;\n if (!PREDICATE_OPERATORS.has(k)) {\n devWarn(\n `predicate: unknown operator \"${k}\" — looks like a typo. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n } else if (hasDollarKey || count === 0) {\n // Mixed $/non-$ keys aren't an operator object; let the caller treat\n // it as a literal/recursive predicate. The non-$ key check happens\n // below by short-circuiting when a non-$ key appears.\n return false;\n }\n count++;\n }\n\n if (!hasDollarKey) {\n return false;\n }\n\n // All keys are `$`-prefixed: this is an operator object, even if some keys\n // are typos. An unknown op makes applyOperator() return false.\n return count > 0;\n}\n\n/**\n * True when `v` is a data-form spec (predicate object/array) rather than a\n * function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.)\n * — only plain `{}` literals and arrays of plain clause shapes qualify.\n *\n * @example\n * ```ts\n * isPredicate({ phase: \"red\" }); // true\n * isPredicate((f) => f.phase === \"red\"); // false\n * isPredicate([{ fact: \"phase\", op: \"$eq\", value: \"red\" }]); // true\n * ```\n */\nexport function isPredicate(v: unknown): boolean {\n if (v === null) {\n return false;\n }\n if (Array.isArray(v)) {\n return v.every(\n (c) =>\n isPlainObjectStrict(c) &&\n \"fact\" in (c as object) &&\n \"op\" in (c as object),\n );\n }\n\n return isPlainObjectStrict(v);\n}\n\n// ============================================================================\n// Structural traversal\n// ============================================================================\n\n/**\n * Visitor passed to {@link walkPredicate}. Every callback is optional; a\n * walker implements only the arms it cares about.\n */\nexport interface PredicateVisitor {\n /**\n * A leaf operator clause: a fact + a `$`-operator + its operand. Fires once\n * per operator in a multi-operator object.\n *\n * @param factPath - Dotted path to the fact (`elapsed`, `auth.token`).\n * @param op - The operator key (`$gte`, `$matches`, …).\n * @param operand - The operator's operand value.\n * @param operandPath - Dotted path to the operand for diagnostics\n * (`elapsed.$gte`, `value` / `[0].value` for the array-clause form).\n */\n operator?(\n factPath: string,\n op: string,\n operand: unknown,\n operandPath: string,\n ): void;\n /**\n * A bare-value (equality) clause — a fact mapped to a non-object literal,\n * an array, or a non-plain class instance (Date, RegExp, Set, …).\n *\n * @param factPath - Dotted path to the fact.\n * @param value - The equality operand.\n */\n literal?(factPath: string, value: unknown): void;\n /**\n * A combinator node (`$all` / `$any` / `$not`), called before descending.\n * Return `false` to skip its children.\n */\n combinator?(kind: \"$all\" | \"$any\" | \"$not\"): boolean | void;\n /**\n * A nested-object (cross-module pivot) key, called before descending.\n * Return `false` to skip its children.\n */\n nested?(key: string): boolean | void;\n /**\n * A `$`-prefixed key appearing where a fact key was expected — either an\n * unknown/typo operator, or an operator mixed with fact keys at predicate\n * top level.\n *\n * @param key - The stray `$`-key.\n * @param factPath - Dotted path to the stray key.\n */\n strayOperatorKey?(key: string, factPath: string): void;\n /**\n * Called when traversal bails out early — a cycle was re-encountered or\n * the depth cap was hit. The subtree below the bail point is NOT visited.\n */\n bail?(reason: \"cycle\" | \"depth\"): void;\n}\n\n/**\n * Single depth-guarded, cycle-guarded structural traversal of a predicate\n * AST. The pure structural walkers — dependency extraction, `$changed`\n * detection, empty/config detection, serialization validation — share this\n * so a new operator or combinator is threaded through one place.\n *\n * Handles the object form, the array-clause form, combinator nodes, nested\n * cross-module objects, operator objects, and bare-value literals. It does\n * **not** evaluate — see {@link evaluatePredicate} for that.\n *\n * @internal\n */\nexport function walkPredicate(\n spec: unknown,\n visitor: PredicateVisitor,\n path = \"\",\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): void {\n if (depth > MAX_PREDICATE_DEPTH) {\n if (isDevelopment) {\n console.warn(\n `[Directive] predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n }\n visitor.bail?.(\"depth\");\n\n return;\n }\n\n // Array-clause form — each `{ fact, op, value }` clause is a leaf operator.\n if (Array.isArray(spec)) {\n spec.forEach((clause, i) => {\n if (!isPlainObject(clause)) {\n return;\n }\n const c = clause as Record<string, unknown>;\n if (typeof c.fact === \"string\" && typeof c.op === \"string\") {\n const clausePath = path ? `${path}[${i}]` : `[${i}]`;\n visitor.operator?.(\n path ? `${path}.${c.fact}` : c.fact,\n c.op,\n c.value,\n `${clausePath}.value`,\n );\n }\n });\n\n return;\n }\n\n if (!isPlainObject(spec)) {\n return;\n }\n if (seen.has(spec)) {\n if (isDevelopment) {\n console.warn(\"[Directive] walkPredicate: cyclic predicate spec\");\n }\n visitor.bail?.(\"cycle\");\n\n return;\n }\n seen.add(spec);\n\n const obj = spec as Record<string, unknown>;\n\n // Combinator node — descend into children unless the visitor opts out.\n for (const kind of [\"$all\", \"$any\", \"$not\"] as const) {\n if (kind in obj) {\n const descend = visitor.combinator?.(kind);\n if (descend === false) {\n return;\n }\n const children =\n kind === \"$not\" ? [obj.$not] : ((obj[kind] as unknown[]) ?? []);\n for (const child of children) {\n walkPredicate(child, visitor, path, seen, depth + 1);\n }\n\n return;\n }\n }\n\n // Object form — one entry per key.\n for (const key of Object.keys(obj)) {\n const childPath = path ? `${path}.${key}` : key;\n\n if (key.startsWith(\"$\")) {\n // A `$`-key at fact position — typo operator or top-level operator\n // mixed with fact keys. Surface it; do not descend.\n visitor.strayOperatorKey?.(key, childPath);\n continue;\n }\n\n const value = obj[key];\n\n if (isOperatorObject(value)) {\n const opObj = value as Record<string, unknown>;\n for (const op of Object.keys(opObj)) {\n visitor.operator?.(childPath, op, opObj[op], `${childPath}.${op}`);\n }\n continue;\n }\n\n // Only a strict plain object (`{}` / `Object.create(null)`) recurses as\n // a nested cross-module predicate. A Set, Map, or class instance is a\n // bare-value leaf — surfacing it as `literal` lets a walker inspect its\n // runtime class (e.g. validatePredicate's JSON-serializability check).\n if (isPlainObjectStrict(value)) {\n const descend = visitor.nested?.(key);\n if (descend === false) {\n continue;\n }\n walkPredicate(value, visitor, childPath, seen, depth + 1);\n continue;\n }\n\n // Bare value — equality leaf (also array / Set / Map / class instances).\n visitor.literal?.(childPath, value);\n }\n}\n\n/**\n * True when `v` structurally passes {@link isPredicate} but contains no\n * operators, no combinators, and no fact-clause entries that resolve to a\n * primitive/operator leaf — i.e. an empty `{}` or a deeply-nested object\n * tree that never bottoms out in a leaf value. Used by the dynamic\n * `register()` / `assign()` paths to dev-warn when a config object is\n * passed where a predicate (or function) was expected.\n *\n * Returns `false` for arrays — array-form predicates with `fact`+`op`\n * clauses are handled by the structural `isPredicate` check upstream.\n *\n * @example\n * ```ts\n * isEmptyOrConfigPredicate({}); // true (empty — config-object misuse)\n * isEmptyOrConfigPredicate({ phase: \"red\" }); // false (real fact clause)\n * isEmptyOrConfigPredicate({ $eq: 5 }); // false (operator)\n * isEmptyOrConfigPredicate({ count: { $gt: 5 } }); // false (operator clause)\n * ```\n *\n * @internal\n */\nexport function isEmptyOrConfigPredicate(v: unknown): boolean {\n // Arrays and non-plain-object specs are never \"empty config objects\".\n if (!isPlainObjectStrict(v)) {\n return false;\n }\n\n // A spec is a config tree only when walkPredicate fires NONE of the\n // predicate-semantic callbacks — no operator, no combinator, no literal\n // leaf, no stray `$`-key. Nested plain objects are descended; an empty\n // `{}` or a tree of empty `{}` fires nothing and stays \"config\". A cycle\n // or depth-cap bail is treated as \"not a config object\" (can't determine\n // — fail safe so the dev-warn is not spuriously emitted).\n let isPredicateBody = false;\n walkPredicate(v, {\n operator() {\n isPredicateBody = true;\n },\n literal() {\n isPredicateBody = true;\n },\n combinator() {\n isPredicateBody = true;\n },\n strayOperatorKey() {\n isPredicateBody = true;\n },\n bail() {\n isPredicateBody = true;\n },\n });\n\n return !isPredicateBody;\n}\n\n/**\n * True when `v` is a {@link FactTemplate} (`{ $template: string }`).\n *\n * @example\n * ```ts\n * isTemplate({ $template: \"Hi ${name}\" }); // true\n * isTemplate({ $set: { name: \"x\" } }); // false\n * ```\n */\nexport function isTemplate(v: unknown): v is FactTemplate {\n return (\n isPlainObject(v) &&\n Object.hasOwn(v, \"$template\") &&\n typeof (v as { $template: unknown }).$template === \"string\"\n );\n}\n\n// ============================================================================\n// Load-time validation\n// ============================================================================\n\n/**\n * Throw when a predicate spec contains an operand that cannot survive a\n * JSON round-trip — i.e. that would silently mis-evaluate if the spec was\n * loaded from `JSON.parse`.\n *\n * Three failure classes are detected:\n *\n * - **Lost `RegExp` operand.** A `$matches` operand that is not a\n * `RegExp` instance. `JSON.parse` reconstructs a serialized regex as\n * `{}`, so a `$matches` clause with an empty-object operand is the\n * signature of a regex that did not survive serialization. Reify it\n * with `new RegExp(pattern, flags)` before installing the predicate.\n * - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a\n * `bigint` operand cannot have been produced by a JSON pipeline and\n * cannot be persisted by one either.\n * - **`Set` / `Map` operand.** Both serialize to `{}` and lose all\n * members; a predicate carrying one is not JSON-safe.\n *\n * This is an opt-in helper — the engine does not call it automatically.\n * Users who load predicates from JSON should call it after `JSON.parse`\n * to fail loud rather than silently mis-evaluate. See the\n * \"Serialization\" section of RFC-0004.\n *\n * @example\n * ```ts\n * validatePredicate({ phase: { $matches: {} } });\n * // throws — empty object where a RegExp is required\n *\n * validatePredicate({ phase: \"red\", elapsed: { $gte: 30 } });\n * // ok — JSON-clean operands\n * ```\n */\nexport function validatePredicate(spec: unknown, path = \"\"): void {\n /**\n * Recursively walk an operand's object/array structure, throwing on any\n * value that cannot survive a JSON round-trip — `bigint`, `Set`, `Map`, or\n * a nested `RegExp`. Depth- and cycle-guarded. A top-level operand is\n * inspected by the operator-specific {@link checkOperand} (which permits a\n * `RegExp` as the direct `$matches` operand); this helper handles values\n * nested *inside* a plain-object or array operand, where a `RegExp` is just\n * as JSON-unsafe as a `Set`.\n */\n function checkValueJsonSafe(\n value: unknown,\n at: string,\n seen: WeakSet<object>,\n depth: number,\n ): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (value instanceof RegExp) {\n throw new Error(\n `[Directive] validatePredicate: RegExp operand at \"${at}\" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`,\n );\n }\n if (value === null || typeof value !== \"object\") {\n return;\n }\n if (depth > MAX_PREDICATE_DEPTH) {\n return;\n }\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, seen, depth + 1);\n });\n\n return;\n }\n\n for (const k of Object.keys(value as Record<string, unknown>)) {\n checkValueJsonSafe(\n (value as Record<string, unknown>)[k],\n at ? `${at}.${k}` : k,\n seen,\n depth + 1,\n );\n }\n }\n\n /** Throw on a JSON-unrehydratable operand value. */\n function checkOperand(value: unknown, op: string, at: string): void {\n if (typeof value === \"bigint\") {\n throw new Error(\n `[Directive] validatePredicate: bigint operand at \"${at}\" is not JSON-serializable (JSON.stringify throws on bigint).`,\n );\n }\n if (value instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (value instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand at \"${at}\" is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n if (op === \"$matches\" && !(value instanceof RegExp)) {\n throw new Error(\n `[Directive] validatePredicate: $matches operand at \"${at}\" must be a RegExp; got ${value === null ? \"null\" : typeof value}. A regex lost to JSON.parse becomes {} — reify with new RegExp(pattern, flags) before installing.`,\n );\n }\n // A plain-object / array operand (e.g. `$eq: { ... }`, `$in: [ ... ]`)\n // can carry a `bigint`, `Set`, `Map`, or nested `RegExp` arbitrarily deep\n // — `checkOperand` only sees the operand's top type, so recurse into its\n // structure. The direct `$matches` RegExp is handled above and never\n // reaches this branch (a RegExp is not a plain object / array).\n if (Array.isArray(value)) {\n value.forEach((el, i) => {\n checkValueJsonSafe(el, `${at}[${i}]`, new WeakSet(), 1);\n });\n } else if (isPlainObjectStrict(value)) {\n for (const k of Object.keys(value)) {\n checkValueJsonSafe(value[k], `${at}.${k}`, new WeakSet(), 1);\n }\n }\n }\n\n // Top-level Set / Map node — a regex / set / map handed in directly as the\n // whole spec. walkPredicate would treat it as an empty object, so check\n // the entry node here.\n if (spec instanceof Set) {\n throw new Error(\n `[Directive] validatePredicate: Set operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all members).`,\n );\n }\n if (spec instanceof Map) {\n throw new Error(\n `[Directive] validatePredicate: Map operand${path ? ` at \"${path}\"` : \"\"} is not JSON-serializable (serializes to {} and loses all entries).`,\n );\n }\n\n // Single structural traversal — every operator clause and equality leaf is\n // checked for a JSON-unrehydratable operand. The walker threads the dotted\n // operand path so error messages point at the offending clause.\n walkPredicate(spec, {\n operator(_factPath, op, operand, operandPath) {\n checkOperand(operand, op, path ? `${path}.${operandPath}` : operandPath);\n },\n literal(factPath, value) {\n checkOperand(value, \"\", path ? `${path}.${factPath}` : factPath);\n },\n });\n}\n\n// ============================================================================\n// Schema-aware validation (semantic — operator on kind, operator-count cap)\n// ============================================================================\n\nimport {\n type SchemaKindNode,\n getOperatorsForKind,\n} from \"./schema-introspection.js\";\n\nexport interface SchemaValidationError {\n /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */\n readonly path: string;\n /** The operator that failed (or the literal-equality marker `$eq`). */\n readonly op: string;\n /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */\n readonly kind?: SchemaKindNode;\n /** The operators that ARE allowed for this fact's kind. */\n readonly allowedOps?: readonly string[];\n /** Human-readable failure reason (suitable for feeding back to an LLM). */\n readonly reason: string;\n}\n\nexport interface SchemaValidationOptions {\n /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */\n readonly maxOperatorCount?: number;\n /**\n * Reject `$in` / `$nin` operands that contain more than this many elements\n * (query-planner DoS guard). Default unbounded. A typical safe cap is 1000\n * — beyond that, a downstream query compiler may degrade quadratically.\n */\n readonly maxArrayOperandLength?: number;\n}\n\n/**\n * Heuristic: flag a regex source string that has obvious nested quantifiers\n * (e.g. `(.+)+`, `(.*)*`, `(\\w+)+`, `(a|a)+`) — the classic ReDoS shapes.\n * Not a full ReDoS prover; intentionally conservative so a string-rehydrated\n * `$matches` operand can be rejected before it ever reaches `RegExp.test`.\n *\n * Callers MUST NOT treat a `false` result as \"safe\" — a determined adversary\n * can craft patterns this heuristic misses. The right answer for untrusted\n * regex is \"don't accept untrusted regex\"; this helper exists to catch the\n * obvious foot-guns.\n *\n * @example\n * ```ts\n * dangerousRegex(\"(a+)+\"); // → true\n * dangerousRegex(\"(.*)*\"); // → true\n * dangerousRegex(\"(\\\\w+)+\"); // → true\n * dangerousRegex(\"^[a-z]+$\"); // → false\n * ```\n */\nexport function dangerousRegex(source: string): boolean {\n if (typeof source !== \"string\" || source.length === 0) {\n return false;\n }\n // Nested quantifiers — a group ending in `*` or `+` (or `{n,}`) immediately\n // followed by another `*` / `+` / `{n,}` quantifier. Allow `?` between\n // (lazy) since `(...)?+` is still pathological. Also catch `{n,m}` upper\n // bounds when they wrap a quantified group.\n //\n // Patterns flagged:\n // (.+)+ (.*)* (.+)* (.*)+\n // (\\w+)+ (\\d*)+ ([abc]+)+\n // (a|a)+ (a|b|c)* ((x))+ (?:x+)+\n //\n // The check looks for a closing `)` preceded by a quantifier-bearing token\n // (`+`, `*`, `}` from `{n,m}`, or `+?` / `*?` lazy) and followed by another\n // quantifier (`+`, `*`, or `{n,`).\n const nestedQuantifier = /\\)(?:[+*]\\??|\\{\\d+,?\\d*\\})\\s*[+*?]\\s*[+*]/;\n if (nestedQuantifier.test(source)) {\n return true;\n }\n // Group whose inner content already has a `+` / `*` / `{n,}` quantifier on\n // a character class or token, and the group is then itself quantified.\n // E.g. `(a+)+`, `(\\w+)+`, `(.*)*`, `([abc]+)*`.\n const groupedQuantified =\n /\\(([^()]*?[+*]|[^()]*?\\{\\d+,?\\d*\\})[^()]*\\)\\s*[+*]/;\n if (groupedQuantified.test(source)) {\n return true;\n }\n // Alternation of identical branches: `(a|a)+`, `(foo|foo)*`.\n const sameBranchAlt = /\\(\\??:?([^()|]+)\\|\\1\\)\\s*[+*]/;\n if (sameBranchAlt.test(source)) {\n return true;\n }\n\n return false;\n}\n\nexport type SchemaValidationResult =\n | { ok: true; operatorCount: number }\n | {\n ok: false;\n errors: readonly SchemaValidationError[];\n operatorCount: number;\n };\n\n/**\n * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate\n * against a schema's runtime kind map. Catches errors that\n * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a\n * boolean fact), unknown fact paths, and (optionally) operator-count\n * exhaustion DoS attempts.\n *\n * Pair with {@link validatePredicate} (structural / JSON safety) for full\n * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a\n * module schema.\n *\n * Designed for the LLM-emit retry loop: returns a list of errors with\n * structured `{path, op, kind, allowedOps, reason}` rather than throwing,\n * so the caller can feed the errors back to the model.\n *\n * @example\n * ```ts\n * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } });\n * const result = validatePredicateAgainstSchema(\n * { cartTotal: { $gte: 50 }, active: { $gte: true } },\n * kindMap,\n * );\n * // → { ok: false, errors: [{ path: \"active\", op: \"$gte\", reason: \"...\" }], operatorCount: 2 }\n * ```\n */\nexport function validatePredicateAgainstSchema(\n spec: unknown,\n kindMap: Map<string, SchemaKindNode>,\n opts: SchemaValidationOptions = {},\n): SchemaValidationResult {\n const errors: SchemaValidationError[] = [];\n let operatorCount = 0;\n const maxOperatorCount = opts.maxOperatorCount;\n const maxArrayOperandLength = opts.maxArrayOperandLength;\n\n walkPredicate(spec, {\n operator(factPath, op, operand, _operandPath) {\n operatorCount++;\n if (maxOperatorCount !== undefined && operatorCount > maxOperatorCount) {\n // Don't pile up identical errors past the cap; one is enough.\n if (!errors.some((e) => e.reason.includes(\"maxOperatorCount\"))) {\n errors.push({\n path: factPath,\n op,\n reason: `Predicate exceeds maxOperatorCount=${maxOperatorCount} — too many clauses (DoS guard).`,\n });\n }\n\n return;\n }\n\n // M1: $in / $nin operand length cap — too-large array operands choke\n // downstream query planners and OR-tree compilers.\n if (\n maxArrayOperandLength !== undefined &&\n (op === \"$in\" || op === \"$nin\") &&\n Array.isArray(operand) &&\n operand.length > maxArrayOperandLength\n ) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator ${op} operand exceeds maxArrayOperandLength=${maxArrayOperandLength} (got ${operand.length}) — too large for a query planner.`,\n });\n\n return;\n }\n\n // M2: $matches operand ReDoS heuristic — flag obvious nested\n // quantifiers in either a RegExp or a string-form pattern. String-form\n // patterns are rejected at evaluation time (see applyOperator), but\n // a static check here catches them before they ever load.\n //\n // WARNING: don't rehydrate LLM-emitted string-form regex without your\n // own complexity audit; `dangerousRegex()` is a foot-gun catcher, not\n // a ReDoS prover.\n if (op === \"$matches\") {\n let regexSource: string | undefined;\n if (operand instanceof RegExp) {\n regexSource = operand.source;\n } else if (typeof operand === \"string\") {\n regexSource = operand;\n }\n if (regexSource !== undefined && dangerousRegex(regexSource)) {\n errors.push({\n path: factPath,\n op,\n reason: `Operator $matches operand at \"${factPath}\" contains nested quantifiers (ReDoS risk: ${JSON.stringify(regexSource)}). Reject untrusted regex or rewrite without nested + / *.`,\n });\n\n return;\n }\n }\n\n const kind = kindMap.get(factPath);\n if (!kind) {\n errors.push({\n path: factPath,\n op,\n reason: `Unknown fact \"${factPath}\" — not in schema. Known facts: ${\n kindMap.size === 0\n ? \"(empty schema)\"\n : Array.from(kindMap.keys()).join(\", \")\n }`,\n });\n\n return;\n }\n\n const allowedOps = getOperatorsForKind(kind);\n if (!allowedOps.includes(op as never)) {\n errors.push({\n path: factPath,\n op,\n kind,\n allowedOps,\n reason: `Operator \"${op}\" is not allowed on fact \"${factPath}\" of kind \"${kind.kind}\". Allowed operators for this kind: ${allowedOps.join(\", \")}.`,\n });\n }\n },\n literal(factPath, _value) {\n operatorCount++;\n // Bare-value (equality) — always permitted as long as fact exists.\n if (!kindMap.has(factPath)) {\n errors.push({\n path: factPath,\n op: \"$eq\",\n reason: `Unknown fact \"${factPath}\" — not in schema.`,\n });\n }\n },\n strayOperatorKey(key, factPath) {\n errors.push({\n path: factPath,\n op: key,\n reason: `Stray operator key \"${key}\" at \"${factPath}\" — operators must live inside a fact's operator object, not at the predicate top level.`,\n });\n },\n });\n\n if (errors.length === 0) return { ok: true, operatorCount };\n\n return { ok: false, errors, operatorCount };\n}\n\n// ============================================================================\n// Equality\n// ============================================================================\n\n/**\n * Pairwise cycle-guard state shared across a single `deepEqual` traversal.\n *\n * Asymmetric cycles (only one side cyclic) must not short-circuit; we only\n * treat a pair as equal when the same `(a, b)` pair is re-encountered.\n */\ninterface DeepEqualSeen {\n ids: WeakMap<object, number>;\n next: { v: number };\n pairs: Set<string>;\n}\n\nfunction deepEqualSeen(): DeepEqualSeen {\n return { ids: new WeakMap(), next: { v: 1 }, pairs: new Set() };\n}\n\nfunction pairId(seen: DeepEqualSeen, obj: object): number {\n let id = seen.ids.get(obj);\n if (id === undefined) {\n id = seen.next.v++;\n seen.ids.set(obj, id);\n }\n\n return id;\n}\n\n/** Structural equality with NaN/Date handling and a pairwise cycle guard. */\nfunction deepEqual(a: unknown, b: unknown, seen?: DeepEqualSeen): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n if (\n typeof a !== \"object\" ||\n typeof b !== \"object\" ||\n a === null ||\n b === null\n ) {\n return false;\n }\n\n const guard = seen ?? deepEqualSeen();\n const key = `${pairId(guard, a)}:${pairId(guard, b)}`;\n if (guard.pairs.has(key)) {\n return true; // same (a, b) pair re-encountered — treat as equal\n }\n guard.pairs.add(key);\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n\n return a.every((v, i) => deepEqual(v, b[i], guard));\n }\n\n // Set equality — same size, every element of `a` has a structurally-equal\n // counterpart in `b`. Must precede the `Object.keys` fallback below because\n // `Object.keys(new Set(...))` is always `[]`, which would otherwise let\n // any two Sets (or any two Maps) compare equal regardless of contents.\n if (a instanceof Set || b instanceof Set) {\n if (!(a instanceof Set) || !(b instanceof Set) || a.size !== b.size) {\n return false;\n }\n const bArr = [...b];\n\n return [...a].every((v) => bArr.some((w) => deepEqual(v, w, guard)));\n }\n\n // Map equality — same size, every key in `a` matches a key in `b` with a\n // structurally-equal value. Greedy match with a used-flag to handle\n // structural (non-reference) key equality correctly.\n if (a instanceof Map || b instanceof Map) {\n if (!(a instanceof Map) || !(b instanceof Map) || a.size !== b.size) {\n return false;\n }\n const bEntries = [...b.entries()];\n const used = new Array<boolean>(bEntries.length).fill(false);\n for (const [ka, va] of a) {\n let found = false;\n for (let i = 0; i < bEntries.length; i++) {\n if (used[i]) {\n continue;\n }\n const [kb, vb] = bEntries[i]!;\n if (deepEqual(ka, kb, guard) && deepEqual(va, vb, guard)) {\n used[i] = true;\n found = true;\n break;\n }\n }\n if (!found) {\n return false;\n }\n }\n\n return true;\n }\n\n const ak = Object.keys(a as object);\n const bk = Object.keys(b as object);\n if (ak.length !== bk.length) {\n return false;\n }\n\n return ak.every(\n (k) =>\n Object.hasOwn(b as object, k) &&\n deepEqual(\n (a as Record<string, unknown>)[k],\n (b as Record<string, unknown>)[k],\n guard,\n ),\n );\n}\n\n// ============================================================================\n// Operators\n// ============================================================================\n\nfunction toComparable(v: unknown): number | bigint | string | undefined {\n if (v instanceof Date) {\n return v.getTime();\n }\n if (typeof v === \"number\" || typeof v === \"bigint\" || typeof v === \"string\") {\n return v;\n }\n\n return undefined;\n}\n\nfunction relational(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n): boolean {\n const a = toComparable(actual);\n const b = toComparable(operand);\n if (a === undefined || b === undefined || typeof a !== typeof b) {\n return false;\n }\n\n switch (op) {\n case \"$gt\":\n return a > b;\n case \"$gte\":\n return a >= b;\n case \"$lt\":\n return a < b;\n case \"$lte\":\n return a <= b;\n default:\n return false;\n }\n}\n\n/** Apply one operator. `prevValue` is supplied only for `$changed`. */\nfunction applyOperator(\n op: PredicateOp,\n actual: unknown,\n operand: unknown,\n prevValue: unknown,\n): boolean {\n switch (op) {\n case \"$eq\":\n return deepEqual(actual, operand);\n case \"$ne\":\n return !deepEqual(actual, operand);\n case \"$in\":\n return (\n Array.isArray(operand) && operand.some((v) => deepEqual(actual, v))\n );\n case \"$nin\":\n return (\n Array.isArray(operand) && !operand.some((v) => deepEqual(actual, v))\n );\n case \"$exists\":\n return operand === (actual !== undefined);\n case \"$changed\":\n return !deepEqual(actual, prevValue);\n case \"$gt\":\n case \"$gte\":\n case \"$lt\":\n case \"$lte\":\n return relational(op, actual, operand);\n case \"$between\": {\n if (!Array.isArray(operand) || operand.length !== 2) {\n return false;\n }\n const lo = toComparable(operand[0]);\n const hi = toComparable(operand[1]);\n if (\n lo !== undefined &&\n hi !== undefined &&\n typeof lo === typeof hi &&\n lo > hi\n ) {\n devWarn(\"$between: reversed pair — [min, max] required\");\n\n return false;\n }\n\n return (\n relational(\"$gte\", actual, operand[0]) &&\n relational(\"$lte\", actual, operand[1])\n );\n }\n case \"$matches\": {\n if (!(operand instanceof RegExp)) {\n // String operands are not accepted — a string cannot carry flags\n // (case-insensitivity, dotall, multiline) and would also enable a\n // ReDoS surface for data-loaded predicates. Throw immediately so\n // the bug surfaces at the point of use.\n throw new Error(\n \"[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).\",\n );\n }\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return operand.test(actual);\n }\n case \"$startsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.startsWith(String(operand));\n case \"$endsWith\":\n if (typeof actual !== \"string\") {\n return false;\n }\n\n return actual.endsWith(String(operand));\n case \"$contains\":\n if (typeof actual === \"string\") {\n return actual.includes(String(operand));\n }\n if (Array.isArray(actual)) {\n return actual.some((v) => deepEqual(v, operand));\n }\n // Set membership — uses `.has()` which is reference-equality for\n // objects (matches native Set semantics) and value-equality for\n // primitives. Map `$contains` is deferred to v2; users who need it\n // today can fall back to a function-form predicate.\n if (actual instanceof Set) {\n return actual.has(operand);\n }\n\n return false;\n default:\n return false;\n }\n}\n\n// ============================================================================\n// Evaluation\n// ============================================================================\n\nfunction devWarn(message: string): void {\n if (isDevelopment) {\n console.warn(`[Directive] ${message}`);\n }\n}\n\nfunction evalField(\n value: unknown,\n actual: unknown,\n prev: unknown,\n depth: number,\n): boolean {\n if (isOperatorObject(value)) {\n const keys = Object.keys(value);\n // Type rejects multi-operator objects; the runtime ANDs them on a\n // best-effort basis but dev-warns so the author knows to switch to the\n // array form or `$all`.\n if (keys.length > 1) {\n devWarn(\n `predicate: operator object has ${keys.length} operators (${keys.join(\", \")}) — write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`,\n );\n }\n for (const op of keys) {\n if (!applyOperator(op as PredicateOp, actual, value[op], prev)) {\n return false;\n }\n }\n\n return true;\n }\n\n // A plain (non-operator) object recurses — nested / namespaced predicate.\n if (isPlainObject(value)) {\n return evaluatePredicate(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev) ? prev : undefined,\n depth + 1,\n );\n }\n\n // Bare value → equality.\n return deepEqual(actual, value);\n}\n\n/**\n * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous\n * snapshot) is consulted only by the `$changed` operator.\n *\n * @example\n * ```ts\n * evaluatePredicate({ phase: \"red\", elapsed: { $gte: 30 } }, { phase: \"red\", elapsed: 45 });\n * // → true\n * evaluatePredicate({ $any: [{ phase: \"red\" }, { phase: \"yellow\" }] }, { phase: \"green\" });\n * // → false\n * ```\n */\nexport function evaluatePredicate(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n depth = 0,\n): boolean {\n // `freezeSpec` permits cycles (it uses a WeakSet seen-guard), so a\n // registered spec can be self-referential. Cap recursion to defend the\n // reconcile loop against a stack overflow at evaluation time.\n if (depth > MAX_PREDICATE_DEPTH) {\n devWarn(\n `predicate depth limit (${MAX_PREDICATE_DEPTH}) exceeded — flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`,\n );\n\n return false;\n }\n // Array form — clauses AND-ed.\n if (Array.isArray(spec)) {\n return spec.every((clause) => {\n if (!isPlainObject(clause)) {\n return false;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n\n return applyOperator(op, facts?.[fact], value, prev?.[fact]);\n });\n }\n\n if (!isPlainObject(spec)) {\n return Boolean(spec);\n }\n\n // Combinator node.\n if (\"$all\" in spec) {\n return (spec.$all as unknown[]).every((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$any\" in spec) {\n return (spec.$any as unknown[]).some((p) =>\n evaluatePredicate(p, facts, prev, depth + 1),\n );\n }\n if (\"$not\" in spec) {\n return !evaluatePredicate(spec.$not, facts, prev, depth + 1);\n }\n\n // Object form — every key AND-ed.\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `predicate: operator \"${key}\" mixed with fact keys — wrap operators in a per-fact object`,\n );\n\n return false;\n }\n if (!evalField(spec[key], facts?.[key], prev?.[key], depth)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Evaluate a predicate and return a per-clause breakdown — the data feed for\n * devtools, `system.explain()`, and `directive explain`.\n *\n * @example\n * ```ts\n * evaluatePredicateExplained(\n * { phase: \"red\", elapsed: { $gte: 30 } },\n * { phase: \"red\", elapsed: 20 },\n * );\n * // → [\n * // { path: \"phase\", op: \"$eq\", expected: \"red\", actual: \"red\", pass: true },\n * // { path: \"elapsed\", op: \"$gte\", expected: 30, actual: 20, pass: false },\n * // ]\n * ```\n */\nexport function evaluatePredicateExplained(\n spec: unknown,\n facts: Scope,\n prev?: Scope,\n pathPrefix = \"\",\n): ClauseResult[] {\n const out: ClauseResult[] = [];\n\n if (Array.isArray(spec)) {\n for (const clause of spec) {\n if (!isPlainObject(clause)) {\n continue;\n }\n const { fact, op, value } = clause as {\n fact: string;\n op: PredicateOp;\n value: unknown;\n };\n const actual = facts?.[fact];\n out.push({\n path: pathPrefix + fact,\n op,\n expected: value,\n actual,\n pass: applyOperator(op, actual, value, prev?.[fact]),\n });\n }\n\n return out;\n }\n\n if (!isPlainObject(spec)) {\n return out;\n }\n\n for (const key of [\"$all\", \"$any\", \"$not\"] as const) {\n if (key in spec) {\n const childSpecs =\n key === \"$not\" ? [spec.$not] : (spec[key] as unknown[]);\n const children: ClauseResult[] = [];\n for (const child of childSpecs) {\n children.push(\n ...evaluatePredicateExplained(child, facts, prev, pathPrefix),\n );\n }\n const passCount = children.filter((c) => c.pass).length;\n let pass: boolean;\n if (key === \"$all\") {\n pass = children.length === 0 || passCount === children.length;\n } else if (key === \"$any\") {\n pass = children.length > 0 && passCount > 0;\n } else {\n // $not — single child wrapped above\n pass = !children.every((c) => c.pass);\n }\n out.push({\n path: pathPrefix || key,\n op: key,\n expected: childSpecs.length,\n actual: passCount,\n pass,\n children,\n });\n\n return out;\n }\n }\n\n for (const key of Object.keys(spec)) {\n if (PREDICATE_OPERATORS.has(key)) {\n continue;\n }\n const value = spec[key];\n const actual = facts?.[key];\n const path = pathPrefix + key;\n\n if (isOperatorObject(value)) {\n for (const op of Object.keys(value)) {\n out.push({\n path,\n op: op as PredicateOp,\n expected: value[op],\n actual,\n pass: applyOperator(\n op as PredicateOp,\n actual,\n value[op],\n prev?.[key],\n ),\n });\n }\n } else if (isPlainObject(value)) {\n out.push(\n ...evaluatePredicateExplained(\n value,\n isPlainObject(actual) ? actual : Object.create(null),\n isPlainObject(prev?.[key]) ? (prev?.[key] as Scope) : undefined,\n `${path}.`,\n ),\n );\n } else {\n out.push({\n path,\n op: \"$eq\",\n expected: value,\n actual,\n pass: deepEqual(actual, value),\n });\n }\n }\n\n return out;\n}\n\nconst memoizedCache = new WeakMap<\n object,\n (facts: Scope, prev?: Scope) => boolean\n>();\n\n/**\n * Memoize a predicate as a reusable evaluation closure.\n *\n * The returned function accepts any `facts` scope (the reactive proxy in\n * production, a plain object in tests) plus an optional `prev` snapshot for\n * `$changed`. The closure is cached **by predicate identity** in a\n * `WeakMap`, so passing the same `predicate` reference repeatedly is\n * allocation-free; cleanup is automatic once the predicate is no longer\n * reachable.\n *\n * Note: no actual compilation happens — the returned closure re-walks the\n * spec on every call via `evaluatePredicate`. The name reflects what the\n * function does (closure memoization keyed by predicate identity), not a\n * bytecode/AST compile step.\n *\n * Intended for advanced users who want a stable function reference per\n * predicate (custom devtools, batched analyses). Regular module code does\n * not need to call this — the engine wraps data-form `when` / `on` specs\n * automatically at registration.\n *\n * @example\n * ```ts\n * const predicate = { phase: \"red\", elapsed: { $gte: 30 } };\n * const check = memoizePredicate(predicate);\n * check({ phase: \"red\", elapsed: 45 }); // → true\n * check({ phase: \"red\", elapsed: 5 }); // → false\n * ```\n */\nexport function memoizePredicate(\n predicate: object,\n): (facts: Scope, prev?: Scope) => boolean {\n if (predicate === null || typeof predicate !== \"object\") {\n throw new Error(\n `[Directive] memoizePredicate: predicate must be a plain object or array; got ${typeof predicate}`,\n );\n }\n const cached = memoizedCache.get(predicate);\n if (cached) {\n return cached;\n }\n\n const fn = (facts: Scope, prev?: Scope): boolean =>\n evaluatePredicate(predicate, facts, prev);\n memoizedCache.set(predicate, fn);\n\n return fn;\n}\n\n// ============================================================================\n// Dependency extraction\n// ============================================================================\n\n/**\n * Collect the fact keys a predicate references. Used for static analysis,\n * devtools, and effect `on` dependency wiring. Nested predicates contribute\n * dotted keys (`auth.token`).\n *\n * @example\n * ```ts\n * extractDeps({ phase: \"red\", elapsed: { $gte: 30 } });\n * // → Set { \"phase\", \"elapsed\" }\n * extractDeps({ self: { phase: \"red\" }, auth: { token: { $exists: true } } });\n * // → Set { \"self.phase\", \"auth.token\" }\n * ```\n */\nexport function extractDeps(spec: unknown, prefix = \"\"): Set<string> {\n const deps = new Set<string>();\n\n // Single structural traversal — every operator clause and equality leaf\n // contributes its dotted fact path. Combinators and nested objects are\n // descended automatically; stray `$`-keys never synthesize phantom deps.\n walkPredicate(spec, {\n operator(factPath) {\n deps.add(prefix + factPath);\n },\n literal(factPath) {\n deps.add(prefix + factPath);\n },\n strayOperatorKey(key) {\n // A `$`-key at fact position never synthesizes a phantom dep. A typo'd\n // operator (e.g. `$eqq`) additionally dev-warns; a known operator\n // mixed with fact keys is skipped silently (evaluatePredicate warns).\n if (!PREDICATE_OPERATORS.has(key)) {\n devWarn(\n `extractDeps: unknown operator \"${key}\" — skipping. Known operators: ${[...PREDICATE_OPERATORS].join(\", \")}`,\n );\n }\n },\n });\n\n return deps;\n}\n\n// ============================================================================\n// Templates\n// ============================================================================\n\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** Stringify a value without dev-warns for null/undefined — used when the\n * caller has already emitted a higher-level diagnostic (e.g. \"unknown key\"). */\nfunction stringifyValueQuiet(v: unknown): string {\n if (typeof v === \"symbol\") {\n return \"\";\n }\n if (v === undefined || v === null) {\n return \"\";\n }\n\n return String(v);\n}\n\nfunction stringifyValue(v: unknown, key?: string): string {\n if (typeof v === \"symbol\") {\n devWarn(\"template: cannot interpolate a symbol value — using empty string\");\n\n return \"\";\n }\n if (v === undefined) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}undefined — using empty string`,\n );\n\n return \"\";\n }\n if (v === null) {\n devWarn(\n `template: ${key ? `key \"${key}\" is ` : \"\"}null — using empty string`,\n );\n\n return \"\";\n }\n\n return String(v);\n}\n\n/**\n * Interpolate a {@link FactTemplate} against a scope. Single-pass character\n * scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal\n * `${`; unknown keys dev-warn and yield an empty string.\n *\n * @example\n * ```ts\n * evaluateTemplate({ $template: \"Hi ${name}!\" }, { name: \"Ada\" });\n * // → \"Hi Ada!\"\n * evaluateTemplate({ $template: \"$${price}\" }, {});\n * // → \"${price}\"\n * ```\n */\nexport function evaluateTemplate(spec: FactTemplate, scope: Scope): string {\n const tpl = spec.$template;\n let out = \"\";\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n out += \"${\";\n i += 3;\n continue;\n }\n\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n devWarn(`template: unterminated \"\\${\" in ${JSON.stringify(tpl)}`);\n out += tpl.slice(i);\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (!IDENTIFIER.test(key)) {\n devWarn(\n `template: invalid placeholder \"\\${${key}}\" — not an identifier`,\n );\n } else {\n // `stringifyValue` dev-warns separately for null vs undefined; here\n // we only warn when the key itself is missing from the scope (vs\n // present-but-null), so users see distinct diagnostics. Use\n // Object.hasOwn rather than `in` so prototype-chain keys (e.g.\n // `toString`, `constructor`) are never interpolated.\n const present = scope != null && Object.hasOwn(scope, key);\n const value = present ? scope[key] : undefined;\n if (!present) {\n devWarn(`template: unknown key \"${key}\"`);\n out += stringifyValueQuiet(value);\n } else {\n out += stringifyValue(value, key);\n }\n }\n i = end + 1;\n continue;\n }\n\n out += tpl[i];\n i++;\n }\n\n return out;\n}\n\n/**\n * Collect the placeholder keys referenced by a template. The static-analysis\n * counterpart to {@link extractDeps} — useful for devtools, codegen, and\n * \"which facts does this template read\" inspections. Only valid identifier\n * placeholders are collected; malformed ones are ignored.\n *\n * @example\n * ```ts\n * extractTemplateKeys({ $template: \"${firstName} ${lastName}\" });\n * // → Set { \"firstName\", \"lastName\" }\n * extractTemplateKeys({ $template: \"$${literal}\" });\n * // → Set {} (escaped — not a placeholder)\n * ```\n */\nexport function extractTemplateKeys(spec: FactTemplate): Set<string> {\n const keys = new Set<string>();\n const tpl = spec.$template;\n let i = 0;\n\n while (i < tpl.length) {\n if (tpl[i] === \"$\" && tpl[i + 1] === \"$\" && tpl[i + 2] === \"{\") {\n i += 3;\n continue;\n }\n if (tpl[i] === \"$\" && tpl[i + 1] === \"{\") {\n const end = tpl.indexOf(\"}\", i + 2);\n if (end === -1) {\n break;\n }\n const key = tpl.slice(i + 2, end);\n if (IDENTIFIER.test(key)) {\n keys.add(key);\n }\n i = end + 1;\n continue;\n }\n i++;\n }\n\n return keys;\n}\n\n// ============================================================================\n// Selectors\n// ============================================================================\n\n/**\n * Build a stable dedup key by selecting fields from a requirement payload.\n * Order-as-declared; values are stable-stringified (keys sorted recursively)\n * so two payloads with the same fields in different orders dedupe to the\n * same key.\n *\n * @example\n * ```ts\n * evaluateKeySelector([\"url\", \"method\"], { url: \"/a\", method: \"GET\" });\n * // → '\"/a\"|\"GET\"'\n * evaluateKeySelector([\"id\"], { id: 42 });\n * // → '42'\n * ```\n */\nexport function evaluateKeySelector(\n selector: readonly string[],\n source: Record<string, unknown>,\n): string {\n return selector.map((field) => stableStringify(source?.[field])).join(\"|\");\n}\n\n// ============================================================================\n// Patch\n// ============================================================================\n\n/**\n * Apply a {@link PatchSpec} — assign facts from literals, payload copies\n * (`$ref`), or interpolated strings (`$template`). Mutates through the passed\n * `facts` proxy so change-tracking and downstream invalidation fire.\n *\n * @example\n * ```ts\n * const spec = {\n * $set: {\n * active: true,\n * userId: { $ref: \"id\" },\n * label: { $template: \"user ${name}\" },\n * },\n * };\n * applyPatch(spec, facts, { id: \"u_1\", name: \"Ada\" });\n * // facts.active = true; facts.userId = \"u_1\"; facts.label = \"user Ada\"\n * ```\n */\nexport function applyPatch(\n spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>,\n facts: Record<string, unknown>,\n payload: Record<string, unknown>,\n): void {\n const set = spec.$set;\n const safePayload = payload ?? {};\n for (const key of Object.keys(set)) {\n const value = (set as Record<string, unknown>)[key];\n\n if (isTemplate(value)) {\n facts[key] = evaluateTemplate(value, safePayload);\n } else if (\n isPlainObject(value) &&\n Object.hasOwn(value, \"$ref\") &&\n typeof value.$ref === \"string\"\n ) {\n const refKey = value.$ref;\n // Use Object.hasOwn rather than `in` — tightens defense against\n // prototype-chain lookups so a payload `__proto__` shape can't smuggle\n // an inherited property into the fact assignment. The proxy already\n // blocks writes to dangerous keys, but this keeps the read symmetric.\n if (!Object.hasOwn(safePayload, refKey)) {\n devWarn(\n `applyPatch: $ref \"${refKey}\" is missing from event payload — assigning undefined to fact \"${key}\"`,\n );\n }\n facts[key] = safePayload[refKey];\n } else {\n facts[key] = value;\n }\n }\n}\n"]}
@@ -1,3 +1,3 @@
1
- 'use strict';var b=typeof process<"u"&&process.env?.NODE_ENV!=="production";function m(n,o=new WeakSet){if(n===null||typeof n!="object")return n;let r=n;if(o.has(r)||Object.isFrozen(r))return n;if(o.add(r),Array.isArray(r))for(let s of r)m(s,o);else for(let s of Object.keys(r))m(r[s],o);return Object.freeze(r),n}function A(n){return m(n)}function x(n,o,r){return (...s)=>{try{return r(...s)}catch(u){throw u instanceof Error&&u.message.startsWith("[Directive] ")?new Error(`[Directive] ${n} '${o}': ${u.message.slice(12)}`,{cause:u}):u}}}async function T(n,o,r){let s,u=new Promise((g,d)=>{s=setTimeout(()=>d(new Error(r)),o);});try{return await Promise.race([n,u])}finally{clearTimeout(s);}}function l(n,o=50){let r=new WeakSet;function s(t){if(t===null)return "null";if(t===void 0)return "undefined";let e=typeof t;if(e==="string")return JSON.stringify(t);if(e==="number"||e==="boolean")return String(t);if(e==="function")return '"[function]"';if(e==="symbol")return '"[symbol]"'}function u(t,e){if(r.has(t))return '"[circular]"';r.add(t);let i=e();return r.delete(t),i}function g(t,e){return u(t,()=>`[${t.map(i=>c(i,e+1)).join(",")}]`)}function d(t,e){return u(t,()=>`{${Object.keys(t).sort().map(f=>`${JSON.stringify(f)}:${c(t[f],e+1)}`).join(",")}}`)}function c(t,e){if(e>o)return '"[max depth exceeded]"';if(typeof t=="bigint")return `${t.toString()}n`;let i=s(t);if(i!==void 0)return i;if(t instanceof Date)return `D:${t.toISOString()}`;if(t instanceof RegExp)return `R:${t.source}:${t.flags}`;if(t instanceof Map){let a=[...t.entries()].sort();return `M:${c(a,e+1)}`}if(t instanceof Set){let a=[...t].sort();return `S:${c(a,e+1)}`}return Array.isArray(t)?g(t,e):typeof t=="object"?d(t,e):'"[unknown]"'}return c(n,0)}function D(n,o=50){let r=new Set(["__proto__","constructor","prototype"]),s=new WeakSet;function u(t,e){if(s.has(t))return true;s.add(t);let i=e();return s.delete(t),i}function g(t,e){for(let i of t)if(!c(i,e+1))return false;return true}function d(t,e){for(let i of Object.keys(t))if(r.has(i)||!c(t[i],e+1))return false;return true}function c(t,e){if(e>o)return false;if(t==null||typeof t!="object")return true;let i=t;return Array.isArray(i)?u(i,()=>g(i,e)):u(i,()=>d(i,e))}return c(n,0)}function E(n,o){if(n===o)return true;if(!n||!o)return false;let r=Object.keys(n),s=Object.keys(o);if(r.length!==s.length)return false;for(let u of r)if(n[u]!==o[u])return false;return true}function $(n){let o=l(n),r=5381;for(let s=0;s<o.length;s++)r=(r<<5)+r^o.charCodeAt(s);return (r>>>0).toString(16)}function h(n,o=Date.now()){return n.expiresAt!==void 0&&o>n.expiresAt}function R(n,o=Date.now()){if(!n||typeof n!="object")throw new Error("[Directive] Invalid snapshot: expected an object with 'data' and 'createdAt' properties.");if(!("data"in n))throw new Error("[Directive] Invalid snapshot: missing required 'data' property.");if(!("createdAt"in n)||typeof n.createdAt!="number")throw new Error("[Directive] Invalid snapshot: missing or invalid 'createdAt' property (expected number).");if(h(n,o)){let r=new Date(n.expiresAt).toISOString();throw new Error(`[Directive] Snapshot expired at ${r}. Obtain a fresh snapshot from the source.`)}return n.data}function P(n,o){let r=[];function s(e,i,a,f){r.push({path:e,oldValue:i,newValue:a,type:f});}function u(e,i,a){return e==null?(i!=null&&s(a,e,i,"added"),true):i==null?(s(a,e,i,"removed"),true):false}function g(e,i,a){if(e.length!==i.length){s(a,e,i,"changed");return}for(let f=0;f<e.length;f++)c(e[f],i[f],`${a}[${f}]`);}function d(e,i,a){let f=new Set([...Object.keys(e),...Object.keys(i)]);for(let y of f){let p=a?`${a}.${y}`:y;y in e?y in i?c(e[y],i[y],p):s(p,e[y],void 0,"removed"):s(p,void 0,i[y],"added");}}function c(e,i,a){if(!u(e,i,a)){if(typeof e!="object"||typeof i!="object"){Object.is(e,i)||s(a,e,i,"changed");return}if(Array.isArray(e)&&Array.isArray(i)){g(e,i,a);return}d(e,i,a);}}c(n.data,o.data,"");let t=n.version!==o.version&&(n.version!==void 0||o.version!==void 0);return {identical:r.length===0,changes:r,versionChanged:t,oldVersion:n.version,newVersion:o.version}}function C(n){return "signature"in n&&typeof n.signature=="string"}async function v(n,o){let r=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),s=await k(r,o);return {...n,signature:s,algorithm:"hmac-sha256"}}async function I(n,o){if(!n.signature||n.algorithm!=="hmac-sha256")return false;let r=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),s=await k(r,o);return w(n.signature,s)}async function k(n,o){let r=typeof o=="string"?new TextEncoder().encode(o):o,s={name:"HMAC",hash:{name:"SHA-256"}},u=await crypto.subtle.importKey("raw",r,s,false,["sign"]),g=new TextEncoder().encode(n),d=await crypto.subtle.sign("HMAC",u,g);return Array.from(new Uint8Array(d)).map(c=>c.toString(16).padStart(2,"0")).join("")}function w(n,o){if(n.length!==o.length)return false;let r=0;for(let s=0;s<n.length;s++)r|=n.charCodeAt(s)^o.charCodeAt(s);return r===0}function L(n,o=500){try{let r=JSON.stringify(n,(s,u)=>typeof u=="bigint"?`${u}n`:u,2);return r?r.length<=o?r:`${r.slice(0,o)}
2
- ... (truncated, ${r.length} chars total)`:"[undefined]"}catch{return "[unserializable]"}}exports.a=b;exports.b=A;exports.c=x;exports.d=T;exports.e=l;exports.f=D;exports.g=E;exports.h=$;exports.i=h;exports.j=R;exports.k=P;exports.l=C;exports.m=v;exports.n=I;exports.o=L;//# sourceMappingURL=chunk-4MNQDXH7.cjs.map
3
- //# sourceMappingURL=chunk-4MNQDXH7.cjs.map
1
+ 'use strict';var b=typeof process<"u"&&process.env?.NODE_ENV!=="production";function m(n,o=new WeakSet){if(n===null||typeof n!="object")return n;let r=n;if(o.has(r)||Object.isFrozen(r))return n;if(o.add(r),Array.isArray(r))for(let s of r)m(s,o);else for(let s of Object.keys(r))m(r[s],o);return Object.freeze(r),n}function x(n){return m(n)}function A(n,o,r){return (...s)=>{try{return r(...s)}catch(u){throw u instanceof Error&&u.message.startsWith("[Directive] ")?new Error(`[Directive] ${n} '${o}': ${u.message.slice(12)}`,{cause:u}):u}}}async function T(n,o,r){let s,u=new Promise((g,d)=>{s=setTimeout(()=>d(new Error(r)),o);});try{return await Promise.race([n,u])}finally{clearTimeout(s);}}function l(n,o=50){let r=new WeakSet;function s(t){if(t===null)return "null";if(t===void 0)return "undefined";let e=typeof t;if(e==="string")return JSON.stringify(t);if(e==="number"||e==="boolean")return String(t);if(e==="function")return '"[function]"';if(e==="symbol")return '"[symbol]"'}function u(t,e){if(r.has(t))return '"[circular]"';r.add(t);let i=e();return r.delete(t),i}function g(t,e){return u(t,()=>`[${t.map(i=>c(i,e+1)).join(",")}]`)}function d(t,e){return u(t,()=>`{${Object.keys(t).sort().map(f=>`${JSON.stringify(f)}:${c(t[f],e+1)}`).join(",")}}`)}function c(t,e){if(e>o)return '"[max depth exceeded]"';if(typeof t=="bigint")return `${t.toString()}n`;let i=s(t);if(i!==void 0)return i;if(t instanceof Date)return `D:${t.toISOString()}`;if(t instanceof RegExp)return `R:${t.source}:${t.flags}`;if(t instanceof Map){let a=[...t.entries()].sort();return `M:${c(a,e+1)}`}if(t instanceof Set){let a=[...t].sort();return `S:${c(a,e+1)}`}return Array.isArray(t)?g(t,e):typeof t=="object"?d(t,e):'"[unknown]"'}return c(n,0)}function D(n,o=50){let r=new Set(["__proto__","constructor","prototype"]),s=new WeakSet;function u(t,e){if(s.has(t))return true;s.add(t);let i=e();return s.delete(t),i}function g(t,e){for(let i of t)if(!c(i,e+1))return false;return true}function d(t,e){for(let i of Object.keys(t))if(r.has(i)||!c(t[i],e+1))return false;return true}function c(t,e){if(e>o)return false;if(t==null||typeof t!="object")return true;let i=t;return Array.isArray(i)?u(i,()=>g(i,e)):u(i,()=>d(i,e))}return c(n,0)}function E(n,o){if(n===o)return true;if(!n||!o)return false;let r=Object.keys(n),s=Object.keys(o);if(r.length!==s.length)return false;for(let u of r)if(n[u]!==o[u])return false;return true}function $(n){let o=l(n),r=5381;for(let s=0;s<o.length;s++)r=(r<<5)+r^o.charCodeAt(s);return (r>>>0).toString(16)}function k(n,o=Date.now()){return n.expiresAt!==void 0&&o>n.expiresAt}function R(n,o=Date.now()){if(!n||typeof n!="object")throw new Error("[Directive] Invalid snapshot: expected an object with 'data' and 'createdAt' properties.");if(!("data"in n))throw new Error("[Directive] Invalid snapshot: missing required 'data' property.");if(!("createdAt"in n)||typeof n.createdAt!="number")throw new Error("[Directive] Invalid snapshot: missing or invalid 'createdAt' property (expected number).");if(k(n,o)){let r=new Date(n.expiresAt).toISOString();throw new Error(`[Directive] Snapshot expired at ${r}. Obtain a fresh snapshot from the source.`)}return n.data}function P(n,o){let r=[];function s(e,i,a,f){r.push({path:e,oldValue:i,newValue:a,type:f});}function u(e,i,a){return e==null?(i!=null&&s(a,e,i,"added"),true):i==null?(s(a,e,i,"removed"),true):false}function g(e,i,a){if(e.length!==i.length){s(a,e,i,"changed");return}for(let f=0;f<e.length;f++)c(e[f],i[f],`${a}[${f}]`);}function d(e,i,a){let f=new Set([...Object.keys(e),...Object.keys(i)]);for(let y of f){let p=a?`${a}.${y}`:y;y in e?y in i?c(e[y],i[y],p):s(p,e[y],void 0,"removed"):s(p,void 0,i[y],"added");}}function c(e,i,a){if(!u(e,i,a)){if(typeof e!="object"||typeof i!="object"){Object.is(e,i)||s(a,e,i,"changed");return}if(Array.isArray(e)&&Array.isArray(i)){g(e,i,a);return}d(e,i,a);}}c(n.data,o.data,"");let t=n.version!==o.version&&(n.version!==void 0||o.version!==void 0);return {identical:r.length===0,changes:r,versionChanged:t,oldVersion:n.version,newVersion:o.version}}function C(n){return "signature"in n&&typeof n.signature=="string"}async function v(n,o){let r=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),s=await h(r,o);return {...n,signature:s,algorithm:"hmac-sha256"}}async function I(n,o,r){if(!n.signature||n.algorithm!=="hmac-sha256")return false;let s=l({data:n.data,createdAt:n.createdAt,expiresAt:n.expiresAt,version:n.version,metadata:n.metadata}),u=await h(s,o);return !(!w(n.signature,u)||!r?.ignoreExpiry&&k(n,r?.now))}async function h(n,o){let r=typeof o=="string"?new TextEncoder().encode(o):o,s={name:"HMAC",hash:{name:"SHA-256"}},u=await crypto.subtle.importKey("raw",r,s,false,["sign"]),g=new TextEncoder().encode(n),d=await crypto.subtle.sign("HMAC",u,g);return Array.from(new Uint8Array(d)).map(c=>c.toString(16).padStart(2,"0")).join("")}function w(n,o){if(n.length!==o.length)return false;let r=0;for(let s=0;s<n.length;s++)r|=n.charCodeAt(s)^o.charCodeAt(s);return r===0}function L(n,o=500){try{let r=JSON.stringify(n,(s,u)=>typeof u=="bigint"?`${u}n`:u,2);return r?r.length<=o?r:`${r.slice(0,o)}
2
+ ... (truncated, ${r.length} chars total)`:"[undefined]"}catch{return "[unserializable]"}}exports.a=b;exports.b=x;exports.c=A;exports.d=T;exports.e=l;exports.f=D;exports.g=E;exports.h=$;exports.i=k;exports.j=R;exports.k=P;exports.l=C;exports.m=v;exports.n=I;exports.o=L;//# sourceMappingURL=chunk-GBCWXTXW.cjs.map
3
+ //# sourceMappingURL=chunk-GBCWXTXW.cjs.map