@directive-run/core 1.10.0 → 1.12.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 (56) hide show
  1. package/dist/adapter-utils.d.cts +1 -1
  2. package/dist/adapter-utils.d.ts +1 -1
  3. package/dist/audit-ledger-9IElAHH9.d.ts +205 -0
  4. package/dist/audit-ledger-qMjEBqiP.d.cts +205 -0
  5. package/dist/chunk-26Z5VNPZ.js +16 -0
  6. package/dist/{chunk-FCOZCTLY.js.map → chunk-26Z5VNPZ.js.map} +1 -1
  7. package/dist/chunk-4VZOZWXM.cjs +2 -0
  8. package/dist/chunk-4VZOZWXM.cjs.map +1 -0
  9. package/dist/chunk-7NMXRATK.cjs +3 -0
  10. package/dist/chunk-7NMXRATK.cjs.map +1 -0
  11. package/dist/chunk-7TSYQEN3.js +2 -0
  12. package/dist/chunk-7TSYQEN3.js.map +1 -0
  13. package/dist/{chunk-2OS4RCLV.cjs → chunk-EX3XG667.cjs} +3 -3
  14. package/dist/{chunk-2OS4RCLV.cjs.map → chunk-EX3XG667.cjs.map} +1 -1
  15. package/dist/chunk-TPOKS4RY.js +3 -0
  16. package/dist/chunk-TPOKS4RY.js.map +1 -0
  17. package/dist/{helpers-BwAThjnJ.d.ts → helpers-D2pfb6vT.d.ts} +1 -1
  18. package/dist/{helpers-CG27mEGG.d.cts → helpers-hh6UanB1.d.cts} +1 -1
  19. package/dist/index.cjs +4 -4
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +344 -4
  22. package/dist/index.d.ts +344 -4
  23. package/dist/index.js +4 -4
  24. package/dist/index.js.map +1 -1
  25. package/dist/internals.cjs +1 -1
  26. package/dist/internals.d.cts +4 -4
  27. package/dist/internals.d.ts +4 -4
  28. package/dist/internals.js +1 -1
  29. package/dist/plugins/index.cjs +2 -2
  30. package/dist/plugins/index.cjs.map +1 -1
  31. package/dist/plugins/index.d.cts +2 -1
  32. package/dist/plugins/index.d.ts +2 -1
  33. package/dist/plugins/index.js +2 -2
  34. package/dist/plugins/index.js.map +1 -1
  35. package/dist/{plugins-DvrsPhzx.d.cts → plugins-Ykl_sAPE.d.cts} +1 -1
  36. package/dist/{plugins-DvrsPhzx.d.ts → plugins-Ykl_sAPE.d.ts} +1 -1
  37. package/dist/system-GK3NSFQH.cjs +2 -0
  38. package/dist/{system-DEMPYZHI.cjs.map → system-GK3NSFQH.cjs.map} +1 -1
  39. package/dist/system-VZWB6WXX.js +2 -0
  40. package/dist/{system-R4JL6U4S.js.map → system-VZWB6WXX.js.map} +1 -1
  41. package/dist/testing.cjs +1 -1
  42. package/dist/testing.d.cts +1 -1
  43. package/dist/testing.d.ts +1 -1
  44. package/dist/testing.js +1 -1
  45. package/dist/worker.cjs +1 -1
  46. package/dist/worker.d.cts +1 -1
  47. package/dist/worker.d.ts +1 -1
  48. package/dist/worker.js +1 -1
  49. package/package.json +1 -1
  50. package/dist/chunk-FCOZCTLY.js +0 -16
  51. package/dist/chunk-WIZHZF4G.cjs +0 -3
  52. package/dist/chunk-WIZHZF4G.cjs.map +0 -1
  53. package/dist/chunk-ZE2RY5KP.js +0 -3
  54. package/dist/chunk-ZE2RY5KP.js.map +0 -1
  55. package/dist/system-DEMPYZHI.cjs +0 -2
  56. package/dist/system-R4JL6U4S.js +0 -2
package/dist/index.d.ts CHANGED
@@ -1,8 +1,133 @@
1
- import { P as PatchSpec, C as ClauseResult, F as FactTemplate, a as FactPredicate, S as SchemaType, D as DefinitionMeta, M as ModuleSchema, b as Facts, T as TypedDerivationsDef, c as TypedEventsDef, E as EffectsDef, d as TypedConstraintsDef, e as TypedResolversDef, f as ModuleHooks, g as CrossModuleDeps, h as CrossModuleDerivationsDef, i as CrossModuleEffectsDef, j as CrossModuleConstraintsDef, k as ModuleDef, l as CreateSystemOptionsSingle, m as SingleModuleSystem, n as ModulesMap, o as CreateSystemOptionsNamed, N as NamespacedSystem, p as Plugin, q as TraceOption, r as ErrorBoundaryConfig, R as RequirementWithId, s as Requirement, t as RequirementKeyFn } from './plugins-DvrsPhzx.js';
2
- export { A as AnySystem, B as BatchConfig, u as DirectiveError, v as DistributableSnapshot, w as DistributableSnapshotOptions, x as DynamicConstraintDef, y as DynamicEffectDef, z as DynamicResolverDef, G as FactsSnapshot, H as HistoryAPI, I as HistoryOption, J as HistoryState, K as InferDerivations, L as InferEvents, O as InferFacts, Q as InferRequirementTypes, U as InferRequirements, V as InferSchemaType, W as InferSelectorState, X as KeySelector, Y as MetaAccessor, Z as MetaMatch, _ as ObservationEvent, $ as OperatorObject, a0 as PatchValue, a1 as PayloadRef, a2 as PredicateClause, a3 as PredicateCombinator, a4 as PredicateCombinatorKey, a5 as PredicateObject, a6 as PredicateOp, a7 as RetryPolicy, a8 as Schema, a9 as Snapshot, aa as System, ab as SystemConfig, ac as SystemInspection, ad as SystemMode, ae as SystemSnapshot, af as TraceEntry, ag as isNamespacedSystem, ah as isSingleModuleSystem } from './plugins-DvrsPhzx.js';
3
- export { D as DerivationDefWithMeta, t as typedConstraint, a as typedResolver } from './helpers-BwAThjnJ.js';
1
+ import { P as PredicateOp, a as PatchSpec, C as ClauseResult, F as FactTemplate, b as FactPredicate, S as SchemaType, D as DefinitionMeta, M as ModuleSchema, c as Facts, T as TypedDerivationsDef, d as TypedEventsDef, E as EffectsDef, e as TypedConstraintsDef, f as TypedResolversDef, g as ModuleHooks, h as CrossModuleDeps, i as CrossModuleDerivationsDef, j as CrossModuleEffectsDef, k as CrossModuleConstraintsDef, l as ModuleDef, m as CreateSystemOptionsSingle, n as SingleModuleSystem, o as ModulesMap, p as CreateSystemOptionsNamed, N as NamespacedSystem, q as Plugin, r as TraceOption, s as ErrorBoundaryConfig, R as RequirementWithId, t as Requirement, u as RequirementKeyFn } from './plugins-Ykl_sAPE.js';
2
+ export { A as AnySystem, B as BatchConfig, v as DirectiveError, w as DistributableSnapshot, x as DistributableSnapshotOptions, y as DynamicConstraintDef, z as DynamicEffectDef, G as DynamicResolverDef, H as FactsSnapshot, I as HistoryAPI, J as HistoryOption, K as HistoryState, L as InferDerivations, O as InferEvents, Q as InferFacts, U as InferRequirementTypes, V as InferRequirements, W as InferSchemaType, X as InferSelectorState, Y as KeySelector, Z as MetaAccessor, _ as MetaMatch, $ as ObservationEvent, a0 as OperatorObject, a1 as PatchValue, a2 as PayloadRef, a3 as PredicateClause, a4 as PredicateCombinator, a5 as PredicateCombinatorKey, a6 as PredicateObject, a7 as RetryPolicy, a8 as Schema, a9 as Snapshot, aa as System, ab as SystemConfig, ac as SystemInspection, ad as SystemMode, ae as SystemSnapshot, af as TraceEntry, ag as isNamespacedSystem, ah as isSingleModuleSystem } from './plugins-Ykl_sAPE.js';
3
+ export { D as DerivationDefWithMeta, t as typedConstraint, a as typedResolver } from './helpers-D2pfb6vT.js';
4
+ export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, e as createAuditLedger, m as memorySink } from './audit-ledger-9IElAHH9.js';
4
5
  export { D as DistributableSnapshotLike, S as SignedSnapshot, a as SnapshotDiff, b as SnapshotDiffEntry, d as diffSnapshots, i as isSignedSnapshot, c as isSnapshotExpired, s as shallowEqual, e as signSnapshot, v as validateSnapshot, f as verifySnapshotSignature } from './utils-BnQajqPu.js';
5
6
 
7
+ /**
8
+ * Schema Introspection
9
+ *
10
+ * A runtime discriminant for every `t.*()` builder result, so downstream
11
+ * consumers (`predicateFromIntent`, `doctor`, future `predicateToZod`)
12
+ * can ask "what kind is this fact?" without grepping the source.
13
+ *
14
+ * The discriminant lives at `_kind?: SchemaKindNode` on `ExtendedSchemaType`.
15
+ * Base builders set it; chain mutators (`.nullable()`, `.brand()`, etc.)
16
+ * preserve / decorate it. When `_kind` is absent (legacy or third-party
17
+ * builder), the parser falls back to reading the freeform `_typeName`
18
+ * string. When even that fails: `{ kind: "unknown" }` — graceful close.
19
+ *
20
+ * This module has zero hot-path cost; it is only invoked when an
21
+ * introspecting caller asks for it.
22
+ */
23
+
24
+ /**
25
+ * The closed set of kinds a Directive schema field can be.
26
+ *
27
+ * Drives operator availability via {@link getOperatorsForKind}: e.g.
28
+ * `"number"` gets the orderable operators (`$gte`, `$lte`); `"boolean"`
29
+ * does not.
30
+ */
31
+ type SchemaKind = "number" | "string" | "boolean" | "bigint" | "date" | "array" | "object" | "record" | "tuple" | "enum" | "literal" | "union" | "branded" | "unknown";
32
+ /**
33
+ * A tree-shaped discriminator for a schema field. Composite kinds
34
+ * (array, object, tuple, etc.) carry their element / shape information
35
+ * so an LLM-prompt builder can show "cartTotal is a number" AND
36
+ * "items is an array of { sku: string, qty: number }".
37
+ *
38
+ * `nullable` / `hasDefault` flags appear on the inner node (NOT a
39
+ * wrapping kind) so operator-lookup on `t.number().nullable()` returns
40
+ * the number's operators unchanged — `$gte` works on the non-null arm.
41
+ */
42
+ type SchemaKindNode = ({
43
+ kind: "number" | "string" | "boolean" | "bigint" | "date" | "unknown";
44
+ } | {
45
+ kind: "literal";
46
+ value: string | number | boolean | null;
47
+ primitive: "string" | "number" | "boolean" | "null";
48
+ } | {
49
+ kind: "enum";
50
+ values: readonly (string | number)[];
51
+ primitive: "string" | "number";
52
+ } | {
53
+ kind: "array";
54
+ element: SchemaKindNode;
55
+ } | {
56
+ kind: "tuple";
57
+ elements: readonly SchemaKindNode[];
58
+ } | {
59
+ kind: "object";
60
+ shape: Record<string, SchemaKindNode>;
61
+ } | {
62
+ kind: "record";
63
+ value: SchemaKindNode;
64
+ } | {
65
+ kind: "union";
66
+ members: readonly SchemaKindNode[];
67
+ } | {
68
+ kind: "branded";
69
+ inner: SchemaKindNode;
70
+ }) & {
71
+ /** True if the schema accepts `null` (from `.nullable()` / `.optional()`). */
72
+ nullable?: boolean;
73
+ /** True if the schema has a `.default()`. */
74
+ hasDefault?: boolean;
75
+ };
76
+ /**
77
+ * Return the {@link SchemaKindNode} for a schema field. Prefers the
78
+ * explicit `_kind` discriminant set by the builder; falls back to
79
+ * parsing the freeform `_typeName` string for legacy / third-party
80
+ * builders that don't set `_kind`.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * getKind(t.number()) // → { kind: "number" }
85
+ * getKind(t.string().nullable()) // → { kind: "string", nullable: true }
86
+ * getKind(t.array(t.number())) // → { kind: "array", element: { kind: "number" } }
87
+ * ```
88
+ */
89
+ declare function getKind(schema: unknown): SchemaKindNode;
90
+ /**
91
+ * Walk the `facts` block of a module schema and emit a flat map from
92
+ * dotted path → kind node. Nested `t.object()` shapes flatten using
93
+ * `.` as the separator, matching the convention used by
94
+ * `OperatorObject<V>`'s nested-path support.
95
+ *
96
+ * Passing a top-level schema directly (without the `facts:` wrapper)
97
+ * also works — anything iterable as `Record<string, ExtendedSchemaType>`
98
+ * is acceptable.
99
+ */
100
+ declare function getSchemaFieldKinds(schema: unknown): Map<string, SchemaKindNode>;
101
+ /**
102
+ * Return the set of `PredicateOp` strings that are valid against a
103
+ * given {@link SchemaKindNode}.
104
+ *
105
+ * Mirrors the type-level matrix encoded in `OperatorObject<V>` in
106
+ * `types/predicate.ts` — drift between the two is enforced by the
107
+ * compile-time conformance test
108
+ * (`schema-introspection-conformance.test-d.ts`).
109
+ *
110
+ * - **Common to all kinds:** `$eq`, `$ne`, `$in`, `$nin`, `$exists`
111
+ * - **Orderable (`number`/`string`/`bigint`/`date`):** + `$gt`, `$gte`,
112
+ * `$lt`, `$lte`, `$between`
113
+ * - **String-specific:** + `$matches`, `$startsWith`, `$endsWith`, `$contains`
114
+ * - **Array:** + `$contains` (over the element type)
115
+ * - **Union:** *intersection* across members (the operand must be valid
116
+ * for every branch).
117
+ * - **Branded:** delegates to the inner kind.
118
+ * - **Literal / Enum:** operators of the primitive, with `$eq` / `$in`
119
+ * operand restricted at the LLM-prompt layer (not enforced here).
120
+ *
121
+ * `nullable` does not change operator availability — `$gte` on a
122
+ * nullable number is fine on the non-null arm; `$exists` handles null.
123
+ */
124
+ declare function getOperatorsForKind(node: SchemaKindNode): readonly PredicateOp[];
125
+ /**
126
+ * Return all known predicate operators — convenience for prompt builders
127
+ * that need to show the LLM the full set.
128
+ */
129
+ declare function listAllPredicateOperators(): readonly PredicateOp[];
130
+
6
131
  /**
7
132
  * Runtime for data-configuration predicates and templates.
8
133
  *
@@ -69,6 +194,57 @@ declare function isTemplate(v: unknown): v is FactTemplate;
69
194
  * ```
70
195
  */
