@bjornpagen/bumbledb 0.8.0 → 0.10.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/src/statements.ts CHANGED
@@ -41,6 +41,7 @@ import {
41
41
  type CapacityWindow,
42
42
  isCapacityWeight,
43
43
  isCapacityWindow,
44
+ type UnitDimensionBan,
44
45
  type UnitWindowBan,
45
46
  unitWeight,
46
47
  type WeightOnSource
@@ -357,13 +358,15 @@ function assertBoundsOnTarget(window: CapacityWindowSpec, target: FaceData, stat
357
358
  * on(Device, "pool"))` bounds each pool's summed draw by the pool's own
358
359
  * row. The two faces pair by arity AND structural shape
359
360
  * ({@link SameShapes}), exactly as containment — the grouping join reads
360
- * the same positionwise field pairing. The weight-sensitive `{1..*}` ban
361
- * rides the UNIT overload only ({@link UnitWindowBan} — on a weighted
362
- * statement "positive total" is a different, weaker law than containment).
361
+ * the same positionwise field pairing. The weight-sensitive bans ride the
362
+ * UNIT overload only: `{1..*}` ({@link UnitWindowBan} — on a weighted
363
+ * statement "positive total" is a different, weaker law than containment)
364
+ * and the `duration()` bound ({@link UnitDimensionBan} — a count of facts
365
+ * bounded by a span of time mixes dimensions, C18).
363
366
  */
364
367
  function capacity<B extends AnyFace, W extends CapacityWindow, A extends AnyFace>(
365
368
  target: B,
366
- window: W & UnitWindowBan<W> & BoundsOnTarget<W, B>,
369
+ window: W & UnitWindowBan<W> & UnitDimensionBan<W> & BoundsOnTarget<W, B>,
367
370
  source: A & SameArity<B, A> & SameShapes<B, A>
368
371
  ): CapacityStatement<B["data"], A["data"]>
369
372
  function capacity<B extends AnyFace, M extends CapacityWeight, W extends CapacityWindow, A extends AnyFace>(
@@ -401,6 +404,15 @@ function capacity(
401
404
  "`{1..*}` on the unit instance says only what the bare containment says — drop the annotation and write the containment: contained(source, target)"
402
405
  )
403
406
  }
407
+ // The C18 dimension gate, unit instance (the engine's
408
+ // CapacityDimensionMixing twin — ruled 2026-07-24): a count of facts
409
+ // bounded by a span of time mixes dimensions. Judged here for untyped
410
+ // callers; the engine's validate_capacity stays the final authority.
411
+ if (weight.kind === "unit" && window.kind === "range" && window.hi.kind === "durationField") {
412
+ throw errors.new(
413
+ `a unit (count) window against the duration() bound on ${window.hi.field} mixes dimensions (C18) — weigh the source with weigh(duration(field)), or bound by a u64 field or literal`
414
+ )
415
+ }
404
416
  const data: CapacityData = Object.freeze({
405
417
  kind: "capacity",
406
418
  target: target.data,