You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
spec: declare the aggregate × field-type compatibility matrix (AggregationFunction × FieldType) that dataset measures are refused against (spec half of #16099) #16353
Spec half of #16099, split by director ruling (decision batch #59, 2026-09-06, "both legs, table in spec"). The two consumer legs — compile-time refusal in dataset-compiler (#16099 itself, services) and an authoring-time lint rule (devx sub-card) — are pm:blocked on this card and consume this one table.
Why
A dataset measure pairing avg with a Field.datetime compiles to AVG(col) and reaches the backend: SQLite renders a mean of epoch milliseconds, Postgres fails with 42883. Nothing between author and driver correlates aggregate with the field's type. Which pairs are accepted is a narrowing of a published acceptance set, so it is a contract, declared once in @objectstack/spec and executed by both legs.
Scope
Export a compatibility table from the spec (next to AggregationFunction / DatasetMeasureSchema), e.g. AGGREGATE_FIELD_TYPE_COMPATIBILITY: Record<AggregationFunction, readonly FieldType[]> plus a predicate isAggregateCompatibleWithFieldType(aggregate, fieldType).
Starting rows (director's ruling; the spec seat finalises against the full FieldType membership):
count, countDistinct: any type
sum: numeric types only (number, currency, integer-class) — excludes percent (analytics-service.ts already calls that pair incoherent)
avg: numeric types including percent
min, max: numeric types plus temporal (date, datetime)
Clause-② conformance limb: yes (a previously accepted authoring shape becomes refused once the consumers land) — carry needs:contract-review on the landing PR; changeset states the narrowing.
Spec half of #16099, split by director ruling (decision batch #59, 2026-09-06, "both legs, table in spec"). The two consumer legs — compile-time refusal in
dataset-compiler(#16099 itself, services) and an authoring-time lint rule (devx sub-card) — arepm:blockedon this card and consume this one table.Why
A dataset measure pairing
avgwith aField.datetimecompiles toAVG(col)and reaches the backend: SQLite renders a mean of epoch milliseconds, Postgres fails with42883. Nothing between author and driver correlatesaggregatewith the field's type. Which pairs are accepted is a narrowing of a published acceptance set, so it is a contract, declared once in@objectstack/specand executed by both legs.Scope
AggregationFunction/DatasetMeasureSchema), e.g.AGGREGATE_FIELD_TYPE_COMPATIBILITY: Record<AggregationFunction, readonly FieldType[]>plus a predicateisAggregateCompatibleWithFieldType(aggregate, fieldType).FieldTypemembership):count,countDistinct: any typesum: numeric types only (number,currency,integer-class) — excludespercent(analytics-service.tsalready calls that pair incoherent)avg: numeric types includingpercentmin,max: numeric types plus temporal (date,datetime)needs:contract-reviewon the landing PR; changeset states the narrowing.Out of scope
avgover a datetime works on SQLite and errors on Postgres #16099; lint leg: devx sub-card).Acceptance
AggregationFunctionmember has a row; everyFieldTypemember is classified