71
196
  declare function validatePredicate(spec: unknown, path?: string): void;
197
+
198
+ interface SchemaValidationError {
199
+ /** Dotted path to the failing clause (e.g. `cartTotal`, `auth.token.$gte`). */
200
+ readonly path: string;
201
+ /** The operator that failed (or the literal-equality marker `$eq`). */
202
+ readonly op: string;
203
+ /** The kind of the fact at this path, or `undefined` when the fact wasn't in the kind map. */
204
+ readonly kind?: SchemaKindNode;
205
+ /** The operators that ARE allowed for this fact's kind. */
206
+ readonly allowedOps?: readonly string[];
207
+ /** Human-readable failure reason (suitable for feeding back to an LLM). */
208
+ readonly reason: string;
209
+ }
210
+ interface SchemaValidationOptions {
211
+ /** Reject predicates with more than this many operator clauses (DoS guard). Default unbounded. */
212
+ readonly maxOperatorCount?: number;
213
+ }
214
+ type SchemaValidationResult = {
215
+ ok: true;
216
+ operatorCount: number;
217
+ } | {
218
+ ok: false;
219
+ errors: readonly SchemaValidationError[];
220
+ operatorCount: number;
221
+ };
222
+ /**
223
+ * Cross-check an LLM-emitted (or otherwise externally-sourced) predicate
224
+ * against a schema's runtime kind map. Catches errors that
225
+ * {@link validatePredicate} cannot — operator-on-wrong-kind (`$gte` on a
226
+ * boolean fact), unknown fact paths, and (optionally) operator-count
227
+ * exhaustion DoS attempts.
228
+ *
229
+ * Pair with {@link validatePredicate} (structural / JSON safety) for full
230
+ * coverage. Use {@link getSchemaFieldKinds} to derive `kindMap` from a
231
+ * module schema.
232
+ *
233
+ * Designed for the LLM-emit retry loop: returns a list of errors with
234
+ * structured `{path, op, kind, allowedOps, reason}` rather than throwing,
235
+ * so the caller can feed the errors back to the model.
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * const kindMap = getSchemaFieldKinds({ facts: { cartTotal: t.number(), active: t.boolean() } });
240
+ * const result = validatePredicateAgainstSchema(
241
+ * { cartTotal: { $gte: 50 }, active: { $gte: true } },
242
+ * kindMap,
243
+ * );
244
+ * // → { ok: false, errors: [{ path: "active", op: "$gte", reason: "..." }], operatorCount: 2 }
245
+ * ```
246
+ */
247
+ declare function validatePredicateAgainstSchema(spec: unknown, kindMap: Map<string, SchemaKindNode>, opts?: SchemaValidationOptions): SchemaValidationResult;
72
248
  /**
73
249
  * Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous
74
250
  * snapshot) is consulted only by the `$changed` operator.
@@ -648,6 +824,163 @@ declare function diffRules(options: DiffRulesOptions): RulesDiffReport;
648
824
  */
649
825
  declare function diffClauses(before: unknown, after: unknown): Change[];
650
826
 
827
+ /**
828
+ * predict() — "would this predicate fire against these facts, and if
829
+ * not, what facts must change to make it fire?"
830
+ *
831
+ * Closes the LLM-emit iteration loop: the model writes a rule,
832
+ * `predict()` says "this rule needs cartTotal ≥ 50 to fire; current
833
+ * value is 30," and the model rewrites accordingly. A predicate-aware
834
+ * preview that costs one walk of the predicate tree.
835
+ *
836
+ * Pure, sync, no engine dependency. Reuses `evaluatePredicateExplained`.
837
+ */
838
+
839
+ interface PredictMissingChange {
840
+ /** Dotted path to the fact. */
841
+ readonly path: string;
842
+ /** The operator that failed. */
843
+ readonly op: string;
844
+ /** What the predicate expected. */
845
+ readonly expected: unknown;
846
+ /** What the fact currently is. */
847
+ readonly actual: unknown;
848
+ /** Human-readable hint suitable for feeding back to an LLM or showing to a user. */
849
+ readonly suggestion: string;
850
+ }
851
+ interface PredictResult<F> {
852
+ /** True iff the predicate would fire against `facts`. */
853
+ readonly wouldFire: boolean;
854
+ /** Full clause-by-clause result (reuses the whenExplain payload). */
855
+ readonly whenExplain: readonly ClauseResult[];
856
+ /**
857
+ * List of failing clauses, each with a `suggestion` describing the
858
+ * smallest concrete change to `facts` that would make that clause pass.
859
+ * Empty when `wouldFire === true`.
860
+ */
861
+ readonly missingChanges: readonly PredictMissingChange[];
862
+ /** Reference to the predicate evaluated, for telemetry. */
863
+ readonly predicate: FactPredicate<F>;
864
+ }
865
+ /**
866
+ * Run a predicate against the current fact state and report whether it
867
+ * would fire — *and if not, which facts must change*.
868
+ *
869
+ * Designed for the LLM-iteration loop and for "preview the impact of this
870
+ * rule" UIs.
871
+ *
872
+ * @example
873
+ * ```ts
874
+ * const predicate = { cartTotal: { $gte: 50 }, region: { $in: ["US", "EU"] } };
875
+ * const facts = { cartTotal: 30, region: "US" };
876
+ *
877
+ * predict(predicate, facts);
878
+ * // → {
879
+ * // wouldFire: false,
880
+ * // whenExplain: [ {path: "cartTotal", op: "$gte", pass: false, ...}, ... ],
881
+ * // missingChanges: [
882
+ * // { path: "cartTotal", op: "$gte", expected: 50, actual: 30,
883
+ * // suggestion: "set cartTotal to at least 50 (currently 30)" },
884
+ * // ],
885
+ * // predicate: { cartTotal: { $gte: 50 }, region: { $in: ["US", "EU"] } },
886
+ * // }
887
+ * ```
888
+ */
889
+ declare function predict<F = Record<string, unknown>>(predicate: FactPredicate<F>, facts: F, prev?: F): PredictResult<F>;
890
+
891
+ /**
892
+ * doctor — "this rule contradicts an existing rule" gate (v1 stub).
893
+ *
894
+ * Walks a candidate FactPredicate against an existing system's
895
+ * constraint set (via `system.inspect().constraints`), flagging:
896
+ *
897
+ * - **direct contradiction:** same fact path, opposite-direction
898
+ * comparison (`$gte 50` vs `$lt 50` — they cannot both fire).
899
+ * - **subset:** candidate's range is a strict subset of an existing
900
+ * constraint's range (candidate `$gte 100` when existing already
901
+ * has `$gte 50`; the new rule never fires independently of the old).
902
+ * - **overlap:** shares ≥1 fact path with non-trivial intersection —
903
+ * a warning, not a hard error.
904
+ *
905
+ * Pairs with `predicateFromIntent`: an LLM-emitted predicate can be
906
+ * doctor-checked before assignment, and contradictions fed back into
907
+ * the LLM's retry prompt.
908
+ *
909
+ * This is a **structural** v1. Full SMT-lite (Z3.wasm) is deferred to
910
+ * a dedicated R4.B sprint; the primitive of "doctor says no" is what
911
+ * this slice ships. False negatives are acceptable (no contradiction
912
+ * reported when one exists in semantics that the structural checker
913
+ * can't see). False positives (contradiction reported where none
914
+ * exists) are NOT acceptable — every reported contradiction must be
915
+ * defensible.
916
+ *
917
+ * Pure, sync, no engine dependency.
918
+ */
919
+
920
+ type ContradictionType = "direct" | "subset" | "overlap";
921
+ interface Contradiction {
922
+ /** ID of the existing constraint that conflicts with the candidate. */
923
+ readonly constraintId: string;
924
+ /** Type of contradiction detected. */
925
+ readonly type: ContradictionType;
926
+ /** Human-readable explanation, suitable for showing to a user or LLM. */
927
+ readonly reason: string;
928
+ /** Path on the candidate predicate that triggered the finding. */
929
+ readonly candidatePath?: string;
930
+ /** Operator + value on the candidate side. */
931
+ readonly candidate?: {
932
+ op: string;
933
+ value: unknown;
934
+ };
935
+ /** Operator + value on the existing side. */
936
+ readonly existing?: {
937
+ op: string;
938
+ value: unknown;
939
+ };
940
+ }
941
+ interface CheckAgainstResult {
942
+ /** Hard contradictions — candidate never co-fires with existing rule. */
943
+ readonly contradictions: readonly Contradiction[];
944
+ /** Soft overlaps — shared facts with non-trivial intersection. */
945
+ readonly warnings: readonly Contradiction[];
946
+ }
947
+ /** Shape of `system.inspect().constraints[N]` we care about — accepts any superset. */
948
+ interface ExistingConstraint {
949
+ readonly id: string;
950
+ readonly whenSpec?: unknown;
951
+ }
952
+ declare const doctor: {
953
+ /**
954
+ * Check a candidate predicate against existing constraints. Returns
955
+ * contradictions (hard) + warnings (soft overlaps).
956
+ *
957
+ * @param candidate - The proposed predicate (typically LLM-emitted).
958
+ * @param existing - Either `system.inspect().constraints` directly,
959
+ * or any array of `{ id, whenSpec? }` shapes.
960
+ * Constraints without `whenSpec` (function-form
961
+ * `when:`) are skipped — they're opaque to us.
962
+ *
963
+ * @example
964
+ * ```ts
965
+ * const candidate = { cartTotal: { $gte: 100 } };
966
+ * const report = doctor.checkAgainst(
967
+ * candidate,
968
+ * system.inspect().constraints,
969
+ * );
970
+ * // → {
971
+ * // contradictions: [
972
+ * // { constraintId: "freeShipping", type: "subset",
973
+ * // reason: "Candidate's lower bound on cartTotal..." }
974
+ * // ],
975
+ * // warnings: []
976
+ * // }
977
+ * ```
978
+ */
979
+ checkAgainst<F = Record<string, unknown>>(candidate: FactPredicate<F>, existing: readonly ExistingConstraint[] | {
980
+ constraints: readonly ExistingConstraint[];
981
+ }): CheckAgainstResult;
982
+ };
983
+
651
984
  /**
652
985
  * Compile a `FactPredicate` to a parameterized Postgres-style SQL WHERE
653
986
  * clause. The same predicate that gates a constraint on the client can
@@ -835,6 +1168,13 @@ interface ExtendedSchemaType<T> extends SchemaType<T> {
835
1168
  _lastFailedIndex?: number;
836
1169
  /** Optional metadata for debugging and devtools (never read on hot path). */
