How do I add a new codegen entity model?

Table of Contents

Entity models drive C++ + SQL codegen. The current form is a literate ores.<component>.<entity>.org file under the component's modeling/ directory; codegen discovers it from the modeling_dir manifest entry by matching #+type: ores.codegen.entity in the frontmatter. The shape is documented in the Codegen org-entity meta-model.

Question

How do I add a new codegen entity model?

Answer

1. Scaffold the file

projects/ores.compass/compass.sh add entity_org \
    --slug <entity> --component <component> \
    --description "<one-line description of the modelled entity>" \
    --shape <shape>

--shape is the important part: pick the domain_entity shape that matches the entity being commissioned — simple-text-key (country-like), fk-scoped (book-like), hierarchical-composite (party/counterparty-like), richest (currency-like, every optional knob exercised), or timeseries (market_observation-like, no Qt). Each pre-populates the scaffold's Flags/SQL/Qt sections with that shape's knobs already set correctly, sampled from a real, proven-correct reference entity — omit --shape only to get the old bare, unknobbed skeleton. Individual --entity-<knob> flags (e.g. --entity-has-workspace-id false) override any preset value. Anything a shape can't derive (actual columns, foreign-key targets, display fields, …) is left as a visible, one-line TODO in the output — never silently omitted. See Codegen org-entity meta-model for the full knob catalogue behind each shape.

The scaffold writes projects/ores.<component>/modeling/ores.<component>.<entity>.org with the required frontmatter (#+type: ores.codegen.entity and friends) and the shape's knobbed sections (Flags, Primary key, Natural keys, Columns, SQL, optionally Foreign keys=/=Insert trigger, C++, optionally Qt).

2. Fill in the model

Open the scaffolded file and resolve every TODO — the shape sets knobs, not entity-specific facts like actual columns, foreign-key targets, or display fields. The meta-model documents every required property and the well-known block kinds (e.g. additional repository declarations / implementations / includes) that custom methods attach to via :implements <kind-UUID>. Once the model compiles and generates cleanly, work through the post-generation checklist — the fixed manual integration steps (registrar wiring, NATS event-relay wiring, …) codegen does not and will not wire up for you.

3. Wire the component (first entity in a component only)

If projects/ores.<component>/modeling/ is the first org model in this component, add a modeling_dir entry to the component's COMPONENTS record in projects/ores.codegen/src/codegen/manifest.py:

"<component>-cpp": Component(
    name="<component>-cpp",
    models_dir="projects/ores.codegen/models/<component>",
    entity_glob="*_domain_entity.json",
    exclude_suffix=None,
    modeling_dir="projects/ores.<component>/modeling",
),

Existing components that already have modeling_dir set need no change to add another entity.

4. Regenerate

./compass.sh codegen regenerate \
    --component <component>-cpp --address ores.cpp

Codegen unions matches from the legacy JSON glob and the new modeling_dir (org files whose #+type: says ores.codegen.entity).

Script

projects/ores.compass/compass.sh add entity_org — the scaffold itself. The codegen template is projects/ores.codegen/library/templates/doc_entity_org.org.mustache.

Tested by

The pilot entity ores.refdata.party under projects/ores.refdata/modeling/. Regenerating refdata picks it up via the modeling_dir entry and produces byte-identical output to the legacy party_entity.org location.

See also

Emacs 29.3 (Org mode 9.6.15)