What to build
An expression-capable group key for aggregate projections, temporal first: a portable truncation surface — t.date.trunc("month") (or ferro.trunc("month", t.date)) — compiling to date_trunc on Postgres, usable as a projected field, group key, and order_by source exactly like a plain column.
Requested by Pinch (M8 reporting, PRD 0012, found at the M8 CP0 spike pinch-backend#46). Blocks nothing — recorded demand, not a gate: M8 ships on daily-grain GROUP BY t.date (verified working on 0.17.1) + Python folding, which is fine while fetched rows = days-with-activity. This retires that fold when key spaces grow, and is the first concrete consumer of the record plan's reserved per-field expr slot (ADR-0007/0009).
The gap, verified on 0.17.1
Group keys are columns only — plain or traversed. No date-part accessor or function surface exists in the query API (src/ferro/query/, aggregation guide). Wanted:
rows = await Transaction.select(
lambda t: {
"month": t.date.trunc("month"), # ← does not exist
"total": t.amount_minor.sum(),
}
).where(lambda t: t.amount_minor < 0).all()
Acceptance criteria
Out of scope
General computed expressions, HAVING, window functions — temporal truncation is the whole ask.
What to build
An expression-capable group key for aggregate projections, temporal first: a portable truncation surface —
t.date.trunc("month")(orferro.trunc("month", t.date)) — compiling todate_truncon Postgres, usable as a projected field, group key, andorder_bysource exactly like a plain column.Requested by Pinch (M8 reporting, PRD 0012, found at the M8 CP0 spike pinch-backend#46). Blocks nothing — recorded demand, not a gate: M8 ships on daily-grain
GROUP BY t.date(verified working on 0.17.1) + Python folding, which is fine while fetched rows = days-with-activity. This retires that fold when key spaces grow, and is the first concrete consumer of the record plan's reserved per-fieldexprslot (ADR-0007/0009).The gap, verified on 0.17.1
Group keys are columns only — plain or traversed. No date-part accessor or function surface exists in the query API (
src/ferro/query/, aggregation guide). Wanted:Acceptance criteria
truncgranularitiesday/week/month/quarter/yearondate/datetimecolumns, both as projected field and group key;order_bycomposes.exprfield shape exercised end to end; golden vectors extended.Out of scope
General computed expressions,
HAVING, window functions — temporal truncation is the whole ask.