Codegen meta-model

Table of Contents

Codegen logical model implementation

The purpose of Logical Space is to separate what to generate from how it is configured: a logical model is a language-neutral description of domain concepts, projected into physical artefacts independently of any generator's internal machinery. ores.codegen's logical model is the set of every .org file an author writes under a component's modeling/ directory — one file per logical element (an entity, a junction, a lookup table, …). For the generator to do anything with one of these files, it first has to answer a prior question: what kind of logical element is this file describing at all? A junction needs its two FK sides read; an entity needs its primary key read; neither reading applies to the other. That classification is the element's metatype, carried in the frontmatter as #+type: ores.codegen.<metatype>, and it is given by the Logical Meta Model (LMM). This section describes the LMM.

Metatypes as metaclasses

Because a metatype classifies what kind of thing each model file is — rather than describing any one model file's content — the eight metatypes can usefully be thought of as metaclasses: classes one level up from the model files themselves, in exactly the sense a UML class is one level up from its instances. ores.codegen.entity is not an entity; it is the class of things that are entities. This is not a loose analogy — it is the same relationship Applied MASD § "Metatype" states plainly: "currency is the entity; domain_entity is its metatype… in MASD, currency is an instance of the metatype domain_entity'."

Reading the eight metaclasses side by side (see Codegen input org-file schema reference for their full frontmatter/section listings) shows they are not unrelated siblings: every one of them requires an :ID:, a #+type, and (with one exception) a #+component — a common shape every metaclass specializes with its own identity fields. That is a generalisation/specialisation relationship, and it is worth drawing as one:

codegen_meta_model.png

(Source: codegen_meta_model.puml, rendered with plantuml.)

Base is abstract — no model file has #+type: ores.codegen.base; it exists only to hold the frontmatter every metaclass inherits, as one typed field. Each of the seven concrete metaclasses below specializes both Base (adding its own segments) and CommonFrontmatter (adding its own identity fields) — see Codegen org-entity meta-model for Entity's specialization drawn out in full, the only metaclass documented to that depth so far.

Segment

ORE Studio extended the MASD logical meta model with segments: not themselves a MASD concept, but a bundle of related fields within logical space — a coherent group of frontmatter keywords, headings, and property-drawer properties that an author fills in together and that project into one facet, or a small closed set of closely related facets, as one unit. Every concrete metaclass is composed of zero or more segments, as drawn in the diagram above. ores.codegen.entity's * SQL heading and everything under it is one segment; so is the ** Qt sub-heading under * C++ and everything under it1 — see Codegen org-entity meta-model for Entity's segments drawn out in full.

A segment exists so a reader (or an LLM) can find "everything about the data this metaclass needs in order to project into its Qt facet" in one page, without also needing to hold the rest of the metaclass's fields in view. A segment lives in logical space, but it is not itself an addressable unit there — the metaclass as a whole is; a segment is only a sub-grouping of its fields. It has no counterpart at all in physical space — a facet does, and is what a segment's fields ultimately project into — which is precisely why every segment page opens with a Physical model mapping table: to make explicit which facets — real points in physical space — that segment's fields project into.

Base's one segment, Common frontmatter, is the first one worth documenting, because every metaclass's own frontmatter inherits from it — not because the rest of a metaclass's segments build on it; most segments (SQL, Qt, …) are unrelated to frontmatter entirely.

Structural versus non-structural variability

A .org model file bundles three logically distinct concerns into a single physical document: the modelled element's shape, its authored variability, and any protected regions it requires. This bundling, and the criterion by which a given field is properly classified as a feature rather than a structural predicate, is treated formally in Applied MASD § "The entity model file as a unified literate document," which also contrasts this approach with how classical UML+Profile MDE distributes the same three concerns across three separate artefacts. A field on any segment page whose classification is not immediately evident should be evaluated against that criterion rather than assumed.

Two questions arising from this distinction remain open for the present meta-model: whether every segment page ought to carry an explicit structural/non-structural label for each of its fields, and whether Entity's domain_entity "shape" concept is properly understood as an instance of MASD's existing profile construct. Both are tracked by capture Formalize the codegen entity knob system as a proper MASD/MDE feature model rather than resolved piecemeal across individual segment pages.

Common frontmatter

Every metaclass's frontmatter inherits from CommonFrontmatter: the properties below are declared once, here, and every metaclass's own frontmatter — documented on that metaclass's own hub page — extends this set rather than repeating it.

Keyword Purpose
:ID: (drawer) UUID of this org file. Used for cross-document links; also what makes the file an org-roam node at all, independently of codegen.
#+type: The metatype discriminator. Its value is what dispatches to a specific archetype set — see Applied MASD § "Metatype".
#+filetags: Org-roam tags; convention is :model:<metatype-noun>:<component>:, e.g. :model:entity:refdata:.
#+component: Component the model belongs to (refdata, trading, …). Present on every metaclass except ServiceRegistry (ores.codegen.service_registry), which is cross-component by nature (one registry of every backend service).

book, an Entity, showing CommonFrontmatter alone (its own specialized fields, #+entity_singular and friends, are layered on top — see below):

,:PROPERTIES:
,:ID: <uuid>
,:END:
#+title: ores.refdata.book
#+type: ores.codegen.entity
#+filetags: :model:entity:refdata:
#+component: refdata

Each concrete metaclass's own specialized frontmatter — the identity/naming fields a generator needs to render that metaclass's archetype set — is documented on its own hub page once one exists; until then, see Codegen input org-file schema reference § that metatype for the quick list. The specialized fields diverge considerably between metaclasses:

Metaclass Specialized fields (on top of the base above)
Entity #+entity_singular, #+entity_plural, #+entity_title, #+brief
Junction #+name, #+name_singular, #+name_title, #+name_singular_words, #+brief — a junction has no single subject to be "the entity," so its naming scheme is built around the relation's plural/singular forms instead.
LookupEntity #+has_tenant_id, #+has_coding_scheme, #+has_image_id, #+has_artefact_insert_fn — structural declarations made at frontmatter level, no naming fields.

Entity's full specialized-frontmatter treatment lives on Codegen entity meta-model — file-level conventions.

The metaclasses

The table below lists the descendants of the base metaclass and provides details of each: its metatype, hub page, and where its model files live. Base itself is abstract and has no row, no model files, and no #+type value of its own.

Metaclass Metatype (#+type) Hub page Model files live under
Entity ores.codegen.entity Codegen org-entity meta-model projects/ores.<component>/modeling/ores.<component>.<entity>.org
Junction ores.codegen.junction (not yet authored to this depth — see schema reference for the shallow treatment) same
LookupEntity ores.codegen.lookup_entity (not yet authored) same
FieldGroup ores.codegen.field_group (not yet authored) same
Table (retired) ores.codegen.table Superseded by ores.codegen.entity; type removed from the generator
ServiceRegistry ores.codegen.service_registry (not yet authored) same
Module ores.codegen.module (not yet authored) same

Every entity model file, regardless of metaclass, is also an instance of the pattern described in Applied MASD § "The entity model file as a unified literate document": one physical .org document bundling the logical element's shape, its authored variability, and any protected regions (paste blocks) it needs. Read that section for why these documents look the way they do.

Use of :ignore: in models

Every metaclass's body is a set of top-level sections, and a generator's templates read only the ones its facets recognise (* SQL, * C++, …). A section outside that recognised set — free-form prose about the model itself, say — is simply invisible to codegen unless it is explicitly tagged :ignore:, which asks the loader to skip that heading when reading the file. The tag means "skip this heading," not "this document is unimportant" — an unfortunate naming collision if you're skimming the table of contents of a model that uses it:

* About this file
,:PROPERTIES:
,:ignore: t
,:END:

Free-form notes for a human reader; codegen never reads this section.

See also

Footnotes:

1

It is confusing that segment names (SQL, Qt, …) look identical to technical space names. They are not a reference to the technical space itself — a segment is a logical-space grouping of fields, not a physical-space one. The name is shared only because the fields bundled into that segment happen to be the ones the matching technical space's facet(s) need.

Emacs 29.3 (Org mode 9.6.15)