Skip to content

FR-044 — Core reporting: measures, dimensions, reports, and semantic-layer exporters #391

Description

@dmealing

Core reporting in the metamodel: entities declare dimensions, measures (aggregate, ratio, derived) and segments; an object.report names 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.

  • Additive vocabulary: metamodelVersion 1.0 → 1.1 (a MINOR on every registry).
  • Bound by FR-037 R5's cross-backend admission rule; no SQL strings in the metamodel.
  • measure.derived depends on FR-037 R5 wave 1 (arithmetic fn members).

Open decisions (D1–D6, spec §8): segment as its own type; object.report subtype vs attributes on object.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.derived only.

Activity

  1. added this to the 1.1 milestone on Oct 2, 2026
  2. added
    FRRoadmap feature request tracked in spec/roadmap.md
    area:metamodelMetamodel vocabulary / loader
    on Oct 2, 2026
  3. dmealing commented on Oct 3, 2026

    @dmealing
    MemberAuthor

    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 @window is dropped in favour of the existing @filter; @dimensions items are strings (name or name:grain); MetricFlow export waits for first adopter demand. Next: implementation plan for phase 1 (metamodel 1.1 vocabulary in five ports + TS view lowering).

  4. dmealing commented on Oct 4, 2026

    @dmealing
    MemberAuthor

    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 metamodelVersion 1.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, migrate and meta docs skip object.report, and a no-churn corpus proves existing output is byte-identical.

    Next is Plan 2: TypeScript view lowering for object.report and relative-date values, plus persistence-conformance reads in every port. measure.derived stays out until FR-037 R5 lands (#393).

  5. dmealing commented on Oct 4, 2026

    @dmealing
    MemberAuthor

    FR-044 Plan 2 has landed in #399.

    • A view-backed object.report (one declaring source.rdb with @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 buildReportViews plus a documented recipe (no CLI surface); time bucketing and now are UTC in v1.
    • Dimension @via joins 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-authoring skill, docs and changelog now cover reporting.

    Next is Plan 3: generated read routes and the api-contract report/ corpus in five ports.

  6. dmealing commented on Oct 6, 2026

    @dmealing
    MemberAuthor

    FR-044 Plan 3 has landed in #407.

    • A view-backed object.report is 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; idColumn is emitted when the key field is not id; 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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FRRoadmap feature request tracked in spec/roadmap.mdarea:codegenCode generationarea:metamodelMetamodel vocabulary / loader

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions