Repository navigation
FR-044 — Core reporting: measures, dimensions, reports, and semantic-layer exporters #391
Description
Activity
- addedFRRoadmap feature request tracked in spec/roadmap.mdRoadmap feature request tracked in spec/roadmap.mdarea:metamodelMetamodel vocabulary / loaderMetamodel vocabulary / loaderarea:codegenCode generationCode generation
on Oct 2, 2026 - added a commit that references this issue
on Oct 2, 2026 Decisions D1–D6 resolved 2026-10-03 (all as recommended), and the ADR-0023 vocabulary list agreed. The spec now carries the per-item justifications in §3.1 (a7802c7). Changes from the draft: the report's
@windowis dropped in favour of the existing@filter;@dimensionsitems are strings (nameorname:grain); MetricFlow export waits for first adopter demand. Next: implementation plan for phase 1 (metamodel 1.1 vocabulary in five ports + TS view lowering).FR-044 Plan 1 has landed in #397.
- The reporting vocabulary (the ADR-0023 list in spec §3.1) is registered and validated at load in all five ports, with
metamodelVersion1.1. - The rule table is enforced rule-for-rule with identical message text across ports: 20 rules (D1–D4, M1–M6, S1, R1–R7, F1–F2), covered by new shared
fixtures/conformance/cases. - Relative-date filter values load only on reporting hosts (
segment,measure.aggregate,object.report). - Reports are inert for now: every generator,
migrateandmeta docsskipobject.report, and a no-churn corpus proves existing output is byte-identical.
Next is Plan 2: TypeScript view lowering for
object.reportand relative-date values, plus persistence-conformance reads in every port.measure.derivedstays out until FR-037 R5 lands (#393).- The reporting vocabulary (the ADR-0023 list in spec §3.1) is registered and validated at load in all five ports, with
FR-044 Plan 2 has landed in #399.
- A view-backed
object.report(one declaringsource.rdbwith@kind: view) now lowers to a SQL view on Postgres, SQLite/D1 and MySQL, including relative-date filter values. A sourceless report stays inert. - MySQL SQL ships through
buildReportViewsplus a documented recipe (no CLI surface); time bucketing andnoware UTC in v1. - Dimension
@viajoins follow the existing projection rule unchanged. - Shared persistence-conformance read scenarios for reports pass in every port (TypeScript, C#, Java, Kotlin, Python). C# and Kotlin generate a report's typed row; the TypeScript, Java and Python generators keep skipping reports until Plan 3.
- The
metaobjects-authoringskill, docs and changelog now cover reporting.
Next is Plan 3: generated read routes and the api-contract
report/corpus in five ports.- A view-backed
FR-044 Plan 3 has landed in #407.
- A view-backed
object.reportis now served over the generated read API in all five ports: list route with filter, sort and paging over every derived field, at the standard pluralized route segment. No/{id}route is mounted for a report. - The api-contract corpus gains a
report/sub-corpus that every port runs. - Reports appear in
meta docs(a sourceless report gets a "not served" model page). - No client-tier output (hooks, grids) is generated for reports; that waits for Plan 5.
- Named behaviour changes for existing projections, recorded in the changelog: a view with no id column answers 404 on
/{id}instead of the first row;idColumnis emitted when the key field is notid; read-only projection API docs list only mounted routes; TypeScript types a view decimal as the string it is; Kotlin decimal/float filters no longer fail.
Follow-up in progress: make projection/report read-route behaviour identical across all five ports and pin it with shared api-contract cases. Next plan is Plan 4 (Cube exporter).
- A view-backed
Core reporting in the metamodel: entities declare dimensions, measures (aggregate, ratio, derived) and segments; an
object.reportnames a fixed combination and compiles to a SQL view that every port can read. A full semantic layer is delegated to established tools through reference exporters (Cube first, dbt MetricFlow second). A MetaObjects query-time engine is parked with a re-entry trigger.metamodelVersion1.0 → 1.1 (a MINOR on every registry).measure.deriveddepends on FR-037 R5 wave 1 (arithmeticfnmembers).Open decisions (D1–D6, spec §8):
segmentas its own type;object.reportsubtype vs attributes onobject.projection; week start; time-dimension field naming; second exporter timing; Search-backend capability gate for exact distinct.Spec / design: https://github.com/metaobjectsdev/metaobjects/blob/main/docs/superpowers/specs/2026-10-02-fr-044-core-reporting-design.md
Target release: 1.1
Status and target release live on this issue (milestone). Process: docs/ROADMAP-PROCESS.md.
Depends on #393 (FR-037 R5) for
measure.derivedonly.