837
1170
  readonly _meta?: DefinitionMeta;
1171
+ /**
1172
+ * Structured kind discriminant used by introspection-time consumers
1173
+ * (`predicateFromIntent`, `doctor`, `predicateToZod`). Optional for
1174
+ * back-compat with legacy / third-party builders; when absent, the
1175
+ * introspection layer parses `_typeName` instead.
1176
+ */
1177
+ readonly _kind?: SchemaKindNode;
838
1178
  }
839
1179
  /** Chainable schema type with all common methods */
840
1180
  interface ChainableSchemaType<T> extends ExtendedSchemaType<T> {
@@ -2075,4 +2415,4 @@ declare const Backoff: {
2075
2415
  readonly Exponential: "exponential";
2076
2416
  };
2077
2417
 
2078
- export { Backoff, type Branded, type ChainableSchemaType, type Change, type ChangeKind, ClauseResult, type ConstraintDiff, type ConstraintStatus, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, type DiffRulesOptions, ErrorBoundaryConfig, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, type LeafClause, MAX_REPLAY_FRAMES, MAX_SWEEP_POINTS, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, type PredicateToMongoOptions, type PredicateToPostgrestOptions, type PredicateToSqlOptions, type PredicateToSqlResult, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, type RulesDiffReport, type RulesMapInput, SchemaType, type SignalClock, SingleModuleSystem, type SweepHole, type SweepPoint, type SweepReport, type SweepUnderOptions, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, diffClauses, diffRules, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, flattenPredicate, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isPredicate, isRequirementType, isTemplate, memoizePredicate, pauseTimer, predicateToMongo, predicateToPostgrest, predicateToSQL, predicateToWhere, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, sweepUnder, t, tickTimer, timerOps, toReplayFrames, toRulesMap, validatePredicate, virtualClock };
2418
+ export { Backoff, type Branded, type ChainableSchemaType, type Change, type ChangeKind, type CheckAgainstResult, ClauseResult, type ConstraintDiff, type ConstraintStatus, type Contradiction, type ContradictionType, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, type DiffRulesOptions, ErrorBoundaryConfig, type ExistingConstraint, type ExtendedSchemaType, FactPredicate, FactTemplate, Facts, type LeafClause, MAX_REPLAY_FRAMES, MAX_SWEEP_POINTS, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, PatchSpec, Plugin, type PredicateBacktestReport, PredicateOp, type PredicateToMongoOptions, type PredicateToPostgrestOptions, type PredicateToSqlOptions, type PredicateToSqlResult, type PredictMissingChange, type PredictResult, type ReplayDiffSample, type ReplayFrame, type ReplayUnderOptions, Requirement, RequirementSet, type RequirementTypeStatus, RequirementWithId, type RulesDiffReport, type RulesMapInput, type SchemaKind, type SchemaKindNode, SchemaType, type SchemaValidationError, type SchemaValidationOptions, type SchemaValidationResult, type SignalClock, SingleModuleSystem, type SweepHole, type SweepPoint, type SweepReport, type SweepUnderOptions, type TimerFactOpts, type TimerFactState, TraceOption, applyPatch, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, diffClauses, diffRules, doctor, elapsedMs, evaluateKeySelector, evaluatePredicate, evaluatePredicateExplained, evaluateTemplate, extractDeps, extractTemplateKeys, flattenPredicate, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, getKind, getOperatorsForKind, getSchemaFieldKinds, initialTimerState, isPredicate, isRequirementType, isTemplate, listAllPredicateOperators, memoizePredicate, pauseTimer, predicateToMongo, predicateToPostgrest, predicateToSQL, predicateToWhere, predict, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, sweepUnder, t, tickTimer, timerOps, toReplayFrames, toRulesMap, validatePredicate, validatePredicateAgainstSchema, virtualClock };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import {a as a$1}from'./chunk-FCOZCTLY.js';export{a as createSystem}from'./chunk-FCOZCTLY.js';import {h,i,g,d as d$1,e,a as a$2,b,c}from'./chunk-ZE2RY5KP.js';export{q as DirectiveError,D as RequirementSet,o as applyPatch,n as evaluateKeySelector,h as evaluatePredicate,i as evaluatePredicateExplained,l as evaluateTemplate,k as extractDeps,m as extractTemplateKeys,C as forType,z as generateRequirementId,w as isNamespacedSystem,d as isPredicate,B as isRequirementType,v as isSingleModuleSystem,f as isTemplate,j as memoizePredicate,A as req,t as typedConstraint,u as typedResolver,g as validatePredicate}from'./chunk-ZE2RY5KP.js';import {a,l}from'./chunk-TZHC4E6S.js';import {d}from'./chunk-T6IJUWYR.js';export{j as diffSnapshots,k as isSignedSnapshot,h as isSnapshotExpired,f as shallowEqual,l as signSnapshot,i as validateSnapshot,m as verifySnapshotSignature}from'./chunk-T6IJUWYR.js';var R=1e6;function fe(e$1,t){try{g(e$1);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!d$1(e$1)){let r=e$1===null||typeof e$1!="object"?`${typeof e$1} \u2014 ${JSON.stringify(e$1)}`:JSON.stringify(e$1).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(e(e$1,{operator(r,i){n===void 0&&i.startsWith("$")&&!a$2.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!a$2.has(r)&&!b.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...a$2].join(", ")}`)}function he(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return me(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>R)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,o={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(o.timestamp=i.timestamp),o}return {id:`#${r}`,facts:n??{}}})}function me(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return Q(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return Q(n.snapshots)}function Q(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>R)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return he(e)}function N(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,o=e.maxSamples??20,s=o>0?o:0;if(t.length>R)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);fe(n,"original"),fe(r,"proposed");let c=0,a=0,u=0,l=0,d=0,f=[],g=[],y=i?new Set:void 0,h$1=i?new Set:void 0,v;for(let C of t){let b=C.facts,S=h(n,b,v),k=h(r,b,v);S&&(c++,y?.add(b[i])),k&&(a++,h$1?.add(b[i])),S===k?d++:!S&&k?(u++,f.length<s&&f.push(ge(C,n,r,v))):(l++,g.length<s&&g.push(ge(C,n,r,v))),v=b;}let E={framesEvaluated:t.length,original:{matched:c},proposed:{matched:a},delta:a-c,newMatchCount:u,lostMatchCount:l,unchanged:d,newMatches:f,lostMatches:g};return y&&h$1&&(E.original.matchedEntities=y.size,E.proposed.matchedEntities=h$1.size),E}function ge(e,t,n,r){let i$1=e.facts,o={frameId:e.id,facts:i$1,originalExplain:i(t,i$1,r),proposedExplain:i(n,i$1,r)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var Z=1e4,ye=5e7;function dt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function X(e,t,n=new Set,r=0){if(r>c)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${c}) \u2014 flatten the template or split the sweep`);if(dt(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(o=>X(o,t,n,r+1));let i={};for(let[o,s]of Object.entries(e))i[o]=X(s,t,n,r+1);return i}finally{n.delete(e);}}function*we(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let o of i)for(let s of we(r,t))yield {[n]:o,...s};}function pt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function ft(e){let{frames:t,original:n,template:r,sweep:i,objective:o=b=>b.proposed.matched,entityKey:s,maxSamples:c=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let u=pt(i);if(u>Z)throw new Error(`[Directive] sweepUnder: grid has ${u} points, exceeds the MAX_SWEEP_POINTS limit (${Z}) \u2014 narrow the sweep ranges or split the run`);if(u===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=u*t.length;if(l>ye)throw new Error(`[Directive] sweepUnder: ${u} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${ye}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,f=b=>{let S;try{S=o(b);}catch(k){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${k.message})`)),Number.NEGATIVE_INFINITY}return typeof S!="number"||!Number.isFinite(S)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(S)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):S},g=N({frames:t,original:n,proposed:n,entityKey:s,maxSamples:c}),y={values:{},report:g,score:f(g)},h=[],v=0,E=Number.NEGATIVE_INFINITY;for(let b of we(a,i)){let S=X(r,b),k=N({frames:t,original:n,proposed:S,entityKey:s,maxSamples:c}),U=f(k);U>E&&(E=U,v=h.length),h.push({values:b,report:k,score:U});}let C=h[v];return {points:h,bestIndex:v,best:C,baseline:y}}function Y(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var gt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),ht=new Set(["$all","$any","$not"]);function be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function mt(e){if(!be(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;gt.has(r)&&(n=true);}return n}function M(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,o)=>{M(i,`${t}$all[${o}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,o)=>{M(i,`${t}$any[${o}]`,n);}),n;if("$not"in e)return M(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let o=t?`${t}.${r}`:r;if(mt(i))for(let[s,c]of Object.entries(i))n.push({path:o,op:s,value:c});else be(i)&&!ht.has(r)?M(i,o,n):n.push({path:o,op:"$eq",value:i});}return n}function D(e){return typeof e=="number"&&Number.isFinite(e)}function yt(e,t,n){switch(e){case "$gte":case "$gt":if(D(t)&&D(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(D(t)&&D(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&D(t[0])&&D(t[1])&&D(n[0])&&D(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function wt(e){let t=Y(e.before),n=Y(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),o=[],s={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let c of i){let a=t[c],u=n[c],l=c in t,d=c in n;if(l&&!d){let g=M(a),y=g.length===0?[{path:"(function-form predicate)",kind:"removed"}]:g.map(h=>({path:h.path,kind:"removed",before:{op:h.op,value:h.value}}));J(y),o.push({id:c,status:"removed",changes:y}),s.removed++,s.totalClauseChanges+=y.length;continue}if(!l&&d){let g=M(u),y=g.length===0?[{path:"(function-form predicate)",kind:"added"}]:g.map(h=>({path:h.path,kind:"added",after:{op:h.op,value:h.value}}));J(y),o.push({id:c,status:"added",changes:y}),s.added++,s.totalClauseChanges+=y.length;continue}let f=Te(a,u);f.length===0?(o.push({id:c,status:"unchanged",changes:[]}),s.unchanged++):(o.push({id:c,status:"changed",changes:f}),s.changed++,s.totalClauseChanges+=f.length);}return {constraints:o,summary:s}}function Te(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return d(e)===d(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let n=e===void 0?[]:M(e),r=t===void 0?[]:M(t),i=u=>`${u.path}::${u.op}`,o=new Map(n.map(u=>[i(u),u])),s=new Map(r.map(u=>[i(u),u])),c=new Set([...o.keys(),...s.keys()]),a=[];for(let u of c){let l=o.get(u),d$1=s.get(u);if(l&&!d$1){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d$1){a.push({path:d$1.path,kind:"added",after:{op:d$1.op,value:d$1.value}});continue}if(l&&d$1){if(d(l.value)===d(d$1.value))continue;let f=yt(l.op,l.value,d$1.value);a.push({path:l.path,kind:f??"changed",before:{op:l.op,value:l.value},after:{op:d$1.op,value:d$1.value}});}}return J(a),a}function J(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",o=n.before?.op??n.after?.op??"";return i.localeCompare(o)});}var bt=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function F(e,t){if(typeof e!="string"||!bt.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function $e(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function Tt(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)F(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(F(t,"column"),t)}function w(e,t){return e.params.push(t),e.placeholder(e.params.length)}function G(e,t,n,r){switch(t){case "$eq":return `${e} = ${w(r,n)}`;case "$ne":return `${e} <> ${w(r,n)}`;case "$gt":return `${e} > ${w(r,n)}`;case "$gte":return `${e} >= ${w(r,n)}`;case "$lt":return `${e} < ${w(r,n)}`;case "$lte":return `${e} <= ${w(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${w(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${w(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${w(r,n[0])} AND ${w(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${w(r,V(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${w(r,V(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${w(r,V(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${w(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...a$2].join(", ")}`)}}function V(e){return e.replace(/[\\%_]/g,"\\$&")}function Se(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function $t(e){if(!Se(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function ee(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function O(e,t,n){if(n>c)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${c}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(o=>{if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let s=o;return F(s.fact,"column"),$e(s.fact,t.allowed),G(s.fact,s.op,s.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){ee(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let o=i.map(s=>O(s,t,n+1));return o.length===1?o[0]:`(${o.join(" AND ")})`}if("$any"in e){ee(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let o=i.map(s=>O(s,t,n+1));return o.length===1?o[0]:`(${o.join(" OR ")})`}if("$not"in e){ee(e,"$not");let i=e.$not;return `NOT (${O(i,t,n+1)})`}let r=[];for(let[i,o]of Object.entries(e))if(F(i,"column"),$e(i,t.allowed),$t(o))for(let[s,c]of Object.entries(o)){if(!a$2.has(s))throw new Error(`[Directive] predicateToSQL: unknown operator "${s}" on column "${i}" \u2014 known: ${[...a$2].join(", ")}`);r.push(G(i,s,c,t));}else {if(Se(o))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(G(i,"$eq",o,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var ve=e=>`$${e}`;function St(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??ve,o=t.select??"*";F(n,"table");let s=Tt(o),c={params:[],placeholder:i,allowed:r},a=O(e,c,0);return {sql:`SELECT ${s} FROM ${n} WHERE ${a}`,where:a,params:c.params}}function vt(e,t={}){let n=t.placeholder??ve,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:O(e,r,0),params:r.params}}function te(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function re(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Mt(e){if(!re(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var kt=/^[A-Za-z_][A-Za-z0-9_]*$/,Dt=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function Me(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?Dt:kt).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function ke(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function ne(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function De(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${te(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${te(t)}$`};case "$contains":if(typeof t=="string")return {$regex:te(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...a$2].join(", ")}`)}}function A(e,t,n){if(n>c)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${c}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},o=[];for(let s of e){if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let c=s;Me(c.fact,t),ke(c.fact,t.allowedKeys);let a=De(c.op,c.value);if(c.fact in i&&re(i[c.fact])){let u=i[c.fact];Object.keys(a).some(d=>d in u)?o.push({[c.fact]:a}):i[c.fact]={...u,...a};}else c.fact in i?o.push({[c.fact]:a}):i[c.fact]=a;}if(o.length>0){let s=[];for(let[c,a]of Object.entries(i))s.push({[c]:a});return s.push(...o),{$and:s}}return i}if("$all"in e){ne(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?A(i[0],t,n+1):{$and:i.map(o=>A(o,t,n+1))}}if("$any"in e){ne(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?A(i[0],t,n+1):{$or:i.map(o=>A(o,t,n+1))}}if("$not"in e){ne(e,"$not");let i=e.$not;return {$nor:[A(i,t,n+1)]}}let r={};for(let[i,o]of Object.entries(e))if(Me(i,t),ke(i,t.allowedKeys),Mt(o)){let s={};for(let[c,a]of Object.entries(o)){if(!a$2.has(c))throw new Error(`[Directive] predicateToMongo: unknown operator "${c}" on field "${i}" \u2014 known: ${[...a$2].join(", ")}`);Object.assign(s,De(c,a));}r[i]=s;}else r[i]=o;return r}function Rt(e,t={}){return A(e,t,0)}var Et=/^[A-Za-z_][A-Za-z0-9_]*$/;function Re(e,t){if(typeof e!="string"||!Et.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function ie(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function $(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function Ee(e){return `(${e.map($).join(",")})`}function oe(e){return e.replace(/[\\%_*]/g,"\\$&")}function x(e,t){switch(e){case "$eq":return `eq.${$(t)}`;case "$ne":return `neq.${$(t)}`;case "$gt":return `gt.${$(t)}`;case "$gte":return `gte.${$(t)}`;case "$lt":return `lt.${$(t)}`;case "$lte":return `lte.${$(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${Ee(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${Ee(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${$(oe(t)+"*")}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${$("*"+oe(t))}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${$("*"+oe(t)+"*")}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${$(t.source)}`;if(typeof t=="string")return `match.${$(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...a$2].join(", ")}`)}}function Ae(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function At(e){if(!Ae(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function se(e,t){return `${e}=${t}`}function L(e,t){return `${e}=(${t.join(",")})`}function ae(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?se(e,x("$gte",n[0])):`${e}.${x("$gte",n[0])}`,o=r?se(e,x("$lte",n[1])):`${e}.${x("$lte",n[1])}`;return [i,o]}return [r?se(e,x(t,n)):`${e}.${x(t,n)}`]}function _(e,t,n,r){if(r>c)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${c}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let o=[];for(let s of e){if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let c=s;Re(c.fact,t),o.push(...ae(c.fact,c.op,c.value,n));}return o}if("$all"in e){ie(e,"$all");let o=e.$all;if(!Array.isArray(o))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let c=[];for(let a of o)c.push(..._(a,t,true,r+1));return c}let s=[];for(let c of o)s.push(..._(c,t,false,r+1));return [L("and",s)]}if("$any"in e){ie(e,"$any");let o=e.$any;if(!Array.isArray(o))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(o.length===0)return n?["id=is.null","id=not.is.null"]:[L("and",["id.is.null","id.not.is.null"])];let s=[];for(let c of o)s.push(..._(c,t,false,r+1));return [L("or",s)]}if("$not"in e){ie(e,"$not");let o=e.$not,s=_(o,t,false,r+1);return [L("not.and",s)]}let i=[];for(let[o,s]of Object.entries(e))if(Re(o,t),At(s))for(let[c,a]of Object.entries(s)){if(!a$2.has(c))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${c}" on column "${o}" \u2014 known: ${[...a$2].join(", ")}`);i.push(...ae(o,c,a,n));}else {if(Ae(s))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${o}" \u2014 single-table queries only`);i.push(...ae(o,"$eq",s,n));}return i}function xt(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Ct(e,t={}){let n=t.mode??"querystring",r=_(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(xt).join("&")}function B(e=[],t,n,r,i,o,s){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:o,_meta:s,validate(c){return B([...e,c],t,n,r,i,o,s)}}}function p(e,t,n,r,i,o,s){return {...B(e,t,n,r,i,o,s),default(a){return p(e,t,a,r,i,o,s)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,s)},brand(){return p(e,`Branded<${t}>`,n,r,i,o,s)},describe(a){return p(e,t,n,r,a,o,s)},refine(a,u){let l=[...o??[],{predicate:a,message:u}];return p([...e,a],t,n,r,i,l,s)},nullable(){return p([a=>a===null||e.every(u=>u(a))],`${t} | null`,n,r,i,void 0,s)},optional(){return p([a=>a===void 0||e.every(u=>u(a))],`${t} | undefined`,n,r,i,void 0,s)},meta(a){return p(e,t,n,r,i,o,a)}}}var jt=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),Pt={string(){let e=(t,n,r,i,o,s)=>({...p(t,"string",n,r,i,o,s),minLength(a){return e([...t,u=>u.length>=a],n,r,i,o,s)},maxLength(a){return e([...t,u=>u.length<=a],n,r,i,o,s)},pattern(a){return e([...t,u=>a.test(u)],n,r,i,o,s)},default(a){return e(t,a,r,i,o,s)},describe(a){return e(t,n,r,a,o,s)},refine(a,u){let l=[...o??[],{predicate:a,message:u}];return e([...t,a],n,r,i,l,s)},meta(a){return e(t,n,r,i,o,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,o,s)=>({...p(t,"number",n,r,i,o,s),min(a){return e([...t,u=>u>=a],n,r,i,o,s)},max(a){return e([...t,u=>u<=a],n,r,i,o,s)},default(a){return e(t,a,r,i,o,s)},describe(a){return e(t,n,r,a,o,s)},refine(a,u){let l=[...o??[],{predicate:a,message:u}];return e([...t,a],n,r,i,l,s)},meta(a){return e(t,n,r,i,o,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,o,s)=>{let c=p(t,"array",r,void 0,i,void 0,s),a=o??{value:-1};return {...c,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,f=>{for(let g=0;g<f.length;g++)if(!l._validators.every(y=>y(f[g])))return d.value=g,false;return true}],l,r,i,d,s)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,s)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,s)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,s)},default(l){return e(t,n,l,i,a,s)},describe(l){return e(t,n,r,l,a,s)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(s){return e([...t,c=>{for(let[a,u]of Object.entries(s)){let l=c[a],d=u;if(d&&!d._validators.every(f=>f(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,s=>s!=null],n,r,i)},hasKeys(...s){return e([...t,c=>s.every(a=>a in c)],n,r,i)},default(s){return e(t,s,r,i)},describe(s){return e(t,n,s,i)},meta(s){return e(t,n,r,s)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return B([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return B([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:jt,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(o=>o(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Ot(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function xe(e,t,n,r,i){for(let o of e)t.has(o)||console.warn(`[Directive] ${n} "${o}" not declared in ${r}`);for(let o of t)e.has(o)||console.warn(`[Directive] ${r}["${o}"] ${i}`);}function Ft(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function _t(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let o=i;typeof o.requirement=="string"&&!n.has(o.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${o.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function It(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),o="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let s of o)i.add(s);for(let s of r)if(i.has(s))throw new Error(`[Directive] module '${e}': fact key '${s}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes:
2
- 1. Rename the fact (e.g. ${s}_)
3
- 2. Remove '${s}' from this module's crossModuleDeps if it's not actually needed
4
- 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function qt(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let o=i?.owns;if(o){for(let s of o)if(l.has(s)||s.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': owns key '${s}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function Nt(e,t){Ot(e),t.schema?t.schema.facts||console.warn("[Directive] Module schema.facts is required"):console.warn("[Directive] Module schema is required"),xe(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),xe(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Ft(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&_t(t.resolvers,t.schema.requirements);}function Ce(e,t){It(e,t),qt(e,t),a&&Nt(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function Lt(e){return t=>Ce(t,e)}function ue(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,u){let l=a.get(u);return l||(l=new Set,a.set(u,l)),l}function r(a){let u=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,f=e.errors.get(a)??null;return {pending:u.size,inflight:l.size,failed:d.size,isLoading:u.size>0||l.size>0,hasError:d.size>0,lastError:f}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),u=new Map;for(let l of a)u.set(l,r(l));return u}function o(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function s(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let u=a.requirement.type;n(e.pending,u).add(a.id),e.failed.get(u)?.delete(a.id),t();},onResolverStart(a,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),n(e.inflight,l).add(u.id),t();},onResolverComplete(a,u){let l=u.requirement.type;e.inflight.get(l)?.delete(u.id),e.pending.get(l)?.delete(u.id),t();},onResolverError(a,u,l){let d=u.requirement.type;e.inflight.get(d)?.delete(u.id),n(e.failed,d).add(u.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),e.inflight.get(l)?.delete(u.id),t();},onRequirementMet(a){let u=a.requirement.type;e.pending.get(u)?.delete(a.id),e.inflight.get(u)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:o,reset:s}}function Bt(e){return t=>e.getStatus(t)}function Wt(e){let t=ue(),r=[...e.plugins??[],t.plugin];return {system:a$1({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function je(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function Ut(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,o)=>{let s={id:n++,deadlineMs:t+o,cb:i,canceled:false};return r.push(s),()=>{s.canceled=true;}},advanceBy:i=>{let o=t+i;for(;;){let s=r.filter(a=>!a.canceled&&a.deadlineMs<=o).sort((a,u)=>a.deadlineMs!==u.deadlineMs?a.deadlineMs-u.deadlineMs:a.id-u.id);if(s.length===0)break;let c=s[0];t=Math.max(t,c.deadlineMs),c.canceled=true,c.cb();}t=Math.max(t,o);}}}function Kt(){return je()}function ce(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function W(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function Pe(e,t,n){return Math.max(0,n-W(e,t))}function Oe(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function Fe(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function _e(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function Ie(){return ce()}function qe(e){return {...e,status:"completed"}}function Ne(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function Le(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=W(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function zt(e){return {initial:ce,start:Oe,pause:Fe,resume:_e,reset:Ie,complete:qe,registerRepeat:t=>Ne(t,e.ms),tick:(t,n)=>Le(t,n,e),elapsedMs:W,remainingMs:(t,n)=>Pe(t,n,e.ms)}}var $n={None:"none",Linear:"linear",Exponential:"exponential"};export{$n as Backoff,R as MAX_REPLAY_FRAMES,Z as MAX_SWEEP_POINTS,qe as completeTimer,Ce as createModule,Lt as createModuleFactory,ue as createRequirementStatusPlugin,Bt as createStatusHook,Wt as createSystemWithStatus,Kt as defaultClock,Te as diffClauses,wt as diffRules,W as elapsedMs,M as flattenPredicate,me as framesFromHistory,Q as framesFromSnapshots,ce as initialTimerState,Fe as pauseTimer,Rt as predicateToMongo,Ct as predicateToPostgrest,St as predicateToSQL,vt as predicateToWhere,je as realClock,Ne as registerRepeat,Pe as remainingMs,N as replayUnder,Ie as resetTimer,_e as resumeTimer,Oe as startTimer,ft as sweepUnder,Pt as t,Le as tickTimer,zt as timerOps,he as toReplayFrames,Y as toRulesMap,Ut as virtualClock};//# sourceMappingURL=index.js.map
1
+ export{b as createAuditLedger,a as memorySink}from'./chunk-7TSYQEN3.js';import {a as a$1}from'./chunk-26Z5VNPZ.js';export{a as createSystem}from'./chunk-26Z5VNPZ.js';import {m,n,k,h,i,a as a$2,b,g}from'./chunk-TPOKS4RY.js';export{v as DirectiveError,I as RequirementSet,t as applyPatch,s as evaluateKeySelector,m as evaluatePredicate,n as evaluatePredicateExplained,q as evaluateTemplate,p as extractDeps,r as extractTemplateKeys,H as forType,E as generateRequirementId,c as getKind,e as getOperatorsForKind,d as getSchemaFieldKinds,B as isNamespacedSystem,h as isPredicate,G as isRequirementType,A as isSingleModuleSystem,j as isTemplate,f as listAllPredicateOperators,o as memoizePredicate,F as req,y as typedConstraint,z as typedResolver,k as validatePredicate,l as validatePredicateAgainstSchema}from'./chunk-TPOKS4RY.js';import {a,l}from'./chunk-TZHC4E6S.js';import {d}from'./chunk-T6IJUWYR.js';export{j as diffSnapshots,k as isSignedSnapshot,h as isSnapshotExpired,f as shallowEqual,l as signSnapshot,i as validateSnapshot,m as verifySnapshotSignature}from'./chunk-T6IJUWYR.js';var R=1e6;function ye(e,t){try{k(e);}catch(r){let i=r instanceof Error?r.message:String(r);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${i}`)}if(!h(e)){let r=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${r})`)}let n;if(i(e,{operator(r,i){n===void 0&&i.startsWith("$")&&!a$2.has(i)&&(n=i);},strayOperatorKey(r){n===void 0&&!a$2.has(r)&&!b.has(r)&&(n=r);}}),n!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${n}" \u2014 known operators: ${[...a$2].join(", ")}`)}function we(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return $e(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>R)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);return t.map((n,r)=>{if(n&&typeof n=="object"&&"facts"in n){let i=n,s={id:i.id??`#${r}`,facts:i.facts??{}};return typeof i.timestamp=="number"&&(s.timestamp=i.timestamp),s}return {id:`#${r}`,facts:n??{}}})}function $e(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return X(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let n=t;if(n.version!==void 0&&n.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(n.version)} \u2014 expected 1`);if(!Array.isArray(n.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return X(n.snapshots)}function X(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>R)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let n=e[t];if(!n||typeof n!="object"||!("facts"in n))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return we(e)}function L(e){let{frames:t,original:n,proposed:r,entityKey:i}=e,s=e.maxSamples??20,o=s>0?s:0;if(t.length>R)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${R}) \u2014 split or down-sample the history`);ye(n,"original"),ye(r,"proposed");let c=0,a=0,u=0,l=0,d=0,f=[],g=[],m$1=i?new Set:void 0,h=i?new Set:void 0,k;for(let P of t){let $=P.facts,v=m(n,$,k),M=m(r,$,k);v&&(c++,m$1?.add($[i])),M&&(a++,h?.add($[i])),v===M?d++:!v&&M?(u++,f.length<o&&f.push(me(P,n,r,k))):(l++,g.length<o&&g.push(me(P,n,r,k))),k=$;}let E={framesEvaluated:t.length,original:{matched:c},proposed:{matched:a},delta:a-c,newMatchCount:u,lostMatchCount:l,unchanged:d,newMatches:f,lostMatches:g};return m$1&&h&&(E.original.matchedEntities=m$1.size,E.proposed.matchedEntities=h.size),E}function me(e,t,n$1,r){let i=e.facts,s={frameId:e.id,facts:i,originalExplain:n(t,i,r),proposedExplain:n(n$1,i,r)};return e.timestamp!==void 0&&(s.timestamp=e.timestamp),s}var Y=1e4,be=5e7;function vt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function G(e,t,n=new Set,r=0){if(r>g)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${g}) \u2014 flatten the template or split the sweep`);if(vt(e)){let i=e.$hole;if(!(i in t))throw new Error(`[Directive] sweepUnder: template references hole "${i}" but sweep has no values for it`);return t[i]}if(e===null||typeof e!="object")return e;if(n.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");n.add(e);try{if(Array.isArray(e))return e.map(s=>G(s,t,n,r+1));let i={};for(let[s,o]of Object.entries(e))i[s]=G(o,t,n,r+1);return i}finally{n.delete(e);}}function*Te(e,t){if(e.length===0){yield {};return}let n=e[0],r=e.slice(1),i=t[n]??[];for(let s of i)for(let o of Te(r,t))yield {[n]:s,...o};}function kt(e){let t=1;for(let n of Object.values(e))t*=n.length;return t}function Mt(e){let{frames:t,original:n,template:r,sweep:i,objective:s=$=>$.proposed.matched,entityKey:o,maxSamples:c=0}=e,a=Object.keys(i);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let u=kt(i);if(u>Y)throw new Error(`[Directive] sweepUnder: grid has ${u} points, exceeds the MAX_SWEEP_POINTS limit (${Y}) \u2014 narrow the sweep ranges or split the run`);if(u===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let l=u*t.length;if(l>be)throw new Error(`[Directive] sweepUnder: ${u} points \xD7 ${t.length} frames = ${l} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${be}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,f=$=>{let v;try{v=s($);}catch(M){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${M.message})`)),Number.NEGATIVE_INFINITY}return typeof v!="number"||!Number.isFinite(v)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(v)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):v},g=L({frames:t,original:n,proposed:n,entityKey:o,maxSamples:c}),m={values:{},report:g,score:f(g)},h=[],k=0,E=Number.NEGATIVE_INFINITY;for(let $ of Te(a,i)){let v=G(r,$),M=L({frames:t,original:n,proposed:v,entityKey:o,maxSamples:c}),H=f(M);H>E&&(E=H,k=h.length),h.push({values:$,report:M,score:H});}let P=h[k];return {points:h,bestIndex:k,best:P,baseline:m}}function V(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let n={};for(let r of t){if(!r||typeof r!="object"||!("id"in r))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let i=r;if(typeof i.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");n[i.id]=i.whenSpec;}return n}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var Dt=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Rt=new Set(["$all","$any","$not"]);function Se(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Et(e){if(!Se(e))return false;let t=Object.keys(e);if(t.length===0)return false;let n=false;for(let r of t){if(!r.startsWith("$"))return false;Dt.has(r)&&(n=true);}return n}function T(e,t="",n=[]){if(e===null||typeof e!="object")return n;if(Array.isArray(e)){for(let r of e)if(r&&typeof r=="object"&&"fact"in r&&"op"in r){let i=r;n.push({path:t?`${t}.${String(i.fact)}`:String(i.fact),op:String(i.op),value:i.value});}return n}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((i,s)=>{T(i,`${t}$all[${s}]`,n);}),n;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((i,s)=>{T(i,`${t}$any[${s}]`,n);}),n;if("$not"in e)return T(e.$not,`${t}$not`,n),n;for(let[r,i]of Object.entries(e)){let s=t?`${t}.${r}`:r;if(Et(i))for(let[o,c]of Object.entries(i))n.push({path:s,op:o,value:c});else Se(i)&&!Rt.has(r)?T(i,s,n):n.push({path:s,op:"$eq",value:i});}return n}function D(e){return typeof e=="number"&&Number.isFinite(e)}function xt(e,t,n){switch(e){case "$gte":case "$gt":if(D(t)&&D(n)){if(n<t)return "relaxed";if(n>t)return "tightened"}return null;case "$lte":case "$lt":if(D(t)&&D(n)){if(n>t)return "relaxed";if(n<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(n)&&t.length===2&&n.length===2&&D(t[0])&&D(t[1])&&D(n[0])&&D(n[1])){let r=t[1]-t[0],i=n[1]-n[0];if(i>r)return "relaxed";if(i<r)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(n))if(e==="$in"){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}else {if(n.length>t.length)return "tightened";if(n.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(n)){if(n.length>t.length)return "relaxed";if(n.length<t.length)return "tightened"}return null}default:return null}}function At(e){let t=V(e.before),n=V(e.after),i=[...new Set([...Object.keys(t),...Object.keys(n)])].sort(),s=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let c of i){let a=t[c],u=n[c],l=c in t,d=c in n;if(l&&!d){let g=T(a),m=g.length===0?[{path:"(function-form predicate)",kind:"removed"}]:g.map(h=>({path:h.path,kind:"removed",before:{op:h.op,value:h.value}}));ee(m),s.push({id:c,status:"removed",changes:m}),o.removed++,o.totalClauseChanges+=m.length;continue}if(!l&&d){let g=T(u),m=g.length===0?[{path:"(function-form predicate)",kind:"added"}]:g.map(h=>({path:h.path,kind:"added",after:{op:h.op,value:h.value}}));ee(m),s.push({id:c,status:"added",changes:m}),o.added++,o.totalClauseChanges+=m.length;continue}let f=ve(a,u);f.length===0?(s.push({id:c,status:"unchanged",changes:[]}),o.unchanged++):(s.push({id:c,status:"changed",changes:f}),o.changed++,o.totalClauseChanges+=f.length);}return {constraints:s,summary:o}}function ve(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return d(e)===d(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let n=e===void 0?[]:T(e),r=t===void 0?[]:T(t),i=u=>`${u.path}::${u.op}`,s=new Map(n.map(u=>[i(u),u])),o=new Map(r.map(u=>[i(u),u])),c=new Set([...s.keys(),...o.keys()]),a=[];for(let u of c){let l=s.get(u),d$1=o.get(u);if(l&&!d$1){a.push({path:l.path,kind:"removed",before:{op:l.op,value:l.value}});continue}if(!l&&d$1){a.push({path:d$1.path,kind:"added",after:{op:d$1.op,value:d$1.value}});continue}if(l&&d$1){if(d(l.value)===d(d$1.value))continue;let f=xt(l.op,l.value,d$1.value);a.push({path:l.path,kind:f??"changed",before:{op:l.op,value:l.value},after:{op:d$1.op,value:d$1.value}});}}return ee(a),a}function ee(e){e.sort((t,n)=>{let r=t.path.localeCompare(n.path);if(r!==0)return r;let i=t.before?.op??t.after?.op??"",s=n.before?.op??n.after?.op??"";return i.localeCompare(s)});}function B(e){return e===null?"null":e===void 0?"undefined":e instanceof Date?e.toISOString():typeof e=="string"||typeof e=="object"?JSON.stringify(e):String(e)}function Ct(e){let t=e.path,n=B(e.expected),r=B(e.actual);switch(e.op){case "$eq":return `set ${t} to ${n} (currently ${r})`;case "$ne":return `change ${t} to anything other than ${n} (currently ${r})`;case "$gt":return `set ${t} above ${n} (currently ${r})`;case "$gte":return `set ${t} to at least ${n} (currently ${r})`;case "$lt":return `set ${t} below ${n} (currently ${r})`;case "$lte":return `set ${t} to at most ${n} (currently ${r})`;case "$in":return `set ${t} to one of ${n} (currently ${r})`;case "$nin":return `set ${t} to something other than ${n} (currently ${r})`;case "$exists":return e.expected===true?`set ${t} to a non-null value (currently null/missing)`:`unset ${t} (currently ${r})`;case "$between":return Array.isArray(e.expected)&&e.expected.length===2?`set ${t} between ${B(e.expected[0])} and ${B(e.expected[1])} (currently ${r})`:`set ${t} within range ${n} (currently ${r})`;case "$startsWith":return `set ${t} to start with ${n} (currently ${r})`;case "$endsWith":return `set ${t} to end with ${n} (currently ${r})`;case "$contains":return `set ${t} to contain ${n} (currently ${r})`;case "$matches":return `set ${t} to match the pattern ${n} (currently ${r})`;case "$changed":return `the previous-vs-current change of ${t} is required to differ (currently they match: ${r})`;case "$all":case "$any":case "$not":return `the ${e.op} group at "${t}" did not pass \u2014 see its child clauses`;default:return `clause at ${t} (${e.op}) failed: expected ${n}, got ${r}`}}function ke(e,t){for(let n of e)if(!n.pass){if((n.op==="$all"||n.op==="$any"||n.op==="$not")&&n.children){ke(n.children,t);continue}t.push({path:n.path,op:n.op,expected:n.expected,actual:n.actual,suggestion:Ct(n)});}}function Pt(e,t,n$1){let r=n(e,t,n$1),i=r.every(o=>o.pass),s=[];return i||ke(r,s),{wouldFire:i,whenExplain:r,missingChanges:s,predicate:e}}var Me=new Set(["$eq","$ne","$gt","$gte","$lt","$lte","$in","$nin"]);function W(e,t){if(e===t)return 0;if(typeof e=="number"&&typeof t=="number"||typeof e=="bigint"&&typeof t=="bigint")return e<t?-1:e>t?1:0;if(e instanceof Date&&t instanceof Date){let n=e.getTime(),r=t.getTime();return n<r?-1:n>r?1:0}return typeof e=="string"&&typeof t=="string"?e<t?-1:e>t?1:0:Number.NaN}function F(e,t){if(e===t)return true;if(typeof e!=typeof t||e===null||t===null||typeof e!="object"||Array.isArray(e)!==Array.isArray(t))return false;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return false;for(let i=0;i<e.length;i++)if(!F(e[i],t[i]))return false;return true}let n=Object.keys(e),r=Object.keys(t);if(n.length!==r.length)return false;for(let i of n)if(!F(e[i],t[i]))return false;return true}function jt(e,t){if(!Me.has(e.op)||!Me.has(t.op))return {type:"overlap",reason:`Both rules touch "${e.path}".`};if(e.op==="$eq"&&t.op==="$eq")return F(e.value,t.value)?{type:"subset",reason:`Both rules require ${e.path} = ${JSON.stringify(e.value)} \u2014 candidate is redundant.`}:{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires ${e.path} = ${JSON.stringify(t.value)} \u2014 they cannot both fire.`};if(e.op==="$eq"&&t.op==="$ne")return F(e.value,t.value)?{type:"direct",reason:`Candidate requires ${e.path} = ${JSON.stringify(e.value)} but an existing rule excludes that value.`}:null;if(e.op==="$ne"&&t.op==="$eq")return F(e.value,t.value)?{type:"direct",reason:`Candidate excludes ${e.path} = ${JSON.stringify(e.value)} but an existing rule requires that exact value.`}:null;if(e.op==="$in"&&t.op==="$in"){let o=new Set(Array.isArray(e.value)?e.value:[]),c=new Set(Array.isArray(t.value)?t.value:[]),a=[...o].filter(u=>c.has(u));return a.length===0?{type:"direct",reason:`Candidate $in set for ${e.path} (${JSON.stringify([...o])}) and existing $in set (${JSON.stringify([...c])}) have no values in common \u2014 the candidate can never fire while the existing rule holds.`}:a.length===o.size&&a.length<c.size?{type:"subset",reason:`Candidate $in set for ${e.path} is a strict subset of the existing rule's $in set.`}:null}let n=e.op==="$gt"||e.op==="$gte"?e.value:void 0,r=e.op==="$lt"||e.op==="$lte"?e.value:void 0,i=t.op==="$gt"||t.op==="$gte"?t.value:void 0,s=t.op==="$lt"||t.op==="$lte"?t.value:void 0;if(n!==void 0&&s!==void 0){let o=W(n,s);if(!Number.isNaN(o)&&(o>0||o===0&&(e.op==="$gt"||t.op==="$lt")))return {type:"direct",reason:`Candidate requires ${e.path} ${e.op==="$gt"?">":"\u2265"} ${JSON.stringify(n)} but an existing rule caps it at ${t.op==="$lt"?"<":"\u2264"} ${JSON.stringify(s)}.`}}if(i!==void 0&&r!==void 0){let o=W(i,r);if(!Number.isNaN(o)&&(o>0||o===0&&(t.op==="$gt"||e.op==="$lt")))return {type:"direct",reason:`Candidate caps ${e.path} at ${e.op==="$lt"?"<":"\u2264"} ${JSON.stringify(r)} but an existing rule requires it ${t.op==="$gt"?">":"\u2265"} ${JSON.stringify(i)}.`}}if(n!==void 0&&i!==void 0){let o=W(n,i);if(!Number.isNaN(o)&&o>0)return {type:"subset",reason:`Candidate's lower bound on ${e.path} (${JSON.stringify(n)}) is stricter than the existing rule's lower bound (${JSON.stringify(i)}) \u2014 candidate is a subset.`}}if(r!==void 0&&s!==void 0){let o=W(r,s);if(!Number.isNaN(o)&&o<0)return {type:"subset",reason:`Candidate's upper bound on ${e.path} (${JSON.stringify(r)}) is stricter than the existing rule's upper bound (${JSON.stringify(s)}) \u2014 candidate is a subset.`}}return {type:"overlap",reason:`Both rules constrain "${e.path}".`}}function Ot(e){return typeof e=="object"&&e!==null&&typeof e.id=="string"}var Ft={checkAgainst(e,t){let n=Array.isArray(t)?t:"constraints"in t&&Array.isArray(t.constraints)?t.constraints:[],r=T(e);if(r.length===0)return {contradictions:[],warnings:[]};let i=new Map;for(let c of r){let a=i.get(c.path)??[];a.push(c),i.set(c.path,a);}let s=[],o=[];for(let c of n){if(!Ot(c)||c.whenSpec===void 0)continue;let a=T(c.whenSpec);for(let u of a){let l=i.get(u.path);if(l)for(let d of l){let f=jt(d,u);if(!f)continue;let g={constraintId:c.id,type:f.type,reason:f.reason,candidatePath:d.path,candidate:{op:d.op,value:d.value},existing:{op:u.op,value:u.value}};f.type==="overlap"?o.push(g):s.push(g);}}}return {contradictions:s,warnings:o}}};var _t=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)?$/;function N(e,t){if(typeof e!="string"||!_t.test(e))throw new Error(`[Directive] predicateToSQL: invalid ${t} identifier "${e}" \u2014 must match /^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)?$/`)}function De(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToSQL: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function Nt(e){if(Array.isArray(e)){if(e.length===0)throw new Error("[Directive] predicateToSQL: select must not be empty");for(let n of e)N(n,"column");return e.join(", ")}let t=e;return t==="*"?"*":(N(t,"column"),t)}function w(e,t){return e.params.push(t),e.placeholder(e.params.length)}function te(e,t,n,r){switch(t){case "$eq":return `${e} = ${w(r,n)}`;case "$ne":return `${e} <> ${w(r,n)}`;case "$gt":return `${e} > ${w(r,n)}`;case "$gte":return `${e} >= ${w(r,n)}`;case "$lt":return `${e} < ${w(r,n)}`;case "$lte":return `${e} <= ${w(r,n)}`;case "$in":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $in operand must be an array");return `${e} = ANY(${w(r,n)})`;case "$nin":if(!Array.isArray(n))throw new Error("[Directive] predicateToSQL: $nin operand must be an array");return `NOT (${e} = ANY(${w(r,n)}))`;case "$exists":return n===true?`${e} IS NOT NULL`:`${e} IS NULL`;case "$between":{if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToSQL: $between operand must be a [low, high] tuple");return `${e} BETWEEN ${w(r,n[0])} AND ${w(r,n[1])}`}case "$startsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $startsWith operand must be a string");return `${e} LIKE ${w(r,ne(n))} || '%' ESCAPE '\\'`;case "$endsWith":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $endsWith operand must be a string");return `${e} LIKE '%' || ${w(r,ne(n))} ESCAPE '\\'`;case "$contains":if(typeof n!="string")throw new Error("[Directive] predicateToSQL: $contains only supports string operands \u2014 array containment requires a JOIN, not a predicate");return `${e} LIKE '%' || ${w(r,ne(n))} || '%' ESCAPE '\\'`;case "$matches":{if(!(n instanceof RegExp))throw new Error("[Directive] predicateToSQL: $matches operand must be a RegExp");let i=n.flags.includes("i")?"~*":"~";return `${e} ${i} ${w(r,n.source)}`}case "$changed":throw new Error('[Directive] predicateToSQL: $changed is an effects-only operator \u2014 no server-side translation (a database row has no "prev" snapshot)');default:throw new Error(`[Directive] predicateToSQL: unknown operator "${t}" \u2014 known: ${[...a$2].join(", ")}`)}}function ne(e){return e.replace(/[\\%_]/g,"\\$&")}function Re(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function qt(e){if(!Re(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function re(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToSQL: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function _(e,t,n){if(n>g)throw new Error(`[Directive] predicateToSQL: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToSQL: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return "TRUE";let i=e.map(s=>{if(!s||typeof s!="object"||!("fact"in s)||!("op"in s))throw new Error("[Directive] predicateToSQL: array-form clause must be { fact, op, value }");let o=s;return N(o.fact,"column"),De(o.fact,t.allowed),te(o.fact,o.op,o.value,t)});return i.length===1?i[0]:`(${i.join(" AND ")})`}if("$all"in e){re(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $all must be an array");if(i.length===0)return "TRUE";let s=i.map(o=>_(o,t,n+1));return s.length===1?s[0]:`(${s.join(" AND ")})`}if("$any"in e){re(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToSQL: $any must be an array");if(i.length===0)return "FALSE";let s=i.map(o=>_(o,t,n+1));return s.length===1?s[0]:`(${s.join(" OR ")})`}if("$not"in e){re(e,"$not");let i=e.$not;return `NOT (${_(i,t,n+1)})`}let r=[];for(let[i,s]of Object.entries(e))if(N(i,"column"),De(i,t.allowed),qt(s))for(let[o,c]of Object.entries(s)){if(!a$2.has(o))throw new Error(`[Directive] predicateToSQL: unknown operator "${o}" on column "${i}" \u2014 known: ${[...a$2].join(", ")}`);r.push(te(i,o,c,t));}else {if(Re(s))throw new Error(`[Directive] predicateToSQL: nested predicate at "${i}" \u2014 cross-module / partial-match predicates have no SQL equivalent (single-table queries only in v1; pass a flat predicate or build JOIN by hand with predicateToWhere)`);r.push(te(i,"$eq",s,t));}return r.length===0?"TRUE":r.length===1?r[0]:`(${r.join(" AND ")})`}var Ee=e=>`$${e}`;function It(e,t){let{table:n,allowedKeys:r}=t,i=t.placeholder??Ee,s=t.select??"*";N(n,"table");let o=Nt(s),c={params:[],placeholder:i,allowed:r},a=_(e,c,0);return {sql:`SELECT ${o} FROM ${n} WHERE ${a}`,where:a,params:c.params}}function Lt(e,t={}){let n=t.placeholder??Ee,r={params:[],placeholder:n,allowed:t.allowedKeys};return {where:_(e,r,0),params:r.params}}function ie(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function se(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Bt(e){if(!se(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}var Wt=/^[A-Za-z_][A-Za-z0-9_]*$/,Kt=/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;function xe(e,t){if(typeof e!="string"||e.length===0)throw new Error(`[Directive] predicateToMongo: field name must be a non-empty string, got ${typeof e}`);if(e.startsWith("$"))throw new Error(`[Directive] predicateToMongo: field name "${e}" starts with "$" \u2014 reserved for Mongo operators (a top-level $where would be an injection vector)`);if(!(t.allowDottedPaths?Kt:Wt).test(e))throw new Error(`[Directive] predicateToMongo: invalid field name "${e}"${t.allowDottedPaths?"":' \u2014 pass options.allowDottedPaths=true to permit sub-document paths like "user.role"'}`)}function Ae(e,t){if(t&&!t.includes(e))throw new Error(`[Directive] predicateToMongo: field "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function oe(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToMongo: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function Ce(e,t){switch(e){case "$eq":case "$ne":case "$gt":case "$gte":case "$lt":case "$lte":case "$in":case "$nin":case "$exists":return {[e]:t};case "$between":{if(!Array.isArray(t)||t.length!==2)throw new Error("[Directive] predicateToMongo: $between operand must be a [low, high] tuple");return {$gte:t[0],$lte:t[1]}}case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $startsWith operand must be a string");return {$regex:`^${ie(t)}`};case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToMongo: $endsWith operand must be a string");return {$regex:`${ie(t)}$`};case "$contains":if(typeof t=="string")return {$regex:ie(t)};throw new Error("[Directive] predicateToMongo: $contains in Mongo expects a string operand \u2014 for array element membership use $elemMatch or $in directly");case "$matches":{if(t instanceof RegExp)return t.flags?{$regex:t.source,$options:t.flags}:{$regex:t.source};if(typeof t=="string")return {$regex:t};throw new Error("[Directive] predicateToMongo: $matches operand must be a RegExp or string")}case "$changed":throw new Error("[Directive] predicateToMongo: $changed is an effects-only operator \u2014 no MongoDB query equivalent");default:throw new Error(`[Directive] predicateToMongo: unknown operator "${e}" \u2014 known: ${[...a$2].join(", ")}`)}}function A(e,t,n){if(n>g)throw new Error(`[Directive] predicateToMongo: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error(`[Directive] predicateToMongo: predicate must be an object or array, got ${typeof e}`);if(Array.isArray(e)){if(e.length===0)return {};let i={},s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToMongo: array-form clause must be { fact, op, value }");let c=o;xe(c.fact,t),Ae(c.fact,t.allowedKeys);let a=Ce(c.op,c.value);if(c.fact in i&&se(i[c.fact])){let u=i[c.fact];Object.keys(a).some(d=>d in u)?s.push({[c.fact]:a}):i[c.fact]={...u,...a};}else c.fact in i?s.push({[c.fact]:a}):i[c.fact]=a;}if(s.length>0){let o=[];for(let[c,a]of Object.entries(i))o.push({[c]:a});return o.push(...s),{$and:o}}return i}if("$all"in e){oe(e,"$all");let i=e.$all;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $all must be an array");return i.length===0?{}:i.length===1?A(i[0],t,n+1):{$and:i.map(s=>A(s,t,n+1))}}if("$any"in e){oe(e,"$any");let i=e.$any;if(!Array.isArray(i))throw new Error("[Directive] predicateToMongo: $any must be an array");return i.length===0?{$expr:{$eq:[1,0]}}:i.length===1?A(i[0],t,n+1):{$or:i.map(s=>A(s,t,n+1))}}if("$not"in e){oe(e,"$not");let i=e.$not;return {$nor:[A(i,t,n+1)]}}let r={};for(let[i,s]of Object.entries(e))if(xe(i,t),Ae(i,t.allowedKeys),Bt(s)){let o={};for(let[c,a]of Object.entries(s)){if(!a$2.has(c))throw new Error(`[Directive] predicateToMongo: unknown operator "${c}" on field "${i}" \u2014 known: ${[...a$2].join(", ")}`);Object.assign(o,Ce(c,a));}r[i]=o;}else r[i]=s;return r}function Ut(e,t={}){return A(e,t,0)}var zt=/^[A-Za-z_][A-Za-z0-9_]*$/;function Pe(e,t){if(typeof e!="string"||!zt.test(e))throw new Error(`[Directive] predicateToPostgrest: invalid column identifier "${e}"`);if(t&&!t.includes(e))throw new Error(`[Directive] predicateToPostgrest: column "${e}" is not in the allowedKeys list \u2014 add it to options.allowedKeys or remove it from the predicate`)}function ae(e,t){let n=Object.keys(e).filter(r=>r!==t);if(n.length>0)throw new Error(`[Directive] predicateToPostgrest: ${t} cannot coexist with sibling keys (${n.join(", ")}) \u2014 wrap them in $all together, or move them inside the ${t} children`)}function S(e){if(e==null)return "null";if(typeof e=="boolean")return e?"true":"false";if(typeof e=="number"||typeof e=="bigint")return String(e);if(e instanceof Date)return e.toISOString();if(typeof e=="string")return /[,.():"\\\s]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e;throw new Error(`[Directive] predicateToPostgrest: cannot encode value of type ${typeof e}`)}function je(e){return `(${e.map(S).join(",")})`}function ue(e){return e.replace(/[\\%_*]/g,"\\$&")}function C(e,t){switch(e){case "$eq":return `eq.${S(t)}`;case "$ne":return `neq.${S(t)}`;case "$gt":return `gt.${S(t)}`;case "$gte":return `gte.${S(t)}`;case "$lt":return `lt.${S(t)}`;case "$lte":return `lte.${S(t)}`;case "$in":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $in operand must be an array");return `in.${je(t)}`;case "$nin":if(!Array.isArray(t))throw new Error("[Directive] predicateToPostgrest: $nin operand must be an array");return `not.in.${je(t)}`;case "$exists":return t===true?"not.is.null":"is.null";case "$startsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $startsWith operand must be a string");return `like.${S(ue(t)+"*")}`;case "$endsWith":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $endsWith operand must be a string");return `like.${S("*"+ue(t))}`;case "$contains":if(typeof t!="string")throw new Error("[Directive] predicateToPostgrest: $contains expects a string operand (array containment is the cs operator with a different shape \u2014 out of scope for v1)");return `like.${S("*"+ue(t)+"*")}`;case "$matches":if(t instanceof RegExp)return `${t.flags.includes("i")?"imatch":"match"}.${S(t.source)}`;if(typeof t=="string")return `match.${S(t)}`;throw new Error("[Directive] predicateToPostgrest: $matches operand must be a RegExp or string");case "$changed":throw new Error("[Directive] predicateToPostgrest: $changed is an effects-only operator \u2014 no server query equivalent");default:throw new Error(`[Directive] predicateToPostgrest: unknown operator "${e}" \u2014 known: ${[...a$2].join(", ")}`)}}function Oe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ht(e){if(!Oe(e))return false;let t=Object.keys(e);if(t.length===0)return false;for(let n of t)if(!n.startsWith("$"))return false;return true}function ce(e,t){return `${e}=${t}`}function K(e,t){return `${e}=(${t.join(",")})`}function le(e,t,n,r){if(t==="$between"){if(!Array.isArray(n)||n.length!==2)throw new Error("[Directive] predicateToPostgrest: $between operand must be a [low, high] tuple");let i=r?ce(e,C("$gte",n[0])):`${e}.${C("$gte",n[0])}`,s=r?ce(e,C("$lte",n[1])):`${e}.${C("$lte",n[1])}`;return [i,s]}return [r?ce(e,C(t,n)):`${e}.${C(t,n)}`]}function q(e,t,n,r){if(r>g)throw new Error(`[Directive] predicateToPostgrest: predicate depth limit (${g}) exceeded \u2014 flatten the predicate or check for a cyclic spec object`);if(e===null||typeof e!="object")throw new Error("[Directive] predicateToPostgrest: predicate must be an object or array");if(Array.isArray(e)){let s=[];for(let o of e){if(!o||typeof o!="object"||!("fact"in o)||!("op"in o))throw new Error("[Directive] predicateToPostgrest: array-form clause must be { fact, op, value }");let c=o;Pe(c.fact,t),s.push(...le(c.fact,c.op,c.value,n));}return s}if("$all"in e){ae(e,"$all");let s=e.$all;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $all must be an array");if(n){let c=[];for(let a of s)c.push(...q(a,t,true,r+1));return c}let o=[];for(let c of s)o.push(...q(c,t,false,r+1));return [K("and",o)]}if("$any"in e){ae(e,"$any");let s=e.$any;if(!Array.isArray(s))throw new Error("[Directive] predicateToPostgrest: $any must be an array");if(s.length===0)return n?["id=is.null","id=not.is.null"]:[K("and",["id.is.null","id.not.is.null"])];let o=[];for(let c of s)o.push(...q(c,t,false,r+1));return [K("or",o)]}if("$not"in e){ae(e,"$not");let s=e.$not,o=q(s,t,false,r+1);return [K("not.and",o)]}let i=[];for(let[s,o]of Object.entries(e))if(Pe(s,t),Ht(o))for(let[c,a]of Object.entries(o)){if(!a$2.has(c))throw new Error(`[Directive] predicateToPostgrest: unknown operator "${c}" on column "${s}" \u2014 known: ${[...a$2].join(", ")}`);i.push(...le(s,c,a,n));}else {if(Oe(o))throw new Error(`[Directive] predicateToPostgrest: nested predicate at "${s}" \u2014 single-table queries only`);i.push(...le(s,"$eq",o,n));}return i}function Qt(e){let t=e.indexOf("=");if(t<0)return encodeURIComponent(e);let n=e.slice(0,t),r=e.slice(t+1);return `${n}=${encodeURIComponent(r)}`}function Jt(e,t={}){let n=t.mode??"querystring",r=q(e,t.allowedKeys,true,0);return r.length===0?"":n==="raw"?r.join("&"):r.map(Qt).join("&")}function U(e=[],t,n,r,i,s,o){return {_type:void 0,_validators:e,_typeName:t,_default:n,_transform:r,_description:i,_refinements:s,_meta:o,validate(c){return U([...e,c],t,n,r,i,s,o)}}}function p(e,t,n,r,i,s,o){return {...U(e,t,n,r,i,s,o),default(a){return p(e,t,a,r,i,s,o)},transform(a){return p([],t,void 0,l=>{let d=r?r(l):l;return a(d)},i,void 0,o)},brand(){return p(e,`Branded<${t}>`,n,r,i,s,o)},describe(a){return p(e,t,n,r,a,s,o)},refine(a,u){let l=[...s??[],{predicate:a,message:u}];return p([...e,a],t,n,r,i,l,o)},nullable(){return p([a=>a===null||e.every(u=>u(a))],`${t} | null`,n,r,i,void 0,o)},optional(){return p([a=>a===void 0||e.every(u=>u(a))],`${t} | undefined`,n,r,i,void 0,o)},meta(a){return p(e,t,n,r,i,s,a)}}}var Zt=((...e)=>{if(e.length===0)return p([],"union");let t=e.map(n=>n._typeName??"unknown");return p([n=>e.some(r=>r._validators.every(i=>i(n)))],t.join(" | "))}),Xt={string(){let e=(t,n,r,i,s,o)=>({...p(t,"string",n,r,i,s,o),minLength(a){return e([...t,u=>u.length>=a],n,r,i,s,o)},maxLength(a){return e([...t,u=>u.length<=a],n,r,i,s,o)},pattern(a){return e([...t,u=>a.test(u)],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,u){let l=[...s??[],{predicate:a,message:u}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="string"])},number(){let e=(t,n,r,i,s,o)=>({...p(t,"number",n,r,i,s,o),min(a){return e([...t,u=>u>=a],n,r,i,s,o)},max(a){return e([...t,u=>u<=a],n,r,i,s,o)},default(a){return e(t,a,r,i,s,o)},describe(a){return e(t,n,r,a,s,o)},refine(a,u){let l=[...s??[],{predicate:a,message:u}];return e([...t,a],n,r,i,l,o)},meta(a){return e(t,n,r,i,s,a)}});return e([t=>typeof t=="number"])},boolean(){return p([e=>typeof e=="boolean"],"boolean")},array(){let e=(t,n,r,i,s,o)=>{let c=p(t,"array",r,void 0,i,void 0,o),a=s??{value:-1};return {...c,get _lastFailedIndex(){return a.value},set _lastFailedIndex(l){a.value=l;},of(l){let d={value:-1};return e([...t,f=>{for(let g=0;g<f.length;g++)if(!l._validators.every(m=>m(f[g])))return d.value=g,false;return true}],l,r,i,d,o)},nonEmpty(){return e([...t,l=>l.length>0],n,r,i,a,o)},maxLength(l){return e([...t,d=>d.length<=l],n,r,i,a,o)},minLength(l){return e([...t,d=>d.length>=l],n,r,i,a,o)},default(l){return e(t,n,l,i,a,o)},describe(l){return e(t,n,r,l,a,o)},meta(l){return e(t,n,r,i,a,l)}}};return e([t=>Array.isArray(t)])},object(){let e=(t,n,r,i)=>({...p(t,"object",n,void 0,r,void 0,i),shape(o){return e([...t,c=>{for(let[a,u]of Object.entries(o)){let l=c[a],d=u;if(d&&!d._validators.every(f=>f(l)))return false}return true}],n,r,i)},nonNull(){return e([...t,o=>o!=null],n,r,i)},hasKeys(...o){return e([...t,c=>o.every(a=>a in c)],n,r,i)},default(o){return e(t,o,r,i)},describe(o){return e(t,n,o,i)},meta(o){return e(t,n,r,o)}});return e([t=>typeof t=="object"&&t!==null&&!Array.isArray(t)])},enum(...e){a&&e.length===0&&console.warn("[Directive] t.enum() called with no values - this will reject all strings");let t=new Set(e);return p([n=>typeof n=="string"&&t.has(n)],`enum(${e.join("|")})`)},literal(e){return p([t=>t===e],`literal(${String(e)})`)},nullable(e){let t=e._typeName??"unknown";return U([n=>n===null?true:e._validators.every(r=>r(n))],`${t} | null`)},optional(e){let t=e._typeName??"unknown";return U([n=>n===void 0?true:e._validators.every(r=>r(n))],`${t} | undefined`)},union:Zt,record(e){let t=e._typeName??"unknown";return p([n=>typeof n!="object"||n===null||Array.isArray(n)?false:Object.values(n).every(r=>e._validators.every(i=>i(r)))],`Record<string, ${t}>`)},tuple(...e){a&&e.length===0&&console.warn("[Directive] t.tuple() called with no types - this will only accept empty arrays");let t=e.map(n=>n._typeName??"unknown");return p([n=>!Array.isArray(n)||n.length!==e.length?false:e.every((r,i)=>r._validators.every(s=>s(n[i])))],`[${t.join(", ")}]`)},date(){return p([e=>e instanceof Date&&!Number.isNaN(e.getTime())],"Date")},uuid(){let e=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;return p([t=>typeof t=="string"&&e.test(t)],"uuid")},email(){let e=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;return p([t=>typeof t=="string"&&e.test(t)],"email")},url(){return p([e=>{if(typeof e!="string")return false;try{return new URL(e),!0}catch{return false}}],"url")},bigint(){return p([e=>typeof e=="bigint"],"bigint")},any(){return p([],"any")},unknown(){return p([],"unknown")}};function Yt(e){if(!e||typeof e!="string"){console.warn("[Directive] Module ID must be a non-empty string");return}/^(__[a-z][a-z0-9_-]*|[a-z][a-z0-9-]*)$/i.test(e)||console.warn(`[Directive] Module ID "${e}" should follow kebab-case convention (e.g., "my-module")`);}function Fe(e,t,n,r,i){for(let s of e)t.has(s)||console.warn(`[Directive] ${n} "${s}" not declared in ${r}`);for(let s of t)e.has(s)||console.warn(`[Directive] ${r}["${s}"] ${i}`);}function Gt(e,t){e.length===0&&console.warn("[Directive] history.snapshotEvents is an empty array \u2014 no events will create history snapshots. Omit history.snapshotEvents entirely to snapshot all events, or list specific events.");let n=new Set(Object.keys(t));for(let r of e)n.has(r)||console.warn(`[Directive] history.snapshotEvents entry "${r}" not declared in schema.events. Available events: ${[...n].join(", ")||"(none)"}`);}function Vt(e,t){let n=new Set(Object.keys(t));for(let[r,i]of Object.entries(e)){let s=i;typeof s.requirement=="string"&&!n.has(s.requirement)&&console.warn(`[Directive] Resolver "${r}" references unknown requirement type "${s.requirement}". Available types: ${[...n].join(", ")||"(none)"}`);}}function en(e,t){let n=t.schema?.facts??{},r=Object.keys(n);if(r.length===0)return;let i=new Set(["self","prev","current"]),s="crossModuleDeps"in t&&t.crossModuleDeps?Object.keys(t.crossModuleDeps):[];for(let o of s)i.add(o);for(let o of r)if(i.has(o))throw new Error(`[Directive] module '${e}': fact key '${o}' conflicts with a reserved namespace pivot or evaluation alias (self / prev / current / a crossModuleDep namespace). Three fixes:
2
+ 1. Rename the fact (e.g. ${o}_)
3
+ 2. Remove '${o}' from this module's crossModuleDeps if it's not actually needed
4
+ 3. Move the fact under a wrapping namespace (t.object({ inner: ... }))`)}function tn(e,t){let n=t.constraints;if(n)for(let[r,i]of Object.entries(n)){let s=i?.owns;if(s){for(let o of s)if(l.has(o)||o.startsWith("$"))throw new Error(`[Directive] module '${e}' constraint '${r}': owns key '${o}' is reserved (BLOCKED_PROPS or $-prefixed)`)}}}function nn(e,t){Yt(e),t.schema?t.schema.facts||console.warn("[Directive] Module schema.facts is required"):console.warn("[Directive] Module schema is required"),Fe(new Set(Object.keys(t.derive??{})),new Set(Object.keys(t.schema?.derivations??{})),"Derivation","schema.derivations","has no matching implementation in derive"),Fe(new Set(Object.keys(t.events??{})),new Set(Object.keys(t.schema?.events??{})),"Event","schema.events","has no matching handler in events"),t.history?.snapshotEvents&&Gt(t.history.snapshotEvents,t.schema?.events??{}),t.resolvers&&t.schema?.requirements&&Vt(t.resolvers,t.schema.requirements);}function _e(e,t){en(e,t),tn(e,t),a&&nn(e,t);let n="crossModuleDeps"in t?t.crossModuleDeps:void 0;return {id:e,schema:t.schema,init:t.init,derive:t.derive??{},events:t.events??{},effects:t.effects,constraints:t.constraints,resolvers:t.resolvers,hooks:t.hooks,meta:t.meta,history:t.history,crossModuleDeps:n}}function rn(e){return t=>_e(t,e)}function de(){let e={pending:new Map,inflight:new Map,failed:new Map,errors:new Map,listeners:new Set};function t(){for(let a of e.listeners)a();}function n(a,u){let l=a.get(u);return l||(l=new Set,a.set(u,l)),l}function r(a){let u=e.pending.get(a)??new Set,l=e.inflight.get(a)??new Set,d=e.failed.get(a)??new Set,f=e.errors.get(a)??null;return {pending:u.size,inflight:l.size,failed:d.size,isLoading:u.size>0||l.size>0,hasError:d.size>0,lastError:f}}function i(){let a=new Set([...e.pending.keys(),...e.inflight.keys(),...e.failed.keys()]),u=new Map;for(let l of a)u.set(l,r(l));return u}function s(a){return e.listeners.add(a),()=>e.listeners.delete(a)}function o(){e.pending.clear(),e.inflight.clear(),e.failed.clear(),e.errors.clear(),t();}return {plugin:{name:"requirement-status",onRequirementCreated(a){let u=a.requirement.type;n(e.pending,u).add(a.id),e.failed.get(u)?.delete(a.id),t();},onResolverStart(a,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),n(e.inflight,l).add(u.id),t();},onResolverComplete(a,u){let l=u.requirement.type;e.inflight.get(l)?.delete(u.id),e.pending.get(l)?.delete(u.id),t();},onResolverError(a,u,l){let d=u.requirement.type;e.inflight.get(d)?.delete(u.id),n(e.failed,d).add(u.id),e.errors.set(d,l instanceof Error?l:new Error(String(l))),t();},onResolverCancel(a,u){let l=u.requirement.type;e.pending.get(l)?.delete(u.id),e.inflight.get(l)?.delete(u.id),t();},onRequirementMet(a){let u=a.requirement.type;e.pending.get(u)?.delete(a.id),e.inflight.get(u)?.delete(a.id),t();}},getStatus:r,getAllStatus:i,subscribe:s,reset:o}}function on(e){return t=>e.getStatus(t)}function sn(e){let t=de(),r=[...e.plugins??[],t.plugin];return {system:a$1({module:e.module,plugins:r,trace:e.trace,errorBoundary:e.errorBoundary,tickMs:e.tickMs,zeroConfig:e.zeroConfig,initialFacts:e.initialFacts}),statusPlugin:t}}function Ne(){return {now:()=>Date.now(),setTimeout:(e,t)=>{let n=globalThis.setTimeout(e,t);return ()=>globalThis.clearTimeout(n)}}}function an(e=0){let t=e,n=0,r=[];return {now:()=>t,setTimeout:(i,s)=>{let o={id:n++,deadlineMs:t+s,cb:i,canceled:false};return r.push(o),()=>{o.canceled=true;}},advanceBy:i=>{let s=t+i;for(;;){let o=r.filter(a=>!a.canceled&&a.deadlineMs<=s).sort((a,u)=>a.deadlineMs!==u.deadlineMs?a.deadlineMs-u.deadlineMs:a.id-u.id);if(o.length===0)break;let c=o[0];t=Math.max(t,c.deadlineMs),c.canceled=true,c.cb();}t=Math.max(t,s);}}}function un(){return Ne()}function pe(){return {startedAtMs:null,pausedDurationMs:0,pausedAtMs:null,status:"idle",repeats:0}}function z(e,t){return e.startedAtMs===null?0:e.status==="paused"&&e.pausedAtMs!==null?Math.max(0,e.pausedAtMs-e.startedAtMs-e.pausedDurationMs):Math.max(0,t-e.startedAtMs-e.pausedDurationMs)}function qe(e,t,n){return Math.max(0,n-z(e,t))}function Ie(e,t){return e.status==="running"||e.status==="paused"?e:{...e,startedAtMs:t,pausedDurationMs:0,pausedAtMs:null,status:"running",repeats:0}}function Le(e,t){return e.status!=="running"?e:{...e,pausedAtMs:t,status:"paused"}}function Be(e,t){if(e.status!=="paused"||e.pausedAtMs===null)return e;let n=Math.max(0,t-e.pausedAtMs);return {...e,pausedDurationMs:e.pausedDurationMs+n,pausedAtMs:null,status:"running"}}function We(){return pe()}function Ke(e){return {...e,status:"completed"}}function Ue(e,t){return e.startedAtMs===null||e.status==="paused"?e:{...e,startedAtMs:e.startedAtMs+t,pausedDurationMs:0,pausedAtMs:null,repeats:e.repeats+1}}function ze(e,t,n){if(e.status!=="running")return {kind:"no-op"};let r=z(e,t);return n.mode==="up"?{kind:"no-op"}:n.mode==="repeat"?r>=n.ms?{kind:"repeat"}:{kind:"no-op"}:r>=n.ms?{kind:"complete"}:{kind:"no-op"}}function cn(e){return {initial:pe,start:Ie,pause:Le,resume:Be,reset:We,complete:Ke,registerRepeat:t=>Ue(t,e.ms),tick:(t,n)=>ze(t,n,e),elapsedMs:z,remainingMs:(t,n)=>qe(t,n,e.ms)}}var Wn={None:"none",Linear:"linear",Exponential:"exponential"};export{Wn as Backoff,R as MAX_REPLAY_FRAMES,Y as MAX_SWEEP_POINTS,Ke as completeTimer,_e as createModule,rn as createModuleFactory,de as createRequirementStatusPlugin,on as createStatusHook,sn as createSystemWithStatus,un as defaultClock,ve as diffClauses,At as diffRules,Ft as doctor,z as elapsedMs,T as flattenPredicate,$e as framesFromHistory,X as framesFromSnapshots,pe as initialTimerState,Le as pauseTimer,Ut as predicateToMongo,Jt as predicateToPostgrest,It as predicateToSQL,Lt as predicateToWhere,Pt as predict,Ne as realClock,Ue as registerRepeat,qe as remainingMs,L as replayUnder,We as resetTimer,Be as resumeTimer,Ie as startTimer,Mt as sweepUnder,Xt as t,ze as tickTimer,cn as timerOps,we as toReplayFrames,V as toRulesMap,an as virtualClock};//# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map