@bjornpagen/bumbledb 0.4.0 → 0.6.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 (103) hide show
  1. package/COOKBOOK.md +191 -92
  2. package/README.md +9 -7
  3. package/dist/closed.d.ts +30 -2
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +66 -20
  6. package/dist/closed.js.map +1 -1
  7. package/dist/db.d.ts +33 -6
  8. package/dist/db.d.ts.map +1 -1
  9. package/dist/db.js +89 -72
  10. package/dist/db.js.map +1 -1
  11. package/dist/exhume.d.ts.map +1 -1
  12. package/dist/exhume.js +1 -14
  13. package/dist/exhume.js.map +1 -1
  14. package/dist/face.d.ts +1 -1
  15. package/dist/face.d.ts.map +1 -1
  16. package/dist/face.js +2 -1
  17. package/dist/face.js.map +1 -1
  18. package/dist/fields.d.ts +18 -1
  19. package/dist/fields.d.ts.map +1 -1
  20. package/dist/fields.js +44 -16
  21. package/dist/fields.js.map +1 -1
  22. package/dist/index.d.ts +18 -10
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +13 -6
  25. package/dist/index.js.map +1 -1
  26. package/dist/law.d.ts +2 -1
  27. package/dist/law.d.ts.map +1 -1
  28. package/dist/law.js +15 -14
  29. package/dist/law.js.map +1 -1
  30. package/dist/lower.d.ts.map +1 -1
  31. package/dist/lower.js +1 -7
  32. package/dist/lower.js.map +1 -1
  33. package/dist/marshal.d.ts.map +1 -1
  34. package/dist/marshal.js +15 -27
  35. package/dist/marshal.js.map +1 -1
  36. package/dist/native.d.ts +21 -2
  37. package/dist/native.d.ts.map +1 -1
  38. package/dist/native.js +20 -3
  39. package/dist/native.js.map +1 -1
  40. package/dist/order.d.ts +36 -0
  41. package/dist/order.d.ts.map +1 -0
  42. package/dist/order.js +135 -0
  43. package/dist/order.js.map +1 -0
  44. package/dist/query/atom.d.ts +140 -206
  45. package/dist/query/atom.d.ts.map +1 -1
  46. package/dist/query/atom.js +33 -52
  47. package/dist/query/atom.js.map +1 -1
  48. package/dist/query/find.d.ts +116 -0
  49. package/dist/query/find.d.ts.map +1 -0
  50. package/dist/query/{select.js → find.js} +22 -22
  51. package/dist/query/find.js.map +1 -0
  52. package/dist/query/lower.d.ts +124 -162
  53. package/dist/query/lower.d.ts.map +1 -1
  54. package/dist/query/lower.js +462 -507
  55. package/dist/query/lower.js.map +1 -1
  56. package/dist/query/predicate.d.ts +22 -14
  57. package/dist/query/predicate.d.ts.map +1 -1
  58. package/dist/query/predicate.js +45 -20
  59. package/dist/query/predicate.js.map +1 -1
  60. package/dist/query/run.d.ts +3 -3
  61. package/dist/query/run.d.ts.map +1 -1
  62. package/dist/query/run.js +10 -11
  63. package/dist/query/run.js.map +1 -1
  64. package/dist/query/scope.d.ts +124 -83
  65. package/dist/query/scope.d.ts.map +1 -1
  66. package/dist/query/scope.js +77 -70
  67. package/dist/query/scope.js.map +1 -1
  68. package/dist/relation.d.ts +9 -22
  69. package/dist/relation.d.ts.map +1 -1
  70. package/dist/relation.js +9 -28
  71. package/dist/relation.js.map +1 -1
  72. package/dist/schema.d.ts.map +1 -1
  73. package/dist/schema.js +7 -31
  74. package/dist/schema.js.map +1 -1
  75. package/dist/statements.d.ts +5 -2
  76. package/dist/statements.d.ts.map +1 -1
  77. package/dist/statements.js +30 -35
  78. package/dist/statements.js.map +1 -1
  79. package/package.json +2 -5
  80. package/src/closed.ts +73 -28
  81. package/src/db.ts +126 -88
  82. package/src/exhume.ts +1 -15
  83. package/src/face.ts +4 -3
  84. package/src/fields.ts +58 -16
  85. package/src/index.ts +19 -13
  86. package/src/law.ts +15 -14
  87. package/src/lower.ts +2 -9
  88. package/src/marshal.ts +15 -31
  89. package/src/native.ts +22 -4
  90. package/src/order.ts +156 -0
  91. package/src/query/atom.ts +186 -276
  92. package/src/query/find.ts +212 -0
  93. package/src/query/lower.ts +614 -749
  94. package/src/query/predicate.ts +47 -20
  95. package/src/query/run.ts +11 -13
  96. package/src/query/scope.ts +165 -132
  97. package/src/relation.ts +9 -51
  98. package/src/schema.ts +7 -33
  99. package/src/statements.ts +33 -38
  100. package/dist/query/select.d.ts +0 -128
  101. package/dist/query/select.d.ts.map +0 -1
  102. package/dist/query/select.js.map +0 -1
  103. package/src/query/select.ts +0 -215
