@directive-run/core 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-utils.cjs +1 -1
- package/dist/adapter-utils.d.cts +2 -2
- package/dist/adapter-utils.d.ts +2 -2
- package/dist/adapter-utils.js +1 -1
- package/dist/adapter-utils.js.map +1 -1
- package/dist/audit-ledger-Dc6hAXam.d.cts +378 -0
- package/dist/audit-ledger-dxvslGi3.d.ts +378 -0
- package/dist/chunk-2FF6QGOA.js +2 -0
- package/dist/chunk-2FF6QGOA.js.map +1 -0
- package/dist/chunk-4MNQDXH7.cjs +3 -0
- package/dist/chunk-4MNQDXH7.cjs.map +1 -0
- package/dist/chunk-644QZVTT.js +16 -0
- package/dist/{chunk-26Z5VNPZ.js.map → chunk-644QZVTT.js.map} +1 -1
- package/dist/chunk-ENZEHIL7.cjs +3 -0
- package/dist/chunk-ENZEHIL7.cjs.map +1 -0
- package/dist/chunk-I722BZA5.js +7 -0
- package/dist/chunk-I722BZA5.js.map +1 -0
- package/dist/chunk-IXRS4LM4.cjs +2 -0
- package/dist/chunk-IXRS4LM4.cjs.map +1 -0
- package/dist/chunk-NPX5EKPP.cjs +16 -0
- package/dist/{chunk-EX3XG667.cjs.map → chunk-NPX5EKPP.cjs.map} +1 -1
- package/dist/chunk-PA6VC32N.js +2 -0
- package/dist/chunk-PA6VC32N.js.map +1 -0
- package/dist/chunk-PXRV64PA.js +3 -0
- package/dist/chunk-PXRV64PA.js.map +1 -0
- package/dist/chunk-R2GHSCTR.js +3 -0
- package/dist/chunk-R2GHSCTR.js.map +1 -0
- package/dist/chunk-T4TRJEJN.cjs +2 -0
- package/dist/chunk-T4TRJEJN.cjs.map +1 -0
- package/dist/chunk-X7G7UBXU.cjs +7 -0
- package/dist/chunk-X7G7UBXU.cjs.map +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +214 -391
- package/dist/index.d.ts +214 -391
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internals.cjs +1 -1
- package/dist/internals.d.cts +5 -5
- package/dist/internals.d.ts +5 -5
- package/dist/internals.js +1 -1
- package/dist/plugins/index.cjs +2 -2
- package/dist/plugins/index.cjs.map +1 -1
- package/dist/plugins/index.d.cts +2 -2
- package/dist/plugins/index.d.ts +2 -2
- package/dist/plugins/index.js +1 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/{plugins-Ykl_sAPE.d.ts → plugins-BIzXaYbg.d.cts} +15 -1
- package/dist/{plugins-Ykl_sAPE.d.cts → plugins-BIzXaYbg.d.ts} +15 -1
- package/dist/predicate-Bnx3LN7P.d.cts +655 -0
- package/dist/predicate-BxQVf0ug.d.ts +655 -0
- package/dist/system-A6VYKLVF.js +2 -0
- package/dist/{system-VZWB6WXX.js.map → system-A6VYKLVF.js.map} +1 -1
- package/dist/system-CDJMD5O5.cjs +2 -0
- package/dist/{system-GK3NSFQH.cjs.map → system-CDJMD5O5.cjs.map} +1 -1
- package/dist/testing.cjs +1 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/{utils-BnQajqPu.d.cts → utils-Mg55IerF.d.cts} +27 -1
- package/dist/{utils-BnQajqPu.d.ts → utils-Mg55IerF.d.ts} +27 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/package.json +1 -1
- package/dist/audit-ledger-9IElAHH9.d.ts +0 -205
- package/dist/audit-ledger-qMjEBqiP.d.cts +0 -205
- package/dist/chunk-26Z5VNPZ.js +0 -16
- package/dist/chunk-4VZOZWXM.cjs +0 -2
- package/dist/chunk-4VZOZWXM.cjs.map +0 -1
- package/dist/chunk-7NMXRATK.cjs +0 -3
- package/dist/chunk-7NMXRATK.cjs.map +0 -1
- package/dist/chunk-7TSYQEN3.js +0 -2
- package/dist/chunk-7TSYQEN3.js.map +0 -1
- package/dist/chunk-EOLY64E6.cjs +0 -3
- package/dist/chunk-EOLY64E6.cjs.map +0 -1
- package/dist/chunk-EX3XG667.cjs +0 -16
- package/dist/chunk-N4KTCKOI.cjs +0 -7
- package/dist/chunk-N4KTCKOI.cjs.map +0 -1
- package/dist/chunk-T6IJUWYR.js +0 -3
- package/dist/chunk-T6IJUWYR.js.map +0 -1
- package/dist/chunk-TPOKS4RY.js +0 -3
- package/dist/chunk-TPOKS4RY.js.map +0 -1
- package/dist/chunk-TZHC4E6S.js +0 -7
- package/dist/chunk-TZHC4E6S.js.map +0 -1
- package/dist/helpers-D2pfb6vT.d.ts +0 -235
- package/dist/helpers-hh6UanB1.d.cts +0 -235
- package/dist/system-GK3NSFQH.cjs +0 -2
- package/dist/system-VZWB6WXX.js +0 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,386 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as AnySystem, B as BatchConfig,
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
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
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Runtime for data-configuration predicates and templates.
|
|
133
|
-
*
|
|
134
|
-
* Pure module — imports only its own types. Reads facts through whatever
|
|
135
|
-
* object it is handed (the reactive `Facts` proxy in production, a plain
|
|
136
|
-
* snapshot in tests), so it never depends on the engine, store, or tracking.
|
|
137
|
-
*/
|
|
138
|
-
|
|
139
|
-
/** A readable scope — the `Facts` proxy and a plain snapshot both satisfy it. */
|
|
140
|
-
type Scope = Record<string, unknown>;
|
|
141
|
-
/**
|
|
142
|
-
* True when `v` is a data-form spec (predicate object/array) rather than a
|
|
143
|
-
* function. Excludes class instances (Date, RegExp, Map, Set, Promise, etc.)
|
|
144
|
-
* — only plain `{}` literals and arrays of plain clause shapes qualify.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```ts
|
|
148
|
-
* isPredicate({ phase: "red" }); // true
|
|
149
|
-
* isPredicate((f) => f.phase === "red"); // false
|
|
150
|
-
* isPredicate([{ fact: "phase", op: "$eq", value: "red" }]); // true
|
|
151
|
-
* ```
|
|
152
|
-
*/
|
|
153
|
-
declare function isPredicate(v: unknown): boolean;
|
|
154
|
-
/**
|
|
155
|
-
* True when `v` is a {@link FactTemplate} (`{ $template: string }`).
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* isTemplate({ $template: "Hi ${name}" }); // true
|
|
160
|
-
* isTemplate({ $set: { name: "x" } }); // false
|
|
161
|
-
* ```
|
|
162
|
-
*/
|
|
163
|
-
declare function isTemplate(v: unknown): v is FactTemplate;
|
|
164
|
-
/**
|
|
165
|
-
* Throw when a predicate spec contains an operand that cannot survive a
|
|
166
|
-
* JSON round-trip — i.e. that would silently mis-evaluate if the spec was
|
|
167
|
-
* loaded from `JSON.parse`.
|
|
168
|
-
*
|
|
169
|
-
* Three failure classes are detected:
|
|
170
|
-
*
|
|
171
|
-
* - **Lost `RegExp` operand.** A `$matches` operand that is not a
|
|
172
|
-
* `RegExp` instance. `JSON.parse` reconstructs a serialized regex as
|
|
173
|
-
* `{}`, so a `$matches` clause with an empty-object operand is the
|
|
174
|
-
* signature of a regex that did not survive serialization. Reify it
|
|
175
|
-
* with `new RegExp(pattern, flags)` before installing the predicate.
|
|
176
|
-
* - **`bigint` operand.** `JSON.stringify` throws on `bigint`, so a
|
|
177
|
-
* `bigint` operand cannot have been produced by a JSON pipeline and
|
|
178
|
-
* cannot be persisted by one either.
|
|
179
|
-
* - **`Set` / `Map` operand.** Both serialize to `{}` and lose all
|
|
180
|
-
* members; a predicate carrying one is not JSON-safe.
|
|
181
|
-
*
|
|
182
|
-
* This is an opt-in helper — the engine does not call it automatically.
|
|
183
|
-
* Users who load predicates from JSON should call it after `JSON.parse`
|
|
184
|
-
* to fail loud rather than silently mis-evaluate. See the
|
|
185
|
-
* "Serialization" section of RFC-0004.
|
|
186
|
-
*
|
|
187
|
-
* @example
|
|
188
|
-
* ```ts
|
|
189
|
-
* validatePredicate({ phase: { $matches: {} } });
|
|
190
|
-
* // throws — empty object where a RegExp is required
|
|
191
|
-
*
|
|
192
|
-
* validatePredicate({ phase: "red", elapsed: { $gte: 30 } });
|
|
193
|
-
* // ok — JSON-clean operands
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
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;
|
|
248
|
-
/**
|
|
249
|
-
* Evaluate a {@link FactPredicate} against a fact scope. `prev` (a previous
|
|
250
|
-
* snapshot) is consulted only by the `$changed` operator.
|
|
251
|
-
*
|
|
252
|
-
* @example
|
|
253
|
-
* ```ts
|
|
254
|
-
* evaluatePredicate({ phase: "red", elapsed: { $gte: 30 } }, { phase: "red", elapsed: 45 });
|
|
255
|
-
* // → true
|
|
256
|
-
* evaluatePredicate({ $any: [{ phase: "red" }, { phase: "yellow" }] }, { phase: "green" });
|
|
257
|
-
* // → false
|
|
258
|
-
* ```
|
|
259
|
-
*/
|
|
260
|
-
declare function evaluatePredicate(spec: unknown, facts: Scope, prev?: Scope, depth?: number): boolean;
|
|
261
|
-
/**
|
|
262
|
-
* Evaluate a predicate and return a per-clause breakdown — the data feed for
|
|
263
|
-
* devtools, `system.explain()`, and `directive explain`.
|
|
264
|
-
*
|
|
265
|
-
* @example
|
|
266
|
-
* ```ts
|
|
267
|
-
* evaluatePredicateExplained(
|
|
268
|
-
* { phase: "red", elapsed: { $gte: 30 } },
|
|
269
|
-
* { phase: "red", elapsed: 20 },
|
|
270
|
-
* );
|
|
271
|
-
* // → [
|
|
272
|
-
* // { path: "phase", op: "$eq", expected: "red", actual: "red", pass: true },
|
|
273
|
-
* // { path: "elapsed", op: "$gte", expected: 30, actual: 20, pass: false },
|
|
274
|
-
* // ]
|
|
275
|
-
* ```
|
|
276
|
-
*/
|
|
277
|
-
declare function evaluatePredicateExplained(spec: unknown, facts: Scope, prev?: Scope, pathPrefix?: string): ClauseResult[];
|
|
278
|
-
/**
|
|
279
|
-
* Memoize a predicate as a reusable evaluation closure.
|
|
280
|
-
*
|
|
281
|
-
* The returned function accepts any `facts` scope (the reactive proxy in
|
|
282
|
-
* production, a plain object in tests) plus an optional `prev` snapshot for
|
|
283
|
-
* `$changed`. The closure is cached **by predicate identity** in a
|
|
284
|
-
* `WeakMap`, so passing the same `predicate` reference repeatedly is
|
|
285
|
-
* allocation-free; cleanup is automatic once the predicate is no longer
|
|
286
|
-
* reachable.
|
|
287
|
-
*
|
|
288
|
-
* Note: no actual compilation happens — the returned closure re-walks the
|
|
289
|
-
* spec on every call via `evaluatePredicate`. The name reflects what the
|
|
290
|
-
* function does (closure memoization keyed by predicate identity), not a
|
|
291
|
-
* bytecode/AST compile step.
|
|
292
|
-
*
|
|
293
|
-
* Intended for advanced users who want a stable function reference per
|
|
294
|
-
* predicate (custom devtools, batched analyses). Regular module code does
|
|
295
|
-
* not need to call this — the engine wraps data-form `when` / `on` specs
|
|
296
|
-
* automatically at registration.
|
|
297
|
-
*
|
|
298
|
-
* @example
|
|
299
|
-
* ```ts
|
|
300
|
-
* const predicate = { phase: "red", elapsed: { $gte: 30 } };
|
|
301
|
-
* const check = memoizePredicate(predicate);
|
|
302
|
-
* check({ phase: "red", elapsed: 45 }); // → true
|
|
303
|
-
* check({ phase: "red", elapsed: 5 }); // → false
|
|
304
|
-
* ```
|
|
305
|
-
*/
|
|
306
|
-
declare function memoizePredicate(predicate: object): (facts: Scope, prev?: Scope) => boolean;
|
|
307
|
-
/**
|
|
308
|
-
* Collect the fact keys a predicate references. Used for static analysis,
|
|
309
|
-
* devtools, and effect `on` dependency wiring. Nested predicates contribute
|
|
310
|
-
* dotted keys (`auth.token`).
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```ts
|
|
314
|
-
* extractDeps({ phase: "red", elapsed: { $gte: 30 } });
|
|
315
|
-
* // → Set { "phase", "elapsed" }
|
|
316
|
-
* extractDeps({ self: { phase: "red" }, auth: { token: { $exists: true } } });
|
|
317
|
-
* // → Set { "self.phase", "auth.token" }
|
|
318
|
-
* ```
|
|
319
|
-
*/
|
|
320
|
-
declare function extractDeps(spec: unknown, prefix?: string): Set<string>;
|
|
321
|
-
/**
|
|
322
|
-
* Interpolate a {@link FactTemplate} against a scope. Single-pass character
|
|
323
|
-
* scanner: `${ident}` interpolates `scope[ident]`; `$${` emits a literal
|
|
324
|
-
* `${`; unknown keys dev-warn and yield an empty string.
|
|
325
|
-
*
|
|
326
|
-
* @example
|
|
327
|
-
* ```ts
|
|
328
|
-
* evaluateTemplate({ $template: "Hi ${name}!" }, { name: "Ada" });
|
|
329
|
-
* // → "Hi Ada!"
|
|
330
|
-
* evaluateTemplate({ $template: "$${price}" }, {});
|
|
331
|
-
* // → "${price}"
|
|
332
|
-
* ```
|
|
333
|
-
*/
|
|
334
|
-
declare function evaluateTemplate(spec: FactTemplate, scope: Scope): string;
|
|
335
|
-
/**
|
|
336
|
-
* Collect the placeholder keys referenced by a template. The static-analysis
|
|
337
|
-
* counterpart to {@link extractDeps} — useful for devtools, codegen, and
|
|
338
|
-
* "which facts does this template read" inspections. Only valid identifier
|
|
339
|
-
* placeholders are collected; malformed ones are ignored.
|
|
340
|
-
*
|
|
341
|
-
* @example
|
|
342
|
-
* ```ts
|
|
343
|
-
* extractTemplateKeys({ $template: "${firstName} ${lastName}" });
|
|
344
|
-
* // → Set { "firstName", "lastName" }
|
|
345
|
-
* extractTemplateKeys({ $template: "$${literal}" });
|
|
346
|
-
* // → Set {} (escaped — not a placeholder)
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
declare function extractTemplateKeys(spec: FactTemplate): Set<string>;
|
|
350
|
-
/**
|
|
351
|
-
* Build a stable dedup key by selecting fields from a requirement payload.
|
|
352
|
-
* Order-as-declared; values are stable-stringified (keys sorted recursively)
|
|
353
|
-
* so two payloads with the same fields in different orders dedupe to the
|
|
354
|
-
* same key.
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```ts
|
|
358
|
-
* evaluateKeySelector(["url", "method"], { url: "/a", method: "GET" });
|
|
359
|
-
* // → '"/a"|"GET"'
|
|
360
|
-
* evaluateKeySelector(["id"], { id: 42 });
|
|
361
|
-
* // → '42'
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
declare function evaluateKeySelector(selector: readonly string[], source: Record<string, unknown>): string;
|
|
365
|
-
/**
|
|
366
|
-
* Apply a {@link PatchSpec} — assign facts from literals, payload copies
|
|
367
|
-
* (`$ref`), or interpolated strings (`$template`). Mutates through the passed
|
|
368
|
-
* `facts` proxy so change-tracking and downstream invalidation fire.
|
|
369
|
-
*
|
|
370
|
-
* @example
|
|
371
|
-
* ```ts
|
|
372
|
-
* const spec = {
|
|
373
|
-
* $set: {
|
|
374
|
-
* active: true,
|
|
375
|
-
* userId: { $ref: "id" },
|
|
376
|
-
* label: { $template: "user ${name}" },
|
|
377
|
-
* },
|
|
378
|
-
* };
|
|
379
|
-
* applyPatch(spec, facts, { id: "u_1", name: "Ada" });
|
|
380
|
-
* // facts.active = true; facts.userId = "u_1"; facts.label = "user Ada"
|
|
381
|
-
* ```
|
|
382
|
-
*/
|
|
383
|
-
declare function applyPatch(spec: PatchSpec<Record<string, unknown>, Record<string, unknown>>, facts: Record<string, unknown>, payload: Record<string, unknown>): void;
|
|
1
|
+
import { C as ClauseResult, F as FactPredicate, S as SchemaType, D as DefinitionMeta, M as ModuleSchema, a as Facts, T as TypedDerivationsDef, b as TypedEventsDef, E as EffectsDef, c as TypedConstraintsDef, d as TypedResolversDef, e as ModuleHooks, f as CrossModuleDeps, g as CrossModuleDerivationsDef, h as CrossModuleEffectsDef, i as CrossModuleConstraintsDef, j as ModuleDef, k as CreateSystemOptionsSingle, l as SingleModuleSystem, m as ModulesMap, n as CreateSystemOptionsNamed, N as NamespacedSystem, P as Plugin, o as TraceOption, p as ErrorBoundaryConfig, R as RequirementWithId, q as Requirement, r as RequirementKeyFn } from './plugins-BIzXaYbg.cjs';
|
|
2
|
+
export { A as AnySystem, B as BatchConfig, s as DirectiveError, t as DistributableSnapshot, u as DistributableSnapshotOptions, v as DynamicConstraintDef, w as DynamicEffectDef, x as DynamicResolverDef, y as FactTemplate, z as FactsSnapshot, H as HistoryAPI, G as HistoryOption, I as HistoryState, J as InferDerivations, K as InferEvents, L as InferFacts, O as InferRequirementTypes, Q as InferRequirements, U as InferSchemaType, V as InferSelectorState, W as KeySelector, X as MetaAccessor, Y as MetaMatch, Z as ObservationEvent, _ as OperatorObject, $ as PatchSpec, 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-BIzXaYbg.cjs';
|
|
3
|
+
import { S as SchemaKindNode } from './predicate-Bnx3LN7P.cjs';
|
|
4
|
+
export { D as DerivationDefWithMeta, a as SchemaKind, b as SchemaValidationError, c as SchemaValidationOptions, d as SchemaValidationResult, e as applyPatch, f as evaluateKeySelector, g as evaluatePredicate, h as evaluatePredicateExplained, i as evaluateTemplate, j as extractDeps, k as extractTemplateKeys, l as getKind, m as getOperatorsForKind, n as getSchemaFieldKinds, o as isPredicate, p as isTemplate, q as listAllPredicateOperators, r as memoizePredicate, t as typedConstraint, s as typedResolver, v as validatePredicate, u as validatePredicateAgainstSchema } from './predicate-Bnx3LN7P.cjs';
|
|
5
|
+
export { A as AuditEntry, a as AuditEntryKind, b as AuditLedger, c as AuditLedgerOptions, d as AuditLedgerSink, Q as QueryFilter, V as VerifyResult, e as createAuditLedger, m as memorySink } from './audit-ledger-Dc6hAXam.cjs';
|
|
6
|
+
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-Mg55IerF.cjs';
|
|
384
7
|
|
|
385
8
|
/**
|
|
386
9
|
* Predicate backtest — rule-change impact.
|
|
@@ -824,6 +447,40 @@ declare function diffRules(options: DiffRulesOptions): RulesDiffReport;
|
|
|
824
447
|
*/
|
|
825
448
|
declare function diffClauses(before: unknown, after: unknown): Change[];
|
|
826
449
|
|
|
450
|
+
/**
|
|
451
|
+
* `predicateHash` — content-addressed fingerprint for a {@link FactPredicate}.
|
|
452
|
+
*
|
|
453
|
+
* Canonicalized via `stableStringify` so semantically-identical predicates
|
|
454
|
+
* (different key order, different whitespace) produce the same hash.
|
|
455
|
+
* Uses djb2 32-bit (8-character hex). SHA-256 reserved for v2.
|
|
456
|
+
*
|
|
457
|
+
* @module
|
|
458
|
+
*/
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Compute a content-addressed hash for a {@link FactPredicate}. Canonicalised
|
|
462
|
+
* via `stableStringify` so two semantically-identical predicates emitted
|
|
463
|
+
* with different key order or whitespace produce the same hash.
|
|
464
|
+
*
|
|
465
|
+
* Suitable for:
|
|
466
|
+
* - Cache keys, dedupe in `sweepUnder`
|
|
467
|
+
* - Audit-ledger entry indexing (the `whenSpec` field has its own hash chain)
|
|
468
|
+
* - Provenance records (`predicateFromIntentWithProvenance.predicateHash`)
|
|
469
|
+
*
|
|
470
|
+
* **NOT suitable for cryptographic use** — 32-bit djb2 is collision-prone
|
|
471
|
+
* against an adversary. SHA-256 is reserved for v2.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* ```ts
|
|
475
|
+
* predicateHash({ cartTotal: { $gte: 50 } });
|
|
476
|
+
* // → "a1b2c3d4" (stable across runs and runtimes)
|
|
477
|
+
*
|
|
478
|
+
* // Two semantically-identical predicates → same hash
|
|
479
|
+
* predicateHash({ a: 1, b: 2 }) === predicateHash({ b: 2, a: 1 }); // true
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
declare function predicateHash<F = Record<string, unknown>>(spec: FactPredicate<F>): string;
|
|
483
|
+
|
|
827
484
|
/**
|
|
828
485
|
* predict() — "would this predicate fire against these facts, and if
|
|
829
486
|
* not, what facts must change to make it fire?"
|
|
@@ -848,7 +505,7 @@ interface PredictMissingChange {
|
|
|
848
505
|
/** Human-readable hint suitable for feeding back to an LLM or showing to a user. */
|
|
849
506
|
readonly suggestion: string;
|
|
850
507
|
}
|
|
851
|
-
interface PredictResult<
|
|
508
|
+
interface PredictResult<_F = unknown> {
|
|
852
509
|
/** True iff the predicate would fire against `facts`. */
|
|
853
510
|
readonly wouldFire: boolean;
|
|
854
511
|
/** Full clause-by-clause result (reuses the whenExplain payload). */
|
|
@@ -857,10 +514,12 @@ interface PredictResult<F> {
|
|
|
857
514
|
* List of failing clauses, each with a `suggestion` describing the
|
|
858
515
|
* smallest concrete change to `facts` that would make that clause pass.
|
|
859
516
|
* Empty when `wouldFire === true`.
|
|
517
|
+
*
|
|
518
|
+
* If the predicate contains a `$changed` clause AND `prev` was not
|
|
519
|
+
* passed, a synthetic warning is included here (the `$changed` clause
|
|
520
|
+
* cannot be evaluated without a `prev` snapshot).
|
|
860
521
|
*/
|
|
861
522
|
readonly missingChanges: readonly PredictMissingChange[];
|
|
862
|
-
/** Reference to the predicate evaluated, for telemetry. */
|
|
863
|
-
readonly predicate: FactPredicate<F>;
|
|
864
523
|
}
|
|
865
524
|
/**
|
|
866
525
|
* Run a predicate against the current fact state and report whether it
|
|
@@ -869,6 +528,12 @@ interface PredictResult<F> {
|
|
|
869
528
|
* Designed for the LLM-iteration loop and for "preview the impact of this
|
|
870
529
|
* rule" UIs.
|
|
871
530
|
*
|
|
531
|
+
* **`$changed` and `prev`:** the `$changed` operator compares the current
|
|
532
|
+
* value of a fact against the `prev` snapshot. If the predicate uses
|
|
533
|
+
* `$changed` and `prev` is not supplied, the missing-changes list includes
|
|
534
|
+
* a synthetic warning indicating that the clause cannot be evaluated —
|
|
535
|
+
* pass `predict(predicate, facts, prev)` to get a real result.
|
|
536
|
+
*
|
|
872
537
|
* @example
|
|
873
538
|
* ```ts
|
|
874
539
|
* const predicate = { cartTotal: { $gte: 50 }, region: { $in: ["US", "EU"] } };
|
|
@@ -882,7 +547,6 @@ interface PredictResult<F> {
|
|
|
882
547
|
* // { path: "cartTotal", op: "$gte", expected: 50, actual: 30,
|
|
883
548
|
* // suggestion: "set cartTotal to at least 50 (currently 30)" },
|
|
884
549
|
* // ],
|
|
885
|
-
* // predicate: { cartTotal: { $gte: 50 }, region: { $in: ["US", "EU"] } },
|
|
886
550
|
* // }
|
|
887
551
|
* ```
|
|
888
552
|
*/
|
|
@@ -896,9 +560,11 @@ declare function predict<F = Record<string, unknown>>(predicate: FactPredicate<F
|
|
|
896
560
|
*
|
|
897
561
|
* - **direct contradiction:** same fact path, opposite-direction
|
|
898
562
|
* comparison (`$gte 50` vs `$lt 50` — they cannot both fire).
|
|
563
|
+
* Reported under `contradictions`.
|
|
899
564
|
* - **subset:** candidate's range is a strict subset of an existing
|
|
900
565
|
* constraint's range (candidate `$gte 100` when existing already
|
|
901
|
-
* has `$gte 50`; the new rule
|
|
566
|
+
* has `$gte 50`; the new rule is redundant). Reported under
|
|
567
|
+
* `warnings` — a redundant rule is not a contradiction, just noise.
|
|
902
568
|
* - **overlap:** shares ≥1 fact path with non-trivial intersection —
|
|
903
569
|
* a warning, not a hard error.
|
|
904
570
|
*
|
|
@@ -914,6 +580,16 @@ declare function predict<F = Record<string, unknown>>(predicate: FactPredicate<F
|
|
|
914
580
|
* exists) are NOT acceptable — every reported contradiction must be
|
|
915
581
|
* defensible.
|
|
916
582
|
*
|
|
583
|
+
* **v1 scope LIMITATION (M4):** `checkAgainst` operates on predicate
|
|
584
|
+
* logic only. It does NOT consult `bind:` / `owns:` resolver metadata —
|
|
585
|
+
* a candidate that would *write* to a fact owned by another constraint
|
|
586
|
+
* will not be flagged here. Use `doctor.checkOwns()` for that gate.
|
|
587
|
+
*
|
|
588
|
+
* **INVARIANT (M11):** `checkAgainst` depends on `flattenPredicate`
|
|
589
|
+
* emitting `{ path, op, value }` LeafClause shape — if that shape ever
|
|
590
|
+
* changes, every comparison below silently breaks. See
|
|
591
|
+
* `doctor-leaf-shape.contract.test.ts`.
|
|
592
|
+
*
|
|
917
593
|
* Pure, sync, no engine dependency.
|
|
918
594
|
*/
|
|
919
595
|
|
|
@@ -939,15 +615,70 @@ interface Contradiction {
|
|
|
939
615
|
};
|
|
940
616
|
}
|
|
941
617
|
interface CheckAgainstResult {
|
|
942
|
-
/**
|
|
618
|
+
/**
|
|
619
|
+
* Hard contradictions — candidate never co-fires with existing rule.
|
|
620
|
+
* Includes only `type: "direct"` findings. Redundancy (`type: "subset"`)
|
|
621
|
+
* lives under `warnings` — a redundant rule is noise, not a conflict.
|
|
622
|
+
*/
|
|
943
623
|
readonly contradictions: readonly Contradiction[];
|
|
944
|
-
/**
|
|
624
|
+
/**
|
|
625
|
+
* Soft findings — shared facts with non-trivial intersection
|
|
626
|
+
* (`type: "overlap"`) AND subset redundancy (`type: "subset"`).
|
|
627
|
+
*/
|
|
945
628
|
readonly warnings: readonly Contradiction[];
|
|
946
629
|
}
|
|
947
630
|
/** Shape of `system.inspect().constraints[N]` we care about — accepts any superset. */
|
|
948
631
|
interface ExistingConstraint {
|
|
949
632
|
readonly id: string;
|
|
950
633
|
readonly whenSpec?: unknown;
|
|
634
|
+
/**
|
|
635
|
+
* Fact paths the constraint's resolver(s) write to, if exposed by the
|
|
636
|
+
* inspect API. Consulted by {@link doctor.checkOwns} to flag candidates
|
|
637
|
+
* that would write to fields owned elsewhere. Optional — older inspect
|
|
638
|
+
* payloads omit it.
|
|
639
|
+
*/
|
|
640
|
+
readonly owns?: readonly string[];
|
|
641
|
+
/** Same as {@link owns} but for the bind: side of binding metadata. */
|
|
642
|
+
readonly bind?: readonly string[];
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Returned by {@link doctor.checkOwns}.
|
|
646
|
+
*
|
|
647
|
+
* `severity` matches the {@link Contradiction} discriminator on
|
|
648
|
+
* {@link CheckAgainstResult} so callers can route both shapes
|
|
649
|
+
* uniformly: by default, owns-collisions are `"warning"` (the engine
|
|
650
|
+
* still has a runtime gate), but a caller can promote them to
|
|
651
|
+
* `"error"` for stricter pre-deploy linting. (M5)
|
|
652
|
+
*/
|
|
653
|
+
interface CheckOwnsFinding {
|
|
654
|
+
readonly constraintId: string;
|
|
655
|
+
/** The fact path on the candidate predicate that triggered the finding. */
|
|
656
|
+
readonly candidatePath: string;
|
|
657
|
+
/** The owner side it would collide with: "owns" or "bind". */
|
|
658
|
+
readonly source: "owns" | "bind";
|
|
659
|
+
readonly reason: string;
|
|
660
|
+
/**
|
|
661
|
+
* Severity discriminator — `"warning"` by default (the engine has
|
|
662
|
+
* its own runtime gate), `"error"` reserved for callers that want
|
|
663
|
+
* strict pre-deploy lints. (M5)
|
|
664
|
+
*/
|
|
665
|
+
readonly severity?: "error" | "warning";
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Result of {@link doctor.checkOwns}.
|
|
669
|
+
*
|
|
670
|
+
* Owns-/bind- collisions are warnings, not contradictions — the engine
|
|
671
|
+
* itself enforces the runtime binding gate, so a pre-deploy doctor pass
|
|
672
|
+
* treats them as advisory. The {@link CheckOwnsFinding.severity}
|
|
673
|
+
* discriminator anticipates v2 promotion of findings to errors. (M5, F-3)
|
|
674
|
+
*/
|
|
675
|
+
interface CheckOwnsResult {
|
|
676
|
+
/**
|
|
677
|
+
* Owns-/bind- collisions surfaced by {@link doctor.checkOwns}. Empty
|
|
678
|
+
* when constraints expose no `owns:` / `bind:` metadata or the
|
|
679
|
+
* candidate's fact paths don't overlap.
|
|
680
|
+
*/
|
|
681
|
+
readonly warnings: readonly CheckOwnsFinding[];
|
|
951
682
|
}
|
|
952
683
|
declare const doctor: {
|
|
953
684
|
/**
|
|
@@ -979,8 +710,100 @@ declare const doctor: {
|
|
|
979
710
|
checkAgainst<F = Record<string, unknown>>(candidate: FactPredicate<F>, existing: readonly ExistingConstraint[] | {
|
|
980
711
|
constraints: readonly ExistingConstraint[];
|
|
981
712
|
}): CheckAgainstResult;
|
|
713
|
+
/**
|
|
714
|
+
* Flag a candidate predicate whose referenced fact paths overlap with
|
|
715
|
+
* fields *owned* (or `bind:`-bound) by an existing constraint's
|
|
716
|
+
* resolvers. A v1 stub: relies on `inspect()` exposing `owns:` / `bind:`
|
|
717
|
+
* on each constraint snapshot. When that metadata is absent, this
|
|
718
|
+
* returns `{ findings: [] }` — no false positives.
|
|
719
|
+
*
|
|
720
|
+
* **TODO (v2):** wire the engine's resolver-ownership graph through
|
|
721
|
+
* `system.inspect()` so this returns real findings without manual
|
|
722
|
+
* `owns:` annotations on inspect payloads.
|
|
723
|
+
*
|
|
724
|
+
* @example
|
|
725
|
+
* ```ts
|
|
726
|
+
* doctor.checkOwns(
|
|
727
|
+
* { cartTotal: { $gte: 100 } },
|
|
728
|
+
* system.inspect(),
|
|
729
|
+
* );
|
|
730
|
+
* // → { findings: [
|
|
731
|
+
* // { constraintId: "applyDiscount", candidatePath: "cartTotal",
|
|
732
|
+
* // source: "owns",
|
|
733
|
+
* // reason: "Constraint applyDiscount already owns cartTotal." }
|
|
734
|
+
* // ] }
|
|
735
|
+
* ```
|
|
736
|
+
*/
|
|
737
|
+
checkOwns<F = Record<string, unknown>>(candidate: FactPredicate<F>, existing: readonly ExistingConstraint[] | {
|
|
738
|
+
constraints: readonly ExistingConstraint[];
|
|
739
|
+
}): CheckOwnsResult;
|
|
982
740
|
};
|
|
983
741
|
|
|
742
|
+
/**
|
|
743
|
+
* `describePredicate` — turn any {@link FactPredicate} into a precise,
|
|
744
|
+
* human-readable English sentence (or algebraic expression).
|
|
745
|
+
*
|
|
746
|
+
* Closes the LLM-emit round-trip:
|
|
747
|
+
*
|
|
748
|
+
* intent (NL) → predicate (AST) → describePredicate (NL) → reprompt
|
|
749
|
+
*
|
|
750
|
+
* Pure tree walker. No side effects. No throws on a valid predicate. On
|
|
751
|
+
* an invalid input (cyclic spec, non-object) returns a sentinel string
|
|
752
|
+
* rather than throwing, so it is safe to call on user/LLM input.
|
|
753
|
+
*
|
|
754
|
+
* Reuses no traversal infrastructure from `walkPredicate` directly because
|
|
755
|
+
* `walkPredicate` is a callback walker (flat) and English rendering needs a
|
|
756
|
+
* recursive return-value walker (tree). The two are isomorphic — same
|
|
757
|
+
* structural rules, same depth cap, same cycle guard. Operator/value
|
|
758
|
+
* formatting mirrors `rules-diff.ts`'s prose style.
|
|
759
|
+
*
|
|
760
|
+
* @module
|
|
761
|
+
*/
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Options controlling how {@link describePredicate} renders a predicate.
|
|
765
|
+
*/
|
|
766
|
+
interface DescribeOptions {
|
|
767
|
+
/** Locale for number formatting (default: `"en-US"`). */
|
|
768
|
+
locale?: string;
|
|
769
|
+
/** Wrap each clause in parens when there's > 1 clause. Default `true`. */
|
|
770
|
+
parenthesize?: boolean;
|
|
771
|
+
/** Style: `"natural"` (English prose) or `"formal"` (algebraic). Default `"natural"`. */
|
|
772
|
+
style?: "natural" | "formal";
|
|
773
|
+
/**
|
|
774
|
+
* Friendly fact-name renderer. Default: pass-through. Use to map e.g.
|
|
775
|
+
* `cartTotal` → `"cart total"`. Only consulted in `"natural"` style — the
|
|
776
|
+
* formal style preserves the raw dotted path so output stays algebraic.
|
|
777
|
+
*/
|
|
778
|
+
factName?: (path: string) => string;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Render a {@link FactPredicate} as a precise human-readable sentence.
|
|
782
|
+
*
|
|
783
|
+
* Renders a `FactPredicate` as English by default (`style: 'natural'`);
|
|
784
|
+
* pass `style: 'formal'` for algebraic notation (`≥`, `∈`, `∧`, etc.).
|
|
785
|
+
*
|
|
786
|
+
* @remarks
|
|
787
|
+
* Exported as `describePredicate` (not `describe`) to avoid collision with
|
|
788
|
+
* vitest's `describe()`.
|
|
789
|
+
*
|
|
790
|
+
* @example
|
|
791
|
+
* ```ts
|
|
792
|
+
* describePredicate({ cartTotal: { $gte: 50 } });
|
|
793
|
+
* // → "cartTotal is at least 50"
|
|
794
|
+
*
|
|
795
|
+
* describePredicate(
|
|
796
|
+
* { $any: [{ region: "US" }, { region: "EU" }] },
|
|
797
|
+
* { factName: (p) => p.replace(/([A-Z])/g, " $1").toLowerCase() },
|
|
798
|
+
* );
|
|
799
|
+
* // → "(region is US) OR (region is E U)"
|
|
800
|
+
*
|
|
801
|
+
* describePredicate({ cartTotal: { $gte: 50 } }, { style: "formal" });
|
|
802
|
+
* // → "cartTotal ≥ 50"
|
|
803
|
+
* ```
|
|
804
|
+
*/
|
|
805
|
+
declare function describePredicate<F = Record<string, unknown>>(predicate: FactPredicate<F>, opts?: DescribeOptions): string;
|
|
806
|
+
|
|
984
807
|
/**
|
|
985
808
|
* Compile a `FactPredicate` to a parameterized Postgres-style SQL WHERE
|
|
986
809
|
* clause. The same predicate that gates a constraint on the client can
|
|
@@ -2415,4 +2238,4 @@ declare const Backoff: {
|
|
|
2415
2238
|
readonly Exponential: "exponential";
|
|
2416
2239
|
};
|
|
2417
2240
|
|
|
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,
|
|
2241
|
+
export { Backoff, type Branded, type ChainableSchemaType, type Change, type ChangeKind, type CheckAgainstResult, type CheckOwnsFinding, type CheckOwnsResult, ClauseResult, type ConstraintDiff, type ConstraintStatus, type Contradiction, type ContradictionType, CreateSystemOptionsNamed, CreateSystemOptionsSingle, CrossModuleDeps, DefinitionMeta, type DescribeOptions, type DiffRulesOptions, ErrorBoundaryConfig, type ExistingConstraint, type ExtendedSchemaType, FactPredicate, Facts, type LeafClause, MAX_REPLAY_FRAMES, MAX_SWEEP_POINTS, type ModuleConfig, type ModuleConfigWithDeps, ModuleDef, ModuleHooks, ModuleSchema, ModulesMap, NamespacedSystem, Plugin, type PredicateBacktestReport, 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, SchemaKindNode, SchemaType, type SignalClock, SingleModuleSystem, type SweepHole, type SweepPoint, type SweepReport, type SweepUnderOptions, type TimerFactOpts, type TimerFactState, TraceOption, completeTimer, createModule, createModuleFactory, createRequirementStatusPlugin, createStatusHook, createSystem, createSystemWithStatus, defaultClock, describePredicate, diffClauses, diffRules, doctor, elapsedMs, flattenPredicate, forType, framesFromHistory, framesFromSnapshots, generateRequirementId, initialTimerState, isRequirementType, pauseTimer, predicateHash, predicateToMongo, predicateToPostgrest, predicateToSQL, predicateToWhere, predict, realClock, registerRepeat, remainingMs, replayUnder, req, resetTimer, resumeTimer, startTimer, sweepUnder, t, tickTimer, timerOps, toReplayFrames, toRulesMap, virtualClock };
|