Per-key validating constraint over a candidate mapping M — applied
by the public aggregate / rolling / reduce signatures on top of
the permissive AggregateMap shape, as a self-referential
constraint:
Inference still comes from the argument (the const type parameter
keeps literal types); the constraint then checks each entry by key:
Key names a source column → a shorthand reducer must be valid
for that column's kind (AggregateFunctionsForKind — so
host: 'avg' on a string column is a compile error), or any
spec.
Any other literal key → spec form only. A bare reducer on an
unknown key (ghost: 'avg') is a typo the runtime rejects with
"unknown source column"; this surfaces it at compile time instead.
Spec values are intentionally NOT correlated between from and
using here — AggregateOutputSpec<S> checks using against the
union of all columns' reducers, not the specific from column's
({ from: 'host', using: 'avg' } compiles; the runtime emits an
empty column). That looseness predates the unification; tightening it
requires a distributed spec union and is left as a follow-up so this
change stays guard-restoring only.
Two deliberate escape hatches degrade to the permissive
AggregateMap shape:
Broad schemas (TimeSeries<SeriesSchema>) — there are no
literal column names to validate against.
Pre-widened values (a variable explicitly typed
AggregateMap<S>, whose keys are an index signature) — validation
applies to literal keys, which inline mapping literals always have.
Internal generic call sites (live mirrors, partitioned delegation)
cannot prove a generic M satisfies its own validation and must not
call through the public overloads — they route through the loose
implementation paths instead (see the trust-boundary notes at those
sites).
Per-key validating constraint over a candidate mapping
M— applied by the publicaggregate/rolling/reducesignatures on top of the permissive AggregateMap shape, as a self-referential constraint:Inference still comes from the argument (the
consttype parameter keeps literal types); the constraint then checks each entry by key:host: 'avg'on astringcolumn is a compile error), or any spec.ghost: 'avg') is a typo the runtime rejects with "unknown source column"; this surfaces it at compile time instead.Spec values are intentionally NOT correlated between
fromandusinghere —AggregateOutputSpec<S>checksusingagainst the union of all columns' reducers, not the specificfromcolumn's ({ from: 'host', using: 'avg' }compiles; the runtime emits an empty column). That looseness predates the unification; tightening it requires a distributed spec union and is left as a follow-up so this change stays guard-restoring only.Two deliberate escape hatches degrade to the permissive AggregateMap shape:
TimeSeries<SeriesSchema>) — there are no literal column names to validate against.AggregateMap<S>, whose keys are an index signature) — validation applies to literal keys, which inline mapping literals always have.Internal generic call sites (live mirrors, partitioned delegation) cannot prove a generic
Msatisfies its own validation and must not call through the public overloads — they route through the loose implementation paths instead (see the trust-boundary notes at those sites).