package/src/query/atom.ts CHANGED
@@ -1,86 +1,60 @@
1
1
  /**
2
- * Atoms and conditions, STRUCTURAL edition — the body vocabulary of a
3
- * rule, mirroring the engine IR variant for variant
2
+ * Atoms and conditions, REFERENCE-IDENTITY edition — the body vocabulary of
3
+ * a rule, mirroring the engine IR variant for variant
4
4
  * (`bumbledb/crates/bumbledb/src/ir.rs`, the bijection target;
5
5
  * `docs/architecture/20-query-ir.md` normative). A `match` binding record
6
- * binds fields to vars, params, ∈-set params, or bare structural literals
7
- * — a closed-reference field's literal is its handle NAME, and a plain
8
- * ARRAY of names there is membership, folded into the program (closed-only
9
- * by owner ruling; see {@link BindingInput})
6
+ * binds fields to VARIABLES (minted by {@link v}), params, ∈-set params, or
7
+ * bare structural literals — a closed-reference field's literal is its
8
+ * handle NAME, and a plain ARRAY of names there is membership
10
9
  * (unmentioned fields ARE the wildcard — no wildcard value exists);
11
10
  * `not(Rel, {...})` is negation-as-position (anti-join); `eq`/`ne` and the
12
- * order roster, `pointIn`/`covers` (both spellings of `ir::CmpOp::PointIn`,
11
+ * order roster, `pointIn` (the one spelling of `ir::CmpOp::PointIn`,
13
12
  * always lowered interval-left), `allen` (the 13-bit mask pair
14
13
  * comparison), and `and`/`or` (the input condition-tree grammar) complete
15
14
  * the roster. Nothing beyond the IR exists here — and the walls the engine
16
- * enforces at prepare are TYPES first: a var joins only domain-equal
17
- * fields (`JoinOk`, checked against the rule environment AND against the
18
- * binding record's own same-named siblings two first occurrences of one
19
- * name inside one record are a join too), an
20
- * interval-typed var under a non-`pointIn` comparison is unwritable, and a
21
- * negated atom's variables must be positively bound (env membership IS the
22
- * safety rule). Every condition value carries its operands raw the
23
- * runtime representation is the type-inference carrier, no phantoms.
15
+ * enforces at prepare are TYPES first: a variable joins only class-equal
16
+ * fields, judged at every binding position against the var's MINT slot
17
+ * ({@link MintSlotOf}); because {@link JoinOk} is an equality, that ALONE
18
+ * makes every cross-binding join transitively class-equal (the env/sibling
19
+ * checks the name-keyed edition needed are gone). An interval-typed var
20
+ * under a non-`pointIn` comparison is unwritable. BOUNDNESS (a negated
21
+ * atom's variables must be positively bound) is the one check types cannot
22
+ * carry object identity is invisible to TS so it is a construction-time
23
+ * wall only.
24
24
  *
25
25
  * This module also owns the plain runtime DATA a built rule is made of
26
26
  * (`RuleData`/`RecData` and friends): frozen values the lowering walks —
27
- * pure data, so lowering stays a pure, stable function of the query value.
27
+ * pure data (variable references included), so lowering stays a pure,
28
+ * stable function of the query value.
28
29
  */
29
30
 
30
31
  import * as errors from "@superbuilders/errors"
31
- import type { AnyClosed } from "#closed.ts"
32
32
  import type { AnyField, ClosedIdField, ClosedRoster, Infer, IntervalValue } from "#fields.ts"
33
33
  import type { ClassLookup, ClassRecordOf, SchemaClasses } from "#law.ts"
34
34
  import type {
35
+ AnyVar,
35
36
  ClassedField,
36
37
  Duration,
37
- EnvShape,
38
38
  JoinOk,
39
39
  MaskParam,
40
+ MatchFields,
41
+ MatchOwner,
42
+ MintSlotOf,
40
43
  Param,
41
44
  ParamValueAt,
42
45
  SetParam,
43
- ShapeOf,
44
- Var
46
+ ShapeOf
45
47
  } from "#query/scope.ts"
46
48
  import { isTerm } from "#query/scope.ts"
47
- import type { AnyRelation, FieldsShape, RelationFields } from "#relation.ts"
48
-
49
- /**
50
- * What a query atom matches over: an ordinary relation or a CLOSED
51
- * vocabulary (ψ query atoms — the engine folds a resolvable closed atom
52
- * into a plan-constant member set at prepare, or joins the L1-resident
53
- * virtual image when the shape does not fold; the SDK never pre-folds and
54
- * never knows which — transparency is the contract).
55
- */
56
- type MatchOwner = AnyRelation | AnyClosed
49
+ import type { FieldsShape } from "#relation.ts"
57
50
 
58
51
  /**
59
- * The matchable field block of an atom owner: a relation's declared
60
- * fields; a closed relation's SEALED shape — the synthetic `id` (the
61
- * value's OWN roster-carrying descriptor, at its precise type: the handle
62
- * union rides into ψ id bindings and joins exactly as it does on a
63
- * referencing column) first, then the declared payload columns read
64
- * through the typed `columns` carrier (the one source of payload typing —
65
- * no parallel column table exists). The runtime twin is `matchFieldsOf` in
66
- * `#query/lower.ts`; the id-first ordinal shift the two tiers share is
67
- * pinned by the lowering golden.
68
- */
69
- type MatchFields<R extends MatchOwner> = R extends AnyClosed
70
- ? { readonly id: R["id"] } & R["columns"]
71
- : R extends AnyRelation
72
- ? RelationFields<R>
73
- : never
74
-
75
- /**
76
- * One atom-binding position as runtime data. `literalSet` is a membership
77
- * ARRAY at a closed-reference field, folded into the program: `name` is
78
- * the content-addressed registry key its dense `ParamId` is minted under
79
- * (the lowering rides the existing param-set term; the SDK itself supplies
80
- * the translated member set at every execute — never the host).
52
+ * One atom-binding position as runtime data. A variable rides BY REFERENCE
53
+ * (`ref`) object identity is the join. `literalSet` is a membership
54
+ * ARRAY at a closed-reference field, folded into the program.
81
55
  */
82
56
  type BindingTermData =
83
- | { readonly kind: "var"; readonly name: string }
57
+ | { readonly kind: "var"; readonly ref: AnyVar }
84
58
  | { readonly kind: "param"; readonly name: string }
85
59
  | { readonly kind: "setParam"; readonly name: string }
86
60
  | { readonly kind: "literalSet"; readonly name: string; readonly members: readonly string[] }
@@ -103,12 +77,12 @@ interface AtomData {
103
77
  /** One comparison operator name (mirrors `ir::CmpOp`). */
104
78
  type CmpKind = "eq" | "ne" | "lt" | "le" | "gt" | "ge" | "pointIn" | "allen"
105
79
 
106
- /** One comparison side as runtime data. */
80
+ /** One comparison side as runtime data (variables and the measure ride BY REFERENCE). */
107
81
  type CmpTermData =
108
- | { readonly kind: "var"; readonly name: string }
82
+ | { readonly kind: "var"; readonly ref: AnyVar }
109
83
  | { readonly kind: "param"; readonly name: string }
110
84
  | { readonly kind: "setParam"; readonly name: string }
111
- | { readonly kind: "measure"; readonly name: string }
85
+ | { readonly kind: "measure"; readonly ref: AnyVar }
112
86
  | { readonly kind: "literal"; readonly value: unknown }
113
87
 
114
88
  /** The `allen` mask position as runtime data. */
@@ -133,48 +107,61 @@ interface TreeData {
133
107
  /** Any condition node as runtime data. */
134
108
  type CondData = CmpData | TreeData
135
109
 
136
- /** One aggregate's runtime description (select vocabulary, over var NAMES). */
110
+ /** One aggregate's runtime description (find vocabulary, over variable REFERENCES). */
137
111
  type AggData =
138
112
  | { readonly op: "count" }
139
- | { readonly op: "countDistinct"; readonly over: string }
140
- | { readonly op: "fold"; readonly fold: "sum" | "min" | "max"; readonly over: string | { readonly duration: string } }
141
- | { readonly op: "arg"; readonly direction: "argMax" | "argMin"; readonly over: string; readonly key: string }
142
- | { readonly op: "pack"; readonly over: string }
143
-
144
- /** One classified select entry as runtime data. */
145
- type SelectEntryData =
146
- | { readonly kind: "var"; readonly over: string }
147
- | { readonly kind: "measure"; readonly over: string }
113
+ | { readonly op: "countDistinct"; readonly over: AnyVar }
114
+ | {
115
+ readonly op: "fold"
116
+ readonly fold: "sum" | "min" | "max"
117
+ readonly over: AnyVar | { readonly duration: AnyVar }
118
+ }
119
+ | { readonly op: "arg"; readonly direction: "argMax" | "argMin"; readonly over: AnyVar; readonly key: AnyVar }
120
+ | { readonly op: "pack"; readonly over: AnyVar }
121
+
122
+ /** One classified find entry as runtime data (variables and the measure ride BY REFERENCE). */
123
+ type FindEntryData =
124
+ | { readonly kind: "var"; readonly over: AnyVar }
125
+ | { readonly kind: "measure"; readonly over: AnyVar }
148
126
  | { readonly kind: "aggregate"; readonly agg: AggData }
149
127
 
150
128
  /**
151
- * One answer column: its name (the row object key), its entry, and when
152
- * the column's value is a closed reference (a projected var or an
153
- * Arg-carried payload bound at a closed-referencing field) the roster the
154
- * decode lifts row ids back to handle NAMES through (the read half of the
155
- * marshal bijection; `undefined` on every bare column). The slice is
156
- * SDK-side marshaling data only: the wire `ProgramIr` never carries it.
129
+ * One answer column: its name (the row object key the find record's key,
130
+ * so renames are real and a duplicate column is unrepresentable), its entry,
131
+ * the classed mint SLOT its values flow from (a projected var or an
132
+ * Arg-carried payload; `undefined` for counts/folds/measures/pack, which
133
+ * derive numbers or intervals), and when that slot is a closed reference —
134
+ * the roster the decode lifts row ids back to handle NAMES through
135
+ * (`undefined` on every bare column). The slice is SDK-side marshaling data
136
+ * only: the wire `ProgramIr` never carries it.
157
137
  */
158
- interface SelectColumn {
138
+ interface FindColumn {
159
139
  readonly name: string
160
- readonly entry: SelectEntryData
140
+ readonly entry: FindEntryData
161
141
  readonly closed: ClosedRoster | undefined
142
+ readonly slot: ClassedField | undefined
162
143
  }
163
144
 
164
- /** One body item of a rule, in written order. */
145
+ /**
146
+ * One body item of a rule, in written order. The idb join is a NAMED record
147
+ * over the rec's head keys (`key`) bound to local variables (`ref`) — the
148
+ * typed wall a record's unordered keys would otherwise lose.
149
+ */
165
150
  type RuleItem =
166
151
  | { readonly kind: "atom"; readonly atom: AtomData }
167
152
  | { readonly kind: "negated"; readonly atom: AtomData }
168
- | { readonly kind: "idb"; readonly rec: RecData; readonly vars: readonly string[] }
153
+ | {
154
+ readonly kind: "idb"
155
+ readonly rec: RecData
156
+ readonly bindings: ReadonlyArray<{ readonly key: string; readonly ref: AnyVar }>
157
+ }
169
158
  | { readonly kind: "cond"; readonly cond: CondData }
170
159
 
171
160
  /**
172
161
  * One use of a parameter inside a rule, in written order: the census the
173
162
  * query-level registry folds (first use mints the dense `ParamId`, first
174
163
  * FIELD-ANCHORED use types the wire). `members` is present exactly on a
175
- * membership-array use (a literal set folded into the program): the handle
176
- * names the SDK itself translates and supplies at execute — the entry
177
- * never appears in the host's params object.
164
+ * membership-array use.
178
165
  */
179
166
  interface ParamUse {
180
167
  readonly name: string
@@ -187,9 +174,7 @@ interface ParamUse {
187
174
  /** One complete rule as runtime data. */
188
175
  interface RuleData {
189
176
  readonly items: readonly RuleItem[]
190
- readonly select: readonly SelectColumn[]
191
- /** Variable name → the classed slot its FIRST positive binding carries (the runtime env — descriptor + class). */
192
- readonly varFields: Readonly<Record<string, ClassedField>>
177
+ readonly finds: readonly FindColumn[]
193
178
  readonly paramUses: readonly ParamUse[]
194
179
  }
195
180
 
@@ -205,23 +190,15 @@ interface RecData {
205
190
 
206
191
  /**
207
192
  * What a binding position of field `F` accepts: a bare structural literal
208
- * of the field's value type, a var/param/∈-set-param term — and, when the
209
- * field is interval-typed, a bare point literal (the IR's membership
210
- * typing rule: an element-typed term at an interval field is point
211
- * membership; an interval-typed term is value equality). A
212
- * CLOSED-reference field additionally takes a plain ARRAY of handle names
213
- * read as membership — `kind: ["Practice", "Review"]` (the drizzle law:
214
- * set membership is an array, never an operator). Arrays are CLOSED-ONLY
215
- * in this packet by owner ruling: ordinary u64/str membership already has
216
- * its spelling through `r.inSet` params; widening literal arrays to every
217
- * literal-capable kind is a separate future taste call — deliberately not
218
- * done here.
193
+ * of the field's value type, a variable/param/∈-set-param term — and, when
194
+ * the field is interval-typed, a bare point literal. A CLOSED-reference
195
+ * field additionally takes a plain ARRAY of handle names read as membership.
219
196
  */
220
197
  type BindingInput<F extends AnyField> =
221
198
  | Infer<F>
222
199
  | (F extends ClosedIdField ? readonly Infer<F>[] : never)
223
200
  | (F extends { readonly kind: "interval" } ? bigint : never)
224
- | Var<string>
201
+ | AnyVar
225
202
  | Param<string>
226
203
  | SetParam<string>
227
204
 
@@ -237,8 +214,8 @@ type MatchShape<F extends FieldsShape> = {
237
214
  /**
238
215
  * One field position of a bindings record as a classed slot: the declared
239
216
  * descriptor plus the slot's law-computed class, read off the relation's
240
- * class record (`CR` the schema class map's entry for the atom's
241
- * relation). The one shape every join judgment compares.
217
+ * class record (`CR`). The one shape a binding position's join judgment
218
+ * compares against.
242
219
  */
243
220
  type SlotAt<F extends FieldsShape, CR, K> = {
244
221
  readonly field: F[K & keyof F]
@@ -246,49 +223,20 @@ type SlotAt<F extends FieldsShape, CR, K> = {
246
223
  }
247
224
 
248
225
  /**
249
- * The var binding's judgment against the incoming rule environment: a name
250
- * already bound must land on a class-equal slot (bare pairs only with bare).
251
- */
252
- type EnvJoinOk<Env extends EnvShape, F extends FieldsShape, CR, K, N extends string> = N extends keyof Env
253
- ? JoinOk<Env[N], SlotAt<F, CR, K>>
254
- : true
255
-
256
- /**
257
- * The var binding's judgment against its OWN record's siblings: two
258
- * bindings of one var name inside a single bindings record are the same
259
- * join the environment check judges across atoms, so every same-named
260
- * sibling must be class-equal too. Without this arm two FIRST occurrences
261
- * of one name (a record the environment has not seen yet) would meet no
262
- * check at all — the intra-atom join would silently cross classes.
226
+ * The per-property join judgment of a bindings record: a VARIABLE binding
227
+ * must join its own MINT slot to the position slot (a cross-class reuse maps
228
+ * the property to `never`). Because {@link JoinOk} is an equality, judging
229
+ * every position against the mint slot makes all cross-binding joins
230
+ * mutually class-equal by transitivity — no env or sibling arm is needed.
263
231
  */
264
- type SiblingJoinOk<F extends FieldsShape, CR, B, K extends keyof B, N extends string> = false extends {
265
- [K2 in Exclude<keyof B & keyof F, K>]: B[K2] extends Var<N> ? JoinOk<SlotAt<F, CR, K2>, SlotAt<F, CR, K>> : true
266
- }[Exclude<keyof B & keyof F, K>]
267
- ? false
268
- : true
269
-
270
- /**
271
- * The per-property join judgment of a bindings record: a var binding must
272
- * be class-equal to the rule environment's binding of the name AND to
273
- * every same-named sibling of its own record (a cross-class reuse maps
274
- * the property to `never` — the compile error the old value brand carried,
275
- * now law-born off the schema type's class map).
276
- */
277
- type BindingOk<Env extends EnvShape, F extends FieldsShape, CR, B, K extends keyof B> =
278
- B[K] extends Var<infer N extends string>
279
- ? [EnvJoinOk<Env, F, CR, K, N>, SiblingJoinOk<F, CR, B, K, N>] extends [true, true]
280
- ? true
281
- : false
282
- : true
283
-
284
- /** The validated bindings record (intersect with the inferred `B` — errors land on the offending property). */
285
- type CheckBindings<Env extends EnvShape, F extends FieldsShape, CR, B> = {
286
- readonly [K in keyof B]: K extends keyof F ? (BindingOk<Env, F, CR, B, K> extends true ? B[K] : never) : never
287
- }
288
-
289
- /** The environment a bindings record contributes: var name → the bound slot (descriptor + class). */
290
- type BindEnv<F extends FieldsShape, CR, B> = {
291
- readonly [K in keyof B & keyof F as B[K] extends Var<infer N extends string> ? N : never]: SlotAt<F, CR, K>
232
+ type CheckBindings<Classes extends SchemaClasses, F extends FieldsShape, CR, B> = {
233
+ readonly [K in keyof B]: K extends keyof F
234
+ ? B[K] extends AnyVar
235
+ ? JoinOk<MintSlotOf<Classes, B[K]>, SlotAt<F, CR, K>> extends true
236
+ ? B[K]
237
+ : never
238
+ : B[K]
239
+ : never
292
240
  }
293
241
 
294
242
  /** The params-object fragments a bindings record contributes (one union member per param use). */
@@ -302,8 +250,8 @@ type BindParams<F extends FieldsShape, B> = {
302
250
 
303
251
  /**
304
252
  * One comparison VALUE: op plus its operands, raw — the runtime
305
- * representation carries the operand types, so `.where`'s environment
306
- * check and the params inference both read the value itself (no phantom).
253
+ * representation carries the operands (variable references included), so
254
+ * `.where`'s judgment and the params inference both read the value itself.
307
255
  * `mask` is populated exactly for `allen`.
308
256
  */
309
257
  interface Cmp<Op extends CmpKind, L, R, M = undefined> {
@@ -324,9 +272,9 @@ interface Tree<Ch extends readonly AnyTreeChild[]> {
324
272
  /**
325
273
  * One negated-atom VALUE — negation is a position in the rule (anti-join
326
274
  * over sets, no null trick): a binding satisfies it iff NO fact matches.
327
- * Its variables must be positively bound in the rule — environment
328
- * membership at `.where` IS the safety rule, a compile error before it is
329
- * the engine's refusal.
275
+ * Its variables must be positively bound in the rule — a construction-time
276
+ * wall (BOUNDNESS is invisible to the type tier), before the engine's own
277
+ * refusal.
330
278
  */
331
279
  interface NotAtom<R extends MatchOwner, B> {
332
280
  readonly cond: "not"
@@ -347,19 +295,19 @@ type AnyNotAtom = NotAtom<MatchOwner, unknown>
347
295
  type AnyCond = AnyCmp | Tree<readonly AnyTreeChild[]> | AnyNotAtom
348
296
 
349
297
  /** What `eq`'s right side accepts (`ParamSet` is `Eq`-only — the IR's rule). */
350
- type EqRight = Var<string> | Param<string> | SetParam<string> | bigint | string | boolean | Uint8Array | IntervalValue
298
+ type EqRight = AnyVar | Param<string> | SetParam<string> | bigint | string | boolean | Uint8Array | IntervalValue
351
299
 
352
300
  /** What `ne`'s right side accepts. */
353
- type NeRight = Var<string> | Param<string> | bigint | string | boolean | Uint8Array | IntervalValue
301
+ type NeRight = AnyVar | Param<string> | bigint | string | boolean | Uint8Array | IntervalValue
354
302
 
355
303
  /** One side of an order comparison: orderable terms only (the IR's comparison rules). */
356
- type OrderSide = Var<string> | Param<string> | Duration<string> | bigint
304
+ type OrderSide = AnyVar | Param<string> | Duration | bigint
357
305
 
358
- /** The point side of `pointIn`/`covers`. */
359
- type PointSide = Var<string> | Param<string> | bigint
306
+ /** The point side of `pointIn`. */
307
+ type PointSide = AnyVar | Param<string> | bigint
360
308
 
361
- /** The interval side of `pointIn`/`covers`/`allen`. */
362
- type IntervalSide = Var<string> | Param<string> | IntervalValue
309
+ /** The interval side of `pointIn`/`allen`. */
310
+ type IntervalSide = AnyVar | Param<string> | IntervalValue
363
311
 
364
312
  /** Builds one comparison value. */
365
313
  function comparison<Op extends CmpKind, L, R, M>(op: Op, lhs: L, rhs: R, mask: M): Cmp<Op, L, R, M> {
@@ -381,17 +329,17 @@ function assertTermSide(op: string, lhs: unknown, rhs: unknown): void {
381
329
 
382
330
  /**
383
331
  * The equality comparison (`ir::CmpOp::Eq`) — a bound variable against a
384
- * variable (var-to-var unification, domain-equal by the environment
385
- * check), a param (typed by the variable), an ∈-set param (`Eq`-only, the
386
- * IR's set rule), or a bare literal of the variable's own value type.
387
- * Prefer direct placement in `match` where punning applies.
332
+ * variable (var-to-var unification, class-equal by the join judgment), a
333
+ * param (typed by the variable), an ∈-set param (`Eq`-only), or a bare
334
+ * literal of the variable's own value type. Prefer direct placement in
335
+ * `match` where punning applies.
388
336
  */
389
- function eq<L extends Var<string>, const R extends EqRight>(left: L, right: R): Cmp<"eq", L, R> {
337
+ function eq<L extends AnyVar, const R extends EqRight>(left: L, right: R): Cmp<"eq", L, R> {
390
338
  return comparison("eq", left, right, undefined)
391
339
  }
392
340
 
393
341
  /** Typed disequality (`ir::CmpOp::Ne`). "Not in set" has no operator — write a negated atom. */
394
- function ne<L extends Var<string>, const R extends NeRight>(left: L, right: R): Cmp<"ne", L, R> {
342
+ function ne<L extends AnyVar, const R extends NeRight>(left: L, right: R): Cmp<"ne", L, R> {
395
343
  return comparison("ne", left, right, undefined)
396
344
  }
397
345
 
@@ -426,43 +374,28 @@ function ge<const L extends OrderSide, const R extends OrderSide>(left: L, right
426
374
  }
427
375
 
428
376
  /**
429
- * Point membership as a predicate (`ir::CmpOp::PointIn`), membership
377
+ * Point membership as a predicate (`ir::CmpOp::PointIn`) — THE one
430
378
  * spelling: `pointIn(t, w)` holds iff `w.start ≤ t < w.end`. The IR
431
379
  * orders the operands interval-left, point-right; the value stores them
432
- * that way whatever the surface spelling.
380
+ * that way whatever the surface argument order. Interval ⊇ interval is NOT
381
+ * this operator; that predicate is `allen(a, ALLEN.covers, b)`.
433
382
  */
434
383
  function pointIn<const P extends PointSide, const I extends IntervalSide>(point: P, interval: I): Cmp<"pointIn", I, P> {
435
384
  assertTermSide("pointIn", point, interval)
436
385
  return comparison("pointIn", interval, point, undefined)
437
386
  }
438
387
 
439
- /**
440
- * Point membership, coverage spelling — `covers(w, t)` is `pointIn(t, w)`
441
- * with the interval written first (the IR's own operand order; a literal
442
- * `span(...)` left operand is legal and tags by the point sibling's
443
- * element domain — the bug-hunt fix, now also a type-level guarantee).
444
- * Interval ⊇ interval is NOT this operator; that predicate is
445
- * `allen(a, ALLEN.covers, b)`.
446
- */
447
- function covers<const I extends IntervalSide, const P extends PointSide>(interval: I, point: P): Cmp<"pointIn", I, P> {
448
- assertTermSide("covers", interval, point)
449
- return comparison("pointIn", interval, point, undefined)
450
- }
451
-
452
388
  /**
453
389
  * The 13-bit mask range: bits above the low 13 are unrepresentable in the
454
390
  * engine's `AllenMask` (`bumbledb/crates/bumbledb/src/allen.rs`:
455
- * `AllenMask::new` refuses them) — the check here is the same boundary,
456
- * moved to construction where the message can name the constants.
391
+ * `AllenMask::new` refuses them).
457
392
  */
458
393
  const ALLEN_ALL_BITS = (1 << 13) - 1
459
394
 
460
395
  /**
461
396
  * The Allen coordinate system's named constants — the 13 basics in the
462
- * engine's palindromic bit order (bit i = basic i:
463
- * `bumbledb/crates/bumbledb/src/allen.rs`, a specified representation)
464
- * plus the workload composites, values identical to the engine's. Compose
465
- * with `|`: `ALLEN.before | ALLEN.meets`.
397
+ * engine's palindromic bit order plus the workload composites, values
398
+ * identical to the engine's. Compose with `|`: `ALLEN.before | ALLEN.meets`.
466
399
  */
467
400
  const ALLEN = Object.freeze({
468
401
  before: 1 << 0,
@@ -492,9 +425,7 @@ const ALLEN = Object.freeze({
492
425
  * THE interval-pair comparison (`ir::CmpOp::Allen`): two interval terms of
493
426
  * one element type, satisfied iff the pair's classification is in the
494
427
  * 13-bit mask — a literal built from the `ALLEN` constants, or a mask
495
- * parameter (`r.maskParam`). Vacuous masks (empty/full) are the engine's
496
- * two distinct typed rejections; nothing is pre-judged here beyond the
497
- * representable bit range.
428
+ * parameter (`r.maskParam`).
498
429
  */
499
430
  function allen<const A extends IntervalSide, const M extends number | MaskParam<string>, const B extends IntervalSide>(
500
431
  left: A,
@@ -523,22 +454,18 @@ function and<const C extends readonly AnyTreeChild[]>(...children: C): Tree<C> {
523
454
  /**
524
455
  * Disjunction node of the input condition grammar (`ConditionTree::Or`) —
525
456
  * the one place the surface admits a nested OR; validation distributes it
526
- * to DNF rules engine-side (OR is data or it is nothing). `Or([])` keeps
527
- * its algebraic reading (false: the rule denotes nothing).
457
+ * to DNF rules engine-side. `Or([])` keeps its algebraic reading (false).
528
458
  */
529
459
  function or<const C extends readonly AnyTreeChild[]>(...children: C): Tree<C> {
530
460
  return Object.freeze({ cond: "tree", op: "or", children: Object.freeze(children) })
531
461
  }
532
462
 
533
463
  /**
534
- * Negation — anti-join over sets: `not(Rel, { field: r.var("x"), ... })`
464
+ * Negation — anti-join over sets: `not(Rel, { field: someVar, ... })`
535
465
  * rejects every binding some matching fact extends. A negated atom binds
536
466
  * nothing, only rejects: every variable it names must be positively bound
537
- * in the rule, which `.where`'s environment check makes a COMPILE error
538
- * (the engine's safety refusal stands behind it). A CLOSED owner is legal
539
- * here too — the engine folds a resolvable negated closed atom to the
540
- * COMPLEMENT of its member set (domain-witness guarded), and the SDK's
541
- * negation rules apply to it unchanged.
467
+ * in the rule, a construction-time wall (the engine's safety refusal stands
468
+ * behind it). A CLOSED owner is legal here too.
542
469
  */
543
470
  function not<R extends MatchOwner, const B extends MatchShape<MatchFields<R>>>(
544
471
  relation: R,
@@ -549,122 +476,106 @@ function not<R extends MatchOwner, const B extends MatchShape<MatchFields<R>>>(
549
476
  }
550
477
 
551
478
  /**
552
- * Whether a var name is bound in the environment at an orderable (u64/i64)
553
- * field. A CLOSED reference is excluded even though its kind is `u64`: a
554
- * vocabulary's declaration-id order is an accident, not semantics
555
- * (`docs/architecture/10-data-model.md` § orderability order on it is
556
- * refused exactly as the enum's ordinal order was), so every
557
- * order-comparison and fold position refuses closed-bound terms — this
558
- * judgment is the one gate they all read, and the construction-time
559
- * validations in `#query/lower.ts` are its runtime twin.
479
+ * Whether a variable's OWN field is orderable (u64/i64). A CLOSED reference
480
+ * is excluded even though its kind is `u64`: a vocabulary's declaration-id
481
+ * order is an accident, not semantics (`docs/architecture/10-data-model.md`
482
+ * § orderability), so every order-comparison and fold position refuses
483
+ * closed-bound terms this judgment is the one gate they all read, and the
484
+ * construction-time validations in `#query/lower.ts` are its runtime twin.
560
485
  */
561
- type OrderVarOk<Env extends EnvShape, N extends string> = N extends keyof Env
562
- ? Env[N]["field"] extends { readonly closed: ClosedRoster }
563
- ? false
564
- : Env[N]["field"]["kind"] extends "u64" | "i64"
565
- ? true
566
- : false
567
- : false
568
-
569
- /** Whether a var name is bound at an interval field. */
570
- type IntervalVarOk<Env extends EnvShape, N extends string> = N extends keyof Env
571
- ? Env[N]["field"]["kind"] extends "interval"
486
+ type OrderVarOk<V extends AnyVar> = V["field"] extends { readonly closed: ClosedRoster }
487
+ ? false
488
+ : V["field"]["kind"] extends "u64" | "i64"
572
489
  ? true
573
490
  : false
574
- : false
575
491
 
576
- /** One order-comparison side's judgment against the environment. */
577
- type OrderSideOk<Env extends EnvShape, T> =
578
- T extends Var<infer N extends string>
579
- ? OrderVarOk<Env, N>
580
- : T extends Duration<infer N extends string>
581
- ? IntervalVarOk<Env, N>
582
- : true
492
+ /** Whether a variable's OWN field is interval-typed. */
493
+ type IntervalVarOk<V extends AnyVar> = V["field"]["kind"] extends "interval" ? true : false
494
+
495
+ /** One order-comparison side's judgment (off the term's own field). */
496
+ type OrderSideOk<T> = T extends AnyVar
497
+ ? OrderVarOk<T>
498
+ : T extends Duration<infer V extends AnyVar>
499
+ ? IntervalVarOk<V>
500
+ : true
583
501
 
584
502
  /** One point side's judgment. */
585
- type PointSideOk<Env extends EnvShape, T> = T extends Var<infer N extends string> ? OrderVarOk<Env, N> : true
503
+ type PointSideOk<T> = T extends AnyVar ? OrderVarOk<T> : true
586
504
 
587
505
  /** One interval side's judgment. */
588
- type IntervalSideOk<Env extends EnvShape, T> = T extends Var<infer N extends string> ? IntervalVarOk<Env, N> : true
589
-
590
- /** The `eq`/`ne` judgment: left var bound; right joins it (class-equal var, param, or an exact-type literal). */
591
- type EqOk<Env extends EnvShape, L, R> =
592
- L extends Var<infer N extends string>
593
- ? N extends keyof Env
594
- ? R extends Var<infer M extends string>
595
- ? M extends keyof Env
596
- ? JoinOk<Env[N], Env[M]>
597
- : false
598
- : R extends Param<string> | SetParam<string>
599
- ? true
600
- : [R] extends [Infer<Env[N]["field"]>]
601
- ? true
602
- : false
506
+ type IntervalSideOk<T> = T extends AnyVar ? IntervalVarOk<T> : true
507
+
508
+ /** The `eq`/`ne` judgment: var-var joins by mint slot; var-literal is exact-typed by the var's own field. */
509
+ type EqOk<Classes extends SchemaClasses, L, R> = L extends AnyVar
510
+ ? R extends AnyVar
511
+ ? JoinOk<MintSlotOf<Classes, L>, MintSlotOf<Classes, R>> extends true
512
+ ? true
603
513
  : false
604
- : false
514
+ : R extends Param<string> | SetParam<string>
515
+ ? true
516
+ : [R] extends [Infer<L["field"]>]
517
+ ? true
518
+ : false
519
+ : false
605
520
 
606
- /** One negated-atom binding's judgment: a var must be positively bound (safety) AND class-equal. */
607
- type NotBindingOk<Env extends EnvShape, S extends ClassedField, T> =
608
- T extends Var<infer N extends string> ? (N extends keyof Env ? JoinOk<Env[N], S> : false) : true
521
+ /** One negated-atom binding's judgment: a variable must be class-equal (boundness is a runtime wall). */
522
+ type NotBindingOk<Classes extends SchemaClasses, S extends ClassedField, T> = T extends AnyVar
523
+ ? JoinOk<MintSlotOf<Classes, T>, S> extends true
524
+ ? true
525
+ : false
526
+ : true
609
527
 
610
528
  /** The whole negated atom's judgment (`CR` — the negated relation's class record off the schema class map). */
611
- type NotOk<Env extends EnvShape, F extends FieldsShape, CR, B> = false extends {
612
- [K in keyof B]: NotBindingOk<Env, SlotAt<F, CR, K>, B[K]>
529
+ type NotOk<Classes extends SchemaClasses, F extends FieldsShape, CR, B> = false extends {
530
+ [K in keyof B]: NotBindingOk<Classes, SlotAt<F, CR, K>, B[K]>
613
531
  }[keyof B]
614
532
  ? false
615
533
  : true
616
534
 
617
535
  /**
618
- * One condition's judgment against the rule environment the type-level
619
- * twin of the engine's comparison roster: class-equal joins (off the
620
- * schema type's class map), orderable order sides (an interval var under a
621
- * non-`pointIn` op is exactly here refused), kind-correct
622
- * `pointIn`/`covers`/`allen` sides, and negated-atom safety (the negated
623
- * relation's class record is resolved through `Classes` by its name). The
624
- * leading `[AnyTreeChild] extends [C]` arm is the recursion's base case:
625
- * at an UNRESOLVED constraint (the whole condition union — or a tree's
626
- * child union, which is the union itself) the judgment is vacuously true —
627
- * without it the constraint instantiation recurses into itself.
536
+ * One condition's judgment the type-level twin of the engine's comparison
537
+ * roster: class-equal joins (off the mint slots), orderable order sides (an
538
+ * interval var under a non-`pointIn` op is exactly here refused),
539
+ * kind-correct `pointIn`/`allen` sides, and negated-atom class safety. The
540
+ * leading `[AnyTreeChild] extends [C]` arm is the recursion's base case.
628
541
  */
629
- type CondOkBool<Env extends EnvShape, Classes extends SchemaClasses, C> = [AnyTreeChild] extends [C]
542
+ type CondOkBool<Classes extends SchemaClasses, C> = [AnyTreeChild] extends [C]
630
543
  ? true
631
544
  : C extends Cmp<infer Op, infer L, infer R, unknown>
632
545
  ? Op extends "eq" | "ne"
633
- ? EqOk<Env, L, R>
546
+ ? EqOk<Classes, L, R>
634
547
  : Op extends "lt" | "le" | "gt" | "ge"
635
- ? [OrderSideOk<Env, L>, OrderSideOk<Env, R>] extends [true, true]
548
+ ? [OrderSideOk<L>, OrderSideOk<R>] extends [true, true]
636
549
  ? true
637
550
  : false
638
551
  : Op extends "pointIn"
639
- ? [IntervalSideOk<Env, L>, PointSideOk<Env, R>] extends [true, true]
552
+ ? [IntervalSideOk<L>, PointSideOk<R>] extends [true, true]
640
553
  ? true
641
554
  : false
642
555
  : Op extends "allen"
643
- ? [IntervalSideOk<Env, L>, IntervalSideOk<Env, R>] extends [true, true]
556
+ ? [IntervalSideOk<L>, IntervalSideOk<R>] extends [true, true]
644
557
  ? true
645
558
  : false
646
559
  : false
647
560
  : C extends Tree<infer Ch extends readonly AnyTreeChild[]>
648
- ? false extends CondOkBool<Env, Classes, Ch[number]>
561
+ ? false extends CondOkBool<Classes, Ch[number]>
649
562
  ? false
650
563
  : true
651
564
  : C extends NotAtom<infer R extends MatchOwner, infer B>
652
- ? NotOk<Env, MatchFields<R>, ClassRecordOf<Classes, R["name"]>, B>
565
+ ? NotOk<Classes, MatchFields<R>, ClassRecordOf<Classes, R["name"]>, B>
653
566
  : false
654
567
 
655
568
  /** The validated `.where` argument (intersect with the inferred condition type). */
656
- type CheckCond<Env extends EnvShape, Classes extends SchemaClasses, C> =
657
- CondOkBool<Env, Classes, C> extends true ? C : never
658
-
659
- /** The `eq`/`ne` params contribution: the param typed by the left variable's field. */
660
- type EqParams<Env extends EnvShape, L, R> =
661
- L extends Var<infer N extends string>
662
- ? R extends Param<infer P extends string>
663
- ? { readonly [Q in P]: Infer<Env[N & keyof Env]["field"]> }
664
- : R extends SetParam<infer P extends string>
665
- ? { readonly [Q in P]: readonly Infer<Env[N & keyof Env]["field"]>[] }
666
- : never
667
- : never
569
+ type CheckCond<Classes extends SchemaClasses, C> = CondOkBool<Classes, C> extends true ? C : never
570
+
571
+ /** The `eq`/`ne` params contribution: the param typed by the left variable's own field. */
572
+ type EqParams<L, R> = L extends AnyVar
573
+ ? R extends Param<infer P extends string>
574
+ ? { readonly [Q in P]: Infer<L["field"]> }
575
+ : R extends SetParam<infer P extends string>
576
+ ? { readonly [Q in P]: readonly Infer<L["field"]>[] }
577
+ : never
578
+ : never
668
579
 
669
580
  /** An order side's params contribution (order params are always `bigint`). */
670
581
  type OrderSideParams<T> = T extends Param<infer P extends string> ? { readonly [Q in P]: bigint } : never
@@ -678,14 +589,13 @@ type MaskParams<M> = M extends MaskParam<infer P extends string> ? { readonly [Q
678
589
  /**
679
590
  * One condition's params-object fragments (a union; the rule builder folds
680
591
  * them into the inferred `Params` record) — every param typed by its use.
681
- * The leading arm is the same base case as {@link CondOkBool}'s: the
682
- * unresolved constraint contributes nothing.
592
+ * The leading arm is the same base case as {@link CondOkBool}'s.
683
593
  */
684
- type CondParams<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
594
+ type CondParams<C> = [AnyTreeChild] extends [C]
685
595
  ? never
686
596
  : C extends Cmp<infer Op, infer L, infer R, infer M>
687
597
  ? Op extends "eq" | "ne"
688
- ? EqParams<Env, L, R>
598
+ ? EqParams<L, R>
689
599
  : Op extends "lt" | "le" | "gt" | "ge"
690
600
  ? OrderSideParams<L> | OrderSideParams<R>
691
601
  : Op extends "pointIn"
@@ -694,7 +604,7 @@ type CondParams<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
694
604
  ? IntervalSideParams<L> | IntervalSideParams<R> | MaskParams<M>
695
605
  : never
696
606
  : C extends Tree<infer Ch extends readonly AnyTreeChild[]>
697
- ? CondParams<Env, Ch[number]>
607
+ ? CondParams<Ch[number]>
698
608
  : C extends NotAtom<infer R extends MatchOwner, infer B>
699
609
  ? BindParams<MatchFields<R>, B>
700
610
  : never
@@ -703,7 +613,7 @@ type CondParams<Env extends EnvShape, C> = [AnyTreeChild] extends [C]
703
613
  type BindParamsShape<F extends FieldsShape, B> = ShapeOf<BindParams<F, B>>
704
614
 
705
615
  /** The flattened params record one condition contributes. */
706
- type CondParamsShape<Env extends EnvShape, C> = ShapeOf<CondParams<Env, C>>
616
+ type CondParamsShape<C> = ShapeOf<CondParams<C>>
707
617
 
708
618
  export type {
709
619
  AggData,
@@ -712,7 +622,6 @@ export type {
712
622
  AnyNotAtom,
713
623
  AnyTreeChild,
714
624
  AtomData,
715
- BindEnv,
716
625
  BindingEntry,
717
626
  BindingInput,
718
627
  BindingTermData,
@@ -728,6 +637,8 @@ export type {
728
637
  CondOkBool,
729
638
  CondParams,
730
639
  CondParamsShape,
640
+ FindColumn,
641
+ FindEntryData,
731
642
  IntervalSide,
732
643
  IntervalVarOk,
733
644
  MaskData,
@@ -742,9 +653,8 @@ export type {
742
653
  RecData,
743
654
  RuleData,
744
655
  RuleItem,
745
- SelectColumn,
746
- SelectEntryData,
656
+ SlotAt,
747
657
  Tree,
748
658
  TreeData
749
659
  }
750
- export { ALLEN, allen, and, comparison, covers, eq, ge, gt, le, lt, ne, not, or, pointIn }
660
+ export { ALLEN, ALLEN_ALL_BITS, allen, and, comparison, eq, ge, gt, le, lt, ne, not, or, pointIn }